⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethernet.c

📁 基于S3C2410和SM501的彩屏控制器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
				(ntohs(arp->ar_hrd) != ARP_ETHER)   ||
				(ntohs(arp->ar_pro) != PROT_IP)     ||
				(arp->ar_hln != 6) || (arp->ar_pln != 4)) 
			{

				//printf("invalid RARP header\n");
			} 
			else 
			{
				NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
				NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
				memcpy (NetServerEther, &arp->ar_data[ 0], 6);

				(*packetHandler)(0,0,0,0);
			}
			break;

		case PROT_IP:
			tmp = NetReadIP(&ip->ip_dst);
			
			if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF)
			{
				
				return;
			}
			if (len < IP_HDR_SIZE) {
				//debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
				return;
			}
			if (len < ntohs(ip->ip_len)) {
				//printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
				return;
			}
			len = ntohs(ip->ip_len);

			if ((ip->ip_hl_v & 0xf0) != 0x40) {
				return;
			}
			if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
				return;
			}
			if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
					//printf("checksum bad\n");
					return;
			}

			if (ip->ip_p == IPPROTO_ICMP) 
			{
				//
				ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
				switch (icmph->type) 
				{
					case ICMP_REDIRECT:
						if (icmph->code != ICMP_REDIR_HOST)
							return;
						print_IPaddr(icmph->un.gateway);
						break;

					case ICMP_ECHO_REQUEST:		//上位机发来ping请求,ARM目标板应答
						PingAck ((uchar *)ip,(uchar *)et);	//ping回应程序
						return;

					default:
						return;
				}
			}
			else if (ip->ip_p != IPPROTO_UDP) 
			{	/* Only UDP packets */
				return;
			}

		/*
		 *	IP header OK.  Pass the packet to the current handler.
		 */

		/**********************llr note :add 2005.12.12**********************/
		(uchar *) udppack = (uchar *)ip ;

		/**********************llr note :add 2005.12.12**********************/	     
		if((DWORD)packetHandler <= 0x30000000 || (DWORD)packetHandler > 0x34000000) return;
		(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
						ntohs(ip->udp_dst),
						ntohs(ip->udp_src),
						ntohs(ip->udp_len) - 8);
		break;
	}
}//NetReceiveProcess()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: Ping响应.
// 描述: 上位机有Ping请求, 进行Ping响应.
//
// [参数表]
//	ipaddr: ip包指针.
//	etheraddr: 以太网头指针.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PingAck (uchar *ipaddr, uchar *etheraddr)
{
 	volatile ushort *s,*s1;
 	int i=0;
	IP_t	*ipack;
	IP_t *ip = (IP_t *)ipaddr;
	Ethernet_t *et = (Ethernet_t *)etheraddr;
	int NetTxPacketsize;
	
	NetSetEther (NetTxPacket,et->et_src, PROT_IP);
	ipack = (IP_t *)(NetTxPacket + ETHER_HDR_SIZE);
	ipack->ip_hl_v  = 0x45;		
	ipack->ip_tos   = 0;
	ipack->ip_len   = ip->ip_len;
	ipack->ip_id    =  ip->ip_id;	//上位机的ping ID
	ipack->ip_off   = htons(0x4000);	
	ipack->ip_ttl   = 128;
	ipack->ip_p     = 0x01;		// ICMP协议
	ipack->ip_sum   = 0;   		// 校验和
	NetCopyIP((void*)&ipack->ip_src,&ip->ip_dst);	//设置目的ip地址
	NetCopyIP((void*)&ipack->ip_dst,&ip->ip_src);	  
	ipack->ip_sum   = ~NetCksum((uchar *)ipack, IP_HDR_SIZE_NO_UDP / 2);
	
	s = &ipack->udp_src;		
	s1 = (&ip->udp_xsum)+1;
	s[0] = htons(0x0000);	// ping回应类型 
	s[1] = 0;				// checksum
	s[2] = ip->udp_len; 	// identifier 
	s[3] = ip->udp_xsum;
			
	// ping发来的数据送回
	for (i=0;i<ntohs(ip->ip_len)-IP_HDR_SIZE_NO_UDP-8;i++)
	{
		s[i+4] = s1[i];
	}
	
	s[1] = ~NetCksum((uchar *)s, (ntohs(ip->ip_len)-IP_HDR_SIZE_NO_UDP)/2);
	NetTxPacketsize = ETHER_HDR_SIZE + ntohs(ip->ip_len);
	(void) eth_send(NetTxPacket, NetTxPacketsize);
}//PingAck()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络传输初始化.
// 描述: 分配接收、发送缓冲区, 在网络接收、发送前执行初始化.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetTRPackInit(void)
{
	int	i;

	NetArpWaitPacketMAC = NULL;
	NetArpWaitTxPacket = NULL;
	NetArpWaitPacketIP = 0;
	NetArpWaitReplyIP = 0;
	NetArpWaitTxPacket = NULL;
	NetTxPacket = NULL;

	if( !NetTxPacket )
	{
		// 开辟包缓冲区
		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;

		for( i = 0; i < PKTBUFSRX; i++)
		{
			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
		}
	}

	if (!NetArpWaitTxPacket) 
	{
		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
		NetArpWaitTxPacketSize = 0;
	}
 		
 	memcpy (NetOurEther,MACAddr , 6);
	NetCopyIP(&NetOurIP, &IPAddr);
	NetOurIP = ntohl(NetOurIP);
}//NetTRPackInit()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 字符串转为IP.
//
// [参数表]
//	s: 待转换的字符串.
//
// 返回: 转换所得的IP.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IPaddr_t string_to_ip (char *s)
{
	IPaddr_t addr;
	ulong val;
	char *e;
	int i;

	if (s == NULL)
		return(0);

	for (addr=0, i=0; i<4; ++i)
	{
		val = s ? simple_strtoul(s, &e, 10) : 0;
		addr <<= 8;
		addr |= (val & 0xFF);
		if (s)
		{
			s = (*e) ? e+1 : e;
		}
	}
	return (htonl(addr));
}//string_to_ip()



void NetSetTimeout(int iv, thand_f * f)
{
	if (iv == 0) 
	{
		timeHandler = (thand_f *)0;
	} 
	else 
	{
		timeHandler = f;
		timeStart = get_timer(0);
		timeDelta = iv;
	}
}//NetSetTimeout()



static startAgainHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	 //Totally ignore the packet 
	 return 0;
}//startAgainHandler()



void NetWriteIP(void *to, IPaddr_t ip)
{
	memcpy(to, (void*)&ip, sizeof(ip));
}

void NetStartAgain(void)
{
	NetSetTimeout(10 * CFG_HZ, (thand_f *)startAgainTimeout);
	NetSetHandler((rxhand_f *)startAgainHandler);
}



void ArpRequest (void)
{
	int i;
	volatile uchar *pkt;
	ARP_t *	arp;
	pkt = NetTxPacket;

	NetSetEther(pkt, NetBcastAddr, PROT_ARP);/* set ethernet header */
	pkt += ETHER_HDR_SIZE;

	arp = (ARP_t *)pkt;

	arp->ar_hrd = htons(ARP_ETHER);
	arp->ar_pro = htons(PROT_IP);
	arp->ar_hln = 6;
	arp->ar_pln = 4;
	arp->ar_op  = htons(ARPOP_REQUEST);

	memcpy (&arp->ar_data[0], NetOurEther, 6);	/* source ET addr	*/
	NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP);	/* source IP addr	*/
	for (i=10; i<16; ++i) {
		arp->ar_data[i] = 0;			/* dest ET addr = 0	*/
	}

	if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask))
	{
	    NetArpWaitReplyIP = NetOurGatewayIP;
	} else
	    NetArpWaitReplyIP = NetArpWaitPacketIP;
	
	NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP);
		
	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
}//ArpRequest()



void NetSetIP (volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
{
	volatile IP_t *ip = (IP_t *)xip;
 	/*
	 *	If the data is an odd number of bytes, zero the
	 *	byte after the last byte so that the checksum
	 *	will work.
	 */
	if (len & 1)
		xip[IP_HDR_SIZE + len] = 0;

	/*
	 *	Construct an IP and UDP header.
			(need to set no fragment bit - XXX)
	 */
	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
	ip->ip_tos   = 0;
	ip->ip_len   = htons(IP_HDR_SIZE + len);
	ip->ip_id    = htons(NetIPID++);
	ip->ip_off   = htons(0x4000);	/* No fragmentation */
	ip->ip_ttl   = 255;
	ip->ip_p     = 17;		/* UDP */
	ip->ip_sum   = 0;
	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
	NetCopyIP((void*)&ip->ip_dst, &dest);	   /* - "" - */
	ip->udp_src  = htons(sport);
	ip->udp_dst  = htons(dport);
	ip->udp_len  = htons(8 + len);
	ip->udp_xsum = 0;
	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
}//NetSetIP()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络发送UDP包.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int NetSendUDPPacket (uchar *ether, IPaddr_t dest, int dport, int sport, int len)
{
	/* convert to new style broadcast */
	if (dest == 0)
		dest = 0xFFFFFFFF;

	/* if broadcast, make the ether address a broadcast and don't do ARP */
	if (dest == 0xFFFFFFFF)
		ether = NetBcastAddr;

	/* if MAC address was not discovered yet, save the packet and do an ARP request */
	if (memcmp(ether, NetEtherNullAddr, 6) == 0) 
	{

	#ifdef ET_DEBUG
//		printf("sending ARP for %08lx\n", dest);
	#endif

		NetArpWaitPacketIP = dest;
		NetArpWaitPacketMAC = ether;
		NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP);
		NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
		memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE,
			(uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len);

		/* size of the waiting packet */
		NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len;
		/* and do the ARP request */
		NetArpWaitTry = 1;
		NetArpWaitTimerStart = get_timer(0);
			
		ArpRequest();
		return 1;	/* waiting */
	}

#ifdef ET_DEBUG
//	printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
			dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
#endif

	NetSetEther (NetTxPacket, ether, PROT_IP);
	NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);

	return 0;	/* transmited */
}//NetSendUDPPacket()



void ArpTimeoutCheck (void)
{
	ulong t;

	if (!NetArpWaitPacketIP)
		return;

	t = get_timer(0);

	/* check for arp timeout */
	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ)
	{
		NetArpWaitTry++;

		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT)
		{
			NetArpWaitTry = 0;
			NetStartAgain();
		} else {
			NetArpWaitTimerStart = t;
			ArpRequest();
		}
	}
}//ArpTimeoutCheck()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络数据包接收.
// 描述:  UDP包接收.
//
// [参数表]
//	udpdata: 数据指针.
//	ipstring: 目标ip地址字符串, 如“10.10.10.118".
//	srcport: 源端口号.
//	len: 数据长度.
//	
// 返回: 1-发送不成功; 0-发送成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int NetTrPack (uchar *udpdata, char *ipstring, int sport, int len)
{
	int is_arp;
	IPaddr_t dest, tmp;
	uchar ether[6];		// ether只要传送目标mac地址值,即ether->et_dst
	IP_t *netarpip;
	
	memset(ether,0,6);
	dest = string_to_ip(ipstring);
		
	//读出原来在内存的ip地址
	(DWORD)netarpip = (DWORD)NetArpWaitTxPacket+ETHER_HDR_SIZE;//1026
	
	tmp = NetReadIP(&netarpip->ip_dst);

	//eth_current
	/****************************************************************************
		比较目的ip地址与内存ip地址。
		如相等,说明内存中有相应的MAC地址,不用发arp协议,内存mac地址->目的mac地址。
		不相等,在NetSendUDPPacket()函数中发arp协议。		
	*****************************************************************************/	
	if (tmp == dest)
	{
		memcpy(ether,((Ethernet_t *)NetArpWaitTxPacket)->et_dest,6);

	}
	
	//复制包数据
	memcpy((uchar *)((DWORD)NetTxPacket+ (ETHER_HDR_SIZE + IP_HDR_SIZE)),udpdata,len);//1026
	
	is_arp = NetSendUDPPacket(ether, dest, sport, sport, len);
	
	while (is_arp == 1)
	{
	//如果不知道对方mac地址,即(ether)={0,0,0,0,0,0}则发arp
		eth_rx();
		ArpTimeoutCheck();		//每5秒发一次arp请求,发5次
		if (!NetArpWaitTry) 
		{
		// 5次没有arp应答,表示目的不可达
			return 1;
		}
		
	 	if (NetArpWaitTxPacketSize == 0)
	 	{
	 		return 0;//发送数据成功
	    }
	}
	return 0;	//发送数据成功
}//NetTrPack()



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -