diff --git a/core/rtw_br_ext.c.orig b/core/rtw_br_ext.c.orig deleted file mode 100644 index 8e186c7..0000000 --- a/core/rtw_br_ext.c.orig +++ /dev/null @@ -1,1325 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2017 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - *****************************************************************************/ -#define _RTW_BR_EXT_C_ - -#ifdef __KERNEL__ - #include - #include - #include - #include - #include -#endif - -#if 1 /* rtw_wifi_driver */ - #include -#else /* rtw_wifi_driver */ - #include "./8192cd_cfg.h" - - #ifndef __KERNEL__ - #include "./sys-support.h" - #endif - - #include "./8192cd.h" - #include "./8192cd_headers.h" - #include "./8192cd_br_ext.h" - #include "./8192cd_debug.h" -#endif /* rtw_wifi_driver */ - -#ifdef CL_IPV6_PASS - #ifdef __KERNEL__ - #include - #include - #include - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) - #include - #else - #include - #endif - #endif -#endif - -#ifdef CONFIG_BR_EXT - -/* #define BR_EXT_DEBUG */ - -#define NAT25_IPV4 01 -#define NAT25_IPV6 02 -#define NAT25_IPX 03 -#define NAT25_APPLE 04 -#define NAT25_PPPOE 05 - -#define RTL_RELAY_TAG_LEN (ETH_ALEN) -#define TAG_HDR_LEN 4 - -#define MAGIC_CODE 0x8186 -#define MAGIC_CODE_LEN 2 -#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ - -/*----------------------------------------------------------------- - How database records network address: - 0 1 2 3 4 5 6 7 8 9 10 - |----|----|----|----|----|----|----|----|----|----|----| - IPv4 |type| | IP addr | - IPX |type| Net addr | Node addr | - IPX |type| Net addr |Sckt addr| - Apple |type| Network |node| - PPPoE |type| SID | AC MAC | ------------------------------------------------------------------*/ - - -/* Find a tag in pppoe frame and return the pointer */ -static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) -{ - unsigned char *cur_ptr, *start_ptr; - unsigned short tagLen, tagType; - - start_ptr = cur_ptr = (unsigned char *)ph->tag; - while ((cur_ptr - start_ptr) < ntohs(ph->length)) { - /* prevent un-alignment access */ - tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); - tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); - if (tagType == type) - return cur_ptr; - cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; - } - return 0; -} - - -static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) -{ - struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); - int data_len; - - data_len = tag->tag_len + TAG_HDR_LEN; - if (skb_tailroom(skb) < data_len) { - _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n"); - return -1; - } - - skb_put(skb, data_len); - /* have a room for new tag */ - memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); - ph->length = htons(ntohs(ph->length) + data_len); - memcpy((unsigned char *)ph->tag, tag, data_len); - return data_len; -} - -static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) -{ - int tail_len; - unsigned long end, tail; - - if ((src + len) > skb_tail_pointer(skb) || skb->len < len) - return -1; - - tail = (unsigned long)skb_tail_pointer(skb); - end = (unsigned long)src + len; - if (tail < end) - return -1; - - tail_len = (int)(tail - end); - if (tail_len > 0) - memmove(src, src + len, tail_len); - - skb_trim(skb, skb->len - len); - return 0; -} - -static __inline__ unsigned long __nat25_timeout(_adapter *priv) -{ - unsigned long timeout; - - timeout = jiffies - NAT25_AGEING_TIME * HZ; - - return timeout; -} - - -static __inline__ int __nat25_has_expired(_adapter *priv, - struct nat25_network_db_entry *fdb) -{ - if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv))) - return 1; - - return 0; -} - - -static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, - unsigned int *ipAddr) -{ - memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); - - networkAddr[0] = NAT25_IPV4; - memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); -} - -static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, - unsigned char *ac_mac, unsigned short *sid) -{ - memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); - - networkAddr[0] = NAT25_PPPOE; - memcpy(networkAddr + 1, (unsigned char *)sid, 2); - memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); -} - - -#ifdef CL_IPV6_PASS -static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, - unsigned int *ipAddr) -{ - memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); - - networkAddr[0] = NAT25_IPV6; - memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); -} - - -static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) -{ - while (len > 0) { - if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) - return data + 2; - - len -= (*(data + 1)) * 8; - data += (*(data + 1)) * 8; - } - return NULL; -} - - -static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) -{ - struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; - unsigned char *mac; - - if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { - if (len >= 8) { - mac = scan_tlv(&data[8], len - 8, 1, 1); - if (mac) { - RTW_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { - if (len >= 16) { - mac = scan_tlv(&data[16], len - 16, 1, 1); - if (mac) { - RTW_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { - if (len >= 24) { - mac = scan_tlv(&data[24], len - 24, 1, 1); - if (mac) { - RTW_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { - if (len >= 24) { - mac = scan_tlv(&data[24], len - 24, 2, 1); - if (mac) { - RTW_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); - memcpy(mac, replace_mac, 6); - return 1; - } - } - } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { - if (len >= 40) { - mac = scan_tlv(&data[40], len - 40, 2, 1); - if (mac) { - RTW_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); - memcpy(mac, replace_mac, 6); - return 1; - } - } - } - return 0; -} - -#ifdef SUPPORT_RX_UNI2MCAST -static void convert_ipv6_mac_to_mc(struct sk_buff *skb) -{ - struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); - unsigned char *dst_mac = skb->data; - - /* dst_mac[0] = 0xff; */ - /* dst_mac[1] = 0xff; */ - /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ - dst_mac[0] = 0x33; - dst_mac[1] = 0x33; - memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); -#if defined(__LINUX_2_6__) - /*modified by qinjunjie,warning:should not remove next line*/ - skb->pkt_type = PACKET_MULTICAST; -#endif -} -#endif /* CL_IPV6_PASS */ -#endif /* SUPPORT_RX_UNI2MCAST */ - - -static __inline__ int __nat25_network_hash(unsigned char *networkAddr) -{ - if (networkAddr[0] == NAT25_IPV4) { - unsigned long x; - - x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (networkAddr[0] == NAT25_IPX) { - unsigned long x; - - x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ - networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (networkAddr[0] == NAT25_APPLE) { - unsigned long x; - - x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; - - return x & (NAT25_HASH_SIZE - 1); - } else if (networkAddr[0] == NAT25_PPPOE) { - unsigned long x; - - x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; - - return x & (NAT25_HASH_SIZE - 1); - } -#ifdef CL_IPV6_PASS - else if (networkAddr[0] == NAT25_IPV6) { - unsigned long x; - - x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ - networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ - networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ - networkAddr[16]; - - return x & (NAT25_HASH_SIZE - 1); - } -#endif - else { - unsigned long x = 0; - int i; - - for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) - x ^= networkAddr[i]; - - return x & (NAT25_HASH_SIZE - 1); - } -} - - -static __inline__ void __network_hash_link(_adapter *priv, - struct nat25_network_db_entry *ent, int hash) -{ - /* Caller must _enter_critical_bh already! */ - /* _irqL irqL; */ - /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ - - ent->next_hash = priv->nethash[hash]; - if (ent->next_hash != NULL) - ent->next_hash->pprev_hash = &ent->next_hash; - priv->nethash[hash] = ent; - ent->pprev_hash = &priv->nethash[hash]; - - /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ -} - - -static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) -{ - /* Caller must _enter_critical_bh already! */ - /* _irqL irqL; */ - /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ - - *(ent->pprev_hash) = ent->next_hash; - if (ent->next_hash != NULL) - ent->next_hash->pprev_hash = ent->pprev_hash; - ent->next_hash = NULL; - ent->pprev_hash = NULL; - - /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ -} - - -static int __nat25_db_network_lookup_and_replace(_adapter *priv, - struct sk_buff *skb, unsigned char *networkAddr) -{ - struct nat25_network_db_entry *db; - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - - db = priv->nethash[__nat25_network_hash(networkAddr)]; - while (db != NULL) { - if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { - if (!__nat25_has_expired(priv, db)) { - /* replace the destination mac address */ - memcpy(skb->data, db->macAddr, ETH_ALEN); - atomic_inc(&db->use_count); - -#ifdef CL_IPV6_PASS - RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" - "%02x%02x%02x%02x%02x%02x\n", - db->macAddr[0], - db->macAddr[1], - db->macAddr[2], - db->macAddr[3], - db->macAddr[4], - db->macAddr[5], - db->networkAddr[0], - db->networkAddr[1], - db->networkAddr[2], - db->networkAddr[3], - db->networkAddr[4], - db->networkAddr[5], - db->networkAddr[6], - db->networkAddr[7], - db->networkAddr[8], - db->networkAddr[9], - db->networkAddr[10], - db->networkAddr[11], - db->networkAddr[12], - db->networkAddr[13], - db->networkAddr[14], - db->networkAddr[15], - db->networkAddr[16]); -#else - RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", - db->macAddr[0], - db->macAddr[1], - db->macAddr[2], - db->macAddr[3], - db->macAddr[4], - db->macAddr[5], - db->networkAddr[0], - db->networkAddr[1], - db->networkAddr[2], - db->networkAddr[3], - db->networkAddr[4], - db->networkAddr[5], - db->networkAddr[6], - db->networkAddr[7], - db->networkAddr[8], - db->networkAddr[9], - db->networkAddr[10]); -#endif - } - _exit_critical_bh(&priv->br_ext_lock, &irqL); - return 1; - } - - db = db->next_hash; - } - - _exit_critical_bh(&priv->br_ext_lock, &irqL); - return 0; -} - - -static void __nat25_db_network_insert(_adapter *priv, - unsigned char *macAddr, unsigned char *networkAddr) -{ - struct nat25_network_db_entry *db; - int hash; - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - - hash = __nat25_network_hash(networkAddr); - db = priv->nethash[hash]; - while (db != NULL) { - if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { - memcpy(db->macAddr, macAddr, ETH_ALEN); - db->ageing_timer = jiffies; - _exit_critical_bh(&priv->br_ext_lock, &irqL); - return; - } - - db = db->next_hash; - } - - db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db)); - if (db == NULL) { - _exit_critical_bh(&priv->br_ext_lock, &irqL); - return; - } - - memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); - memcpy(db->macAddr, macAddr, ETH_ALEN); - atomic_set(&db->use_count, 1); - db->ageing_timer = jiffies; - - __network_hash_link(priv, db, hash); - - _exit_critical_bh(&priv->br_ext_lock, &irqL); -} - - -static void __nat25_db_print(_adapter *priv) -{ - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - -#ifdef BR_EXT_DEBUG - static int counter = 0; - int i, j; - struct nat25_network_db_entry *db; - - counter++; - if ((counter % 16) != 0) - return; - - for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { - db = priv->nethash[i]; - - while (db != NULL) { -#ifdef CL_IPV6_PASS - 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" - "%02x%02x%02x%02x%02x%02x\n", - j, - i, - atomic_read(&db->use_count), - db->macAddr[0], - db->macAddr[1], - db->macAddr[2], - db->macAddr[3], - db->macAddr[4], - db->macAddr[5], - db->networkAddr[0], - db->networkAddr[1], - db->networkAddr[2], - db->networkAddr[3], - db->networkAddr[4], - db->networkAddr[5], - db->networkAddr[6], - db->networkAddr[7], - db->networkAddr[8], - db->networkAddr[9], - db->networkAddr[10], - db->networkAddr[11], - db->networkAddr[12], - db->networkAddr[13], - db->networkAddr[14], - db->networkAddr[15], - db->networkAddr[16]); -#else - 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", - j, - i, - atomic_read(&db->use_count), - db->macAddr[0], - db->macAddr[1], - db->macAddr[2], - db->macAddr[3], - db->macAddr[4], - db->macAddr[5], - db->networkAddr[0], - db->networkAddr[1], - db->networkAddr[2], - db->networkAddr[3], - db->networkAddr[4], - db->networkAddr[5], - db->networkAddr[6], - db->networkAddr[7], - db->networkAddr[8], - db->networkAddr[9], - db->networkAddr[10]); -#endif - j++; - - db = db->next_hash; - } - } -#endif - - _exit_critical_bh(&priv->br_ext_lock, &irqL); -} - - - - -/* - * NAT2.5 interface - */ - -void nat25_db_cleanup(_adapter *priv) -{ - int i; - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - - for (i = 0; i < NAT25_HASH_SIZE; i++) { - struct nat25_network_db_entry *f; - f = priv->nethash[i]; - while (f != NULL) { - struct nat25_network_db_entry *g; - - g = f->next_hash; - if (priv->scdb_entry == f) { - memset(priv->scdb_mac, 0, ETH_ALEN); - memset(priv->scdb_ip, 0, 4); - priv->scdb_entry = NULL; - } - __network_hash_unlink(f); - rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); - - f = g; - } - } - - _exit_critical_bh(&priv->br_ext_lock, &irqL); -} - - -void nat25_db_expire(_adapter *priv) -{ - int i; - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - - /* if(!priv->ethBrExtInfo.nat25_disable) */ - { - for (i = 0; i < NAT25_HASH_SIZE; i++) { - struct nat25_network_db_entry *f; - f = priv->nethash[i]; - - while (f != NULL) { - struct nat25_network_db_entry *g; - g = f->next_hash; - - if (__nat25_has_expired(priv, f)) { - if (atomic_dec_and_test(&f->use_count)) { -#ifdef BR_EXT_DEBUG -#ifdef CL_IPV6_PASS - 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" - "%02x%02x%02x%02x%02x%02x\n", - i, - f->macAddr[0], - f->macAddr[1], - f->macAddr[2], - f->macAddr[3], - f->macAddr[4], - f->macAddr[5], - f->networkAddr[0], - f->networkAddr[1], - f->networkAddr[2], - f->networkAddr[3], - f->networkAddr[4], - f->networkAddr[5], - f->networkAddr[6], - f->networkAddr[7], - f->networkAddr[8], - f->networkAddr[9], - f->networkAddr[10], - f->networkAddr[11], - f->networkAddr[12], - f->networkAddr[13], - f->networkAddr[14], - f->networkAddr[15], - f->networkAddr[16]); -#else - - 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", - i, - f->macAddr[0], - f->macAddr[1], - f->macAddr[2], - f->macAddr[3], - f->macAddr[4], - f->macAddr[5], - f->networkAddr[0], - f->networkAddr[1], - f->networkAddr[2], - f->networkAddr[3], - f->networkAddr[4], - f->networkAddr[5], - f->networkAddr[6], - f->networkAddr[7], - f->networkAddr[8], - f->networkAddr[9], - f->networkAddr[10]); -#endif -#endif - if (priv->scdb_entry == f) { - memset(priv->scdb_mac, 0, ETH_ALEN); - memset(priv->scdb_ip, 0, 4); - priv->scdb_entry = NULL; - } - __network_hash_unlink(f); - rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry)); - } - } - - f = g; - } - } - } - - _exit_critical_bh(&priv->br_ext_lock, &irqL); -} - - -#ifdef SUPPORT_TX_MCAST2UNI -static int checkIPMcAndReplace(_adapter *priv, struct sk_buff *skb, unsigned int *dst_ip) -{ - struct stat_info *pstat; - struct list_head *phead, *plist; - int i; - - phead = &priv->asoc_list; - plist = phead->next; - - while (plist != phead) { - pstat = list_entry(plist, struct stat_info, asoc_list); - plist = plist->next; - - if (pstat->ipmc_num == 0) - continue; - - for (i = 0; i < MAX_IP_MC_ENTRY; i++) { - if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { - memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); - return 1; - } - } - } - return 0; -} -#endif - -int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method) -{ - unsigned short protocol; - unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; - - if (skb == NULL) - return -1; - - if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) - return -1; - - protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); - - /*---------------------------------------------------*/ - /* Handle IP frame */ - /*---------------------------------------------------*/ - if (protocol == __constant_htons(ETH_P_IP)) { - struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); - - if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { - DEBUG_WARN("NAT25: malformed IP packet !\n"); - return -1; - } - - switch (method) { - case NAT25_CHECK: - return -1; - - case NAT25_INSERT: { - /* some muticast with source IP is all zero, maybe other case is illegal */ - /* in class A, B, C, host address is all zero or all one is illegal */ - if (iph->saddr == 0) - return 0; - RTW_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); - __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); - /* record source IP address and , source mac address into db */ - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); - - __nat25_db_print(priv); - } - return 0; - - case NAT25_LOOKUP: { - RTW_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); -#ifdef SUPPORT_TX_MCAST2UNI - if (priv->pshare->rf_ft_var.mc2u_disable || - ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) - == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && - !checkIPMcAndReplace(priv, skb, &iph->daddr)) || - (OPMODE & WIFI_ADHOC_STATE))) -#endif - { - __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); - - if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { - if (*((unsigned char *)&iph->daddr + 3) == 0xff) { - /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ - RTW_INFO("NAT25: Set DA as boardcast\n"); - memset(skb->data, 0xff, ETH_ALEN); - } else { - /* forward unknow IP packet to upper TCP/IP */ - RTW_INFO("NAT25: Replace DA with BR's MAC\n"); - if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac + 4)) == 0) { - void netdev_br_init(struct net_device *netdev); - printk("Re-init netdev_br_init() due to br_mac==0!\n"); - netdev_br_init(priv->pnetdev); - } - memcpy(skb->data, priv->br_mac, ETH_ALEN); - } - } - } - } - return 0; - - default: - return -1; - } - } - - /*---------------------------------------------------*/ - /* Handle ARP frame */ - /*---------------------------------------------------*/ - else if (protocol == __constant_htons(ETH_P_ARP)) { - struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); - unsigned char *arp_ptr = (unsigned char *)(arp + 1); - unsigned int *sender, *target; - - if (arp->ar_pro != __constant_htons(ETH_P_IP)) { - DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); - return -1; - } - - switch (method) { - case NAT25_CHECK: - return 0; /* skb_copy for all ARP frame */ - - case NAT25_INSERT: { - RTW_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], - arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); - - /* change to ARP sender mac address to wlan STA address */ - memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN); - - arp_ptr += arp->ar_hln; - sender = (unsigned int *)arp_ptr; - - __nat25_generate_ipv4_network_addr(networkAddr, sender); - - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); - - __nat25_db_print(priv); - } - return 0; - - case NAT25_LOOKUP: { - RTW_INFO("NAT25: Lookup ARP\n"); - - arp_ptr += arp->ar_hln; - sender = (unsigned int *)arp_ptr; - arp_ptr += (arp->ar_hln + arp->ar_pln); - target = (unsigned int *)arp_ptr; - - __nat25_generate_ipv4_network_addr(networkAddr, target); - - __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); - - /* change to ARP target mac address to Lookup result */ - arp_ptr = (unsigned char *)(arp + 1); - arp_ptr += (arp->ar_hln + arp->ar_pln); - memcpy(arp_ptr, skb->data, ETH_ALEN); - } - return 0; - - default: - return -1; - } - } - - /*---------------------------------------------------*/ - /* Handle PPPoE frame */ - /*---------------------------------------------------*/ - else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || - (protocol == __constant_htons(ETH_P_PPP_SES))) { - struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); - unsigned short *pMagic; - - switch (method) { - case NAT25_CHECK: - if (ph->sid == 0) - return 0; - return 1; - - case NAT25_INSERT: - if (ph->sid == 0) { /* Discovery phase according to tag */ - if (ph->code == PADI_CODE || ph->code == PADR_CODE) { - if (priv->ethBrExtInfo.addPPPoETag) { - struct pppoe_tag *tag, *pOldTag; - unsigned char tag_buf[40]; - int old_tag_len = 0; - - tag = (struct pppoe_tag *)tag_buf; - pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); - if (pOldTag) { /* if SID existed, copy old value and delete it */ - old_tag_len = ntohs(pOldTag->tag_len); - if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { - DEBUG_ERR("SID tag length too long!\n"); - return -1; - } - - memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, - pOldTag->tag_data, old_tag_len); - - if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { - DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n"); - return -1; - } - ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); - } - - tag->tag_type = PTT_RELAY_SID; - tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); - - /* insert the magic_code+client mac in relay tag */ - pMagic = (unsigned short *)tag->tag_data; - *pMagic = htons(MAGIC_CODE); - memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); - - /* Add relay tag */ - if (__nat25_add_pppoe_tag(skb, tag) < 0) - return -1; - - RTW_INFO("NAT25: Insert PPPoE, forward %s packet\n", - (ph->code == PADI_CODE ? "PADI" : "PADR")); - } else { /* not add relay tag */ - if (priv->pppoe_connection_in_progress && - memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) { - DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); - return -2; - } - - if (priv->pppoe_connection_in_progress == 0) - memcpy(priv->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); - - priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; - } - } else - return -1; - } else { /* session phase */ - RTW_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); - - __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); - - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); - - __nat25_db_print(priv); - - if (!priv->ethBrExtInfo.addPPPoETag && - priv->pppoe_connection_in_progress && - !memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) - priv->pppoe_connection_in_progress = 0; - } - return 0; - - case NAT25_LOOKUP: - if (ph->code == PADO_CODE || ph->code == PADS_CODE) { - if (priv->ethBrExtInfo.addPPPoETag) { - struct pppoe_tag *tag; - unsigned char *ptr; - unsigned short tagType, tagLen; - int offset = 0; - - ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); - if (ptr == 0) { - DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n"); - return -1; - } - - tag = (struct pppoe_tag *)ptr; - tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); - tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); - - if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { - DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); - return -1; - } - - pMagic = (unsigned short *)tag->tag_data; - if (ntohs(*pMagic) != MAGIC_CODE) { - DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n", - (ph->code == PADO_CODE ? "PADO" : "PADS")); - return -1; - } - - memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); - - if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) - offset = TAG_HDR_LEN; - - if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { - DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n"); - return -1; - } - ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); - if (offset > 0) - tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); - - RTW_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n", - (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); - } else { /* not add relay tag */ - if (!priv->pppoe_connection_in_progress) { - DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n"); - return -1; - } - memcpy(skb->data, priv->pppoe_addr, ETH_ALEN); - priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; - } - } else { - if (ph->sid != 0) { - RTW_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); - __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); - - __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); - - __nat25_db_print(priv); - } else - return -1; - - } - return 0; - - default: - return -1; - } - } - - /*---------------------------------------------------*/ - /* Handle EAP frame */ - /*---------------------------------------------------*/ - else if (protocol == __constant_htons(0x888e)) { - switch (method) { - case NAT25_CHECK: - return -1; - - case NAT25_INSERT: - return 0; - - case NAT25_LOOKUP: - return 0; - - default: - return -1; - } - } - - /*---------------------------------------------------*/ - /* Handle C-Media proprietary frame */ - /*---------------------------------------------------*/ - else if ((protocol == __constant_htons(0xe2ae)) || - (protocol == __constant_htons(0xe2af))) { - switch (method) { - case NAT25_CHECK: - return -1; - - case NAT25_INSERT: - return 0; - - case NAT25_LOOKUP: - return 0; - - default: - return -1; - } - } - - /*---------------------------------------------------*/ - /* Handle IPV6 frame */ - /*---------------------------------------------------*/ -#ifdef CL_IPV6_PASS - else if (protocol == __constant_htons(ETH_P_IPV6)) { - struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); - - if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { - DEBUG_WARN("NAT25: malformed IPv6 packet !\n"); - return -1; - } - - switch (method) { - case NAT25_CHECK: - if (skb->data[0] & 1) - return 0; - return -1; - - case NAT25_INSERT: { - RTW_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," - " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", - iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], - iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], - iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], - iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); - - if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { - __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); - __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr); - __nat25_db_print(priv); - - if (iph->nexthdr == IPPROTO_ICMPV6 && - skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { - if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), - skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) { - struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); - hdr->icmp6_cksum = 0; - hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, - iph->payload_len, - IPPROTO_ICMPV6, - csum_partial((__u8 *)hdr, iph->payload_len, 0)); - } - } - } - } - return 0; - - case NAT25_LOOKUP: - RTW_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," - " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", - iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], - iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], - iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], - iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); - - - __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); - if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { -#ifdef SUPPORT_RX_UNI2MCAST - if (iph->daddr.s6_addr[0] == 0xff) - convert_ipv6_mac_to_mc(skb); -#endif - } - return 0; - - default: - return -1; - } - } -#endif /* CL_IPV6_PASS */ - - return -1; -} - - -int nat25_handle_frame(_adapter *priv, struct sk_buff *skb) -{ -#ifdef BR_EXT_DEBUG - if ((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { - panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", - skb->data[0], - skb->data[1], - skb->data[2], - skb->data[3], - skb->data[4], - skb->data[5], - skb->data[6], - skb->data[7], - skb->data[8], - skb->data[9], - skb->data[10], - skb->data[11]); - } -#endif - - if (!(skb->data[0] & 1)) { - int is_vlan_tag = 0, i, retval = 0; - unsigned short vlan_hdr = 0; - - if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { - is_vlan_tag = 1; - vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); - skb_pull(skb, 4); - } - - if (!priv->ethBrExtInfo.nat25_disable) { - _irqL irqL; - _enter_critical_bh(&priv->br_ext_lock, &irqL); - /* - * This function look up the destination network address from - * the NAT2.5 database. Return value = -1 means that the - * corresponding network protocol is NOT support. - */ - if (!priv->ethBrExtInfo.nat25sc_disable && - (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && - !memcmp(priv->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { - memcpy(skb->data, priv->scdb_mac, ETH_ALEN); - - _exit_critical_bh(&priv->br_ext_lock, &irqL); - } else { - _exit_critical_bh(&priv->br_ext_lock, &irqL); - - retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); - } - } else { - if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && - !memcmp(priv->br_ip, skb->data + ETH_HLEN + 16, 4)) || - ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && - !memcmp(priv->br_ip, skb->data + ETH_HLEN + 24, 4))) { - /* for traffic to upper TCP/IP */ - retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); - } - } - - if (is_vlan_tag) { - skb_push(skb, 4); - for (i = 0; i < 6; i++) - *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); - *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); - *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; - } - - if (retval == -1) { - /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ - return -1; - } - } - - return 0; -} - -#if 0 -void mac_clone(_adapter *priv, unsigned char *addr) -{ - struct sockaddr sa; - - memcpy(sa.sa_data, addr, ETH_ALEN); - RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - rtl8192cd_set_hwaddr(priv->dev, &sa); -} - - -int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) -{ - if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { - if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ - if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && - ((priv->dev->br_port) && - memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { - mac_clone(priv, skb->data + ETH_ALEN); - priv->macclone_completed = 1; - } - } - } - - return 0; -} -#endif /* 0 */ - -#define SERVER_PORT 67 -#define CLIENT_PORT 68 -#define DHCP_MAGIC 0x63825363 -#define BROADCAST_FLAG 0x8000 - -struct dhcpMessage { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - u_int16_t secs; - u_int16_t flags; - u_int32_t ciaddr; - u_int32_t yiaddr; - u_int32_t siaddr; - u_int32_t giaddr; - u_int8_t chaddr[16]; - u_int8_t sname[64]; - u_int8_t file[128]; - u_int32_t cookie; - u_int8_t options[308]; /* 312 - cookie */ -}; - -void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb) -{ - if (skb == NULL) - return; - - if (!priv->ethBrExtInfo.dhcp_bcst_disable) { - unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); - - if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ - struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); - - if (iph->protocol == IPPROTO_UDP) { /* UDP */ - struct udphdr *udph = (struct udphdr *)((SIZE_PTR)iph + (iph->ihl << 2)); - - if ((udph->source == __constant_htons(CLIENT_PORT)) - && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ - struct dhcpMessage *dhcph = - (struct dhcpMessage *)((SIZE_PTR)udph + sizeof(struct udphdr)); - - if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ - if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ - register int sum = 0; - - RTW_INFO("DHCP: change flag of DHCP request to broadcast.\n"); - /* or BROADCAST flag */ - dhcph->flags |= htons(BROADCAST_FLAG); - /* recalculate checksum */ - sum = ~(udph->check) & 0xffff; - sum += dhcph->flags; - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - udph->check = ~sum; - } - } - } - } - } - } -} - - -void *scdb_findEntry(_adapter *priv, unsigned char *macAddr, - unsigned char *ipAddr) -{ - unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; - struct nat25_network_db_entry *db; - int hash; - /* _irqL irqL; */ - /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ - - __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); - hash = __nat25_network_hash(networkAddr); - db = priv->nethash[hash]; - while (db != NULL) { - if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { - /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ - return (void *)db; - } - - db = db->next_hash; - } - - /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ - return NULL; -} - -#endif /* CONFIG_BR_EXT */