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