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; unsigned short protocol; protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN))); if (protocol == 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 && (be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == 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 (((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == ETH_P_IP) && !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) || ((be16_to_cpu(*((__be16 *)(skb->data+ETH_ALEN*2))) == 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)); *((__be16 *)(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; }
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 (RTW_RN16A(skb->data + ETH_ALEN * 2) == __constant_htons(ETH_P_8021Q)) { is_vlan_tag = 1; vlan_hdr = RTW_RN16A(skb->data + ETH_ALEN * 2 + 2); for (i = 0; i < 6; i++) RTW_WN16A(skb->data + ETH_ALEN * 2 + 2 - i * 2, RTW_RN16A(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 && RTW_RN16A(skb->data + ETH_ALEN * 2) == __constant_htons(ETH_P_IP) && RTW_RN32(priv->scdb_ip) == RTW_RN32(skb->data + ETH_HLEN + 16)) { copy_mac_addr(skb->data, priv->scdb_mac); _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 ((RTW_RN16A(skb->data + ETH_ALEN * 2) == __constant_htons(ETH_P_IP) && RTW_RN32(priv->br_ip) == RTW_RN32(skb->data + ETH_HLEN + 16)) || (RTW_RN16A(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP) && RTW_RN32(priv->br_ip) == RTW_RN32(skb->data + ETH_HLEN + 24))) { // 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++) RTW_WN16A(skb->data + i * 2, RTW_RN16A(skb->data + 4 + i * 2)); RTW_WN16A(skb->data + ETH_ALEN * 2, __constant_htons(ETH_P_8021Q)); RTW_WN16A(skb->data + ETH_ALEN * 2 + 2, vlan_hdr); } if(retval == -1) { //DEBUG_ERR("NAT25: Lookup fail!\n"); return -1; } }