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 = be16_to_cpu(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 __be32 *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 __be32 *ipxNetAddr, __be16 *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 __be16 *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, __be16 *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,
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 spin_lock_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 spin_lock_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;
356 spin_lock_bh(&priv->br_ext_lock);
358 db = priv->nethash[__nat25_network_hash(networkAddr)];
360 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
361 if (!__nat25_has_expired(priv, db)) {
362 /* replace the destination mac address */
363 memcpy(skb->data, db->macAddr, ETH_ALEN);
364 atomic_inc(&db->use_count);
366 DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
367 "%02x%02x%02x%02x%02x%02x\n",
390 db->networkAddr[16]);
392 spin_unlock_bh(&priv->br_ext_lock);
397 spin_unlock_bh(&priv->br_ext_lock);
401 static void __nat25_db_network_insert(struct adapter *priv,
402 unsigned char *macAddr, unsigned char *networkAddr)
404 struct nat25_network_db_entry *db;
407 spin_lock_bh(&priv->br_ext_lock);
408 hash = __nat25_network_hash(networkAddr);
409 db = priv->nethash[hash];
411 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
412 memcpy(db->macAddr, macAddr, ETH_ALEN);
413 db->ageing_timer = jiffies;
414 spin_unlock_bh(&priv->br_ext_lock);
419 db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
421 spin_unlock_bh(&priv->br_ext_lock);
424 memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
425 memcpy(db->macAddr, macAddr, ETH_ALEN);
426 atomic_set(&db->use_count, 1);
427 db->ageing_timer = jiffies;
429 __network_hash_link(priv, db, hash);
431 spin_unlock_bh(&priv->br_ext_lock);
434 static void __nat25_db_print(struct adapter *priv)
442 void nat25_db_cleanup(struct adapter *priv)
445 spin_lock_bh(&priv->br_ext_lock);
447 for (i = 0; i < NAT25_HASH_SIZE; i++) {
448 struct nat25_network_db_entry *f;
449 f = priv->nethash[i];
451 struct nat25_network_db_entry *g;
454 if (priv->scdb_entry == f) {
455 memset(priv->scdb_mac, 0, ETH_ALEN);
456 memset(priv->scdb_ip, 0, 4);
457 priv->scdb_entry = NULL;
459 __network_hash_unlink(f);
464 spin_unlock_bh(&priv->br_ext_lock);
467 void nat25_db_expire(struct adapter *priv)
470 spin_lock_bh(&priv->br_ext_lock);
472 for (i = 0; i < NAT25_HASH_SIZE; i++) {
473 struct nat25_network_db_entry *f;
474 f = priv->nethash[i];
477 struct nat25_network_db_entry *g;
480 if (__nat25_has_expired(priv, f)) {
481 if (atomic_dec_and_test(&f->use_count)) {
482 if (priv->scdb_entry == f) {
483 memset(priv->scdb_mac, 0, ETH_ALEN);
484 memset(priv->scdb_ip, 0, 4);
485 priv->scdb_entry = NULL;
487 __network_hash_unlink(f);
494 spin_unlock_bh(&priv->br_ext_lock);
497 int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
499 unsigned short protocol;
500 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
506 if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
509 protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
511 /*---------------------------------------------------*/
512 /* Handle IP frame */
513 /*---------------------------------------------------*/
514 if (protocol == ETH_P_IP) {
515 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
517 if (((unsigned char *)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) {
518 DEBUG_WARN("NAT25: malformed IP packet !\n");
526 /* some multicast with source IP is all zero, maybe other case is illegal */
527 /* in class A, B, C, host address is all zero or all one is illegal */
530 tmp = be32_to_cpu(iph->saddr);
531 DEBUG_INFO("NAT25: Insert IP, SA =%08x, DA =%08x\n", tmp, iph->daddr);
532 __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
533 /* record source IP address and , source mac address into db */
534 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
536 __nat25_db_print(priv);
539 DEBUG_INFO("NAT25: Lookup IP, SA =%08x, DA =%08x\n", iph->saddr, iph->daddr);
540 tmp = be32_to_cpu(iph->daddr);
541 __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
543 if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
544 if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
545 /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
546 DEBUG_INFO("NAT25: Set DA as boardcast\n");
547 memset(skb->data, 0xff, ETH_ALEN);
549 /* forward unknow IP packet to upper TCP/IP */
550 DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
551 if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0) {
552 printk("Re-init netdev_br_init() due to br_mac == 0!\n");
553 netdev_br_init(priv->pnetdev);
555 memcpy(skb->data, priv->br_mac, ETH_ALEN);
562 } else if (protocol == ETH_P_ARP) {
563 /*---------------------------------------------------*/
564 /* Handle ARP frame */
565 /*---------------------------------------------------*/
566 struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
567 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
568 unsigned int *sender, *target;
570 if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
571 DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", be16_to_cpu(arp->ar_pro));
577 return 0; /* skb_copy for all ARP frame */
579 DEBUG_INFO("NAT25: Insert ARP, MAC =%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
580 arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
582 /* change to ARP sender mac address to wlan STA address */
583 memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
584 arp_ptr += arp->ar_hln;
585 sender = (unsigned int *)arp_ptr;
586 __nat25_generate_ipv4_network_addr(networkAddr, sender);
587 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
588 __nat25_db_print(priv);
591 DEBUG_INFO("NAT25: Lookup ARP\n");
593 arp_ptr += arp->ar_hln;
594 sender = (unsigned int *)arp_ptr;
595 arp_ptr += (arp->ar_hln + arp->ar_pln);
596 target = (unsigned int *)arp_ptr;
597 __nat25_generate_ipv4_network_addr(networkAddr, target);
598 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
599 /* change to ARP target mac address to Lookup result */
600 arp_ptr = (unsigned char *)(arp + 1);
601 arp_ptr += (arp->ar_hln + arp->ar_pln);
602 memcpy(arp_ptr, skb->data, ETH_ALEN);
607 } else if ((protocol == ETH_P_IPX) ||
608 (protocol <= ETH_FRAME_LEN)) {
609 /*---------------------------------------------------*/
610 /* Handle IPX and Apple Talk frame */
611 /*---------------------------------------------------*/
612 unsigned char ipx_header[2] = {0xFF, 0xFF};
613 struct ipxhdr *ipx = NULL;
614 struct elapaarp *ea = NULL;
615 struct ddpehdr *ddp = NULL;
616 unsigned char *framePtr = skb->data + ETH_HLEN;
618 if (protocol == ETH_P_IPX) {
619 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet II)\n");
620 ipx = (struct ipxhdr *)framePtr;
621 } else if (protocol <= ETH_FRAME_LEN) {
622 if (!memcmp(ipx_header, framePtr, 2)) {
623 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.3)\n");
624 ipx = (struct ipxhdr *)framePtr;
626 unsigned char ipx_8022_type = 0xE0;
627 unsigned char snap_8022_type = 0xAA;
629 if (*framePtr == snap_8022_type) {
630 unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */
631 unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */
632 unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */
634 framePtr += 3; /* eliminate the 802.2 header */
636 if (!memcmp(ipx_snap_id, framePtr, 5)) {
637 framePtr += 5; /* eliminate the SNAP header */
639 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet SNAP)\n");
640 ipx = (struct ipxhdr *)framePtr;
641 } else if (!memcmp(aarp_snap_id, framePtr, 5)) {
642 framePtr += 5; /* eliminate the SNAP header */
644 ea = (struct elapaarp *)framePtr;
645 } else if (!memcmp(ddp_snap_id, framePtr, 5)) {
646 framePtr += 5; /* eliminate the SNAP header */
648 ddp = (struct ddpehdr *)framePtr;
650 DEBUG_WARN("NAT25: Protocol = Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
651 framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
654 } else if (*framePtr == ipx_8022_type) {
655 framePtr += 3; /* eliminate the 802.2 header */
657 if (!memcmp(ipx_header, framePtr, 2)) {
658 DEBUG_INFO("NAT25: Protocol = IPX (Ethernet 802.2)\n");
659 ipx = (struct ipxhdr *)framePtr;
675 if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
676 DEBUG_INFO("NAT25: Check IPX skb_copy\n");
679 DEBUG_INFO("NAT25: Insert IPX, Dest =%08x,%02x%02x%02x%02x%02x%02x,%04x Source =%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
681 ipx->ipx_dest.node[0],
682 ipx->ipx_dest.node[1],
683 ipx->ipx_dest.node[2],
684 ipx->ipx_dest.node[3],
685 ipx->ipx_dest.node[4],
686 ipx->ipx_dest.node[5],
689 ipx->ipx_source.node[0],
690 ipx->ipx_source.node[1],
691 ipx->ipx_source.node[2],
692 ipx->ipx_source.node[3],
693 ipx->ipx_source.node[4],
694 ipx->ipx_source.node[5],
695 ipx->ipx_source.sock);
697 if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
698 DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
700 __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
702 /* change IPX source node addr to wlan STA address */
703 memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
705 __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
707 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
708 __nat25_db_print(priv);
711 if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) {
712 DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
714 __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
716 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
718 /* replace IPX destination node addr with Lookup destination MAC addr */
719 memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
721 __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
723 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
729 } else if (ea != NULL) {
730 /* Sanity check fields. */
731 if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
732 DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
740 /* change to AARP source mac address to wlan STA address */
741 memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
743 DEBUG_INFO("NAT25: Insert AARP, Source =%d,%d Destination =%d,%d\n",
749 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
751 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
753 __nat25_db_print(priv);
756 DEBUG_INFO("NAT25: Lookup AARP, Source =%d,%d Destination =%d,%d\n",
762 __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
764 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
766 /* change to AARP destination mac address to Lookup result */
767 memcpy(ea->hw_dst, skb->data, ETH_ALEN);
772 } else if (ddp != NULL) {
777 DEBUG_INFO("NAT25: Insert DDP, Source =%d,%d Destination =%d,%d\n",
783 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
785 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
787 __nat25_db_print(priv);
790 DEBUG_INFO("NAT25: Lookup DDP, Source =%d,%d Destination =%d,%d\n",
795 __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
796 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
804 } else if ((protocol == ETH_P_PPP_DISC) ||
805 (protocol == ETH_P_PPP_SES)) {
806 /*---------------------------------------------------*/
807 /* Handle PPPoE frame */
808 /*---------------------------------------------------*/
809 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
818 if (ph->sid == 0) { /* Discovery phase according to tag */
819 if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
820 if (priv->ethBrExtInfo.addPPPoETag) {
821 struct pppoe_tag *tag, *pOldTag;
822 unsigned char tag_buf[40];
825 tag = (struct pppoe_tag *)tag_buf;
826 pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
827 if (pOldTag) { /* if SID existed, copy old value and delete it */
828 old_tag_len = ntohs(pOldTag->tag_len);
829 if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
830 DEBUG_ERR("SID tag length too long!\n");
834 memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
835 pOldTag->tag_data, old_tag_len);
837 if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
838 DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
841 ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
844 tag->tag_type = PTT_RELAY_SID;
845 tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
847 /* insert the magic_code+client mac in relay tag */
848 pMagic = (__be16 *)tag->tag_data;
849 *pMagic = htons(MAGIC_CODE);
850 memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
853 if (__nat25_add_pppoe_tag(skb, tag) < 0)
856 DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
857 (ph->code == PADI_CODE ? "PADI" : "PADR"));
858 } else { /* not add relay tag */
859 if (priv->pppoe_connection_in_progress &&
860 memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) {
861 DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
865 if (priv->pppoe_connection_in_progress == 0)
866 memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
868 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
873 } else { /* session phase */
874 DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
876 __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
878 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
880 __nat25_db_print(priv);
882 if (!priv->ethBrExtInfo.addPPPoETag &&
883 priv->pppoe_connection_in_progress &&
884 !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
885 priv->pppoe_connection_in_progress = 0;
889 if (ph->code == PADO_CODE || ph->code == PADS_CODE) {
890 if (priv->ethBrExtInfo.addPPPoETag) {
891 struct pppoe_tag *tag;
893 unsigned short tagType, tagLen;
896 ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
898 DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
902 tag = (struct pppoe_tag *)ptr;
903 tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
904 tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
906 if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) {
907 DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
911 pMagic = (__be16 *)tag->tag_data;
912 if (ntohs(*pMagic) != MAGIC_CODE) {
913 DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
914 (ph->code == PADO_CODE ? "PADO" : "PADS"));
918 memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN);
920 if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN)
921 offset = TAG_HDR_LEN;
923 if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) {
924 DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
927 ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset));
929 tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN);
931 DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
932 (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name);
933 } else { /* not add relay tag */
934 if (!priv->pppoe_connection_in_progress) {
935 DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
938 memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
939 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
943 DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
944 __nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid));
945 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
946 __nat25_db_print(priv);
955 } else if (protocol == 0x888e) {
956 /*---------------------------------------------------*/
957 /* Handle EAP frame */
958 /*---------------------------------------------------*/
969 } else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) {
970 /*---------------------------------------------------*/
971 /* Handle C-Media proprietary frame */
972 /*---------------------------------------------------*/
983 } else if (protocol == ETH_P_IPV6) {
984 /*------------------------------------------------*/
985 /* Handle IPV6 frame */
986 /*------------------------------------------------*/
987 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
989 if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
990 DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
996 if (skb->data[0] & 1)
1000 DEBUG_INFO("NAT25: Insert IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1001 " DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1002 iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
1003 iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
1004 iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
1005 iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
1007 if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
1008 __nat25_generate_ipv6_network_addr(networkAddr, (__be32 *)&iph->saddr);
1009 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
1010 __nat25_db_print(priv);
1012 if (iph->nexthdr == IPPROTO_ICMPV6 &&
1013 skb->len > (ETH_HLEN + sizeof(*iph) + 4)) {
1014 if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
1015 skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
1016 struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
1017 hdr->icmp6_cksum = 0;
1018 hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
1019 be16_to_cpu(iph->payload_len),
1021 csum_partial((__u8 *)hdr,
1022 be16_to_cpu(iph->payload_len), 0));
1028 DEBUG_INFO("NAT25: Lookup IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x, DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1029 iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
1030 iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
1031 iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
1032 iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
1033 __nat25_generate_ipv6_network_addr(networkAddr, (__be32 *)&iph->daddr);
1034 __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
1043 int nat25_handle_frame(struct adapter *priv, struct sk_buff *skb)
1045 if (!(skb->data[0] & 1)) {
1046 int is_vlan_tag = 0, i, retval = 0;
1047 unsigned short vlan_hdr = 0;
1048 unsigned short protocol;
1050 protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
1051 if (protocol == ETH_P_8021Q) {
1053 vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2));
1054 for (i = 0; i < 6; i++)
1055 *((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2));
1059 if (!priv->ethBrExtInfo.nat25_disable) {
1060 spin_lock_bh(&priv->br_ext_lock);
1062 * This function look up the destination network address from
1063 * the NAT2.5 database. Return value = -1 means that the
1064 * corresponding network protocol is NOT support.
1066 if (!priv->ethBrExtInfo.nat25sc_disable &&
1067 (be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
1068 !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) {
1069 memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
1071 spin_unlock_bh(&priv->br_ext_lock);
1073 spin_unlock_bh(&priv->br_ext_lock);
1075 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1078 if (((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) &&
1079 !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) ||
1080 ((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_ARP) &&
1081 !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) {
1082 /* for traffic to upper TCP/IP */
1083 retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
1089 for (i = 0; i < 6; i++)
1090 *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
1091 *((__be16 *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q);
1092 *((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr;
1096 /* DEBUG_ERR("NAT25: Lookup fail!\n"); */
1104 #define SERVER_PORT 67
1105 #define CLIENT_PORT 68
1106 #define DHCP_MAGIC 0x63825363
1107 #define BROADCAST_FLAG 0x8000
1109 struct dhcpMessage {
1121 u_int8_t chaddr[16];
1125 u_int8_t options[308]; /* 312 - cookie */
1128 void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb)
1133 if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
1134 __be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN));
1136 if (protocol == __constant_htons(ETH_P_IP)) { /* IP */
1137 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
1139 if (iph->protocol == IPPROTO_UDP) { /* UDP */
1140 struct udphdr *udph = (struct udphdr *)((size_t)iph + (iph->ihl << 2));
1142 if ((udph->source == __constant_htons(CLIENT_PORT)) &&
1143 (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */
1144 struct dhcpMessage *dhcph =
1145 (struct dhcpMessage *)((size_t)udph + sizeof(struct udphdr));
1146 u32 cookie = be32_to_cpu((__be32)dhcph->cookie);
1148 if (cookie == DHCP_MAGIC) { /* match magic word */
1149 if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
1150 /* if not broadcast */
1151 register int sum = 0;
1153 DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
1154 /* or BROADCAST flag */
1155 dhcph->flags |= htons(BROADCAST_FLAG);
1156 /* recalculate checksum */
1157 sum = ~(udph->check) & 0xffff;
1158 sum += be16_to_cpu(dhcph->flags);
1160 sum = (sum & 0xffff) + (sum >> 16);
1171 void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
1172 unsigned char *ipAddr)
1174 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
1175 struct nat25_network_db_entry *db;
1178 __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
1179 hash = __nat25_network_hash(networkAddr);
1180 db = priv->nethash[hash];
1181 while (db != NULL) {
1182 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))