1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
20 #define _RTW_BR_EXT_C_
22 #include <linux/if_arp.h>
25 #include <linux/atalk.h>
26 #include <linux/udp.h>
27 #include <linux/if_pppox.h>
29 #include <drv_types.h>
30 #include "rtw_br_ext.h"
31 #include <usb_osintf.h>
32 #include <recv_osdep.h>
34 #ifndef csum_ipv6_magic
35 #include <net/ip6_checksum.h>
38 #include <linux/ipv6.h>
39 #include <linux/icmpv6.h>
40 #include <net/ndisc.h>
41 #include <net/checksum.h>
46 #define NAT25_APPLE 04
47 #define NAT25_PPPOE 05
49 #define RTL_RELAY_TAG_LEN (ETH_ALEN)
52 #define MAGIC_CODE 0x8186
53 #define MAGIC_CODE_LEN 2
54 #define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */
56 /*-----------------------------------------------------------------
57 How database records network address:
58 0 1 2 3 4 5 6 7 8 9 10
59 |----|----|----|----|----|----|----|----|----|----|----|
60 IPv4 |type| | IP addr |
61 IPX |type| Net addr | Node addr |
62 IPX |type| Net addr |Sckt addr|
63 Apple |type| Network |node|
64 PPPoE |type| SID | AC MAC |
65 -----------------------------------------------------------------*/
68 /* Find a tag in pppoe frame and return the pointer */
69 static inline unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
71 unsigned char *cur_ptr, *start_ptr;
72 unsigned short tagLen, tagType;
74 start_ptr = cur_ptr = (unsigned char *)ph->tag;
75 while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
76 /* prevent un-alignment access */
77 tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
78 tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
81 cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
87 static inline int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
89 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
92 data_len = tag->tag_len + TAG_HDR_LEN;
93 if (skb_tailroom(skb) < data_len) {
94 _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
98 skb_put(skb, data_len);
99 /* have a room for new tag */
100 memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
101 ph->length = htons(ntohs(ph->length) + data_len);
102 memcpy((unsigned char *)ph->tag, tag, data_len);
106 static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
109 unsigned long end, tail;
111 if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
114 tail = (unsigned long)skb_tail_pointer(skb);
115 end = (unsigned long)src+len;
119 tail_len = (int)(tail-end);
121 memmove(src, src+len, tail_len);
123 skb_trim(skb, skb->len-len);
127 static inline unsigned long __nat25_timeout(struct adapter *priv)
129 unsigned long timeout;
131 timeout = jiffies - NAT25_AGEING_TIME*HZ;
137 static inline int __nat25_has_expired(struct adapter *priv,
138 struct nat25_network_db_entry *fdb)
140 if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
147 static inline void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
148 unsigned int *ipAddr)
150 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
152 networkAddr[0] = NAT25_IPV4;
153 memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
157 static inline void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
158 unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr)
160 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
162 networkAddr[0] = NAT25_IPX;
163 memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
164 memcpy(networkAddr+5, ipxNodeAddr, 6);
168 static inline void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
169 unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr)
171 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
173 networkAddr[0] = NAT25_IPX;
174 memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
175 memcpy(networkAddr+5, (unsigned char *)ipxSocketAddr, 2);
179 static inline void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
180 unsigned short *network, unsigned char *node)
182 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
184 networkAddr[0] = NAT25_APPLE;
185 memcpy(networkAddr+1, (unsigned char *)network, 2);
186 networkAddr[3] = *node;
189 static inline void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
190 unsigned char *ac_mac, unsigned short *sid)
192 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
194 networkAddr[0] = NAT25_PPPOE;
195 memcpy(networkAddr+1, (unsigned char *)sid, 2);
196 memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
199 static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
200 unsigned int *ipAddr)
202 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
204 networkAddr[0] = NAT25_IPV6;
205 memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
208 static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
211 if (*data == tag && *(data+1) == len8b && len >= len8b*8)
214 len -= (*(data+1))*8;
215 data += (*(data+1))*8;
220 static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
222 struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
225 if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
227 mac = scan_tlv(&data[8], len-8, 1, 1);
229 _DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
230 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
231 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
232 memcpy(mac, replace_mac, 6);
236 } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
238 mac = scan_tlv(&data[16], len-16, 1, 1);
240 _DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
241 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
242 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
243 memcpy(mac, replace_mac, 6);
247 } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
249 mac = scan_tlv(&data[24], len-24, 1, 1);
251 _DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
252 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
253 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
254 memcpy(mac, replace_mac, 6);
258 } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
260 mac = scan_tlv(&data[24], len-24, 2, 1);
262 _DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
263 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
264 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
265 memcpy(mac, replace_mac, 6);
269 } else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
271 mac = scan_tlv(&data[40], len-40, 2, 1);
273 _DEBUG_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
274 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
275 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
276 memcpy(mac, replace_mac, 6);
284 static inline int __nat25_network_hash(unsigned char *networkAddr)
286 if (networkAddr[0] == NAT25_IPV4) {
289 x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
291 return x & (NAT25_HASH_SIZE - 1);
292 } else if (networkAddr[0] == NAT25_IPX) {
295 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
296 networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
298 return x & (NAT25_HASH_SIZE - 1);
299 } else if (networkAddr[0] == NAT25_APPLE) {
302 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
304 return x & (NAT25_HASH_SIZE - 1);
305 } else if (networkAddr[0] == NAT25_PPPOE) {
308 x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
310 return x & (NAT25_HASH_SIZE - 1);
311 } else if (networkAddr[0] == NAT25_IPV6) {
314 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
315 networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
316 networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
319 return x & (NAT25_HASH_SIZE - 1);
324 for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
327 return x & (NAT25_HASH_SIZE - 1);
331 static inline void __network_hash_link(struct adapter *priv,
332 struct nat25_network_db_entry *ent, int hash)
334 /* Caller must _enter_critical_bh already! */
335 ent->next_hash = priv->nethash[hash];
336 if (ent->next_hash != NULL)
337 ent->next_hash->pprev_hash = &ent->next_hash;
338 priv->nethash[hash] = ent;
339 ent->pprev_hash = &priv->nethash[hash];
342 static inline void __network_hash_unlink(struct nat25_network_db_entry *ent)
344 /* Caller must _enter_critical_bh already! */
345 *(ent->pprev_hash) = ent->next_hash;
346 if (ent->next_hash != NULL)
347 ent->next_hash->pprev_hash = ent->pprev_hash;
348 ent->next_hash = NULL;
349 ent->pprev_hash = NULL;
352 static int __nat25_db_network_lookup_and_replace(struct adapter *priv,
353 struct sk_buff *skb, unsigned char *networkAddr)
355 struct nat25_network_db_entry *db;
357 _enter_critical_bh(&priv->br_ext_lock, &irqL);
359 db = priv->nethash[__nat25_network_hash(networkAddr)];
361 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
362 if (!__nat25_has_expired(priv, db)) {
363 /* replace the destination mac address */
364 memcpy(skb->data, db->macAddr, ETH_ALEN);
365 atomic_inc(&db->use_count);
367 DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
368 "%02x%02x%02x%02x%02x%02x\n",
391 db->networkAddr[16]);
393 _exit_critical_bh(&priv->br_ext_lock, &irqL);
398 _exit_critical_bh(&priv->br_ext_lock, &irqL);
402 static void __nat25_db_network_insert(struct adapter *priv,
403 unsigned char *macAddr, unsigned char *networkAddr)
405 struct nat25_network_db_entry *db;
409 _enter_critical_bh(&priv->br_ext_lock, &irqL);
410 hash = __nat25_network_hash(networkAddr);
411 db = priv->nethash[hash];
413 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
414 memcpy(db->macAddr, macAddr, ETH_ALEN);
415 db->ageing_timer = jiffies;
416 _exit_critical_bh(&priv->br_ext_lock, &irqL);
421 db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
423 _exit_critical_bh(&priv->br_ext_lock, &irqL);
426 memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
427 memcpy(db->macAddr, macAddr, ETH_ALEN);
428 atomic_set(&db->use_count, 1);
429 db->ageing_timer = jiffies;
431 __network_hash_link(priv, db, hash);
433 _exit_critical_bh(&priv->br_ext_lock, &irqL);
436 static void __nat25_db_print(struct adapter *priv)
444 void nat25_db_cleanup(struct adapter *priv)
448 _enter_critical_bh(&priv->br_ext_lock, &irqL);
450 for (i = 0; i < NAT25_HASH_SIZE; i++) {
451 struct nat25_network_db_entry *f;
452 f = priv->nethash[i];
454 struct nat25_network_db_entry *g;
457 if (priv->scdb_entry == f) {
458 memset(priv->scdb_mac, 0, ETH_ALEN);
459 memset(priv->scdb_ip, 0, 4);
460 priv->scdb_entry = NULL;
462 __network_hash_unlink(f);
467 _exit_critical_bh(&priv->br_ext_lock, &irqL);
470 void nat25_db_expire(struct adapter *priv)
474 _enter_critical_bh(&priv->br_ext_lock, &irqL);
476 for (i = 0; i < NAT25_HASH_SIZE; i++) {
477 struct nat25_network_db_entry *f;
478 f = priv->nethash[i];
481 struct nat25_network_db_entry *g;
484 if (__nat25_has_expired(priv, f)) {
485 if (atomic_dec_and_test(&f->use_count)) {
486 if (priv->scdb_entry == f) {
487 memset(priv->scdb_mac, 0, ETH_ALEN);
488 memset(priv->scdb_ip, 0, 4);
489 priv->scdb_entry = NULL;
491 __network_hash_unlink(f);
498 _exit_critical_bh(&priv->br_ext_lock, &irqL);
501 int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
503 unsigned short protocol;
504 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
510 if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
513 protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
515 /*---------------------------------------------------*/
516 /* Handle IP frame */
517 /*---------------------------------------------------*/
518 if (protocol == ETH_P_IP) {
519 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
521 if (((unsigned char *)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) {
522 DEBUG_WARN("NAT25: malformed IP packet !\n");
530 /* some multicast with source IP is all zero, maybe other case is illegal */
531 /* in class A, B, C, host address is all zero or all one is illegal */
534 tmp = be32_to_cpu(iph->saddr);
535 DEBUG_INFO("NAT25: Insert IP, SA =%08x, DA =%08x\n", tmp, iph->daddr);
536 __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
537 /* record source IP address and , source mac address into db */
538 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
540 __nat25_db_print(priv);
543 DEBUG_INFO("NAT25: Lookup IP, SA =%08x, DA =%08x\n", iph->saddr, iph->daddr);
544 tmp = be32_to_cpu(iph->daddr);
545 __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
547 if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
548 if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
549 /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
550 DEBUG_INFO("NAT25: Set DA as boardcast\n");
551 memset(skb->data, 0xff, ETH_ALEN);
553 /* forward unknow IP packet to upper TCP/IP */
554 DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
555 if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
556 printk("Re-init netdev_br_init() due to br_mac == 0!\n");
557 netdev_br_init(priv->pnetdev);
559 memcpy(skb->data, priv->br_mac, ETH_ALEN);
566 } else if (protocol == ETH_P_ARP) {
567 /*---------------------------------------------------*/
568 /* Handle ARP frame */
569 /*---------------------------------------------------*/
570 struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
571 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
572 unsigned int *sender, *target;
574 if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
575 DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", be16_to_cpu(arp->ar_pro));
581 return 0; /* skb_copy for all ARP frame */
583 DEBUG_INFO("NAT25: Insert ARP, MAC =%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
584 arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
586 /* change to ARP sender mac address to wlan STA address */
587 memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
588 arp_ptr += arp->ar_hln;
589 sender = (unsigned int *)arp_ptr;
590 __nat25_generate_ipv4_network_addr(networkAddr, sender);
591 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
592 __nat25_db_print(priv);
595 DEBUG_INFO("NAT25: Lookup ARP\n");
597 arp_ptr += arp->ar_hln;
598 sender = (unsigned int *)arp_ptr;
599 arp_ptr += (arp->ar_hln + arp->ar_pln);
600 target = (unsigned int *)arp_ptr;
601 __nat25_generate_ipv4_network_addr(networkAddr, target);
602 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
603 /* change to ARP target mac address to Lookup result */
604 arp_ptr = (unsigned char *)(arp + 1);
605 arp_ptr += (arp->ar_hln + arp->ar_pln);
606 memcpy(arp_ptr, skb->data, ETH_ALEN);
611 } else if ((protocol == ETH_P_IPX) ||
612 (protocol <= ETH_FRAME_LEN)) {
613 /*---------------------------------------------------*/
614 /* Handle IPX and Apple Talk frame */
615 /*---------------------------------------------------*/
616 unsigned char ipx_header[2] = {0xFF, 0xFF};
617 struct ipxhdr *ipx = NULL;
618 struct elapaarp *ea = NULL;
619 struct ddpehdr *ddp = NULL;
620 unsigned char *framePtr = skb->data + ETH_HLEN;
622 if (protocol == ETH_P_IPX) {
623 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet II)\n");
624 ipx = (struct ipxhdr *)framePtr;
625 } else if (protocol <= ETH_FRAME_LEN) {
626 if (!memcmp(ipx_header, framePtr, 2)) {
627 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.3)\n");
628 ipx = (struct ipxhdr *)framePtr;
630 unsigned char ipx_8022_type = 0xE0;
631 unsigned char snap_8022_type = 0xAA;
633 if (*framePtr == snap_8022_type) {
634 unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */
635 unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */
636 unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */
638 framePtr += 3; /* eliminate the 802.2 header */
640 if (!memcmp(ipx_snap_id, framePtr, 5)) {
641 framePtr += 5; /* eliminate the SNAP header */
643 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet SNAP)\n");
644 ipx = (struct ipxhdr *)framePtr;
645 } else if (!memcmp(aarp_snap_id, framePtr, 5)) {
646 framePtr += 5; /* eliminate the SNAP header */
648 ea = (struct elapaarp *)framePtr;
649 } else if (!memcmp(ddp_snap_id, framePtr, 5)) {
650 framePtr += 5; /* eliminate the SNAP header */
652 ddp = (struct ddpehdr *)framePtr;
654 DEBUG_WARN("NAT25: Protocol = Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
655 framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
658 } else if (*framePtr == ipx_8022_type) {
659 framePtr += 3; /* eliminate the 802.2 header */
661 if (!memcmp(ipx_header, framePtr, 2)) {
662 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.2)\n");
663 ipx = (struct ipxhdr *)framePtr;
679 if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
680 DEBUG_INFO("NAT25: Check IPX skb_copy\n");
683 DEBUG_INFO("NAT25: Insert IPX, Dest =%08x,%02x%02x%02x%02x%02x%02x,%04x Source =%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
685 ipx->ipx_dest.node[0],
686 ipx->ipx_dest.node[1],
687 ipx->ipx_dest.node[2],
688 ipx->ipx_dest.node[3],
689 ipx->ipx_dest.node[4],
690 ipx->ipx_dest.node[5],
693 ipx->ipx_source.node[0],
694 ipx->ipx_source.node[1],
695 ipx->ipx_source.node[2],
696 ipx->ipx_source.node[3],
697 ipx->ipx_source.node[4],
698 ipx->ipx_source.node[5],
699 ipx->ipx_source.sock);
701 if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
702 DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
704 __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
706 /* change IPX source node addr to wlan STA address */
707 memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
709 __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
711 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
712 __nat25_db_print(priv);
715 if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) {
716 DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
718 __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
720 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
722 /* replace IPX destination node addr with Lookup destination MAC addr */
723 memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
725 __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
727 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
733 } else if (ea != NULL) {
734 /* Sanity check fields. */
735 if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
736 DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
744 /* change to AARP source mac address to wlan STA address */
745 memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
747 DEBUG_INFO("NAT25: Insert AARP, Source =%d,%d Destination =%d,%d\n",
753 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
755 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
757 __nat25_db_print(priv);
760 DEBUG_INFO("NAT25: Lookup AARP, Source =%d,%d Destination =%d,%d\n",
766 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
768 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
770 /* change to AARP destination mac address to Lookup result */
771 memcpy(ea->hw_dst, skb->data, ETH_ALEN);
776 } else if (ddp != NULL) {
781 DEBUG_INFO("NAT25: Insert DDP, Source =%d,%d Destination =%d,%d\n",
787 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
789 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
791 __nat25_db_print(priv);
794 DEBUG_INFO("NAT25: Lookup DDP, Source =%d,%d Destination =%d,%d\n",
799 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
800 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
808 } else if ((protocol == ETH_P_PPP_DISC) ||
809 (protocol == ETH_P_PPP_SES)) {
810 /*---------------------------------------------------*/
811 /* Handle PPPoE frame */
812 /*---------------------------------------------------*/
813 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
814 unsigned short *pMagic;
822 if (ph->sid == 0) { /* Discovery phase according to tag */
823 if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
824 if (priv->ethBrExtInfo.addPPPoETag) {
825 struct pppoe_tag *tag, *pOldTag;
826 unsigned char tag_buf[40];
829 tag = (struct pppoe_tag *)tag_buf;
830 pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
831 if (pOldTag) { /* if SID existed, copy old value and delete it */
832 old_tag_len = ntohs(pOldTag->tag_len);
833 if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
834 DEBUG_ERR("SID tag length too long!\n");
838 memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
839 pOldTag->tag_data, old_tag_len);
841 if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
842 DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
845 ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
848 tag->tag_type = PTT_RELAY_SID;
849 tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
851 /* insert the magic_code+client mac in relay tag */
852 pMagic = (unsigned short *)tag->tag_data;
853 *pMagic = htons(MAGIC_CODE);
854 memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
857 if (__nat25_add_pppoe_tag(skb, tag) < 0)
860 DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
861 (ph->code == PADI_CODE ? "PADI" : "PADR"));
862 } else { /* not add relay tag */
863 if (priv->pppoe_connection_in_progress &&
864 memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) {
865 DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
869 if (priv->pppoe_connection_in_progress == 0)
870 memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
872 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
877 } else { /* session phase */
878 DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
880 __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
882 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
884 __nat25_db_print(priv);
886 if (!priv->ethBrExtInfo.addPPPoETag &&
887 priv->pppoe_connection_in_progress &&
888 !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
889 priv->pppoe_connection_in_progress = 0;
893 if (ph->code == PADO_CODE || ph->code == PADS_CODE) {
894 if (priv->ethBrExtInfo.addPPPoETag) {
895 struct pppoe_tag *tag;
897 unsigned short tagType, tagLen;
900 ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
902 DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
906 tag = (struct pppoe_tag *)ptr;
907 tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
908 tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
910 if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) {
911 DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
915 pMagic = (unsigned short *)tag->tag_data;
916 if (ntohs(*pMagic) != MAGIC_CODE) {
917 DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
918 (ph->code == PADO_CODE ? "PADO" : "PADS"));
922 memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN);
924 if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN)
925 offset = TAG_HDR_LEN;
927 if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) {
928 DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
931 ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset));
933 tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN);
935 DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
936 (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name);
937 } else { /* not add relay tag */
938 if (!priv->pppoe_connection_in_progress) {
939 DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
942 memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
943 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
947 DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
948 __nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid));
949 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
950 __nat25_db_print(priv);
959 } else if (protocol == 0x888e) {
960 /*---------------------------------------------------*/
961 /* Handle EAP frame */
962 /*---------------------------------------------------*/
973 } else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) {
974 /*---------------------------------------------------*/
975 /* Handle C-Media proprietary frame */
976 /*---------------------------------------------------*/
987 } else if (protocol == ETH_P_IPV6) {
988 /*------------------------------------------------*/
989 /* Handle IPV6 frame */
990 /*------------------------------------------------*/
991 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
993 if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
994 DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
1000 if (skb->data[0] & 1)
1004 DEBUG_INFO("NAT25: Insert IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1005 " DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1006 iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
1007 iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
1008 iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
1009 iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
1011 if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
1012 __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
1013 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1014 __nat25_db_print(priv);
1016 if (iph->nexthdr == IPPROTO_ICMPV6 &&
1017 skb->len > (ETH_HLEN + sizeof(*iph) + 4)) {
1018 if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
1019 skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
1020 struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
1021 hdr->icmp6_cksum = 0;
1022 hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
1025 csum_partial((__u8 *)hdr, iph->payload_len, 0));
1031 DEBUG_INFO("NAT25: Lookup IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x, DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1032 iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
1033 iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
1034 iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
1035 iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
1036 __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr);
1037 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1046 int nat25_handle_frame(struct adapter *priv, struct sk_buff *skb)
1048 if (!(skb->data[0] & 1)) {
1049 int is_vlan_tag = 0, i, retval = 0;
1050 unsigned short vlan_hdr = 0;
1051 unsigned short protocol;
1053 protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
1054 if (protocol == ETH_P_8021Q) {
1056 vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2));
1057 for (i = 0; i < 6; i++)
1058 *((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2));
1062 if (!priv->ethBrExtInfo.nat25_disable) {
1064 _enter_critical_bh(&priv->br_ext_lock, &irqL);
1066 * This function look up the destination network address from
1067 * the NAT2.5 database. Return value = -1 means that the
1068 * corresponding network protocol is NOT support.
1070 if (!priv->ethBrExtInfo.nat25sc_disable &&
1071 (be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
1072 !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) {
1073 memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
1075 _exit_critical_bh(&priv->br_ext_lock, &irqL);
1077 _exit_critical_bh(&priv->br_ext_lock, &irqL);
1079 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1082 if (((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
1083 !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) ||
1084 ((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_ARP) &&
1085 !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) {
1086 /* for traffic to upper TCP/IP */
1087 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1093 for (i = 0; i < 6; i++)
1094 *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
1095 *((__be16 *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q);
1096 *((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr;
1100 /* DEBUG_ERR("NAT25: Lookup fail!\n"); */
1108 #define SERVER_PORT 67
1109 #define CLIENT_PORT 68
1110 #define DHCP_MAGIC 0x63825363
1111 #define BROADCAST_FLAG 0x8000
1113 struct dhcpMessage {
1125 u_int8_t chaddr[16];
1129 u_int8_t options[308]; /* 312 - cookie */
1132 void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb)
1137 if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
1138 __be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN));
1140 if (protocol == __constant_htons(ETH_P_IP)) { /* IP */
1141 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
1143 if (iph->protocol == IPPROTO_UDP) { /* UDP */
1144 struct udphdr *udph = (struct udphdr *)((size_t)iph + (iph->ihl << 2));
1146 if ((udph->source == __constant_htons(CLIENT_PORT)) &&
1147 (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */
1148 struct dhcpMessage *dhcph =
1149 (struct dhcpMessage *)((size_t)udph + sizeof(struct udphdr));
1150 u32 cookie = be32_to_cpu((__be32)dhcph->cookie);
1152 if (cookie == DHCP_MAGIC) { /* match magic word */
1153 if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
1154 /* if not broadcast */
1155 register int sum = 0;
1157 DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
1158 /* or BROADCAST flag */
1159 dhcph->flags |= htons(BROADCAST_FLAG);
1160 /* recalculate checksum */
1161 sum = ~(udph->check) & 0xffff;
1162 sum += be16_to_cpu(dhcph->flags);
1164 sum = (sum & 0xffff) + (sum >> 16);
1175 void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
1176 unsigned char *ipAddr)
1178 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
1179 struct nat25_network_db_entry *db;
1181 /* unsigned long irqL; */
1182 /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
1184 __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
1185 hash = __nat25_network_hash(networkAddr);
1186 db = priv->nethash[hash];
1187 while (db != NULL) {
1188 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
1189 /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
1196 /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */