04a0d223a216cb5d43da213cc0b870a99bcb966a
[openwrt/svn-archive/archive.git] / target / linux / lantiq / files-3.3 / 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);