Esempio n. 1
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;
		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;
}
Esempio n. 2
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;
		}
	}