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