Пример #1
0
int _netdev_open(struct net_device *pnetdev)
{
	uint status;
	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;

	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - dev_open\n"));
	DBG_88E("+88eu_drv - drv_open, bup =%d\n", padapter->bup);

	if (pwrctrlpriv->ps_flag) {
		padapter->net_closed = false;
		goto netdev_open_normal_process;
	}

	if (!padapter->bup) {
		padapter->bDriverStopped = false;
		padapter->bSurpriseRemoved = false;
		padapter->bCardDisableWOHSM = false;

		status = rtw_hal_init(padapter);
		if (status == _FAIL) {
			RT_TRACE(_module_os_intfs_c_, _drv_err_, ("rtl88eu_hal_init(): Can't init h/w!\n"));
			goto netdev_open_error;
		}

		pr_info("MAC Address = %pM\n", pnetdev->dev_addr);

		status = rtw_start_drv_threads(padapter);
		if (status == _FAIL) {
			pr_info("Initialize driver software resource Failed!\n");
			goto netdev_open_error;
		}

		if (init_hw_mlme_ext(padapter) == _FAIL) {
			pr_info("can't init mlme_ext_priv\n");
			goto netdev_open_error;
		}
		if (padapter->intf_start)
			padapter->intf_start(padapter);
		rtw_proc_init_one(pnetdev);

		rtw_led_control(padapter, LED_CTL_NO_LINK);

		padapter->bup = true;
	}
	padapter->net_closed = false;

	_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);

	padapter->pwrctrlpriv.bips_processing = false;
	rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);

	if (!rtw_netif_queue_stopped(pnetdev))
		rtw_netif_start_queue(pnetdev);
	else
		rtw_netif_wake_queue(pnetdev);

	netdev_br_init(pnetdev);

netdev_open_normal_process:
	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - dev_open\n"));
	DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup);
	return 0;

netdev_open_error:
	padapter->bup = false;
	netif_carrier_off(pnetdev);
	rtw_netif_stop_queue(pnetdev);
	RT_TRACE(_module_os_intfs_c_, _drv_err_, ("-88eu_drv - dev_open, fail!\n"));
	DBG_88E("-88eu_drv - drv_open fail, bup =%d\n", padapter->bup);
	return -1;
}
Пример #2
0
int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method)
{
	unsigned short protocol;
	unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
	unsigned int tmp;

	if (skb == NULL)
		return -1;

	if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
		return -1;

	protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));

	/*---------------------------------------------------*/
	/*                 Handle IP frame                   */
	/*---------------------------------------------------*/
	if (protocol == 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;
					tmp = be32_to_cpu(iph->saddr);
					DEBUG_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", tmp, iph->daddr);
					__nat25_generate_ipv4_network_addr(networkAddr, &tmp);
					/* 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:
				{
					DEBUG_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
					tmp = be32_to_cpu(iph->daddr);
					__nat25_generate_ipv4_network_addr(networkAddr, &tmp);

					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 */
							DEBUG_INFO("NAT25: Set DA as boardcast\n");
							memset(skb->data, 0xff, ETH_ALEN);
						}
						else {
							/*  forward unknow IP packet to upper TCP/IP */
							DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
							if ( (*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0 ) {
								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 == 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", be16_to_cpu(arp->ar_pro));
			return -1;
		}

		switch (method)
		{
			case NAT25_CHECK:
				return 0;	/*  skb_copy for all ARP frame */

			case NAT25_INSERT:
				{
					DEBUG_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:
				{
					DEBUG_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 IPX and Apple Talk frame           */
	/*---------------------------------------------------*/
	else if ((protocol == ETH_P_IPX) ||
		(protocol <= ETH_FRAME_LEN))
	{
		unsigned char ipx_header[2] = {0xFF, 0xFF};
		struct ipxhdr	*ipx = NULL;
		struct elapaarp	*ea = NULL;
		struct ddpehdr	*ddp = NULL;
		unsigned char *framePtr = skb->data + ETH_HLEN;

		if (protocol == ETH_P_IPX)
		{
			DEBUG_INFO("NAT25: Protocol=IPX (Ethernet II)\n");
			ipx = (struct ipxhdr *)framePtr;
		}
		else if (protocol <= ETH_FRAME_LEN)
		{
			if (!memcmp(ipx_header, framePtr, 2))
			{
				DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n");
				ipx = (struct ipxhdr *)framePtr;
			}
			else
			{
				unsigned char ipx_8022_type =  0xE0;
				unsigned char snap_8022_type = 0xAA;

				if (*framePtr == snap_8022_type)
				{
					unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37};		/*  IPX SNAP ID */
					unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3};	/*  Apple Talk AARP SNAP ID */
					unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B};	/*  Apple Talk DDP SNAP ID */

					framePtr += 3;	/*  eliminate the 802.2 header */

					if (!memcmp(ipx_snap_id, framePtr, 5))
					{
						framePtr += 5;	/*  eliminate the SNAP header */

						DEBUG_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n");
						ipx = (struct ipxhdr *)framePtr;
					}
					else if (!memcmp(aarp_snap_id, framePtr, 5))
					{
						framePtr += 5;	/*  eliminate the SNAP header */

						ea = (struct elapaarp *)framePtr;
					}
					else if (!memcmp(ddp_snap_id, framePtr, 5))
					{
						framePtr += 5;	/*  eliminate the SNAP header */

						ddp = (struct ddpehdr *)framePtr;
					}
					else
					{
						DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
							framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
						return -1;
					}
				}
				else if (*framePtr == ipx_8022_type)
				{
					framePtr += 3;	/*  eliminate the 802.2 header */

					if (!memcmp(ipx_header, framePtr, 2))
					{
						DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n");
						ipx = (struct ipxhdr *)framePtr;
					}
					else
						return -1;
				}
				else
					return -1;
			}
		}
		else
			return -1;

		/*   IPX   */
		if (ipx != NULL)
		{
			switch (method)
			{
				case NAT25_CHECK:
					if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
					{
						DEBUG_INFO("NAT25: Check IPX skb_copy\n");
						return 0;
					}
					return -1;

				case NAT25_INSERT:
					{
						DEBUG_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
							ipx->ipx_dest.net,
							ipx->ipx_dest.node[0],
							ipx->ipx_dest.node[1],
							ipx->ipx_dest.node[2],
							ipx->ipx_dest.node[3],
							ipx->ipx_dest.node[4],
							ipx->ipx_dest.node[5],
							ipx->ipx_dest.sock,
							ipx->ipx_source.net,
							ipx->ipx_source.node[0],
							ipx->ipx_source.node[1],
							ipx->ipx_source.node[2],
							ipx->ipx_source.node[3],
							ipx->ipx_source.node[4],
							ipx->ipx_source.node[5],
							ipx->ipx_source.sock);

						if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
						{
							DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n");

							__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);

							/*  change IPX source node addr to wlan STA address */
                                                        memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
						}
						else
						{
							__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
						}

						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);

						__nat25_db_print(priv);
					}
					return 0;

				case NAT25_LOOKUP:
					{
                                                if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN))
						{
							DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");

							__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);

							__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);

							/*  replace IPX destination node addr with Lookup destination MAC addr */
							memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
						}
						else
						{
							__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);

							__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
						}
					}
					return 0;

				default:
					return -1;
			}
		}

		/*   AARP   */
		else if (ea != NULL)
		{
			/* Sanity check fields. */
			if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN)
			{
				DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
				return -1;
			}

			switch (method)
			{
				case NAT25_CHECK:
					return 0;

				case NAT25_INSERT:
					{
						/*  change to AARP source mac address to wlan STA address */
                                                memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);

						DEBUG_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
							ea->pa_src_net,
							ea->pa_src_node,
							ea->pa_dst_net,
							ea->pa_dst_node);

						__nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);

						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);

						__nat25_db_print(priv);
					}
					return 0;

				case NAT25_LOOKUP:
					{
						DEBUG_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
							ea->pa_src_net,
							ea->pa_src_node,
							ea->pa_dst_net,
							ea->pa_dst_node);

						__nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);

						__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);

						/*  change to AARP destination mac address to Lookup result */
						memcpy(ea->hw_dst, skb->data, ETH_ALEN);
					}
					return 0;

				default:
					return -1;
			}
		}

		/*   DDP   */
		else if (ddp != NULL)
		{
			switch (method)
			{
				case NAT25_CHECK:
					return -1;

				case NAT25_INSERT:
					{
						DEBUG_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
							ddp->deh_snet,
							ddp->deh_snode,
							ddp->deh_dnet,
							ddp->deh_dnode);

						__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);

						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);

						__nat25_db_print(priv);
					}
					return 0;

				case NAT25_LOOKUP:
					{
						DEBUG_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
							ddp->deh_snet,
							ddp->deh_snode,
							ddp->deh_dnet,
							ddp->deh_dnode);

						__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);

						__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
					}
					return 0;

				default:
					return -1;
			}
		}

		return -1;
	}

	/*---------------------------------------------------*/
	/*                Handle PPPoE frame                 */
	/*---------------------------------------------------*/
	else if ((protocol == ETH_P_PPP_DISC) ||
		(protocol == 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;

							DEBUG_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 */
				{
						DEBUG_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;

						if ((ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID))) == NULL) {
							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);

						DEBUG_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)
					{
						DEBUG_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 == 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 == 0xe2ae) ||
		(protocol == 0xe2af))
	{
		switch (method)
		{
			case NAT25_CHECK:
				return -1;

			case NAT25_INSERT:
				return 0;

			case NAT25_LOOKUP:
				return 0;

			default:
				return -1;
		}
	}

	/*---------------------------------------------------*/
	/*         Handle IPV6 frame								  */
	/*---------------------------------------------------*/
	else if (protocol == 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:
				{
					DEBUG_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:
				DEBUG_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);
				__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
				return 0;

			default:
				return -1;
		}
	}
	return -1;
}
Пример #3
0
void netdev_br_init(struct net_device *netdev)
{
	struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);

	rcu_read_lock();

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
	if (rcu_dereference(adapter->pnetdev->rx_handler_data)) {
#else
	if (rcu_dereference(adapter->pnetdev->br_port)) {
#endif
		struct net_device *br_netdev;
		struct net *devnet = NULL;

		devnet = dev_net(netdev);
		br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
		if (br_netdev) {
			memcpy(adapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
			dev_put(br_netdev);
		} else {
			pr_info("%s()-%d: dev_get_by_name(%s) failed!",
				__func__, __LINE__, CONFIG_BR_EXT_BRNAME);
		}
	}
	adapter->ethBrExtInfo.addPPPoETag = 1;

	rcu_read_unlock();
}

int _netdev_open(struct net_device *pnetdev)
{
	uint status;
	struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;

	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - dev_open\n"));
	DBG_88E("+88eu_drv - drv_open, bup =%d\n", padapter->bup);

	if (pwrctrlpriv->ps_flag) {
		padapter->net_closed = false;
		goto netdev_open_normal_process;
	}

	if (!padapter->bup) {
		padapter->bDriverStopped = false;
		padapter->bSurpriseRemoved = false;
		padapter->bCardDisableWOHSM = false;

		status = rtw_hal_init(padapter);
		if (status == _FAIL) {
			RT_TRACE(_module_os_intfs_c_, _drv_err_, ("rtl88eu_hal_init(): Can't init h/w!\n"));
			goto netdev_open_error;
		}

		pr_info("MAC Address = %pM\n", pnetdev->dev_addr);

		status = rtw_start_drv_threads(padapter);
		if (status == _FAIL) {
			pr_info("Initialize driver software resource Failed!\n");
			goto netdev_open_error;
		}

		if (init_hw_mlme_ext(padapter) == _FAIL) {
			pr_info("can't init mlme_ext_priv\n");
			goto netdev_open_error;
		}
		if (padapter->intf_start)
			padapter->intf_start(padapter);
		rtw_proc_init_one(pnetdev);

		rtw_led_control(padapter, LED_CTL_NO_LINK);

		padapter->bup = true;
	}
	padapter->net_closed = false;

	_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);

	padapter->pwrctrlpriv.bips_processing = false;
	rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);

	if (!rtw_netif_queue_stopped(pnetdev))
		rtw_netif_start_queue(pnetdev);
	else
		rtw_netif_wake_queue(pnetdev);

	netdev_br_init(pnetdev);

netdev_open_normal_process:
	RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - dev_open\n"));
	DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup);
	return 0;

netdev_open_error:
	padapter->bup = false;
	netif_carrier_off(pnetdev);
	rtw_netif_stop_queue(pnetdev);
	RT_TRACE(_module_os_intfs_c_, _drv_err_, ("-88eu_drv - dev_open, fail!\n"));
	DBG_88E("-88eu_drv - drv_open fail, bup =%d\n", padapter->bup);
	return -1;
}