1 /******************************************************************************
4 Lantiq Deutschland GmbH
5 Am Campeon 3; 81726 Munich, Germany
7 THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
8 WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
9 SOFTWARE IS FREE OF CHARGE.
11 THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
12 ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
13 WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
14 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
15 OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
16 PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
17 PROPERTY INFRINGEMENT.
19 EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
20 FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
21 OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 DEALINGS IN THE SOFTWARE.
25 ****************************************************************************
27 Description : This file contains implementation of Custom NAT function
28 for Infineon's VINETIC-SVIP16
29 *******************************************************************************/
31 #include <linux/module.h>
32 #include <linux/netfilter_ipv4.h>
33 #include <linux/if_ether.h>
34 #include <linux/netdevice.h>
35 #include <linux/inetdevice.h>
38 #include <linux/if_vlan.h>
39 #include <linux/udp.h>
40 #include <linux/kernel.h>
41 #include <linux/version.h>
42 #include <linux/proc_fs.h>
43 #include <linux/in6.h> /* just to shut up a warning */
44 #include <linux/miscdevice.h>
45 #include <asm/checksum.h>
47 #include <linux/svip_nat.h>
49 MODULE_AUTHOR("Lantiq Deutschland GmbH");
50 MODULE_DESCRIPTION("SVIP Network Address Translation module");
51 MODULE_LICENSE("GPL");
53 #define SVIP_NAT_INFO_STR "@(#)SVIP NAT, version "SVIP_NAT_VERSION
55 /** maximum voice packet channels possible on the SVIP LC system
56 (equals maximum number of Codec channels possible) */
57 #define SVIP_SYS_CODEC_NUM ((SVIP_SYS_NUM) * (SVIP_CODEC_NUM))
59 /** end UDP port number of the SVIP Linecard System */
60 #define SVIP_UDP_TO ((SVIP_UDP_FROM) + (SVIP_SYS_CODEC_NUM) - 1)
62 /** end UDP port number of the Master SVIP in SVIP Linecard System */
63 #define SVIP_UDP_TO_VOFW0 ((SVIP_UDP_FROM) + (SVIP_CODEC_NUM) - 1)
65 #define SVIP_PORT_INRANGE(nPort) \
66 ((nPort) >= (SVIP_UDP_FROM) && (nPort) <= (SVIP_UDP_TO))
68 #define SVIP_PORT_INDEX(nPort) (nPort - SVIP_UDP_FROM)
70 #define SVIP_NET_DEV_ETH0_IDX 0
71 #define SVIP_NET_DEV_VETH0_IDX 1
72 #define SVIP_NET_DEV_LO_IDX 2
74 #define SVIP_NET_DEV_ETH0_NAME "eth0"
75 #define SVIP_NET_DEV_ETH1_NAME "eth1"
76 #define SVIP_NET_DEV_VETH1_NAME "veth0"
77 #define SVIP_NET_DEV_LO_NAME "lo"
79 #define SVIP_NAT_STATS_LOC2REM 0
80 #define SVIP_NAT_STATS_REM2LOC 1
81 #define SVIP_NAT_STATS_TYPES 2
83 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
84 #define SVIP_NAT_FOR_EACH_NETDEV(d) for_each_netdev(&init_net, dev)
85 #define SVIP_NAT_IP_HDR(ethhdr) ip_hdr(ethhdr)
87 #define SVIP_NAT_FOR_EACH_NETDEV(d) for(d=dev_base; dev; dev = dev->next)
88 #define SVIP_NAT_IP_HDR(ethhdr) (ethhdr)->nh.iph
89 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) */
91 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
92 #define SVIP_NAT_SKB_MAC_HEADER(ethhdr) (ethhdr)->mac.ethernet
93 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
94 #define SVIP_NAT_SKB_MAC_HEADER(ethhdr) (ethhdr)->mac.raw
96 #define SVIP_NAT_SKB_MAC_HEADER(ethhdr) skb_mac_header(ethhdr)
99 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
100 #define VLAN_DEV_REAL_DEV(dev) vlan_dev_real_dev(dev)
101 #define VLAN_DEV_VLAN_ID(dev) vlan_dev_vlan_id(dev)
103 #define VLAN_DEV_REAL_DEV(dev) (VLAN_DEV_INFO(dev)->real_dev)
104 #define VLAN_DEV_VLAN_ID(dev) (VLAN_DEV_INFO(dev)->vlan_id)
105 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) */
107 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
108 #define MOD_INC_USE_COUNT
109 #define MOD_DEC_USE_COUNT
112 #if ! ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && \
113 (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)))
114 #define VLAN_8021Q_UNUSED
118 extern spinlock_t vlan_group_lock
;
119 extern struct net_device
*__vlan_find_dev_deep(struct net_device
*real_dev
, unsigned short VID
);
121 typedef struct SVIP_NAT_stats
123 unsigned long inPackets
;
124 unsigned long outPackets
;
125 unsigned long outErrors
;
128 typedef struct SVIP_NAT_table_entry
130 SVIP_NAT_IO_Rule_t natRule
;
131 SVIP_NAT_stats_t natStats
[SVIP_NAT_STATS_TYPES
];
132 } SVIP_NAT_table_entry_t
;
134 /* pointer to the SVIP NAT table */
135 static SVIP_NAT_table_entry_t
*pNatTable
= NULL
;
137 struct net_device
*net_devs
[3];
138 static u32
*paddr_eth0
;
139 static u32
*paddr_eth0_0
;
140 static u32
*paddr_veth0
;
141 static u32
*pmask_veth0
;
143 static struct semaphore
*sem_nat_tbl_access
;
144 static int proc_read_in_progress
= 0;
146 static int nDeviceOpen
= 0;
148 /* saves the NAT table index between subsequent invocation */
149 static int nProcReadIdx
= 0;
151 static long SVIP_NAT_device_ioctl(struct file
*,unsigned int ,unsigned long);
152 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
153 static int SVIP_NAT_device_release (struct inode
*,struct file
*);
155 static void SVIP_NAT_device_release (struct inode
*,struct file
*);
157 static int SVIP_NAT_device_open (struct inode
*,struct file
*);
159 /* This structure holds the interface functions supported by
160 the SVIP NAT configuration device. */
161 struct file_operations SVIP_NAT_Fops
= {
162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
164 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) */
165 llseek
: NULL
, /* seek */
168 readdir
: NULL
, /* readdir */
169 poll
: NULL
, /* select */
170 unlocked_ioctl
: SVIP_NAT_device_ioctl
, /* ioctl */
171 mmap
: NULL
, /* mmap */
172 open
: SVIP_NAT_device_open
, /* open, */
173 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
174 flush
: NULL
, /* flush */
176 release
: SVIP_NAT_device_release
/* close */
179 /** Structure holding MISC module operations */
180 static struct miscdevice SVIP_NAT_miscdev
=
182 minor
: MINOR_NUM_SVIP_NAT
,
183 name
: SVIP_NAT_DEVICE_NAME
,
187 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
188 int nSVIP_NAT_Sniffer
;
189 unsigned char pSVIP_NAT_SnifferMAC
[ETH_ALEN
];
190 int nSVIP_NAT_SnifferMacSet
;
193 /******************************************************************************/
195 Function to read /proc/net/svip_nat/nat proc entry
198 page - pointer to page buffer
199 start - pointer to start address pointer
201 count - maximum data length to read
202 eof - end of file flag
203 data - proc read data (provided by the function
210 Each call of this routine forces a copy_to_user of the data returned by
211 'fn'. This routine will be called by the user until 'len = 0'.
212 ****************************************************************************/
213 static int SVIP_NAT_ProcRead (char *page
, char **start
, off_t off
,
214 int count
, int *eof
, void *data
)
217 int (*fn
)(char *buf
, int size
);
220 /* If the NAT table index is negative, the reading has completed */
221 if (nProcReadIdx
< 0)
225 proc_read_in_progress
= 0;
226 up(sem_nat_tbl_access
);
230 local_irq_save(flags
);
231 if (!proc_read_in_progress
)
233 proc_read_in_progress
= 1;
234 local_irq_restore(flags
);
235 /* we use this semaphore in order to ensure no other party(could be ioctl
236 FIO_SVIP_NAT_RULE_LIST), uses function SVIP_NAT_ProcReadNAT(), during
237 the time read of the proc file takes place */
238 down(sem_nat_tbl_access
);
242 local_irq_restore(flags
);
248 len
= fn (page
, count
);
249 /* In this setup each read of the proc entries returns the read data by
250 'fn' to the user. The user keeps issuing read requests as long as the
251 returned value of 'len' is greater than zero. */
263 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
265 Function to read remaining proc entries
267 static int SVIP_NAT_ProcReadGen (char *page
, char **start
, off_t off
,
268 int count
, int *eof
, void *data
)
270 int (*fn
)(char *buf
, int size
);
282 len
= fn (page
, count
);
284 if (len
<= off
+ count
)
305 /******************************************************************************/
307 Function for setting up /proc/net/svip_nat read data
310 buf - pointer to read buffer
311 count - size of read buffer
314 length of read data into buffer
317 The global variable 'nProcReadIdx' is used to save the table index where
318 the reading of the NAT table stopped. Reading is stopped when the end of
319 the read buffer is approached. On the next itteration the reading continues
320 from the saved index.
321 *******************************************************************************/
322 static int SVIP_NAT_ProcReadNAT(char *buf
, int count
)
326 SVIP_NAT_IO_Rule_t
*pNatRule
;
328 if (nProcReadIdx
== -1)
334 if (nProcReadIdx
== 0)
336 len
= sprintf(buf
+len
,
337 "Remote host IP " /* 16 char */
338 "Remote host MAC " /* 19 char */
339 "Local host IP " /* 15 char */
340 "Local host MAC " /* 19 char */
341 "Local host UDP " /* 16 char */
342 "Loc->Rem(in/out/err) " /* 22 char */
343 "Rem->Loc(in/out/err)\n\r");
346 for (i
= nProcReadIdx
; i
< SVIP_SYS_CODEC_NUM
; i
++)
350 pNatRule
= &pNatTable
[i
].natRule
;
352 if (pNatRule
->remIP
!= 0)
354 /* make sure not to overwrite the buffer */
359 slen
= sprintf(buf
+len
, "%d.%d.%d.%d",
360 (int)((pNatRule
->remIP
>> 24) & 0xff),
361 (int)((pNatRule
->remIP
>> 16) & 0xff),
362 (int)((pNatRule
->remIP
>> 8) & 0xff),
363 (int)((pNatRule
->remIP
>> 0) & 0xff));
365 for (j
= 0; j
< (16-slen
); j
++)
366 len
+= sprintf(buf
+len
, " ");
370 for (j
= 0; j
< ETH_ALEN
; j
++)
372 slen
+= sprintf(buf
+len
+slen
, "%02x%s",
373 pNatRule
->remMAC
[j
], j
< ETH_ALEN
-1 ? ":" : " ");
376 for (j
= 0; j
< (19-slen
); j
++)
377 len
+= sprintf(buf
+len
, " ");
380 slen
= sprintf(buf
+len
, "%d.%d.%d.%d",
381 (int)((pNatRule
->locIP
>> 24) & 0xff),
382 (int)((pNatRule
->locIP
>> 16) & 0xff),
383 (int)((pNatRule
->locIP
>> 8) & 0xff),
384 (int)((pNatRule
->locIP
>> 0) & 0xff));
386 for (j
= 0; j
< (15-slen
); j
++)
387 len
+= sprintf(buf
+len
, " ");
391 for (j
= 0; j
< ETH_ALEN
; j
++)
393 slen
+= sprintf(buf
+len
+slen
, "%02x%s",
394 pNatRule
->locMAC
[j
], j
< ETH_ALEN
-1 ? ":" : " ");
397 for (j
= 0; j
< (19-slen
); j
++)
398 len
+= sprintf(buf
+len
, " ");
401 slen
= sprintf(buf
+len
, "%d", pNatRule
->locUDP
);
403 for (j
= 0; j
< (16-slen
); j
++)
404 len
+= sprintf(buf
+len
, " ");
406 /* NAT statistics, Local to Remote translation */
407 slen
= sprintf(buf
+len
, "(%ld/%ld/%ld)",
408 pNatTable
[i
].natStats
[SVIP_NAT_STATS_LOC2REM
].inPackets
,
409 pNatTable
[i
].natStats
[SVIP_NAT_STATS_LOC2REM
].outPackets
,
410 pNatTable
[i
].natStats
[SVIP_NAT_STATS_LOC2REM
].outErrors
);
412 for (j
= 0; j
< (22-slen
); j
++)
413 len
+= sprintf(buf
+len
, " ");
415 /* NAT statistics, Remote to Local translation */
416 len
+= sprintf(buf
+len
, "(%ld/%ld/%ld)\n\r",
417 pNatTable
[i
].natStats
[SVIP_NAT_STATS_REM2LOC
].inPackets
,
418 pNatTable
[i
].natStats
[SVIP_NAT_STATS_REM2LOC
].outPackets
,
419 pNatTable
[i
].natStats
[SVIP_NAT_STATS_REM2LOC
].outErrors
);
422 if (i
== SVIP_SYS_CODEC_NUM
)
423 nProcReadIdx
= -1; /* reading completed */
425 nProcReadIdx
= i
; /* reading still in process, buffer was full */
430 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
432 Converts MAC address from ascii to hex respesentaion
434 static int SVIP_NAT_MacAsciiToHex(const char *pMacStr
, unsigned char *pMacHex
)
436 int i
=0, c
=0, b
=0, n
=0;
438 memset(pMacHex
, 0, ETH_ALEN
);
439 while (pMacStr
[i
] != '\0')
443 unsigned char nToHex
= 0;
445 /* check for hex digit */
446 if (pMacStr
[i
] >= '0' && pMacStr
[i
] <= '9')
448 else if (pMacStr
[i
] >= 'a' && pMacStr
[i
] <= 'f')
450 else if (pMacStr
[i
] >= 'A' && pMacStr
[i
] <= 'F')
456 printk(KERN_ERR
"SVIP NAT: invalid MAC address format[%s]\n", pMacStr
);
463 pMacHex
[b
] |= ((pMacStr
[i
] - nToHex
)&0xf) << (4*n
);
466 /* advance to next byte, check if complete */
469 /* byte completed, next we expect a colon... */
471 /* and, do not check for hex digit */
479 if (pMacStr
[i
] == ':')
481 /* next we expect hex digit, again */
486 printk(KERN_ERR
"SVIP NAT: invalid MAC address format[%s]\n", pMacStr
);
496 Used to set the destination MAC address of a host where incoming
497 SVIP VoFW packets are to be addressed. In case the address is set
498 to 00:00:00:00:00:00 (the default case), the packets will written
499 out to eth0 with its original MAC addess.
502 usage: 'echo "00:03:19:00:15:D1" > cat /proc/net/svip_nat/snifferMAC'
504 int SVIP_NAT_ProcWriteSnifferMAC (struct file
*file
, const char *buffer
,
505 unsigned long count
, void *data
)
507 /* at least strlen("xx:xx:xx:xx:xx:xx") characters, followed by '\0' */
512 ret
= SVIP_NAT_MacAsciiToHex(buffer
, pSVIP_NAT_SnifferMAC
);
517 if (!(pSVIP_NAT_SnifferMAC
[0]==0 && pSVIP_NAT_SnifferMAC
[1]==0 &&
518 pSVIP_NAT_SnifferMAC
[2]==0 && pSVIP_NAT_SnifferMAC
[3]==0 &&
519 pSVIP_NAT_SnifferMAC
[4]==0 && pSVIP_NAT_SnifferMAC
[5]==0))
521 nSVIP_NAT_SnifferMacSet
= 1;
528 Used to read the destination MAC address of a sniffer host
530 int SVIP_NAT_ProcReadSnifferMAC (char *buf
, int count
)
534 len
= snprintf(buf
, count
, "%02x:%02x:%02x:%02x:%02x:%02x\n",
535 pSVIP_NAT_SnifferMAC
[0], pSVIP_NAT_SnifferMAC
[1],
536 pSVIP_NAT_SnifferMAC
[2], pSVIP_NAT_SnifferMAC
[3],
537 pSVIP_NAT_SnifferMAC
[4], pSVIP_NAT_SnifferMAC
[5]);
541 printk(KERN_ERR
"SVIP NAT: Only part of the text could be put into the buffer\n");
549 Used to switch VoFW message sniffer on/off
552 usage: 'echo "1" > cat /proc/net/svip_nat/snifferOnOff'
554 int SVIP_NAT_ProcWriteSnifferOnOff (struct file
*file
, const char *buffer
,
555 unsigned long count
, void *data
)
557 /* at least one digit expected, followed by '\0' */
560 int ret
, nSnifferOnOff
;
562 ret
= sscanf(buffer
, "%d", &nSnifferOnOff
);
567 if (nSnifferOnOff
> 0)
570 nSVIP_NAT_Sniffer
= nSnifferOnOff
;
576 Used to read the VoFW message sniffer configuration (on/off)
578 int SVIP_NAT_ProcReadSnifferOnOff (char *buf
, int count
)
582 len
= snprintf(buf
, count
, "%d\n", nSVIP_NAT_Sniffer
);
586 printk(KERN_ERR
"SVIP NAT: Only part of the text could be put into the buffer\n");
594 /******************************************************************************/
596 Creates proc read/write entries
599 0 on success, -1 on error
601 /******************************************************************************/
602 static int SVIP_NAT_ProcInstall(void)
604 struct proc_dir_entry
*pProcParentDir
, *pProcDir
;
605 struct proc_dir_entry
*pProcNode
;
607 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
608 pProcParentDir
= proc_net
;
610 pProcParentDir
= init_net
.proc_net
;
612 pProcDir
= proc_mkdir(SVIP_NAT_DEVICE_NAME
, pProcParentDir
);
613 if (pProcDir
== NULL
)
615 printk(KERN_ERR
"SVIP NAT: cannot create proc dir %s/%s\n\r",
616 pProcParentDir
->name
, SVIP_NAT_DEVICE_NAME
);
620 pProcNode
= create_proc_read_entry("nat", S_IFREG
|S_IRUGO
, pProcDir
,
621 SVIP_NAT_ProcRead
, (void *)SVIP_NAT_ProcReadNAT
);
622 if (pProcNode
== NULL
)
624 printk(KERN_ERR
"SVIP NAT: cannot create proc entry %s/%s",
625 pProcDir
->name
, "nat");
629 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
630 nSVIP_NAT_Sniffer
= 0;
631 /* creates proc entry for switching on/off sniffer to VoFW messages */
632 pProcNode
= create_proc_read_entry("snifferOnOff", S_IFREG
|S_IRUGO
|S_IWUGO
,
633 pProcDir
, SVIP_NAT_ProcReadGen
, (void *)SVIP_NAT_ProcReadSnifferOnOff
);
634 if (pProcNode
== NULL
)
636 printk(KERN_ERR
"SVIP NAT: cannot create proc entry %s/%s\n\r",
637 pProcDir
->name
, "snifferOnOff");
640 pProcNode
->write_proc
= SVIP_NAT_ProcWriteSnifferOnOff
;
642 memset (pSVIP_NAT_SnifferMAC
, 0, ETH_ALEN
);
643 nSVIP_NAT_SnifferMacSet
= 0;
644 /* creates proc entry for setting MAC address of sniffer host to VoFW messages */
645 pProcNode
= create_proc_read_entry("snifferMAC", S_IFREG
|S_IRUGO
|S_IWUGO
,
646 pProcDir
, SVIP_NAT_ProcReadGen
, (void *)SVIP_NAT_ProcReadSnifferMAC
);
647 if (pProcNode
== NULL
)
649 printk(KERN_ERR
"SVIP NAT: cannot create proc entry %s/%s\n\r",
650 pProcDir
->name
, "snifferMAC");
653 pProcNode
->write_proc
= SVIP_NAT_ProcWriteSnifferMAC
;
659 /******************************************************************************/
661 No actions done here, simply a check is performed if an open has already
662 been performed. Currently only a single open is allowed as it is a sufficient
663 to have hat a single process configuring the SVIP NAT at one time.
666 inode - pointer to disk file data
667 file - pointer to device file data
670 0 on success, else -1
672 /******************************************************************************/
673 static int SVIP_NAT_device_open(struct inode
*inode
, struct file
*file
)
676 struct in_device
*in_dev
;
677 struct in_ifaddr
*ifa
;
679 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
680 local_irq_save(flags
);
682 local_save_flags(flags
);
688 local_irq_restore(flags
);
693 /* find pointer to IP address of eth0 */
694 if ((in_dev
=in_dev_get(net_devs
[SVIP_NET_DEV_ETH0_IDX
])) != NULL
)
696 for (ifa
= in_dev
->ifa_list
; ifa
!= NULL
; ifa
= ifa
->ifa_next
)
698 if (!paddr_eth0
&& ifa
->ifa_address
!= 0)
700 paddr_eth0
= &ifa
->ifa_address
;
703 if (paddr_eth0
&& ifa
->ifa_address
!= 0)
705 paddr_eth0_0
= &ifa
->ifa_address
;
711 if (paddr_eth0
== NULL
|| paddr_eth0_0
== NULL
)
713 local_irq_restore(flags
);
717 /* find pointer to IP address of veth0 */
718 if ((in_dev
=in_dev_get(net_devs
[SVIP_NET_DEV_VETH0_IDX
])) != NULL
)
720 for (ifa
= in_dev
->ifa_list
; ifa
!= NULL
; ifa
= ifa
->ifa_next
)
722 if (ifa
->ifa_address
!= 0)
724 paddr_veth0
= &ifa
->ifa_address
;
725 pmask_veth0
= &ifa
->ifa_mask
;
731 if (paddr_veth0
== NULL
)
733 local_irq_restore(flags
);
739 local_irq_restore(flags
);
745 /******************************************************************************/
747 This function is called when a process closes the SVIP NAT device file
750 inode - pointer to disk file data
751 file - pointer to device file data
754 0 on success, else -1
757 /******************************************************************************/
758 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
759 static int SVIP_NAT_device_release(struct inode
*inode
,
762 static void SVIP_NAT_device_release(struct inode
*inode
,
768 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
772 local_save_flags(flags
);
775 /* The device can now be openned by the next caller */
780 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
781 restore_flags(flags
);
783 local_irq_restore(flags
);
786 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
792 /******************************************************************************/
794 This function is called when a process closes the SVIP NAT device file
797 inode - pointer to disk file data
798 file - pointer to device file data
799 ioctl_num - ioctl number requested
800 ioctl_param - pointer to data related to the ioctl number
803 0 on success, else -1
806 /******************************************************************************/
807 long SVIP_NAT_device_ioctl (struct file
*file
,
808 unsigned int ioctl_num
, unsigned long ioctl_param
)
811 SVIP_NAT_IO_Rule_t
*pNatRule
, *pNatRuleIn
;
812 SVIP_UDP_PORT_t nPort
;
816 unsigned char *pData
= 0;
819 if (_IOC_DIR(ioctl_num
) & _IOC_WRITE
)
821 if (_IOC_DIR(ioctl_num
) & _IOC_READ
)
823 nSize
= _IOC_SIZE(ioctl_num
);
825 if (nSize
> sizeof(int))
829 pData
= kmalloc (nSize
, GFP_KERNEL
);
832 if (copy_from_user ((void *)pData
, (void *)ioctl_param
, nSize
) != 0)
834 printk(KERN_ERR
"SVIP NAT: ioctl %x: copy_from_user() failed!\n", ioctl_num
);
844 case FIO_SVIP_NAT_RULE_ADD
:
846 pNatRuleIn
= (SVIP_NAT_IO_Rule_t
*)pData
;
848 /* check if destination UDP port is within range */
849 nPort
= ntohs(pNatRuleIn
->locUDP
);
851 if (!SVIP_PORT_INRANGE(nPort
))
853 printk(KERN_ERR
"SVIP NAT: Error, UDP port(%d) is out of range(%d..%d)\n",
854 nPort
, SVIP_UDP_FROM
, SVIP_UDP_TO
);
858 nNatIdx
= SVIP_PORT_INDEX(nPort
);
860 down(sem_nat_tbl_access
);
861 pNatRule
= &pNatTable
[nNatIdx
].natRule
;
863 /* add rule to the NAT table */
864 pNatRule
->remIP
= pNatRuleIn
->remIP
;
865 memcpy((char *)pNatRule
->remMAC
, (char *)pNatRuleIn
->remMAC
, ETH_ALEN
);
866 pNatRule
->locIP
= pNatRuleIn
->locIP
;
867 memcpy((char *)pNatRule
->locMAC
, (char *)pNatRuleIn
->locMAC
, ETH_ALEN
);
868 pNatRule
->locUDP
= pNatRuleIn
->locUDP
;
870 memset(pNatTable
[nNatIdx
].natStats
, 0,
871 sizeof(SVIP_NAT_stats_t
)*SVIP_NAT_STATS_TYPES
);
872 up(sem_nat_tbl_access
);
875 case FIO_SVIP_NAT_RULE_REMOVE
:
877 pNatRuleIn
= (SVIP_NAT_IO_Rule_t
*)pData
;
879 /* check if destination UDP port is within range */
880 nPort
= ntohs(pNatRuleIn
->locUDP
);
881 if (!SVIP_PORT_INRANGE(nPort
))
883 printk(KERN_ERR
"SVIP NAT: Error, UDP port(%d) is out of range(%d..%d)\n",
884 nPort
, SVIP_UDP_FROM
, SVIP_UDP_TO
);
888 nNatIdx
= SVIP_PORT_INDEX(nPort
);
889 down(sem_nat_tbl_access
);
890 /* remove rule from the NAT table */
891 memset(&pNatTable
[nNatIdx
], 0, sizeof(SVIP_NAT_table_entry_t
));
892 up(sem_nat_tbl_access
);
895 case FIO_SVIP_NAT_RULE_LIST
:
900 down(sem_nat_tbl_access
);
901 while (nProcReadIdx
!= -1)
903 len
= SVIP_NAT_ProcReadNAT(buf
, 256);
908 up(sem_nat_tbl_access
);
913 printk(KERN_ERR
"SVIP NAT: unsupported ioctl (%x) command for device %s\n",
914 ioctl_num
, PATH_SVIP_NAT_DEVICE_NAME
);
919 if (nSize
> sizeof(int))
923 if (copy_to_user ((void *)ioctl_param
, (void *)pData
, nSize
) != 0)
925 printk(KERN_ERR
"SVIP NAT: ioctl %x: copy_to_user() failed!\n", ioctl_num
);
940 void dump_msg(unsigned char *pData
, unsigned int nLen
)
944 for (i
=0; i
<nLen
; i
++)
948 else if (i
&& !(i
%4))
950 printk("%02x", pData
[i
]);
957 /******************************************************************************/
959 Used to recalculate IP/UDP checksum using the original IP/UDP checksum
960 coming with the packet. The original source and destination IP addresses
961 are accounted for, and, the checksum is updated using the new source and
962 destination IP addresses.
965 skb - pointer to the receiving socket buffer
966 csum_old - original checksum
967 saddr_old - pointer to original source IP address
968 saddr_new - pointer to new source IP address
969 daddr_old - pointer to original destination IP address
970 daddr_new - pointer to new destination IP address
973 recalculated IP/UDP checksum
975 /******************************************************************************/
976 static inline u16
ip_udp_quick_csum(u16 csum_old
, u16
*saddr_old
, u16
*saddr_new
,
977 u16
*daddr_old
, u16
*daddr_new
)
983 /* convert back from one's complement */
986 if (sum
< saddr_old
[0]) sum
+= 0xffff;
988 if (sum
< saddr_old
[1]) sum
+= 0xffff;
990 if (sum
< daddr_old
[0]) sum
+= 0xffff;
992 if (sum
< daddr_old
[1]) sum
+= 0xffff;
1000 /* take only 16 bits out of the 32 bit sum and add up the carries */
1002 sum
= (sum
& 0xffff)+((sum
>> 16) & 0xffff);
1004 /* one's complement the result */
1007 return (u16
)(sum
& 0xffff);
1011 /******************************************************************************/
1013 Returns a pointer to an ipv4 address assigned to device dev. The ipv4
1014 instance checked is pointed to by ifa_start. The function is suited for
1018 dev - pointer to network interface
1019 ifa_start - pointer to ipv4 instance to return ipv4 address assigned
1020 to, NULL for the first one
1021 ppifa_addr - output parameter
1024 pointer to the next ipv4 instance, which can be null if ifa_start was
1025 the last instance present
1027 /******************************************************************************/
1028 static struct in_ifaddr
*get_ifaddr(struct net_device
*dev
,
1029 struct in_ifaddr
*ifa_start
, unsigned int **ppifa_addr
)
1031 struct in_device
*in_dev
;
1032 struct in_ifaddr
*ifa
= NULL
;
1034 if ((in_dev
=in_dev_get(dev
)) != NULL
)
1036 if (ifa_start
== NULL
)
1037 ifa
= in_dev
->ifa_list
;
1042 *ppifa_addr
= &ifa
->ifa_address
;
1043 ifa
= ifa
->ifa_next
;
1052 /******************************************************************************/
1054 This function performs IP NAT for received packets satisfying the
1055 following requirements:
1057 - packet is destined to local IP host
1058 - transport protocol type is UDP
1059 - destination UDP port is within range
1062 skb - pointer to the receiving socket buffer
1065 returns 1 on performed SVIP NAT, else returns 0
1068 When function returns 0, it indicates the caller to pass the
1069 packet up the IP stack to make further decision about it
1071 /******************************************************************************/
1072 int do_SVIP_NAT (struct sk_buff
*skb
)
1074 struct net_device
*real_dev
;
1076 struct udphdr
*udph
;
1077 SVIP_NAT_IO_Rule_t
*pNatRule
;
1078 int nNatIdx
, in_eth0
, nDir
;
1079 #ifndef VLAN_8021Q_UNUSED
1082 #endif /* ! VLAN_8021Q_UNUSED */
1083 SVIP_UDP_PORT_t nPort
;
1084 u32 orgSrcIp
, orgDstIp
, *pSrcIp
, *pDstIp
;
1085 struct ethhdr
*ethh
;
1087 /* do not consider if SVIP NAT device not open. */
1093 /* consider only UDP packets. */
1094 iph
= SVIP_NAT_IP_HDR(skb
);
1095 if (iph
->protocol
!= IPPROTO_UDP
)
1100 udph
= (struct udphdr
*)((u_int32_t
*)iph
+ iph
->ihl
);
1101 /* consider only packets which UDP port numbers reside within
1102 the predefined SVIP NAT UDP port range. */
1103 if ((!SVIP_PORT_INRANGE(ntohs(udph
->dest
))) &&
1104 (!SVIP_PORT_INRANGE(ntohs(udph
->source
))))
1109 #ifndef VLAN_8021Q_UNUSED
1110 /* check if packet delivered over VLAN. VLAN packets will be routed over
1111 the VLAN interfaces of the respective real Ethernet interface, if one
1112 exists(VIDs must match). Else, the packet will be send out as IEEE 802.3
1114 if (skb
->dev
->priv_flags
& IFF_802_1Q_VLAN
)
1117 vid
= VLAN_DEV_VLAN_ID(skb
->dev
);
1118 real_dev
= VLAN_DEV_REAL_DEV(skb
->dev
);
1124 real_dev
= skb
->dev
;
1126 #endif /* ! VLAN_8021Q_UNUSED */
1128 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
1129 /** Debugging feature which can be enabled by writing,
1130 'echo 1 > /proc/net/svip_nat/snifferOnOff'.
1131 It copies all packets received on veth0 and, sends them out over eth0.
1132 When a destination MAC address is specified through
1133 /proc/net/svip_nat/snifferMAC, this MAC addess will substitute the
1134 original MAC address of the packet.
1135 It is recommended to specify a MAC address of some host where Wireshark
1136 runs and sniffs for this traffic, else you may flood your LAN with
1137 undeliverable traffic.
1139 NOTE: In case of VLAN traffic the VLAN header information is lost. */
1140 if (nSVIP_NAT_Sniffer
)
1142 if (real_dev
== net_devs
[SVIP_NET_DEV_VETH0_IDX
])
1144 struct sk_buff
*copied_skb
;
1146 /* gain the Ethernet header from the skb */
1147 skb_push(skb
, ETH_HLEN
);
1149 copied_skb
= skb_copy (skb
, GFP_ATOMIC
);
1151 if (nSVIP_NAT_SnifferMacSet
== 1)
1153 ethh
= (struct ethhdr
*)SVIP_NAT_SKB_MAC_HEADER(copied_skb
);
1154 memcpy((char *)ethh
->h_dest
, (char *)pSVIP_NAT_SnifferMAC
, ETH_ALEN
);
1156 copied_skb
->dev
= net_devs
[SVIP_NET_DEV_ETH0_IDX
];
1157 dev_queue_xmit(copied_skb
);
1159 /* skip the ETH header again */
1160 skb_pull(skb
, ETH_HLEN
);
1166 /* check if packet arrived on eth0 */
1167 if (real_dev
== net_devs
[SVIP_NET_DEV_ETH0_IDX
])
1169 /* check if destination IP address equals the primary assigned IP address
1170 of interface eth0. This is the case of packets originating from a
1171 remote peer that are to be delivered to a channel residing on THIS
1172 voice linecard system. This is typical SVIP NAT case, therefore this
1173 rule is placed on top. */
1174 if (iph
->daddr
== *paddr_eth0
)
1176 nPort
= ntohs(udph
->dest
);
1177 nDir
= SVIP_NAT_STATS_REM2LOC
;
1179 /* check if destination IP address equals the secondary assigned IP address
1180 of interface eth0. This is not a typical SVIP NAT case. It is basically
1181 there, as someone might like for debugging purpose to use the LCC to route
1182 Slave SVIP packets which are part of voice/fax streaming. */
1183 else if (iph
->daddr
== *paddr_eth0_0
)
1185 nPort
= ntohs(udph
->source
);
1186 nDir
= SVIP_NAT_STATS_LOC2REM
;
1188 #ifndef VLAN_8021Q_UNUSED
1189 /* when the packet did not hit the top two rules, here we check if the packet
1190 has addressed any of the IP addresses assigned to the VLAN interface attached
1191 to eth0. This is not recommended approach because of the CPU cost incurred. */
1194 unsigned int *pifa_addr
;
1195 struct in_ifaddr
*ifa_start
= NULL
;
1200 ifa_start
= get_ifaddr(skb
->dev
, ifa_start
, &pifa_addr
);
1203 /* VLAN packet received on vlan interface attached to eth0,
1204 however no IP address assigned to the interface.
1205 The packet is ignored. */
1208 if (iph
->daddr
== *pifa_addr
)
1210 /* packet destined to... */
1218 } while (ifa_start
);
1221 /* ...primary assigned IP address to the VLAN interface. */
1222 nPort
= ntohs(udph
->dest
);
1223 nDir
= SVIP_NAT_STATS_REM2LOC
;
1227 /* ...secondary assigned IP address to the VLAN interface. */
1228 nPort
= ntohs(udph
->source
);
1229 nDir
= SVIP_NAT_STATS_LOC2REM
;
1232 #endif /* ! VLAN_8021Q_UNUSED */
1239 /* check if packet arrived on veth0 */
1240 else if (real_dev
== net_devs
[SVIP_NET_DEV_VETH0_IDX
])
1242 nPort
= ntohs(udph
->source
);
1243 nDir
= SVIP_NAT_STATS_LOC2REM
;
1248 /* packet arrived neither on eth0, nor veth0 */
1252 /* calculate the respective index of the NAT table */
1253 nNatIdx
= SVIP_PORT_INDEX(nPort
);
1254 /* process the packet if a respective NAT rule exists */
1255 pNatRule
= &pNatTable
[nNatIdx
].natRule
;
1257 ethh
= (struct ethhdr
*)SVIP_NAT_SKB_MAC_HEADER(skb
);
1259 /* copy packet's original source and destination IP addresses to use
1260 later on to perform efficient checksum recalculation */
1261 orgSrcIp
= iph
->saddr
;
1262 orgDstIp
= iph
->daddr
;
1268 /* Process packet arrived on eth0 */
1270 if (nDir
== SVIP_NAT_STATS_REM2LOC
&& iph
->saddr
== pNatRule
->remIP
)
1272 pDstIp
= &pNatRule
->locIP
;
1273 pDstMac
= pNatRule
->locMAC
;
1275 else if (nDir
== SVIP_NAT_STATS_LOC2REM
&& iph
->saddr
== pNatRule
->locIP
)
1277 pDstIp
= &pNatRule
->remIP
;
1278 pDstMac
= pNatRule
->remMAC
;
1282 /* Rule check failed. The packet is passed up the layers,
1283 it will be dropped by UDP */
1287 if ((*pDstIp
& *pmask_veth0
) == (*paddr_veth0
& *pmask_veth0
))
1289 #ifndef VLAN_8021Q_UNUSED
1292 struct net_device
*vlan_dev
;
1294 spin_lock_bh(&vlan_group_lock
);
1295 vlan_dev
= __vlan_find_dev_deep(net_devs
[SVIP_NET_DEV_VETH0_IDX
], vid
);
1296 spin_unlock_bh(&vlan_group_lock
);
1299 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1300 struct vlan_ethhdr
*vethh
;
1302 skb_push(skb
, VLAN_ETH_HLEN
);
1303 /* reconstruct the VLAN header.
1304 NOTE: priority information is lost */
1305 vethh
= (struct vlan_ethhdr
*)skb
->data
;
1306 vethh
->h_vlan_proto
= htons(ETH_P_8021Q
);
1307 vethh
->h_vlan_TCI
= htons(vid
);
1308 vethh
->h_vlan_encapsulated_proto
= htons(ETH_P_IP
);
1309 ethh
= (struct ethhdr
*)vethh
;
1311 skb_push(skb
, ETH_HLEN
);
1313 skb
->dev
= vlan_dev
;
1317 skb
->dev
= net_devs
[SVIP_NET_DEV_VETH0_IDX
];
1318 skb_push(skb
, ETH_HLEN
);
1322 #endif /* ! VLAN_8021Q_UNUSED */
1324 skb
->dev
= net_devs
[SVIP_NET_DEV_VETH0_IDX
];
1325 skb_push(skb
, ETH_HLEN
);
1327 pSrcIp
= paddr_veth0
;
1331 #ifndef VLAN_8021Q_UNUSED
1332 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1335 struct vlan_ethhdr
*vethh
;
1337 /* reconstruct the VLAN header.
1338 NOTE: priority information is lost */
1339 skb_push(skb
, VLAN_ETH_HLEN
);
1340 vethh
= (struct vlan_ethhdr
*)skb
->data
;
1341 vethh
->h_vlan_proto
= htons(ETH_P_8021Q
);
1342 vethh
->h_vlan_TCI
= htons(vid
);
1343 vethh
->h_vlan_encapsulated_proto
= htons(ETH_P_IP
);
1344 ethh
= (struct ethhdr
*)vethh
;
1348 #endif /* ! VLAN_8021Q_UNUSED */
1350 skb_push(skb
, ETH_HLEN
);
1352 /* source IP address equals the destination IP address
1353 of the incoming packet */
1354 pSrcIp
= &iph
->daddr
;
1356 iph
->saddr
= *pSrcIp
;
1357 memcpy((char *)ethh
->h_source
, (char *)skb
->dev
->dev_addr
, ETH_ALEN
);
1358 iph
->daddr
= *pDstIp
;
1359 memcpy((char *)ethh
->h_dest
, (char *)pDstMac
, ETH_ALEN
);
1363 /* Process packet arrived on veth0 */
1365 if (iph
->saddr
!= pNatRule
->locIP
)
1367 /* Rule check failed. The packet is passed up the layers,
1368 it will be dropped by UDP */
1372 if (!((pNatRule
->remIP
& *pmask_veth0
) == (*paddr_veth0
& *pmask_veth0
)))
1374 #ifndef VLAN_8021Q_UNUSED
1377 struct net_device
*vlan_dev
;
1379 spin_lock_bh(&vlan_group_lock
);
1380 vlan_dev
= __vlan_find_dev_deep(net_devs
[SVIP_NET_DEV_ETH0_IDX
], vid
);
1381 spin_unlock_bh(&vlan_group_lock
);
1384 unsigned int *pifa_addr
;
1385 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1386 struct vlan_ethhdr
*vethh
;
1388 skb_push(skb
, VLAN_ETH_HLEN
);
1389 /* construct the VLAN header, note priority information is lost */
1390 vethh
= (struct vlan_ethhdr
*)skb
->data
;
1391 vethh
->h_vlan_proto
= htons(ETH_P_8021Q
);
1392 vethh
->h_vlan_TCI
= htons(vid
);
1393 vethh
->h_vlan_encapsulated_proto
= htons(ETH_P_IP
);
1394 ethh
= (struct ethhdr
*)vethh
;
1396 skb_push(skb
, ETH_HLEN
);
1398 skb
->dev
= vlan_dev
;
1400 get_ifaddr(skb
->dev
, NULL
, &pifa_addr
);
1407 pSrcIp
= paddr_eth0
;
1412 skb
->dev
= net_devs
[SVIP_NET_DEV_ETH0_IDX
];
1413 pSrcIp
= paddr_eth0
;
1414 skb_push(skb
, ETH_HLEN
);
1418 #endif /* ! VLAN_8021Q_UNUSED */
1420 skb
->dev
= net_devs
[SVIP_NET_DEV_ETH0_IDX
];
1421 pSrcIp
= paddr_eth0
;
1422 skb_push(skb
, ETH_HLEN
);
1427 pSrcIp
= paddr_veth0
;
1428 #ifndef VLAN_8021Q_UNUSED
1429 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1432 struct vlan_ethhdr
*vethh
;
1434 skb_push(skb
, VLAN_ETH_HLEN
);
1435 /* reconstruct the VLAN header.
1436 NOTE: priority information is lost. */
1437 vethh
= (struct vlan_ethhdr
*)skb
->data
;
1438 vethh
->h_vlan_proto
= htons(ETH_P_8021Q
);
1439 vethh
->h_vlan_TCI
= htons(vid
);
1440 vethh
->h_vlan_encapsulated_proto
= htons(ETH_P_IP
);
1441 ethh
= (struct ethhdr
*)vethh
;
1445 #endif /* ! VLAN_8021Q_UNUSED */
1447 skb_push(skb
, ETH_HLEN
);
1450 iph
->saddr
= *pSrcIp
;
1451 memcpy((char *)ethh
->h_source
, (char *)skb
->dev
->dev_addr
, ETH_ALEN
);
1452 iph
->daddr
= pNatRule
->remIP
;
1453 memcpy((char *)ethh
->h_dest
, (char *)pNatRule
->remMAC
, ETH_ALEN
);
1455 pNatTable
[nNatIdx
].natStats
[nDir
].inPackets
++;
1457 iph
->check
= ip_udp_quick_csum(iph
->check
, (u16
*)&orgSrcIp
, (u16
*)&iph
->saddr
,
1458 (u16
*)&orgDstIp
, (u16
*)&iph
->daddr
);
1459 if (udph
->check
!= 0)
1461 udph
->check
= ip_udp_quick_csum(udph
->check
, (u16
*)&orgSrcIp
, (u16
*)&iph
->saddr
,
1462 (u16
*)&orgDstIp
, (u16
*)&iph
->daddr
);
1465 /* write the packet out, directly to the network device */
1466 if (dev_queue_xmit(skb
) < 0)
1467 pNatTable
[nNatIdx
].natStats
[nDir
].outErrors
++;
1469 pNatTable
[nNatIdx
].natStats
[nDir
].outPackets
++;
1474 /******************************************************************************/
1476 Function executed upon unloading of the SVIP NAT module. It unregisters the
1477 SVIP NAT configuration device and frees the memory used for the NAT table.
1480 Currently the SVIP NAT module is statically linked into the Linux kernel
1481 therefore this routine cannot be executed.
1482 *******************************************************************************/
1483 static int __init
init(void)
1486 struct net_device
*dev
;
1488 if (misc_register(&SVIP_NAT_miscdev
) != 0)
1490 printk(KERN_ERR
"%s: cannot register SVIP NAT device node.\n",
1491 SVIP_NAT_miscdev
.name
);
1495 /* allocation of memory for NAT table */
1496 pNatTable
= (SVIP_NAT_table_entry_t
*)kmalloc(
1497 sizeof(SVIP_NAT_table_entry_t
) * SVIP_SYS_CODEC_NUM
, GFP_ATOMIC
);
1498 if (pNatTable
== NULL
)
1500 printk (KERN_ERR
"SVIP NAT: Error(%d), allocating memory for NAT table\n", ret
);
1504 /* clear the NAT table */
1505 memset((void *)pNatTable
, 0, sizeof(SVIP_NAT_table_entry_t
) * SVIP_SYS_CODEC_NUM
);
1507 if ((sem_nat_tbl_access
= kmalloc(sizeof(struct semaphore
), GFP_KERNEL
)))
1509 sema_init(sem_nat_tbl_access
, 1);
1512 SVIP_NAT_ProcInstall();
1514 /* find pointers to 'struct net_device' of eth0 and veth0, respectevely */
1515 read_lock(&dev_base_lock
);
1516 SVIP_NAT_FOR_EACH_NETDEV(dev
)
1518 if (!strcmp(dev
->name
, SVIP_NET_DEV_ETH0_NAME
))
1520 net_devs
[SVIP_NET_DEV_ETH0_IDX
] = dev
;
1522 if (!strcmp(dev
->name
, SVIP_NET_DEV_VETH1_NAME
))
1524 net_devs
[SVIP_NET_DEV_VETH0_IDX
] = dev
;
1526 else if (!strcmp(dev
->name
, SVIP_NET_DEV_ETH1_NAME
))
1528 net_devs
[SVIP_NET_DEV_VETH0_IDX
] = dev
;
1531 read_unlock(&dev_base_lock
);
1533 if (net_devs
[SVIP_NET_DEV_ETH0_IDX
] == NULL
||
1534 net_devs
[SVIP_NET_DEV_VETH0_IDX
] == NULL
)
1536 printk (KERN_ERR
"SVIP NAT: Error, unable to locate eth0 and veth0 interfaces\n");
1540 printk ("%s, (c) 2009, Lantiq Deutschland GmbH\n", &SVIP_NAT_INFO_STR
[4]);
1545 /******************************************************************************/
1547 Function executed upon unloading of the SVIP NAT module. It unregisters the
1548 SVIP NAT configuration device and frees the memory used for the NAT table.
1551 Currently the SVIP NAT module is statically linked into the Linux kernel
1552 therefore this routine cannot be executed.
1553 *******************************************************************************/
1554 static void __exit
fini(void)
1558 /* unregister SVIP NAT configuration device */
1559 misc_deregister(&SVIP_NAT_miscdev
);
1561 /* release memory of SVIP NAT table */
1562 if (pNatTable
!= NULL
)