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