[lantiq] prepare Makefile for 3.6
[openwrt.git] / target / linux / lantiq / files / net / ipv4 / svip_nat.c
1 /******************************************************************************
2
3                                Copyright (c) 2009
4                             Lantiq Deutschland GmbH
5                      Am Campeon 3; 81726 Munich, Germany
6
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.
10
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.
18
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.
24
25  ****************************************************************************
26
27 Description : This file contains implementation of Custom NAT function
28 for Infineon's VINETIC-SVIP16
29  *******************************************************************************/
30
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>
36 #include <linux/in.h>
37 #include <linux/ip.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>
46
47 #include <linux/svip_nat.h>
48
49 MODULE_AUTHOR("Lantiq Deutschland GmbH");
50 MODULE_DESCRIPTION("SVIP Network Address Translation module");
51 MODULE_LICENSE("GPL");
52
53 #define SVIP_NAT_INFO_STR "@(#)SVIP NAT, version "SVIP_NAT_VERSION
54
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))
58
59 /** end UDP port number of the SVIP Linecard System */
60 #define SVIP_UDP_TO           ((SVIP_UDP_FROM) + (SVIP_SYS_CODEC_NUM) - 1)
61
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)
64
65 #define SVIP_PORT_INRANGE(nPort) \
66         ((nPort) >= (SVIP_UDP_FROM) && (nPort) <= (SVIP_UDP_TO))
67
68 #define SVIP_PORT_INDEX(nPort)   (nPort - SVIP_UDP_FROM)
69
70 #define SVIP_NET_DEV_ETH0_IDX       0
71 #define SVIP_NET_DEV_VETH0_IDX      1
72 #define SVIP_NET_DEV_LO_IDX         2
73
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"
78
79 #define SVIP_NAT_STATS_LOC2REM   0
80 #define SVIP_NAT_STATS_REM2LOC   1
81 #define SVIP_NAT_STATS_TYPES     2
82
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)
86 #else
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) */
90
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
95 #else
96 #define SVIP_NAT_SKB_MAC_HEADER(ethhdr) skb_mac_header(ethhdr)
97 #endif
98
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)
102 #else
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) */
106
107 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
108 #define MOD_INC_USE_COUNT
109 #define MOD_DEC_USE_COUNT
110 #endif
111
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
115 #endif
116
117
118 extern spinlock_t vlan_group_lock;
119 extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, unsigned short VID);
120
121 typedef struct SVIP_NAT_stats
122 {
123         unsigned long        inPackets;
124         unsigned long        outPackets;
125         unsigned long        outErrors;
126 } SVIP_NAT_stats_t;
127
128 typedef struct SVIP_NAT_table_entry
129 {
130         SVIP_NAT_IO_Rule_t   natRule;
131         SVIP_NAT_stats_t     natStats[SVIP_NAT_STATS_TYPES];
132 } SVIP_NAT_table_entry_t;
133
134 /* pointer to the SVIP NAT table */
135 static SVIP_NAT_table_entry_t *pNatTable = NULL;
136
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;
142
143 static struct semaphore *sem_nat_tbl_access;
144 static int proc_read_in_progress = 0;
145
146 static int nDeviceOpen = 0;
147
148 /* saves the NAT table index between subsequent invocation */
149 static int nProcReadIdx = 0;
150
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 *);
154 #else
155 static void SVIP_NAT_device_release (struct inode *,struct file *);
156 #endif
157 static int  SVIP_NAT_device_open    (struct inode *,struct file *);
158
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)
163 owner:      THIS_MODULE,
164 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) */
165             llseek:  NULL,                      /* seek */
166             read:    NULL,
167             write:   NULL,
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 */
175 #endif
176             release: SVIP_NAT_device_release    /* close */
177 };
178
179 /** Structure holding MISC module operations */
180 static struct miscdevice SVIP_NAT_miscdev =
181 {
182 minor:   MINOR_NUM_SVIP_NAT,
183          name:    SVIP_NAT_DEVICE_NAME,
184          fops:    &SVIP_NAT_Fops
185 };
186
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;
191 #endif
192
193 /******************************************************************************/
194 /**
195   Function to read /proc/net/svip_nat/nat proc entry
196
197   \arguments
198   page     - pointer to page buffer
199   start    - pointer to start address pointer
200   off      - offset
201   count    - maximum data length to read
202   eof      - end of file flag
203   data     - proc read data (provided by the function
204   pointed to by data)
205
206   \return
207   length of read data
208
209   \remarks:
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)
215 {
216         unsigned long flags;
217         int (*fn)(char *buf, int size);
218         int len;
219
220         /* If the NAT table index is negative, the reading has completed */
221         if (nProcReadIdx < 0)
222         {
223                 nProcReadIdx = 0;
224                 *eof = 1;
225                 proc_read_in_progress = 0;
226                 up(sem_nat_tbl_access);
227                 return 0;
228         }
229
230         local_irq_save(flags);
231         if (!proc_read_in_progress)
232         {
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);
239         }
240         else
241         {
242                 local_irq_restore(flags);
243         }
244
245         if (data != NULL)
246         {
247                 fn = data;
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. */
252                 *eof = 1;
253                 *start = page;
254         }
255         else
256         {
257                 len = 0;
258         }
259
260         return len;
261 }
262
263 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
264 /**
265   Function to read remaining proc entries
266   */
267 static int SVIP_NAT_ProcReadGen (char *page, char **start, off_t off,
268                                  int count, int *eof, void *data)
269 {
270         int (*fn)(char *buf, int size);
271         int len = 0;
272
273         MOD_INC_USE_COUNT;
274
275         if (data == NULL)
276         {
277                 MOD_DEC_USE_COUNT;
278                 return 0;
279         }
280
281         fn = data;
282         len = fn (page, count);
283
284         if (len <= off + count)
285         {
286                 *eof = 1;
287         }
288         *start = page + off;
289         len -= off;
290         if (len > count)
291         {
292                 len = count;
293         }
294         if (len < 0)
295         {
296                 len = 0;
297         }
298
299         MOD_DEC_USE_COUNT;
300
301         return len;
302 }
303 #endif
304
305 /******************************************************************************/
306 /**
307   Function for setting up /proc/net/svip_nat read data
308
309   \arguments
310   buf      - pointer to read buffer
311   count    - size of read buffer
312
313   \return
314   length of read data into buffer
315
316   \remarks:
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)
323 {
324         int i, j;
325         int len = 0;
326         SVIP_NAT_IO_Rule_t *pNatRule;
327
328         if (nProcReadIdx == -1)
329         {
330                 nProcReadIdx = 0;
331                 return 0;
332         }
333
334         if (nProcReadIdx == 0)
335         {
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");
344         }
345
346         for (i = nProcReadIdx; i < SVIP_SYS_CODEC_NUM; i++)
347         {
348                 int slen;
349
350                 pNatRule = &pNatTable[i].natRule;
351
352                 if (pNatRule->remIP != 0)
353                 {
354                         /* make sure not to overwrite the buffer */
355                         if (count < len+120)
356                                 break;
357
358                         /* remIP */
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));
364                         len += slen;
365                         for (j = 0; j < (16-slen); j++)
366                                 len += sprintf(buf+len, " ");
367
368                         /* remMAC */
369                         slen = 0;
370                         for (j = 0; j < ETH_ALEN; j++)
371                         {
372                                 slen += sprintf(buf+len+slen, "%02x%s",
373                                                 pNatRule->remMAC[j], j < ETH_ALEN-1 ? ":" : " ");
374                         }
375                         len += slen;
376                         for (j = 0; j < (19-slen); j++)
377                                 len += sprintf(buf+len, " ");
378
379                         /* locIP */
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));
385                         len += slen;
386                         for (j = 0; j < (15-slen); j++)
387                                 len += sprintf(buf+len, " ");
388
389                         /* locMAC */
390                         slen = 0;
391                         for (j = 0; j < ETH_ALEN; j++)
392                         {
393                                 slen += sprintf(buf+len+slen, "%02x%s",
394                                                 pNatRule->locMAC[j], j < ETH_ALEN-1 ? ":" : " ");
395                         }
396                         len += slen;
397                         for (j = 0; j < (19-slen); j++)
398                                 len += sprintf(buf+len, " ");
399
400                         /* locUDP */
401                         slen = sprintf(buf+len, "%d", pNatRule->locUDP);
402                         len += slen;
403                         for (j = 0; j < (16-slen); j++)
404                                 len += sprintf(buf+len, " ");
405
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);
411                         len += slen;
412                         for (j = 0; j < (22-slen); j++)
413                                 len += sprintf(buf+len, " ");
414
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);
420                 }
421         }
422         if (i == SVIP_SYS_CODEC_NUM)
423                 nProcReadIdx = -1;   /* reading completed */
424         else
425                 nProcReadIdx = i;    /* reading still in process, buffer was full */
426
427         return len;
428 }
429
430 #ifdef CONFIG_SVIP_FW_PKT_SNIFFER
431 /**
432   Converts MAC address from ascii to hex respesentaion
433   */
434 static int SVIP_NAT_MacAsciiToHex(const char *pMacStr, unsigned char *pMacHex)
435 {
436         int i=0, c=0, b=0, n=0;
437
438         memset(pMacHex, 0, ETH_ALEN);
439         while (pMacStr[i] != '\0')
440         {
441                 if (n >= 0)
442                 {
443                         unsigned char nToHex = 0;
444
445                         /* check for hex digit */
446                         if (pMacStr[i] >= '0' && pMacStr[i] <= '9')
447                                 nToHex = 0x30;
448                         else if (pMacStr[i] >= 'a' && pMacStr[i] <= 'f')
449                                 nToHex = 0x57;
450                         else if (pMacStr[i] >= 'A' && pMacStr[i] <= 'F')
451                                 nToHex = 0x37;
452                         else
453                         {
454                                 if (n != 0)
455                                 {
456                                         printk(KERN_ERR "SVIP NAT: invalid MAC address format[%s]\n", pMacStr);
457                                         return -1;
458                                 }
459                                 i++;
460                                 continue;
461                         }
462                         n^=1;
463                         pMacHex[b] |= ((pMacStr[i] - nToHex)&0xf) << (4*n);
464                         if (n == 0)
465                         {
466                                 /* advance to next byte, check if complete */
467                                 if (++b >= ETH_ALEN)
468                                         return 0;
469                                 /* byte completed, next we expect a colon... */
470                                 c = 1;
471                                 /* and, do not check for hex digit */
472                                 n = -1;
473                         }
474                         i++;
475                         continue;
476                 }
477                 if (c == 1)
478                 {
479                         if (pMacStr[i] == ':')
480                         {
481                                 /* next we expect hex digit, again */
482                                 n = 0;
483                         }
484                         else
485                         {
486                                 printk(KERN_ERR "SVIP NAT: invalid MAC address format[%s]\n", pMacStr);
487                                 return -1;
488                         }
489                 }
490                 i++;
491         }
492         return 0;
493 }
494
495 /**
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.
500
501   \remark
502 usage: 'echo "00:03:19:00:15:D1" > cat /proc/net/svip_nat/snifferMAC'
503 */
504 int SVIP_NAT_ProcWriteSnifferMAC (struct file *file, const char *buffer,
505                                   unsigned long count, void *data)
506 {
507         /* at least strlen("xx:xx:xx:xx:xx:xx") characters, followed by '\0' */
508         if (count >= 18)
509         {
510                 int ret;
511
512                 ret = SVIP_NAT_MacAsciiToHex(buffer, pSVIP_NAT_SnifferMAC);
513
514                 if (ret != 0)
515                         return 0;
516
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))
520                 {
521                         nSVIP_NAT_SnifferMacSet = 1;
522                 }
523         }
524         return count;
525 }
526
527 /**
528   Used to read the destination MAC address of a sniffer host
529   */
530 int SVIP_NAT_ProcReadSnifferMAC (char *buf, int count)
531 {
532         int len = 0;
533
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]);
538
539         if (len > count)
540         {
541                 printk(KERN_ERR "SVIP NAT: Only part of the text could be put into the buffer\n");
542                 return count;
543         }
544
545         return len;
546 }
547
548 /**
549   Used to switch VoFW message sniffer on/off
550
551   \remark
552 usage: 'echo "1" > cat /proc/net/svip_nat/snifferOnOff'
553 */
554 int SVIP_NAT_ProcWriteSnifferOnOff (struct file *file, const char *buffer,
555                                     unsigned long count, void *data)
556 {
557         /* at least one digit expected, followed by '\0' */
558         if (count >= 2)
559         {
560                 int ret, nSnifferOnOff;
561
562                 ret = sscanf(buffer, "%d", &nSnifferOnOff);
563
564                 if (ret != 1)
565                         return count;
566
567                 if (nSnifferOnOff > 0)
568                         nSnifferOnOff = 1;
569
570                 nSVIP_NAT_Sniffer = nSnifferOnOff;
571         }
572         return count;
573 }
574
575 /**
576   Used to read the VoFW message sniffer configuration (on/off)
577   */
578 int SVIP_NAT_ProcReadSnifferOnOff (char *buf, int count)
579 {
580         int len = 0;
581
582         len = snprintf(buf, count, "%d\n", nSVIP_NAT_Sniffer);
583
584         if (len > count)
585         {
586                 printk(KERN_ERR "SVIP NAT: Only part of the text could be put into the buffer\n");
587                 return count;
588         }
589
590         return len;
591 }
592 #endif
593
594 /******************************************************************************/
595 /**
596   Creates proc read/write entries
597
598   \return
599   0 on success, -1 on error
600   */
601 /******************************************************************************/
602 static int SVIP_NAT_ProcInstall(void)
603 {
604         struct proc_dir_entry *pProcParentDir, *pProcDir;
605         struct proc_dir_entry *pProcNode;
606
607 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
608         pProcParentDir = proc_net;
609 #else
610         pProcParentDir = init_net.proc_net;
611 #endif
612         pProcDir = proc_mkdir(SVIP_NAT_DEVICE_NAME, pProcParentDir);
613         if (pProcDir == NULL)
614         {
615                 printk(KERN_ERR "SVIP NAT: cannot create proc dir %s/%s\n\r",
616                        pProcParentDir->name, SVIP_NAT_DEVICE_NAME);
617                 return -1;
618         }
619
620         pProcNode = create_proc_read_entry("nat", S_IFREG|S_IRUGO, pProcDir,
621                                            SVIP_NAT_ProcRead, (void *)SVIP_NAT_ProcReadNAT);
622         if (pProcNode == NULL)
623         {
624                 printk(KERN_ERR "SVIP NAT: cannot create proc entry %s/%s",
625                        pProcDir->name, "nat");
626                 return -1;
627         }
628
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)
635         {
636                 printk(KERN_ERR "SVIP NAT: cannot create proc entry %s/%s\n\r",
637                        pProcDir->name, "snifferOnOff");
638                 return -1;
639         }
640         pProcNode->write_proc = SVIP_NAT_ProcWriteSnifferOnOff;
641
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)
648         {
649                 printk(KERN_ERR "SVIP NAT: cannot create proc entry %s/%s\n\r",
650                        pProcDir->name, "snifferMAC");
651                 return -1;
652         }
653         pProcNode->write_proc = SVIP_NAT_ProcWriteSnifferMAC;
654 #endif
655
656         return 0;
657 }
658
659 /******************************************************************************/
660 /**
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.
664
665   \arguments
666   inode       - pointer to disk file data
667   file        - pointer to device file data
668
669   \return
670   0 on success, else -1
671   */
672 /******************************************************************************/
673 static int SVIP_NAT_device_open(struct inode *inode, struct file *file)
674 {
675         unsigned long flags;
676         struct in_device *in_dev;
677         struct in_ifaddr *ifa;
678
679 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
680         local_irq_save(flags);
681 #else
682         local_save_flags(flags);
683 #endif
684
685         if (nDeviceOpen)
686         {
687                 MOD_INC_USE_COUNT;
688                 local_irq_restore(flags);
689                 nDeviceOpen++;
690                 return 0;
691         }
692
693         /* find pointer to IP address of eth0 */
694         if ((in_dev=in_dev_get(net_devs[SVIP_NET_DEV_ETH0_IDX])) != NULL)
695         {
696                 for (ifa = in_dev->ifa_list; ifa != NULL; ifa = ifa->ifa_next)
697                 {
698                         if (!paddr_eth0 && ifa->ifa_address != 0)
699                         {
700                                 paddr_eth0 = &ifa->ifa_address;
701                                 continue;
702                         }
703                         if (paddr_eth0 && ifa->ifa_address != 0)
704                         {
705                                 paddr_eth0_0 = &ifa->ifa_address;
706                                 break;
707                         }
708                 }
709                 in_dev_put(in_dev);
710         }
711         if (paddr_eth0 == NULL || paddr_eth0_0 == NULL)
712         {
713                 local_irq_restore(flags);
714                 return -ENODATA;
715         }
716
717         /* find pointer to IP address of veth0 */
718         if ((in_dev=in_dev_get(net_devs[SVIP_NET_DEV_VETH0_IDX])) != NULL)
719         {
720                 for (ifa = in_dev->ifa_list; ifa != NULL; ifa = ifa->ifa_next)
721                 {
722                         if (ifa->ifa_address != 0)
723                         {
724                                 paddr_veth0 = &ifa->ifa_address;
725                                 pmask_veth0 = &ifa->ifa_mask;
726                                 break;
727                         }
728                 }
729                 in_dev_put(in_dev);
730         }
731         if (paddr_veth0 == NULL)
732         {
733                 local_irq_restore(flags);
734                 return -ENODATA;
735         }
736
737         MOD_INC_USE_COUNT;
738         nDeviceOpen++;
739         local_irq_restore(flags);
740
741         return 0;
742 }
743
744
745 /******************************************************************************/
746 /**
747   This function is called when a process closes the SVIP NAT device file
748
749   \arguments
750   inode       - pointer to disk file data
751   file        - pointer to device file data
752
753   \return
754   0 on success, else -1
755
756 */
757 /******************************************************************************/
758 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
759 static int SVIP_NAT_device_release(struct inode *inode,
760                                    struct file *file)
761 #else
762 static void SVIP_NAT_device_release(struct inode *inode,
763                                     struct file *file)
764 #endif
765 {
766         unsigned long flags;
767
768 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
769         save_flags(flags);
770         cli();
771 #else
772         local_save_flags(flags);
773 #endif
774
775         /* The device can now be openned by the next caller */
776         nDeviceOpen--;
777
778         MOD_DEC_USE_COUNT;
779
780 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
781         restore_flags(flags);
782 #else
783         local_irq_restore(flags);
784 #endif
785
786 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
787         return 0;
788 #endif
789 }
790
791
792 /******************************************************************************/
793 /**
794   This function is called when a process closes the SVIP NAT device file
795
796   \arguments
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
801
802   \return
803   0 on success, else -1
804
805 */
806 /******************************************************************************/
807 long SVIP_NAT_device_ioctl (struct file *file,
808                            unsigned int ioctl_num, unsigned long ioctl_param)
809 {
810         int ret = 0;
811         SVIP_NAT_IO_Rule_t *pNatRule, *pNatRuleIn;
812         SVIP_UDP_PORT_t nPort;
813         int nNatIdx;
814         int bWrite = 0;
815         int bRead = 0;
816         unsigned char *pData = 0;
817         int nSize;
818
819         if (_IOC_DIR(ioctl_num) & _IOC_WRITE)
820                 bWrite = 1;
821         if (_IOC_DIR(ioctl_num) & _IOC_READ)
822                 bRead = 1;
823         nSize = _IOC_SIZE(ioctl_num);
824
825         if (nSize > sizeof(int))
826         {
827                 if (bRead || bWrite)
828                 {
829                         pData = kmalloc (nSize, GFP_KERNEL);
830                         if (bWrite)
831                         {
832                                 if (copy_from_user ((void *)pData, (void *)ioctl_param, nSize) != 0)
833                                 {
834                                         printk(KERN_ERR "SVIP NAT: ioctl %x: copy_from_user() failed!\n", ioctl_num);
835                                         ret = -1;
836                                         goto error;
837                                 }
838                         }
839                 }
840         }
841
842         switch (ioctl_num)
843         {
844         case FIO_SVIP_NAT_RULE_ADD:
845
846                 pNatRuleIn = (SVIP_NAT_IO_Rule_t *)pData;
847
848                 /* check if destination UDP port is within range */
849                 nPort = ntohs(pNatRuleIn->locUDP);
850
851                 if (!SVIP_PORT_INRANGE(nPort))
852                 {
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);
855                         ret = -1;
856                         goto error;
857                 }
858                 nNatIdx = SVIP_PORT_INDEX(nPort);
859
860                 down(sem_nat_tbl_access);
861                 pNatRule = &pNatTable[nNatIdx].natRule;
862
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;
869
870                 memset(pNatTable[nNatIdx].natStats, 0,
871                        sizeof(SVIP_NAT_stats_t)*SVIP_NAT_STATS_TYPES);
872                 up(sem_nat_tbl_access);
873                 break;
874
875         case FIO_SVIP_NAT_RULE_REMOVE:
876
877                 pNatRuleIn = (SVIP_NAT_IO_Rule_t *)pData;
878
879                 /* check if destination UDP port is within range */
880                 nPort = ntohs(pNatRuleIn->locUDP);
881                 if (!SVIP_PORT_INRANGE(nPort))
882                 {
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);
885                         ret = -1;
886                         goto error;
887                 }
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);
893                 break;
894
895         case FIO_SVIP_NAT_RULE_LIST:
896                 {
897                         int len;
898                         char buf[256];
899
900                         down(sem_nat_tbl_access);
901                         while (nProcReadIdx != -1)
902                         {
903                                 len = SVIP_NAT_ProcReadNAT(buf, 256);
904                                 if (len > 0)
905                                         printk("%s", buf);
906                         }
907                         nProcReadIdx = 0;
908                         up(sem_nat_tbl_access);
909                         break;
910                 }
911
912         default:
913                 printk(KERN_ERR "SVIP NAT: unsupported ioctl (%x) command for device %s\n",
914                        ioctl_num, PATH_SVIP_NAT_DEVICE_NAME);
915                 ret = -1;
916                 goto error;
917         }
918
919         if (nSize > sizeof(int))
920         {
921                 if (bRead)
922                 {
923                         if (copy_to_user ((void *)ioctl_param, (void *)pData, nSize) != 0)
924                         {
925                                 printk(KERN_ERR "SVIP NAT: ioctl %x: copy_to_user() failed!\n", ioctl_num);
926                                 ret = -1;
927                                 goto error;
928                         }
929                 }
930         }
931
932 error:
933         if (pData)
934                 kfree(pData);
935
936         return ret;
937 }
938
939 #if 0
940 void dump_msg(unsigned char *pData, unsigned int nLen)
941 {
942         int i;
943
944         for (i=0; i<nLen; i++)
945         {
946                 if (!i || !(i%16))
947                         printk("\n    ");
948                 else if (i && !(i%4))
949                         printk(" ");
950                 printk("%02x", pData[i]);
951         }
952         if (--i%16)
953                 printk("\n");
954 }
955 #endif
956
957 /******************************************************************************/
958 /**
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.
963
964   \arguments
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
971
972   \return
973   recalculated IP/UDP checksum
974   */
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)
978 {
979         u32 sum;
980
981         sum = csum_old;
982
983         /* convert back from one's complement */
984         sum = ~sum & 0xffff;
985
986         if (sum < saddr_old[0]) sum += 0xffff;
987         sum -= saddr_old[0];
988         if (sum < saddr_old[1]) sum += 0xffff;
989         sum -= saddr_old[1];
990         if (sum < daddr_old[0]) sum += 0xffff;
991         sum -= daddr_old[0];
992         if (sum < daddr_old[1]) sum += 0xffff;
993         sum -= daddr_old[1];
994
995         sum += saddr_new[0];
996         sum += saddr_new[1];
997         sum += daddr_new[0];
998         sum += daddr_new[1];
999
1000         /* take only 16 bits out of the 32 bit sum and add up the carries */
1001         while (sum >> 16)
1002                 sum = (sum & 0xffff)+((sum >> 16) & 0xffff);
1003
1004         /* one's complement the result */
1005         sum = ~sum;
1006
1007         return (u16)(sum & 0xffff);
1008 }
1009
1010
1011 /******************************************************************************/
1012 /**
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
1015   itterative calls.
1016
1017   \arguments
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
1022
1023   \return
1024   pointer to the next ipv4 instance, which can be null if ifa_start was
1025   the last instance present
1026   */
1027 /******************************************************************************/
1028 static struct in_ifaddr *get_ifaddr(struct net_device *dev,
1029                                     struct in_ifaddr *ifa_start, unsigned int **ppifa_addr)
1030 {
1031         struct in_device *in_dev;
1032         struct in_ifaddr *ifa = NULL;
1033
1034         if ((in_dev=in_dev_get(dev)) != NULL)
1035         {
1036                 if (ifa_start == NULL)
1037                         ifa = in_dev->ifa_list;
1038                 else
1039                         ifa = ifa_start;
1040                 if (ifa)
1041                 {
1042                         *ppifa_addr = &ifa->ifa_address;
1043                         ifa = ifa->ifa_next;
1044                 }
1045                 in_dev_put(in_dev);
1046                 return ifa;
1047         }
1048         *ppifa_addr = NULL;
1049         return NULL;
1050 }
1051
1052 /******************************************************************************/
1053 /**
1054   This function performs IP NAT for received packets satisfying the
1055   following requirements:
1056
1057   - packet is destined to local IP host
1058   - transport protocol type is UDP
1059   - destination UDP port is within range
1060
1061   \arguments
1062   skb         - pointer to the receiving socket buffer
1063
1064   \return
1065   returns 1 on performed SVIP NAT, else returns 0
1066
1067   \remarks
1068   When function returns 0, it indicates the caller to pass the
1069   packet up the IP stack to make further decision about it
1070   */
1071 /******************************************************************************/
1072 int do_SVIP_NAT (struct sk_buff *skb)
1073 {
1074         struct net_device *real_dev;
1075         struct iphdr *iph;
1076         struct udphdr *udph;
1077         SVIP_NAT_IO_Rule_t *pNatRule;
1078         int nNatIdx, in_eth0, nDir;
1079 #ifndef VLAN_8021Q_UNUSED
1080         int vlan;
1081         unsigned short vid;
1082 #endif /* ! VLAN_8021Q_UNUSED */
1083         SVIP_UDP_PORT_t nPort;
1084         u32 orgSrcIp, orgDstIp, *pSrcIp, *pDstIp;
1085         struct ethhdr *ethh;
1086
1087         /* do not consider if SVIP NAT device not open. */
1088         if (!nDeviceOpen)
1089         {
1090                 return 0;
1091         }
1092
1093         /* consider only UDP packets. */
1094         iph = SVIP_NAT_IP_HDR(skb);
1095         if (iph->protocol != IPPROTO_UDP)
1096         {
1097                 return 0;
1098         }
1099
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))))
1105         {
1106                 return 0;
1107         }
1108
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
1113            Ethernet frame */
1114         if (skb->dev->priv_flags & IFF_802_1Q_VLAN)
1115         {
1116                 vlan = 1;
1117                 vid = VLAN_DEV_VLAN_ID(skb->dev);
1118                 real_dev = VLAN_DEV_REAL_DEV(skb->dev);
1119         }
1120         else
1121         {
1122                 vlan = 0;
1123                 vid = 0;
1124                 real_dev = skb->dev;
1125         }
1126 #endif /* ! VLAN_8021Q_UNUSED */
1127
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.
1138
1139 NOTE: In case of VLAN traffic the VLAN header information is lost. */
1140         if (nSVIP_NAT_Sniffer)
1141         {
1142                 if (real_dev == net_devs[SVIP_NET_DEV_VETH0_IDX])
1143                 {
1144                         struct sk_buff *copied_skb;
1145
1146                         /* gain the Ethernet header from the skb */
1147                         skb_push(skb, ETH_HLEN);
1148
1149                         copied_skb = skb_copy (skb, GFP_ATOMIC);
1150
1151                         if (nSVIP_NAT_SnifferMacSet == 1)
1152                         {
1153                                 ethh = (struct ethhdr *)SVIP_NAT_SKB_MAC_HEADER(copied_skb);
1154                                 memcpy((char *)ethh->h_dest, (char *)pSVIP_NAT_SnifferMAC, ETH_ALEN);
1155                         }
1156                         copied_skb->dev = net_devs[SVIP_NET_DEV_ETH0_IDX];
1157                         dev_queue_xmit(copied_skb);
1158
1159                         /* skip the ETH header again */
1160                         skb_pull(skb, ETH_HLEN);
1161                 }
1162         }
1163 #endif
1164
1165
1166         /* check if packet arrived on eth0 */
1167         if (real_dev == net_devs[SVIP_NET_DEV_ETH0_IDX])
1168         {
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)
1175                 {
1176                         nPort = ntohs(udph->dest);
1177                         nDir = SVIP_NAT_STATS_REM2LOC;
1178                 }
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)
1184                 {
1185                         nPort = ntohs(udph->source);
1186                         nDir = SVIP_NAT_STATS_LOC2REM;
1187                 }
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. */
1192                 else if (vlan)
1193                 {
1194                         unsigned int *pifa_addr;
1195                         struct in_ifaddr *ifa_start = NULL;
1196                         int i = 0;
1197
1198                         do
1199                         {
1200                                 ifa_start = get_ifaddr(skb->dev, ifa_start, &pifa_addr);
1201                                 if (!pifa_addr)
1202                                 {
1203                                         /* VLAN packet received on vlan interface attached to eth0,
1204                                            however no IP address assigned to the interface.
1205                                            The packet is ignored. */
1206                                         return 0;
1207                                 }
1208                                 if (iph->daddr == *pifa_addr)
1209                                 {
1210                                         /* packet destined to... */
1211                                         break;
1212                                 }
1213                                 if (!ifa_start)
1214                                 {
1215                                         return 0;
1216                                 }
1217                                 i++;
1218                         } while (ifa_start);
1219                         if (!i)
1220                         {
1221                                 /* ...primary assigned IP address to the VLAN interface. */
1222                                 nPort = ntohs(udph->dest);
1223                                 nDir = SVIP_NAT_STATS_REM2LOC;
1224                         }
1225                         else
1226                         {
1227                                 /* ...secondary assigned IP address to the VLAN interface. */
1228                                 nPort = ntohs(udph->source);
1229                                 nDir = SVIP_NAT_STATS_LOC2REM;
1230                         }
1231                 }
1232 #endif /* ! VLAN_8021Q_UNUSED */
1233                 else
1234                 {
1235                         return 0;
1236                 }
1237                 in_eth0 = 1;
1238         }
1239         /* check if packet arrived on veth0 */
1240         else if (real_dev == net_devs[SVIP_NET_DEV_VETH0_IDX])
1241         {
1242                 nPort = ntohs(udph->source);
1243                 nDir = SVIP_NAT_STATS_LOC2REM;
1244                 in_eth0 = 0;
1245         }
1246         else
1247         {
1248                 /* packet arrived neither on eth0, nor veth0 */
1249                 return 0;
1250         }
1251
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;
1256
1257         ethh = (struct ethhdr *)SVIP_NAT_SKB_MAC_HEADER(skb);
1258
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;
1263
1264         if (in_eth0)
1265         {
1266                 u8 *pDstMac;
1267
1268                 /* Process packet arrived on eth0 */
1269
1270                 if (nDir == SVIP_NAT_STATS_REM2LOC && iph->saddr == pNatRule->remIP)
1271                 {
1272                         pDstIp = &pNatRule->locIP;
1273                         pDstMac = pNatRule->locMAC;
1274                 }
1275                 else if (nDir == SVIP_NAT_STATS_LOC2REM && iph->saddr == pNatRule->locIP)
1276                 {
1277                         pDstIp = &pNatRule->remIP;
1278                         pDstMac = pNatRule->remMAC;
1279                 }
1280                 else
1281                 {
1282                         /* Rule check failed. The packet is passed up the layers,
1283                            it will be dropped by UDP */
1284                         return 0;
1285                 }
1286
1287                 if ((*pDstIp & *pmask_veth0) == (*paddr_veth0 & *pmask_veth0))
1288                 {
1289 #ifndef VLAN_8021Q_UNUSED
1290                         if (vlan)
1291                         {
1292                                 struct net_device *vlan_dev;
1293
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);
1297                                 if (vlan_dev)
1298                                 {
1299 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1300                                         struct vlan_ethhdr *vethh;
1301
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;
1310 #else
1311                                         skb_push(skb, ETH_HLEN);
1312 #endif
1313                                         skb->dev = vlan_dev;
1314                                 }
1315                                 else
1316                                 {
1317                                         skb->dev = net_devs[SVIP_NET_DEV_VETH0_IDX];
1318                                         skb_push(skb, ETH_HLEN);
1319                                 }
1320                         }
1321                         else
1322 #endif /* ! VLAN_8021Q_UNUSED */
1323                         {
1324                                 skb->dev = net_devs[SVIP_NET_DEV_VETH0_IDX];
1325                                 skb_push(skb, ETH_HLEN);
1326                         }
1327                         pSrcIp = paddr_veth0;
1328                 }
1329                 else
1330                 {
1331 #ifndef VLAN_8021Q_UNUSED
1332 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1333                         if (vlan)
1334                         {
1335                                 struct vlan_ethhdr *vethh;
1336
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;
1345                         }
1346                         else
1347 #endif
1348 #endif /* ! VLAN_8021Q_UNUSED */
1349                         {
1350                                 skb_push(skb, ETH_HLEN);
1351                         }
1352                         /* source IP address equals the destination IP address
1353                            of the incoming packet */
1354                         pSrcIp = &iph->daddr;
1355                 }
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);
1360         }
1361         else
1362         {
1363                 /* Process packet arrived on veth0 */
1364
1365                 if (iph->saddr != pNatRule->locIP)
1366                 {
1367                         /* Rule check failed. The packet is passed up the layers,
1368                            it will be dropped by UDP */
1369                         return 0;
1370                 }
1371
1372                 if (!((pNatRule->remIP & *pmask_veth0) == (*paddr_veth0 & *pmask_veth0)))
1373                 {
1374 #ifndef VLAN_8021Q_UNUSED
1375                         if (vlan)
1376                         {
1377                                 struct net_device *vlan_dev;
1378
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);
1382                                 if (vlan_dev)
1383                                 {
1384                                         unsigned int *pifa_addr;
1385 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1386                                         struct vlan_ethhdr *vethh;
1387
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;
1395 #else
1396                                         skb_push(skb, ETH_HLEN);
1397 #endif
1398                                         skb->dev = vlan_dev;
1399
1400                                         get_ifaddr(skb->dev, NULL, &pifa_addr);
1401                                         if (pifa_addr)
1402                                         {
1403                                                 pSrcIp = pifa_addr;
1404                                         }
1405                                         else
1406                                         {
1407                                                 pSrcIp = paddr_eth0;
1408                                         }
1409                                 }
1410                                 else
1411                                 {
1412                                         skb->dev = net_devs[SVIP_NET_DEV_ETH0_IDX];
1413                                         pSrcIp = paddr_eth0;
1414                                         skb_push(skb, ETH_HLEN);
1415                                 }
1416                         }
1417                         else
1418 #endif /* ! VLAN_8021Q_UNUSED */
1419                         {
1420                                 skb->dev = net_devs[SVIP_NET_DEV_ETH0_IDX];
1421                                 pSrcIp = paddr_eth0;
1422                                 skb_push(skb, ETH_HLEN);
1423                         }
1424                 }
1425                 else
1426                 {
1427                         pSrcIp = paddr_veth0;
1428 #ifndef VLAN_8021Q_UNUSED
1429 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1430                         if (vlan)
1431                         {
1432                                 struct vlan_ethhdr *vethh;
1433
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;
1442                         }
1443                         else
1444 #endif
1445 #endif /* ! VLAN_8021Q_UNUSED */
1446                         {
1447                                 skb_push(skb, ETH_HLEN);
1448                         }
1449                 }
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);
1454         }
1455         pNatTable[nNatIdx].natStats[nDir].inPackets++;
1456
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)
1460         {
1461                 udph->check = ip_udp_quick_csum(udph->check, (u16 *)&orgSrcIp, (u16 *)&iph->saddr,
1462                                                 (u16 *)&orgDstIp, (u16 *)&iph->daddr);
1463         }
1464
1465         /* write the packet out, directly to the network device */
1466         if (dev_queue_xmit(skb) < 0)
1467                 pNatTable[nNatIdx].natStats[nDir].outErrors++;
1468         else
1469                 pNatTable[nNatIdx].natStats[nDir].outPackets++;
1470
1471         return 1;
1472 }
1473
1474 /******************************************************************************/
1475 /**
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.
1478
1479   \remarks:
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)
1484 {
1485         int ret = 0;
1486         struct net_device *dev;
1487
1488         if (misc_register(&SVIP_NAT_miscdev) != 0)
1489         {
1490                 printk(KERN_ERR "%s: cannot register SVIP NAT device node.\n",
1491                        SVIP_NAT_miscdev.name);
1492                 return -EIO;
1493         }
1494
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)
1499         {
1500                 printk (KERN_ERR "SVIP NAT: Error(%d), allocating memory for NAT table\n", ret);
1501                 return -1;
1502         }
1503
1504         /* clear the NAT table */
1505         memset((void *)pNatTable, 0, sizeof(SVIP_NAT_table_entry_t) * SVIP_SYS_CODEC_NUM);
1506
1507         if ((sem_nat_tbl_access = kmalloc(sizeof(struct semaphore), GFP_KERNEL)))
1508         {
1509                 sema_init(sem_nat_tbl_access, 1);
1510         }
1511
1512         SVIP_NAT_ProcInstall();
1513
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)
1517         {
1518                 if (!strcmp(dev->name, SVIP_NET_DEV_ETH0_NAME))
1519                 {
1520                         net_devs[SVIP_NET_DEV_ETH0_IDX] = dev;
1521                 }
1522                 if (!strcmp(dev->name, SVIP_NET_DEV_VETH1_NAME))
1523                 {
1524                         net_devs[SVIP_NET_DEV_VETH0_IDX] = dev;
1525                 }
1526                 else if (!strcmp(dev->name, SVIP_NET_DEV_ETH1_NAME))
1527                 {
1528                         net_devs[SVIP_NET_DEV_VETH0_IDX] = dev;
1529                 }
1530         }
1531         read_unlock(&dev_base_lock);
1532
1533         if (net_devs[SVIP_NET_DEV_ETH0_IDX] == NULL ||
1534             net_devs[SVIP_NET_DEV_VETH0_IDX] == NULL)
1535         {
1536                 printk (KERN_ERR "SVIP NAT: Error, unable to locate eth0 and veth0 interfaces\n");
1537                 return -1;
1538         }
1539
1540         printk ("%s, (c) 2009, Lantiq Deutschland GmbH\n", &SVIP_NAT_INFO_STR[4]);
1541
1542         return ret;
1543 }
1544
1545 /******************************************************************************/
1546 /**
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.
1549
1550   \remarks:
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)
1555 {
1556         MOD_DEC_USE_COUNT;
1557
1558         /* unregister SVIP NAT configuration device */
1559         misc_deregister(&SVIP_NAT_miscdev);
1560
1561         /* release memory of SVIP NAT table */
1562         if (pNatTable != NULL)
1563         {
1564                 kfree (pNatTable);
1565         }
1566 }
1567
1568 module_init(init);
1569 module_exit(fini);