Root/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
27Description : This file contains implementation of Custom NAT function
28for 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
49MODULE_AUTHOR("Lantiq Deutschland GmbH");
50MODULE_DESCRIPTION("SVIP Network Address Translation module");
51MODULE_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
118extern spinlock_t vlan_group_lock;
119extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, unsigned short VID);
120
121typedef struct SVIP_NAT_stats
122{
123    unsigned long inPackets;
124    unsigned long outPackets;
125    unsigned long outErrors;
126} SVIP_NAT_stats_t;
127
128typedef 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 */
135static SVIP_NAT_table_entry_t *pNatTable = NULL;
136
137struct net_device *net_devs[3];
138static u32 *paddr_eth0;
139static u32 *paddr_eth0_0;
140static u32 *paddr_veth0;
141static u32 *pmask_veth0;
142
143static struct semaphore *sem_nat_tbl_access;
144static int proc_read_in_progress = 0;
145
146static int nDeviceOpen = 0;
147
148/* saves the NAT table index between subsequent invocation */
149static int nProcReadIdx = 0;
150
151static long SVIP_NAT_device_ioctl(struct file *,unsigned int ,unsigned long);
152#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
153static int SVIP_NAT_device_release (struct inode *,struct file *);
154#else
155static void SVIP_NAT_device_release (struct inode *,struct file *);
156#endif
157static 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. */
161struct file_operations SVIP_NAT_Fops = {
162#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
163owner: 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 */
180static struct miscdevice SVIP_NAT_miscdev =
181{
182minor: MINOR_NUM_SVIP_NAT,
183     name: SVIP_NAT_DEVICE_NAME,
184     fops: &SVIP_NAT_Fops
185};
186
187#ifdef CONFIG_SVIP_FW_PKT_SNIFFER
188int nSVIP_NAT_Sniffer;
189unsigned char pSVIP_NAT_SnifferMAC[ETH_ALEN];
190int 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 ****************************************************************************/
213static 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  */
267static 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 *******************************************************************************/
322static 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  */
434static 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
502usage: 'echo "00:03:19:00:15:D1" > cat /proc/net/svip_nat/snifferMAC'
503*/
504int 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  */
530int 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
552usage: 'echo "1" > cat /proc/net/svip_nat/snifferOnOff'
553*/
554int 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  */
578int 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/******************************************************************************/
602static 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/******************************************************************************/
673static 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)
759static int SVIP_NAT_device_release(struct inode *inode,
760                   struct file *file)
761#else
762static 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/******************************************************************************/
807long 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
932error:
933    if (pData)
934        kfree(pData);
935
936    return ret;
937}
938
939#if 0
940void 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/******************************************************************************/
976static 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/******************************************************************************/
1028static 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/******************************************************************************/
1072int 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
1139NOTE: 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.
1304NOTE: 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.
1338NOTE: 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.
1436NOTE: 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 *******************************************************************************/
1483static 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 *******************************************************************************/
1554static 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
1568module_init(init);
1569module_exit(fini);
1570

Archive Download this file



interactive