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