b1fc8aa2cf5d5b8a91ef5ebf2eaf6dbcc405efaa
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bs / core / rtw_br_ext.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *                                        
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_BR_EXT_C_
21
22 #ifdef __KERNEL__
23 #include <linux/if_arp.h>
24 #include <net/ip.h>
25 #include <net/ipx.h>
26 #include <linux/atalk.h>
27 #include <linux/udp.h>
28 #include <linux/if_pppox.h>
29 #endif
30
31 #if 1   // rtw_wifi_driver
32 #include <drv_types.h>
33 #else   // rtw_wifi_driver
34 #include "./8192cd_cfg.h"
35
36 #ifndef __KERNEL__
37 #include "./sys-support.h"
38 #endif
39
40 #include "./8192cd.h"
41 #include "./8192cd_headers.h"
42 #include "./8192cd_br_ext.h"
43 #include "./8192cd_debug.h"
44 #endif  // rtw_wifi_driver
45
46 #ifdef CL_IPV6_PASS
47 #ifdef __KERNEL__
48 #include <linux/ipv6.h>
49 #include <linux/icmpv6.h>
50 #include <net/ndisc.h>
51 #include <net/checksum.h>
52 #include <net/ip6_checksum.h>
53 #endif
54 #endif
55
56 #ifdef CONFIG_BR_EXT
57
58 //#define BR_EXT_DEBUG
59
60 #define NAT25_IPV4              01
61 #define NAT25_IPV6              02
62 #define NAT25_IPX               03
63 #define NAT25_APPLE             04
64 #define NAT25_PPPOE             05
65
66 #define RTL_RELAY_TAG_LEN (ETH_ALEN)
67 #define TAG_HDR_LEN             4
68
69 #define MAGIC_CODE              0x8186
70 #define MAGIC_CODE_LEN  2
71 #define WAIT_TIME_PPPOE 5       // waiting time for pppoe server in sec
72
73 /*-----------------------------------------------------------------
74   How database records network address:
75            0    1    2    3    4    5    6    7    8    9   10
76         |----|----|----|----|----|----|----|----|----|----|----|
77   IPv4  |type|                             |      IP addr      |
78   IPX   |type|      Net addr     |          Node addr          |
79   IPX   |type|      Net addr     |Sckt addr|
80   Apple |type| Network |node|
81   PPPoE |type|   SID   |           AC MAC            |
82 -----------------------------------------------------------------*/
83
84
85 //Find a tag in pppoe frame and return the pointer
86 static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
87 {
88         unsigned char *cur_ptr, *start_ptr;
89         unsigned short tagLen, tagType;
90
91         start_ptr = cur_ptr = (unsigned char *)ph->tag;
92         while((cur_ptr - start_ptr) < ntohs(ph->length)) {
93                 // prevent un-alignment access
94                 tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
95                 tagLen  = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
96                 if(tagType == type)
97                         return cur_ptr;
98                 cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
99         }
100         return 0;
101 }
102
103
104 static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
105 {
106         struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
107         int data_len;
108
109         data_len = tag->tag_len + TAG_HDR_LEN;
110         if (skb_tailroom(skb) < data_len) {
111                 _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
112                 return -1;
113         }
114
115         skb_put(skb, data_len);
116         // have a room for new tag
117         memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
118         ph->length = htons(ntohs(ph->length) + data_len);
119         memcpy((unsigned char *)ph->tag, tag, data_len);
120         return data_len;
121 }
122
123 static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
124 {
125         int tail_len;
126         unsigned long end, tail;
127
128         if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
129                 return -1;
130
131         tail = (unsigned long)skb_tail_pointer(skb);
132         end = (unsigned long)src+len;
133         if (tail < end)
134                 return -1;
135
136         tail_len = (int)(tail-end);
137         if (tail_len > 0)
138                 memmove(src, src+len, tail_len);
139
140         skb_trim(skb, skb->len-len);
141         return 0;
142 }
143
144 static __inline__ unsigned long __nat25_timeout(_adapter *priv)
145 {
146         unsigned long timeout;
147
148         timeout = jiffies - NAT25_AGEING_TIME*HZ;
149
150         return timeout;
151 }
152
153
154 static __inline__ int  __nat25_has_expired(_adapter *priv,
155                                 struct nat25_network_db_entry *fdb)
156 {
157         if(time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
158                 return 1;
159
160         return 0;
161 }
162
163
164 static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
165                                 unsigned int *ipAddr)
166 {
167         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
168
169         networkAddr[0] = NAT25_IPV4;
170         memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
171 }
172
173
174 static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
175                                 unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr)
176 {
177         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
178
179         networkAddr[0] = NAT25_IPX;
180         memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
181         memcpy(networkAddr+5, ipxNodeAddr, 6);
182 }
183
184
185 static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
186                                 unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr)
187 {
188         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
189
190         networkAddr[0] = NAT25_IPX;
191         memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
192         memcpy(networkAddr+5, (unsigned char *)ipxSocketAddr, 2);
193 }
194
195
196 static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
197                                 unsigned short *network, unsigned char *node)
198 {
199         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
200
201         networkAddr[0] = NAT25_APPLE;
202         memcpy(networkAddr+1, (unsigned char *)network, 2);
203         networkAddr[3] = *node;
204 }
205
206
207 static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
208                                 unsigned char *ac_mac, unsigned short *sid)
209 {
210         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
211
212         networkAddr[0] = NAT25_PPPOE;
213         memcpy(networkAddr+1, (unsigned char *)sid, 2);
214         memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
215 }
216
217
218 #ifdef CL_IPV6_PASS
219 static  void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
220                                 unsigned int *ipAddr)
221 {
222         memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
223
224         networkAddr[0] = NAT25_IPV6;
225         memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
226 }
227
228
229 static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
230 {
231         while (len > 0) {
232                 if (*data == tag && *(data+1) == len8b && len >= len8b*8)
233                         return data+2;  
234                 
235                 len -= (*(data+1))*8;           
236                 data += (*(data+1))*8;          
237         }
238         return NULL;
239 }
240
241
242 static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
243 {
244         struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
245         unsigned char *mac;
246         
247         if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { 
248                 if (len >= 8) {
249                         mac = scan_tlv(&data[8], len-8, 1, 1);
250                         if (mac) {
251                                 DBG_871X("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
252                                         mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],                                      
253                                         replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
254                                 memcpy(mac, replace_mac, 6);    
255                                 return 1;                               
256                         }
257                 }
258         }
259         else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
260                 if (len >= 16) {
261                         mac = scan_tlv(&data[16], len-16, 1, 1);
262                         if (mac) {
263                                 DBG_871X("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
264                                         mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],                                      
265                                         replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
266                                 memcpy(mac, replace_mac, 6);                    
267                                 return 1;                               
268                         }
269                 }               
270         }
271         else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
272                 if (len >= 24) {
273                         mac = scan_tlv(&data[24], len-24, 1, 1);
274                         if (mac) {              
275                                 DBG_871X("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
276                                         mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],                                      
277                                         replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
278                                 memcpy(mac, replace_mac, 6);    
279                                 return 1;                                                               
280                         }
281                 }               
282         }
283         else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
284                 if (len >= 24) {
285                         mac = scan_tlv(&data[24], len-24, 2, 1);
286                         if (mac) {
287                                 DBG_871X("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
288                                         mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],                                      
289                                         replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
290                                 memcpy(mac, replace_mac, 6);            
291                                 return 1;                               
292                         }
293                 }               
294         }
295         else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
296                 if (len >= 40) {
297                         mac = scan_tlv(&data[40], len-40, 2, 1);
298                         if (mac) {                              
299                                 DBG_871X("Redirect,  replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
300                                         mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],                                      
301                                         replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
302                                 memcpy(mac, replace_mac, 6);    
303                                 return 1;                               
304                         }
305                 }               
306         }       
307         return 0;
308 }
309
310
311 static void convert_ipv6_mac_to_mc(struct sk_buff *skb)
312 {       
313         struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
314         unsigned char *dst_mac = skb->data;
315
316         //dst_mac[0] = 0xff;
317         //dst_mac[1] = 0xff;
318         /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/
319         dst_mac[0] = 0x33;
320         dst_mac[1] = 0x33;
321         memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4);
322         #if defined(__LINUX_2_6__) 
323         /*modified by qinjunjie,warning:should not remove next line*/
324         skb->pkt_type = PACKET_MULTICAST;
325         #endif
326 }
327 #endif /* CL_IPV6_PASS */
328
329
330 static __inline__ int __nat25_network_hash(unsigned char *networkAddr)
331 {
332         if(networkAddr[0] == NAT25_IPV4)
333         {
334                 unsigned long x;
335
336                 x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
337
338                 return x & (NAT25_HASH_SIZE - 1);
339         }
340         else if(networkAddr[0] == NAT25_IPX)
341         {
342                 unsigned long x;
343
344                 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
345                         networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
346
347                 return x & (NAT25_HASH_SIZE - 1);
348         }
349         else if(networkAddr[0] == NAT25_APPLE)
350         {
351                 unsigned long x;
352
353                 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
354
355                 return x & (NAT25_HASH_SIZE - 1);
356         }
357         else if(networkAddr[0] == NAT25_PPPOE)
358         {
359                 unsigned long x;
360
361                 x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
362
363                 return x & (NAT25_HASH_SIZE - 1);
364         }
365 #ifdef CL_IPV6_PASS
366         else if(networkAddr[0] == NAT25_IPV6)
367         {
368                 unsigned long x;
369
370                 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
371                         networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
372                         networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
373                         networkAddr[16];
374         
375                 return x & (NAT25_HASH_SIZE - 1);
376         }
377 #endif  
378         else
379         {
380                 unsigned long x = 0;
381                 int i;
382
383                 for (i=0; i<MAX_NETWORK_ADDR_LEN; i++)
384                         x ^= networkAddr[i];
385
386                 return x & (NAT25_HASH_SIZE - 1);
387         }
388 }
389
390
391 static __inline__ void __network_hash_link(_adapter *priv,
392                                 struct nat25_network_db_entry *ent, int hash)
393 {
394         // Caller must _enter_critical_bh already!
395         //_irqL irqL;
396         //_enter_critical_bh(&priv->br_ext_lock, &irqL);
397
398         ent->next_hash = priv->nethash[hash];
399         if(ent->next_hash != NULL)
400                 ent->next_hash->pprev_hash = &ent->next_hash;
401         priv->nethash[hash] = ent;
402         ent->pprev_hash = &priv->nethash[hash];
403
404         //_exit_critical_bh(&priv->br_ext_lock, &irqL);
405 }
406
407
408 static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent)
409 {
410         // Caller must _enter_critical_bh already!
411         //_irqL irqL;
412         //_enter_critical_bh(&priv->br_ext_lock, &irqL);
413
414         *(ent->pprev_hash) = ent->next_hash;
415         if(ent->next_hash != NULL)
416                 ent->next_hash->pprev_hash = ent->pprev_hash;
417         ent->next_hash = NULL;
418         ent->pprev_hash = NULL;
419
420         //_exit_critical_bh(&priv->br_ext_lock, &irqL);
421 }
422
423
424 static int __nat25_db_network_lookup_and_replace(_adapter *priv,
425                                 struct sk_buff *skb, unsigned char *networkAddr)
426 {
427         struct nat25_network_db_entry *db;
428         _irqL irqL;
429         _enter_critical_bh(&priv->br_ext_lock, &irqL);
430
431         db = priv->nethash[__nat25_network_hash(networkAddr)];
432         while (db != NULL)
433         {
434                 if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))
435                 {
436                         if(!__nat25_has_expired(priv, db))
437                         {
438                                 // replace the destination mac address
439                                 memcpy(skb->data, db->macAddr, ETH_ALEN);
440                                 atomic_inc(&db->use_count);
441
442 #ifdef CL_IPV6_PASS
443                                 DBG_871X("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"      
444                                                         "%02x%02x%02x%02x%02x%02x\n",                           
445                                         db->macAddr[0],
446                                         db->macAddr[1],
447                                         db->macAddr[2],
448                                         db->macAddr[3],
449                                         db->macAddr[4],
450                                         db->macAddr[5],
451                                         db->networkAddr[0],
452                                         db->networkAddr[1],
453                                         db->networkAddr[2],
454                                         db->networkAddr[3],
455                                         db->networkAddr[4],
456                                         db->networkAddr[5],
457                                         db->networkAddr[6],
458                                         db->networkAddr[7],
459                                         db->networkAddr[8],
460                                         db->networkAddr[9],
461                                         db->networkAddr[10],
462                                         db->networkAddr[11],
463                                         db->networkAddr[12],
464                                         db->networkAddr[13],
465                                         db->networkAddr[14],
466                                         db->networkAddr[15],
467                                         db->networkAddr[16]);
468 #else                           
469                                 DBG_871X("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
470                                         db->macAddr[0],
471                                         db->macAddr[1],
472                                         db->macAddr[2],
473                                         db->macAddr[3],
474                                         db->macAddr[4],
475                                         db->macAddr[5],
476                                         db->networkAddr[0],
477                                         db->networkAddr[1],
478                                         db->networkAddr[2],
479                                         db->networkAddr[3],
480                                         db->networkAddr[4],
481                                         db->networkAddr[5],
482                                         db->networkAddr[6],
483                                         db->networkAddr[7],
484                                         db->networkAddr[8],
485                                         db->networkAddr[9],
486                                         db->networkAddr[10]);
487 #endif
488                         }
489                         _exit_critical_bh(&priv->br_ext_lock, &irqL);
490                         return 1;
491                 }
492
493                 db = db->next_hash;
494         }
495
496         _exit_critical_bh(&priv->br_ext_lock, &irqL);
497         return 0;
498 }
499
500
501 static void __nat25_db_network_insert(_adapter *priv,
502                                 unsigned char *macAddr, unsigned char *networkAddr)
503 {
504         struct nat25_network_db_entry *db;
505         int hash;
506         _irqL irqL;
507         _enter_critical_bh(&priv->br_ext_lock, &irqL);
508
509         hash = __nat25_network_hash(networkAddr);
510         db = priv->nethash[hash];
511         while (db != NULL)
512         {
513                 if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))
514                 {
515                         memcpy(db->macAddr, macAddr, ETH_ALEN);
516                         db->ageing_timer = jiffies;
517                         _exit_critical_bh(&priv->br_ext_lock, &irqL);
518                         return;
519                 }
520
521                 db = db->next_hash;
522         }
523
524         db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
525         if(db == NULL) {
526                 _exit_critical_bh(&priv->br_ext_lock, &irqL);
527                 return;
528         }
529
530         memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
531         memcpy(db->macAddr, macAddr, ETH_ALEN);
532         atomic_set(&db->use_count, 1);
533         db->ageing_timer = jiffies;
534
535         __network_hash_link(priv, db, hash);
536
537         _exit_critical_bh(&priv->br_ext_lock, &irqL);
538 }
539
540
541 static void __nat25_db_print(_adapter *priv)
542 {
543         _irqL irqL;
544         _enter_critical_bh(&priv->br_ext_lock, &irqL);
545
546 #ifdef BR_EXT_DEBUG
547         static int counter = 0;
548         int i, j;
549         struct nat25_network_db_entry *db;
550
551         counter++;
552         if((counter % 16) != 0)
553                 return;
554
555         for(i=0, j=0; i<NAT25_HASH_SIZE; i++)
556         {
557                 db = priv->nethash[i];
558
559                 while (db != NULL)
560                 {
561 #ifdef CL_IPV6_PASS
562                         panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
563                                         "%02x%02x%02x%02x%02x%02x\n",
564                                 j,
565                                 i,
566                                 atomic_read(&db->use_count),
567                                 db->macAddr[0],
568                                 db->macAddr[1],
569                                 db->macAddr[2],
570                                 db->macAddr[3],
571                                 db->macAddr[4],
572                                 db->macAddr[5],
573                                 db->networkAddr[0],
574                                 db->networkAddr[1],
575                                 db->networkAddr[2],
576                                 db->networkAddr[3],
577                                 db->networkAddr[4],
578                                 db->networkAddr[5],
579                                 db->networkAddr[6],
580                                 db->networkAddr[7],
581                                 db->networkAddr[8],
582                                 db->networkAddr[9],
583                                 db->networkAddr[10],
584                                 db->networkAddr[11],
585                                 db->networkAddr[12],
586                                 db->networkAddr[13],
587                                 db->networkAddr[14],
588                                 db->networkAddr[15],
589                                 db->networkAddr[16]);
590 #else
591                         panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
592                                 j,
593                                 i,
594                                 atomic_read(&db->use_count),
595                                 db->macAddr[0],
596                                 db->macAddr[1],
597                                 db->macAddr[2],
598                                 db->macAddr[3],
599                                 db->macAddr[4],
600                                 db->macAddr[5],
601                                 db->networkAddr[0],
602                                 db->networkAddr[1],
603                                 db->networkAddr[2],
604                                 db->networkAddr[3],
605                                 db->networkAddr[4],
606                                 db->networkAddr[5],
607                                 db->networkAddr[6],
608                                 db->networkAddr[7],
609                                 db->networkAddr[8],
610                                 db->networkAddr[9],
611                                 db->networkAddr[10]);
612 #endif
613                         j++;
614
615                         db = db->next_hash;
616                 }
617         }
618 #endif
619
620         _exit_critical_bh(&priv->br_ext_lock, &irqL);
621 }
622
623
624
625
626 /*
627  *      NAT2.5 interface
628  */
629
630 void nat25_db_cleanup(_adapter *priv)
631 {
632         int i;
633         _irqL irqL;
634         _enter_critical_bh(&priv->br_ext_lock, &irqL);
635         
636         for(i=0; i<NAT25_HASH_SIZE; i++)
637         {
638                 struct nat25_network_db_entry *f;
639                 f = priv->nethash[i];
640                 while (f != NULL) {
641                         struct nat25_network_db_entry *g;
642
643                         g = f->next_hash;
644                         if(priv->scdb_entry == f)
645                         {
646                                 memset(priv->scdb_mac, 0, ETH_ALEN);
647                                 memset(priv->scdb_ip, 0, 4);
648                                 priv->scdb_entry = NULL;
649                         }
650                         __network_hash_unlink(f);
651                         rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
652
653                         f = g;
654                 }
655         }
656
657         _exit_critical_bh(&priv->br_ext_lock, &irqL);
658 }
659
660
661 void nat25_db_expire(_adapter *priv)
662 {
663         int i;
664         _irqL irqL;
665         _enter_critical_bh(&priv->br_ext_lock, &irqL);
666         
667         //if(!priv->ethBrExtInfo.nat25_disable)
668         {
669                 for (i=0; i<NAT25_HASH_SIZE; i++)
670                 {
671                         struct nat25_network_db_entry *f;
672                         f = priv->nethash[i];
673
674                         while (f != NULL)
675                         {
676                                 struct nat25_network_db_entry *g;
677                                 g = f->next_hash;
678
679                                 if(__nat25_has_expired(priv, f))
680                                 {
681                                         if(atomic_dec_and_test(&f->use_count))
682                                         {
683 #ifdef BR_EXT_DEBUG
684 #ifdef CL_IPV6_PASS
685                                                 panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
686                                                                 "%02x%02x%02x%02x%02x%02x\n",
687                                                         i,
688                                                         f->macAddr[0],
689                                                         f->macAddr[1],
690                                                         f->macAddr[2],
691                                                         f->macAddr[3],
692                                                         f->macAddr[4],
693                                                         f->macAddr[5],
694                                                         f->networkAddr[0],
695                                                         f->networkAddr[1],
696                                                         f->networkAddr[2],
697                                                         f->networkAddr[3],
698                                                         f->networkAddr[4],
699                                                         f->networkAddr[5],
700                                                         f->networkAddr[6],
701                                                         f->networkAddr[7],
702                                                         f->networkAddr[8],
703                                                         f->networkAddr[9],
704                                                         f->networkAddr[10],
705                                                         f->networkAddr[11],
706                                                         f->networkAddr[12],
707                                                         f->networkAddr[13],
708                                                         f->networkAddr[14],
709                                                         f->networkAddr[15],
710                                                         f->networkAddr[16]);
711 #else
712
713                                                 panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
714                                                         i,
715                                                         f->macAddr[0],
716                                                         f->macAddr[1],
717                                                         f->macAddr[2],
718                                                         f->macAddr[3],
719                                                         f->macAddr[4],
720                                                         f->macAddr[5],
721                                                         f->networkAddr[0],
722                                                         f->networkAddr[1],
723                                                         f->networkAddr[2],
724                                                         f->networkAddr[3],
725                                                         f->networkAddr[4],
726                                                         f->networkAddr[5],
727                                                         f->networkAddr[6],
728                                                         f->networkAddr[7],
729                                                         f->networkAddr[8],
730                                                         f->networkAddr[9],
731                                                         f->networkAddr[10]);
732 #endif
733 #endif
734                                                 if(priv->scdb_entry == f)
735                                                 {
736                                                         memset(priv->scdb_mac, 0, ETH_ALEN);
737                                                         memset(priv->scdb_ip, 0, 4);
738                                                         priv->scdb_entry = NULL;
739                                                 }
740                                                 __network_hash_unlink(f);
741                                                 rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
742                                         }
743                                 }
744
745                                 f = g;
746                         }
747                 }
748         }
749
750         _exit_critical_bh(&priv->br_ext_lock, &irqL);
751 }
752
753
754 #ifdef SUPPORT_TX_MCAST2UNI
755 static int checkIPMcAndReplace(_adapter *priv, struct sk_buff *skb, unsigned int *dst_ip)
756 {
757         struct stat_info        *pstat;
758         struct list_head        *phead, *plist;
759         int i;
760
761         phead = &priv->asoc_list;
762         plist = phead->next;
763
764         while (plist != phead) {
765                 pstat = list_entry(plist, struct stat_info, asoc_list);
766                 plist = plist->next;
767
768                 if (pstat->ipmc_num == 0)
769                         continue;
770
771                 for (i=0; i<MAX_IP_MC_ENTRY; i++) {
772                         if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip)+1, 3)) {
773                                 memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN);
774                                 return 1;
775                         }
776                 }
777         }
778         return 0;
779 }
780 #endif
781
782 int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method)
783 {
784         unsigned short protocol;
785         unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
786
787         if(skb == NULL)
788                 return -1;
789
790         if((method <= NAT25_MIN) || (method >= NAT25_MAX))
791                 return -1;
792
793         protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
794
795         /*---------------------------------------------------*/
796         /*                 Handle IP frame                   */
797         /*---------------------------------------------------*/
798         if(protocol == __constant_htons(ETH_P_IP))
799         {
800                 struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN);
801
802                 if(((unsigned char*)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len))
803                 {
804                         DEBUG_WARN("NAT25: malformed IP packet !\n");
805                         return -1;
806                 }
807
808                 switch(method)
809                 {
810                         case NAT25_CHECK:
811                                 return -1;
812
813                         case NAT25_INSERT:
814                                 {
815                                         //some muticast with source IP is all zero, maybe other case is illegal
816                                         //in class A, B, C, host address is all zero or all one is illegal
817                                         if (iph->saddr == 0)
818                                                 return 0;
819                                         DBG_871X("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
820                                         __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr);
821                                         //record source IP address and , source mac address into db
822                                         __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
823
824                                         __nat25_db_print(priv);
825                                 }
826                                 return 0;
827
828                         case NAT25_LOOKUP:
829                                 {
830                                         DBG_871X("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
831 #ifdef SUPPORT_TX_MCAST2UNI
832                                         if (priv->pshare->rf_ft_var.mc2u_disable ||
833                                                         ((((OPMODE & (WIFI_STATION_STATE|WIFI_ASOC_STATE))
834                                                         == (WIFI_STATION_STATE|WIFI_ASOC_STATE)) &&
835                                                         !checkIPMcAndReplace(priv, skb, &iph->daddr)) ||
836                                                         (OPMODE & WIFI_ADHOC_STATE)))
837 #endif
838                                         {
839                                                 __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr);
840
841                                                 if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
842                                                         if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
843                                                                 // L2 is unicast but L3 is broadcast, make L2 bacome broadcast
844                                                                 DBG_871X("NAT25: Set DA as boardcast\n");
845                                                                 memset(skb->data, 0xff, ETH_ALEN);
846                                                         }
847                                                         else {
848                                                                 // forward unknow IP packet to upper TCP/IP
849                                                                 DBG_871X("NAT25: Replace DA with BR's MAC\n");
850                                                                 if ( (*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0 ) {
851                                                                         void netdev_br_init(struct net_device *netdev);
852                                                                         printk("Re-init netdev_br_init() due to br_mac==0!\n");
853                                                                         netdev_br_init(priv->pnetdev);
854                                                                 }
855                                                                 memcpy(skb->data, priv->br_mac, ETH_ALEN);
856                                                         }
857                                                 }
858                                         }
859                                 }
860                                 return 0;
861
862                         default:
863                                 return -1;
864                 }
865         }
866
867         /*---------------------------------------------------*/
868         /*                 Handle ARP frame                  */
869         /*---------------------------------------------------*/
870         else if(protocol == __constant_htons(ETH_P_ARP))
871         {
872                 struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
873                 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
874                 unsigned int *sender, *target;
875
876                 if(arp->ar_pro != __constant_htons(ETH_P_IP))
877                 {
878                         DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro));
879                         return -1;
880                 }
881
882                 switch(method)
883                 {
884                         case NAT25_CHECK:
885                                 return 0;       // skb_copy for all ARP frame
886
887                         case NAT25_INSERT:
888                                 {
889                                         DBG_871X("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
890                                                 arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
891
892                                         // change to ARP sender mac address to wlan STA address
893                                         memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
894
895                                         arp_ptr += arp->ar_hln;
896                                         sender = (unsigned int *)arp_ptr;
897
898                                         __nat25_generate_ipv4_network_addr(networkAddr, sender);
899
900                                         __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
901
902                                         __nat25_db_print(priv);
903                                 }
904                                 return 0;
905
906                         case NAT25_LOOKUP:
907                                 {
908                                         DBG_871X("NAT25: Lookup ARP\n");
909
910                                         arp_ptr += arp->ar_hln;
911                                         sender = (unsigned int *)arp_ptr;
912                                         arp_ptr += (arp->ar_hln + arp->ar_pln);
913                                         target = (unsigned int *)arp_ptr;
914
915                                         __nat25_generate_ipv4_network_addr(networkAddr, target);
916
917                                         __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
918
919                                         // change to ARP target mac address to Lookup result
920                                         arp_ptr = (unsigned char *)(arp + 1);
921                                         arp_ptr += (arp->ar_hln + arp->ar_pln);
922                                         memcpy(arp_ptr, skb->data, ETH_ALEN);
923                                 }
924                                 return 0;
925
926                         default:
927                                 return -1;
928                 }
929         }
930
931         /*---------------------------------------------------*/
932         /*         Handle IPX and Apple Talk frame           */
933         /*---------------------------------------------------*/
934         else if((protocol == __constant_htons(ETH_P_IPX)) || 
935                 (protocol == __constant_htons(ETH_P_ATALK)) ||
936                 (protocol == __constant_htons(ETH_P_AARP)))
937         {
938                 unsigned char ipx_header[2] = {0xFF, 0xFF};
939                 struct ipxhdr   *ipx = NULL;
940                 struct elapaarp *ea = NULL;
941                 struct ddpehdr  *ddp = NULL;
942                 unsigned char *framePtr = skb->data + ETH_HLEN;
943
944                 if(protocol == __constant_htons(ETH_P_IPX))
945                 {
946                         DBG_871X("NAT25: Protocol=IPX (Ethernet II)\n");
947                         ipx = (struct ipxhdr *)framePtr;
948                 }
949                 else //if(protocol <= __constant_htons(ETH_FRAME_LEN))
950                 {
951                         if(!memcmp(ipx_header, framePtr, 2))
952                         {
953                                 DBG_871X("NAT25: Protocol=IPX (Ethernet 802.3)\n");
954                                 ipx = (struct ipxhdr *)framePtr;
955                         }
956                         else
957                         {
958                                 unsigned char ipx_8022_type =  0xE0;
959                                 unsigned char snap_8022_type = 0xAA;
960
961                                 if(*framePtr == snap_8022_type)
962                                 {
963                                         unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37};             // IPX SNAP ID
964                                         unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; // Apple Talk AARP SNAP ID
965                                         unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B};  // Apple Talk DDP SNAP ID
966
967                                         framePtr += 3;  // eliminate the 802.2 header
968
969                                         if(!memcmp(ipx_snap_id, framePtr, 5))
970                                         {
971                                                 framePtr += 5;  // eliminate the SNAP header
972
973                                                 DBG_871X("NAT25: Protocol=IPX (Ethernet SNAP)\n");
974                                                 ipx = (struct ipxhdr *)framePtr;
975                                         }
976                                         else if(!memcmp(aarp_snap_id, framePtr, 5))
977                                         {
978                                                 framePtr += 5;  // eliminate the SNAP header
979
980                                                 ea = (struct elapaarp *)framePtr;
981                                         }
982                                         else if(!memcmp(ddp_snap_id, framePtr, 5))
983                                         {
984                                                 framePtr += 5;  // eliminate the SNAP header
985
986                                                 ddp = (struct ddpehdr *)framePtr;
987                                         }
988                                         else
989                                         {
990                                                 DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
991                                                         framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
992                                                 return -1;
993                                         }
994                                 }
995                                 else if(*framePtr == ipx_8022_type)
996                                 {
997                                         framePtr += 3;  // eliminate the 802.2 header
998
999                                         if(!memcmp(ipx_header, framePtr, 2))
1000                                         {
1001                                                 DBG_871X("NAT25: Protocol=IPX (Ethernet 802.2)\n");
1002                                                 ipx = (struct ipxhdr *)framePtr;
1003                                         }
1004                                         else
1005                                                 return -1;
1006                                 }
1007                         }
1008                 }
1009
1010                 /*   IPX   */
1011                 if(ipx != NULL)
1012                 {
1013                         switch(method)
1014                         {
1015                                 case NAT25_CHECK:
1016                                         if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
1017                                         {
1018                                                 DBG_871X("NAT25: Check IPX skb_copy\n");
1019                                                 return 0;
1020                                         }
1021                                         return -1;
1022
1023                                 case NAT25_INSERT:
1024                                         {
1025                                                 DBG_871X("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
1026                                                         ipx->ipx_dest.net,
1027                                                         ipx->ipx_dest.node[0],
1028                                                         ipx->ipx_dest.node[1],
1029                                                         ipx->ipx_dest.node[2],
1030                                                         ipx->ipx_dest.node[3],
1031                                                         ipx->ipx_dest.node[4],
1032                                                         ipx->ipx_dest.node[5],
1033                                                         ipx->ipx_dest.sock,
1034                                                         ipx->ipx_source.net,
1035                                                         ipx->ipx_source.node[0],
1036                                                         ipx->ipx_source.node[1],
1037                                                         ipx->ipx_source.node[2],
1038                                                         ipx->ipx_source.node[3],
1039                                                         ipx->ipx_source.node[4],
1040                                                         ipx->ipx_source.node[5],
1041                                                         ipx->ipx_source.sock);
1042
1043                                                 if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
1044                                                 {
1045                                                         DBG_871X("NAT25: Use IPX Net, and Socket as network addr\n");
1046
1047                                                         __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
1048
1049                                                         // change IPX source node addr to wlan STA address
1050                                                         memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
1051                                                 }
1052                                                 else
1053                                                 {
1054                                                         __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
1055                                                 }
1056
1057                                                 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1058
1059                                                 __nat25_db_print(priv);
1060                                         }
1061                                         return 0;
1062
1063                                 case NAT25_LOOKUP:
1064                                         {
1065                                                 if(!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN))
1066                                                 {
1067                                                         DBG_871X("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
1068
1069                                                         __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
1070
1071                                                         __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1072
1073                                                         // replace IPX destination node addr with Lookup destination MAC addr
1074                                                         memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
1075                                                 }
1076                                                 else
1077                                                 {
1078                                                         __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
1079
1080                                                         __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1081                                                 }
1082                                         }
1083                                         return 0;
1084
1085                                 default:
1086                                         return -1;
1087                         }
1088                 }
1089
1090                 /*   AARP   */
1091                 else if(ea != NULL)
1092                 {
1093                         /* Sanity check fields. */
1094                         if(ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN)
1095                         {
1096                                 DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
1097                                 return -1;
1098                         }
1099
1100                         switch(method)
1101                         {
1102                                 case NAT25_CHECK:
1103                                         return 0;
1104
1105                                 case NAT25_INSERT:
1106                                         {
1107                                                 // change to AARP source mac address to wlan STA address
1108                                                 memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
1109
1110                                                 DBG_871X("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
1111                                                         ea->pa_src_net,
1112                                                         ea->pa_src_node,
1113                                                         ea->pa_dst_net,
1114                                                         ea->pa_dst_node);
1115
1116                                                 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
1117
1118                                                 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1119
1120                                                 __nat25_db_print(priv);
1121                                         }
1122                                         return 0;
1123
1124                                 case NAT25_LOOKUP:
1125                                         {
1126                                                 DBG_871X("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
1127                                                         ea->pa_src_net,
1128                                                         ea->pa_src_node,
1129                                                         ea->pa_dst_net,
1130                                                         ea->pa_dst_node);
1131
1132                                                 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
1133
1134                                                 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1135
1136                                                 // change to AARP destination mac address to Lookup result
1137                                                 memcpy(ea->hw_dst, skb->data, ETH_ALEN);
1138                                         }
1139                                         return 0;
1140
1141                                 default:
1142                                         return -1;
1143                         }
1144                 }
1145
1146                 /*   DDP   */
1147                 else if(ddp != NULL)
1148                 {
1149                         switch(method)
1150                         {
1151                                 case NAT25_CHECK:
1152                                         return -1;
1153
1154                                 case NAT25_INSERT:
1155                                         {
1156                                                 DBG_871X("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
1157                                                         ddp->deh_snet,
1158                                                         ddp->deh_snode,
1159                                                         ddp->deh_dnet,
1160                                                         ddp->deh_dnode);
1161
1162                                                 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
1163
1164                                                 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1165
1166                                                 __nat25_db_print(priv);
1167                                         }
1168                                         return 0;
1169
1170                                 case NAT25_LOOKUP:
1171                                         {
1172                                                 DBG_871X("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
1173                                                         ddp->deh_snet,
1174                                                         ddp->deh_snode,
1175                                                         ddp->deh_dnet,
1176                                                         ddp->deh_dnode);
1177
1178                                                 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
1179
1180                                                 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1181                                         }
1182                                         return 0;
1183
1184                                 default:
1185                                         return -1;
1186                         }
1187                 }
1188
1189                 return -1;
1190         }
1191
1192         /*---------------------------------------------------*/
1193         /*                Handle PPPoE frame                 */
1194         /*---------------------------------------------------*/
1195         else if((protocol == __constant_htons(ETH_P_PPP_DISC)) ||
1196                 (protocol == __constant_htons(ETH_P_PPP_SES)))
1197         {
1198                 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
1199                 unsigned short *pMagic;
1200
1201                 switch(method)
1202                 {
1203                         case NAT25_CHECK:
1204                                 if (ph->sid == 0)
1205                                         return 0;
1206                                 return 1;
1207
1208                         case NAT25_INSERT:
1209                                 if(ph->sid == 0)        // Discovery phase according to tag
1210                                 {
1211                                         if(ph->code == PADI_CODE || ph->code == PADR_CODE)
1212                                         {
1213                                                 if (priv->ethBrExtInfo.addPPPoETag) {
1214                                                         struct pppoe_tag *tag, *pOldTag;
1215                                                         unsigned char tag_buf[40];
1216                                                         int old_tag_len=0;
1217
1218                                                         tag = (struct pppoe_tag *)tag_buf;
1219                                                         pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
1220                                                         if (pOldTag) { // if SID existed, copy old value and delete it
1221                                                                 old_tag_len = ntohs(pOldTag->tag_len);
1222                                                                 if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
1223                                                                         DEBUG_ERR("SID tag length too long!\n");
1224                                                                         return -1;
1225                                                                 }
1226
1227                                                                 memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
1228                                                                         pOldTag->tag_data, old_tag_len);
1229
1230                                                                 if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
1231                                                                         DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
1232                                                                         return -1;
1233                                                                 }
1234                                                                 ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
1235                                                         }
1236
1237                                                         tag->tag_type = PTT_RELAY_SID;
1238                                                         tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
1239
1240                                                         // insert the magic_code+client mac in relay tag
1241                                                         pMagic = (unsigned short *)tag->tag_data;
1242                                                         *pMagic = htons(MAGIC_CODE);
1243                                                         memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
1244
1245                                                         //Add relay tag
1246                                                         if(__nat25_add_pppoe_tag(skb, tag) < 0)
1247                                                                 return -1;
1248
1249                                                         DBG_871X("NAT25: Insert PPPoE, forward %s packet\n",
1250                                                                                         (ph->code == PADI_CODE ? "PADI" : "PADR"));
1251                                                 }
1252                                                 else { // not add relay tag
1253                                                         if (priv->pppoe_connection_in_progress &&
1254                                                                         memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))  {
1255                                                                 DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
1256                                                                 return -2;
1257                                                         }
1258
1259                                                         if (priv->pppoe_connection_in_progress == 0)
1260                                                                 memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
1261
1262                                                         priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
1263                                                 }
1264                                         }
1265                                         else
1266                                                 return -1;
1267                                 }
1268                                 else    // session phase
1269                                 {
1270                                                 DBG_871X("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
1271
1272                                                 __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
1273
1274                                                 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1275
1276                                                 __nat25_db_print(priv);
1277
1278                                                 if (!priv->ethBrExtInfo.addPPPoETag &&
1279                                                                 priv->pppoe_connection_in_progress &&
1280                                                                         !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
1281                                                         priv->pppoe_connection_in_progress = 0;
1282                                 }
1283                                 return 0;
1284
1285                         case NAT25_LOOKUP:
1286                                 if(ph->code == PADO_CODE || ph->code == PADS_CODE)
1287                                 {
1288                                         if (priv->ethBrExtInfo.addPPPoETag) {
1289                                                 struct pppoe_tag *tag;
1290                                                 unsigned char *ptr;
1291                                                 unsigned short tagType, tagLen;
1292                                                 int offset=0;
1293
1294                                                 if((ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID))) == 0) {
1295                                                         DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
1296                                                         return -1;
1297                                                 }
1298
1299                                                 tag = (struct pppoe_tag *)ptr;
1300                                                 tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
1301                                                 tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
1302
1303                                                 if((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) {
1304                                                         DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
1305                                                         return -1;
1306                                                 }
1307
1308                                                 pMagic = (unsigned short *)tag->tag_data;
1309                                                 if (ntohs(*pMagic) != MAGIC_CODE) {
1310                                                         DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
1311                                                                 (ph->code == PADO_CODE ? "PADO" : "PADS"));
1312                                                         return -1;
1313                                                 }
1314
1315                                                 memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN);
1316
1317                                                 if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN)
1318                                                         offset = TAG_HDR_LEN;
1319
1320                                                 if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) {
1321                                                         DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
1322                                                         return -1;
1323                                                 }
1324                                                 ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset));
1325                                                 if (offset > 0)
1326                                                         tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN);
1327
1328                                                 DBG_871X("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
1329                                                         (ph->code == PADO_CODE ? "PADO" : "PADS"),      skb->dev->name);
1330                                         }
1331                                         else { // not add relay tag
1332                                                 if (!priv->pppoe_connection_in_progress) {
1333                                                         DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
1334                                                         return -1;
1335                                                 }
1336                                                 memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
1337                                                 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
1338                                         }
1339                                 }
1340                                 else {
1341                                         if(ph->sid != 0)
1342                                         {
1343                                                 DBG_871X("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
1344                                                 __nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid));
1345
1346                                                 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1347
1348                                                 __nat25_db_print(priv);
1349                                         }
1350                                         else
1351                                                 return -1;
1352
1353                                 }
1354                                 return 0;
1355
1356                         default:
1357                                 return -1;
1358                 }
1359         }
1360
1361         /*---------------------------------------------------*/
1362         /*                 Handle EAP frame                  */
1363         /*---------------------------------------------------*/
1364         else if(protocol == __constant_htons(0x888e))
1365         {
1366                 switch(method)
1367                 {
1368                         case NAT25_CHECK:
1369                                 return -1;
1370
1371                         case NAT25_INSERT:
1372                                 return 0;
1373
1374                         case NAT25_LOOKUP:
1375                                 return 0;
1376
1377                         default:
1378                                 return -1;
1379                 }
1380         }
1381
1382         /*---------------------------------------------------*/
1383         /*         Handle C-Media proprietary frame          */
1384         /*---------------------------------------------------*/
1385         else if((protocol == __constant_htons(0xe2ae)) ||
1386                 (protocol == __constant_htons(0xe2af)))
1387         {
1388                 switch(method)
1389                 {
1390                         case NAT25_CHECK:
1391                                 return -1;
1392
1393                         case NAT25_INSERT:
1394                                 return 0;
1395
1396                         case NAT25_LOOKUP:
1397                                 return 0;
1398
1399                         default:
1400                                 return -1;
1401                 }
1402         }
1403
1404         /*---------------------------------------------------*/
1405         /*         Handle IPV6 frame                                                              */
1406         /*---------------------------------------------------*/
1407 #ifdef CL_IPV6_PASS
1408         else if(protocol == __constant_htons(ETH_P_IPV6))
1409         {
1410                 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
1411
1412                 if (sizeof(*iph) >= (skb->len - ETH_HLEN))
1413                 {
1414                         DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
1415                         return -1;
1416                 }
1417
1418                 switch(method)
1419                 {
1420                         case NAT25_CHECK:
1421                                 if (skb->data[0] & 1)
1422                                         return 0;                               
1423                                 return -1;
1424
1425                         case NAT25_INSERT:
1426                                 {
1427                                         DBG_871X("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1428                                                                         " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", 
1429                                                 iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3],
1430                                                 iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7],
1431                                                 iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3],
1432                                                 iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]);
1433
1434                                         if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
1435                                                 __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
1436                                                 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1437                                                 __nat25_db_print(priv);
1438
1439                                                 if (iph->nexthdr == IPPROTO_ICMPV6 && 
1440                                                                 skb->len > (ETH_HLEN +  sizeof(*iph) + 4)) {
1441                                                         if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), 
1442                                                                 skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {                                                   
1443                                                                 struct icmp6hdr  *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
1444                                                                 hdr->icmp6_cksum = 0;
1445                                                                 hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
1446                                                                                                 iph->payload_len,
1447                                                                                                 IPPROTO_ICMPV6,
1448                                                                                                 csum_partial((__u8 *)hdr, iph->payload_len, 0));
1449                                                         }
1450                                                 }                                               
1451                                         }
1452                                 }
1453                                 return 0;
1454
1455                         case NAT25_LOOKUP:
1456                                 DBG_871X("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1457                                                                 " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", 
1458                                                 iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3],
1459                                                 iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7],
1460                                                 iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3],
1461                                                 iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]);
1462                         
1463
1464                                 __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr);
1465                                 if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
1466 #ifdef SUPPORT_RX_UNI2MCAST                                                     
1467                                         if (iph->daddr.s6_addr[0] == 0xff)
1468                                                 convert_ipv6_mac_to_mc(skb);    
1469 #endif                                                                                  
1470                                 }
1471                                 return 0;
1472
1473                         default:
1474                                 return -1;
1475                 }
1476         }
1477 #endif  // CL_IPV6_PASS
1478
1479         return -1;
1480 }
1481
1482
1483 int nat25_handle_frame(_adapter *priv, struct sk_buff *skb)
1484 {
1485 #ifdef BR_EXT_DEBUG
1486         if((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1)))
1487         {
1488                 panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n",
1489                         skb->data[0],
1490                         skb->data[1],
1491                         skb->data[2],
1492                         skb->data[3],
1493                         skb->data[4],
1494                         skb->data[5],
1495                         skb->data[6],
1496                         skb->data[7],
1497                         skb->data[8],
1498                         skb->data[9],
1499                         skb->data[10],
1500                         skb->data[11]);
1501         }
1502 #endif
1503
1504         if(!(skb->data[0] & 1))
1505         {
1506                 int is_vlan_tag=0, i, retval=0;
1507                 unsigned short vlan_hdr=0;
1508
1509                 if (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_8021Q)) {
1510                         is_vlan_tag = 1;
1511                         vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2));
1512                         for (i=0; i<6; i++)
1513                                 *((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2));
1514                         skb_pull(skb, 4);
1515                 }
1516
1517                 if (!priv->ethBrExtInfo.nat25_disable)
1518                 {
1519                         _irqL irqL;
1520                         _enter_critical_bh(&priv->br_ext_lock, &irqL);
1521                         /*
1522                          *      This function look up the destination network address from
1523                          *      the NAT2.5 database. Return value = -1 means that the
1524                          *      corresponding network protocol is NOT support.
1525                          */
1526                         if (!priv->ethBrExtInfo.nat25sc_disable &&
1527                                 (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) &&
1528                                 !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) {
1529                                 memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
1530                                 
1531                                 _exit_critical_bh(&priv->br_ext_lock, &irqL);
1532                         }
1533                         else {
1534                                 _exit_critical_bh(&priv->br_ext_lock, &irqL);
1535                                 
1536                                 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1537                         }
1538                 }
1539                 else {
1540                         if (((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) &&
1541                                         !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) ||
1542                                 ((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_ARP)) &&
1543                                         !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) {
1544                                 // for traffic to upper TCP/IP
1545                                 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1546                         }
1547                 }
1548
1549                 if (is_vlan_tag) {
1550                         skb_push(skb, 4);
1551                         for (i=0; i<6; i++)
1552                                 *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
1553                         *((unsigned short *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q);
1554                         *((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr;
1555                 }
1556
1557                 if(retval == -1) {
1558                         //DEBUG_ERR("NAT25: Lookup fail!\n");
1559                         return -1;
1560                 }
1561         }
1562
1563         return 0;
1564 }
1565
1566 #if 0
1567 void mac_clone(_adapter *priv, unsigned char *addr)
1568 {
1569         struct sockaddr sa;
1570
1571         memcpy(sa.sa_data, addr, ETH_ALEN);
1572         DBG_871X("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n",
1573                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
1574         rtl8192cd_set_hwaddr(priv->dev, &sa);
1575 }
1576
1577
1578 int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb)
1579 {
1580         if(priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed)
1581         {
1582                 if(!(skb->data[ETH_ALEN] & 1))  //// check any other particular MAC add
1583                 {
1584                         if(memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) &&
1585                                 ((priv->dev->br_port) &&
1586                                  memcmp(skb->data+ETH_ALEN, priv->br_mac, ETH_ALEN)))
1587                         {
1588                                 mac_clone(priv, skb->data+ETH_ALEN);
1589                                 priv->macclone_completed = 1;
1590                         }
1591                 }
1592         }
1593
1594         return 0;
1595 }
1596 #endif // 0
1597
1598 #define SERVER_PORT                     67
1599 #define CLIENT_PORT                     68
1600 #define DHCP_MAGIC                      0x63825363
1601 #define BROADCAST_FLAG          0x8000
1602
1603 struct dhcpMessage {
1604         u_int8_t op;
1605         u_int8_t htype;
1606         u_int8_t hlen;
1607         u_int8_t hops;
1608         u_int32_t xid;
1609         u_int16_t secs;
1610         u_int16_t flags;
1611         u_int32_t ciaddr;
1612         u_int32_t yiaddr;
1613         u_int32_t siaddr;
1614         u_int32_t giaddr;
1615         u_int8_t chaddr[16];
1616         u_int8_t sname[64];
1617         u_int8_t file[128];
1618         u_int32_t cookie;
1619         u_int8_t options[308]; /* 312 - cookie */
1620 };
1621
1622 void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb)
1623 {
1624         if(skb == NULL)
1625                 return;
1626
1627         if(!priv->ethBrExtInfo.dhcp_bcst_disable)
1628         {
1629                 unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
1630
1631                 if(protocol == __constant_htons(ETH_P_IP)) // IP
1632                 {
1633                         struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN);
1634
1635                         if(iph->protocol == IPPROTO_UDP) // UDP
1636                         {
1637                                 struct udphdr *udph = (struct udphdr *)((SIZE_PTR)iph + (iph->ihl << 2));
1638
1639                                 if((udph->source == __constant_htons(CLIENT_PORT))
1640                                         && (udph->dest == __constant_htons(SERVER_PORT))) // DHCP request
1641                                 {
1642                                         struct dhcpMessage *dhcph =
1643                                                 (struct dhcpMessage *)((SIZE_PTR)udph + sizeof(struct udphdr));
1644
1645                                         if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) // match magic word
1646                                         {
1647                                                 if(!(dhcph->flags & htons(BROADCAST_FLAG))) // if not broadcast
1648                                                 {
1649                                                         register int sum = 0;
1650
1651                                                         DBG_871X("DHCP: change flag of DHCP request to broadcast.\n");
1652                                                         // or BROADCAST flag
1653                                                         dhcph->flags |= htons(BROADCAST_FLAG);
1654                                                         // recalculate checksum
1655                                                         sum = ~(udph->check) & 0xffff;
1656                                                         sum += dhcph->flags;
1657                                                         while(sum >> 16)
1658                                                                 sum = (sum & 0xffff) + (sum >> 16);
1659                                                         udph->check = ~sum;
1660                                                 }
1661                                         }
1662                                 }
1663                         }
1664                 }
1665         }
1666 }
1667
1668
1669 void *scdb_findEntry(_adapter *priv, unsigned char *macAddr,
1670                                 unsigned char *ipAddr)
1671 {
1672         unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
1673         struct nat25_network_db_entry *db;
1674         int hash;
1675         //_irqL irqL;
1676         //_enter_critical_bh(&priv->br_ext_lock, &irqL);
1677
1678         __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
1679         hash = __nat25_network_hash(networkAddr);
1680         db = priv->nethash[hash];
1681         while (db != NULL)
1682         {
1683                 if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
1684                         //_exit_critical_bh(&priv->br_ext_lock, &irqL);
1685                         return (void *)db;
1686                 }
1687
1688                 db = db->next_hash;
1689         }
1690
1691         //_exit_critical_bh(&priv->br_ext_lock, &irqL);
1692         return NULL;
1693 }
1694
1695 #endif  // CONFIG_BR_EXT
1696