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