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

📄 netkernel.c

📁 一个ARM7 芯片Bootload中几个重要的实用代码。比如DHCP
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
 *
 * Copyright (c) 2003 Windond Electronics Corp.
 * All rights reserved.
 * Winbond W90N740 Boot Loader
 *
 * Module Name:	NETKERNEL.C
 *
 * Created by : 
 ******************************************************************************/
#include "W90N740.h"
#include "net.h"
#include "netbuf.h"


#define USE_SIB             0

#define NET_TERM_PORT		65500

UCHAR  _HostMAC[6] = { 0x00, 0x50, 0x51, 0x52, 0x53, 0x57 };
UCHAR	 _HostIP[4] =  { 192, 168, 0, 201 };

UINT16 _IP_packet_ID = 1000;

INT  _netbuf_ready = 0;
static INT  _mac_inited = 0;

/* for TCP */
TCP_CONN	_NetTerm;


INT  NET_flush(void);


UINT16  Nchksum(UINT16 *cp, INT cnt)
{
	volatile UINT16 i1=0, i2;

	while (cnt--)
	{
		i2 = *cp++;
		i2 = NC2(i2);
		i1 += i2;
		if (i1 < i2)
			i1++;
	}
	return NC2(i1);
}



void  TCP_SendPacket(UCHAR *buff, INT len, UCHAR code, INT in_intr)
{
	IP_PACKET	*ip;
	TCP_PACKET	*tcp;
	TCP_PSEUDO	pseudo;
	NETBUF		*txbuf;
	
	//uHALr_printf("TCP_SendPacket, len=%d\n", len);
	if (in_intr)
		txbuf = NetBuf_AllocateIR();
	else
		txbuf = NetBuf_Allocate();
	
	if (txbuf == NULL)
	{
		//uHALr_printf("Fail to allocate a net buffer...\n");
		return;
	}

	txbuf->len = sizeof(TCP_PACKET) + len;
	if (len != 0)
		memcpy((CHAR *)&txbuf->packet[sizeof(TCP_PACKET)], (CHAR *)buff, len);

	txbuf->packet[sizeof(TCP_PACKET)+1] = 0;

	/*- prepare Ethernet header, 14 bytes -*/
	ip = (IP_PACKET *)txbuf->packet;
	tcp = (TCP_PACKET *)txbuf->packet;
	memcpy((CHAR *)ip->tMAC, (CHAR *)_NetTerm.peerMAC, 6);
	memcpy((CHAR *)ip->sMAC, (CHAR *)_HostMAC, 6);
	ip->protocol = NC2(PROTOCOL_IP);

	/*- prepare IP header, 20 bytes -*/
	ip->vers_hlen = 0x45;     		/* fixed value, do not change it */
	ip->stype = 0;            		/* no special priority */
	ip->tlen = NC2(sizeof(TCP_PACKET) + len - 14);
	ip->id = NC2(_IP_packet_ID);
	_IP_packet_ID++;
	ip->ffrag = 0;
	ip->ttl = 64;
	ip->ippro = IP_PRO_TCP;
	ip->hdrchksum = 0;
	memcpy((CHAR *)ip->srcIP, (CHAR *)_HostIP, 4);
	memcpy((CHAR *)ip->destIP, (CHAR *)_NetTerm.peerIP, 4);
	ip->hdrchksum = ~Nchksum((UINT16 *)&(ip->vers_hlen), 10);  /* 20 bytes */

	/*- prepare TCP header -*/
	tcp->sport = NC2(NET_TERM_PORT);
	tcp->dport = NC2(_NetTerm.peerPort);
	
	PUT32(tcp->seqNum, 0, _NetTerm.seqNum);
	PUT32(tcp->ackNum, 0, _NetTerm.ackNum);

	if (code & TCP_SYN)
		tcp->len_code = (6 << 12) | code;
	else	
		tcp->len_code = (5 << 12) | code;
	tcp->len_code = NC2(tcp->len_code);
	
	tcp->win_size = _NetTerm.win_size;
	tcp->tcpchksum = 0;
	tcp->urgent = 0;
	
	/* Caculate the TCP pseudo header checksum */	
	memcpy((CHAR *)pseudo.srcIP, (CHAR *)_HostIP, 4);
	memcpy((CHAR *)pseudo.destIP, (CHAR *)_NetTerm.peerIP, 4);
	pseudo.protocol = NC2(IP_PRO_TCP);
	pseudo.tcp_len = NC2(20 + len);
	tcp->tcpchksum = Nchksum((UINT16 *)&pseudo, 6);
	
	tcp->tcpchksum = ~(Nchksum((UINT16 *)&(tcp->sport), (20 + len + 1) / 2));
	if (tcp->tcpchksum == 0)
		tcp->tcpchksum = 0xffff;

	NIC_SendPacket(txbuf);
	
	if (!(code & TCP_SYN))
		_NetTerm.seqNum += len;
}



INT  TCP_Core(UCHAR *packet, INT len)
{
	TCP_PACKET	*tcp = (TCP_PACKET *)packet;
	UCHAR		option[4] = { 0x02, 0x04, 0x5, 0xAC };	/* Maximum Segment Size 1452 */
	UCHAR		code;
	UINT32	seqNum, ackNum;
	UCHAR		*data = &packet[sizeof(TCP_PACKET)];
	INT			data_len = NC2(tcp->tlen) - 40;
	INT			idx;

	//uHALr_printf("Remote IP: %d.%d.%d.%d\n", _NetTerm.peerIP[0], _NetTerm.peerIP[1], _NetTerm.peerIP[2], _NetTerm.peerIP[3]);

	//uHALr_printf("TCP state=%d\n", _NetTerm.state);

	if (NC2(tcp->dport) != NET_TERM_PORT)
		return -1;
	
	code = NC2(tcp->len_code) & 0x3F;
	seqNum = GET32(tcp->seqNum, 0);
	ackNum = GET32(tcp->ackNum, 0);
	
	if (code & (TCP_RST | TCP_FIN))
	{
		if (NC2(tcp->sport) != _NetTerm.peerPort)
			return 0;
		_NetTerm.state = TCP_DISCONNECT;
		//uHALr_printf("TCP disconnect\n");
		return 0;
	}
	
	switch (_NetTerm.state)
	{
		case TCP_DISCONNECT:
			if (code & TCP_SYN)
			{
				_NetTerm.ackNum = seqNum + 1;
				_NetTerm.rx_head = _NetTerm.rx_tail = 0;
				_NetTerm.win_size = TCP_WIN_SIZE;
				memcpy((CHAR *)_NetTerm.peerMAC, (CHAR *)tcp->sMAC, 6);
				memcpy((CHAR *)_NetTerm.peerIP, (CHAR *)tcp->srcIP, 4);
				_NetTerm.peerPort = NC2(tcp->sport);
				TCP_SendPacket(option, 4, TCP_ACK | TCP_SYN, 1);
				_NetTerm.state = TCP_CONNECTING;
				//uprintf("TCP connecting\n");
			}
			return 0;
		
		case TCP_CONNECTING:
			if (seqNum != _NetTerm.ackNum)
			{	/* incorrect sequence number, discard it */
				return 0;
			}
	
			if (code & TCP_ACK)
			{
				if (ackNum == _NetTerm.seqNum + 1)
				{
					_NetTerm.state = TCP_CONNECTED;
					//uHALr_printf("TCP connected\n");
					_NetTerm.seqNum++;
					NET_flush();
				}
			}
			return 0;
			
		case TCP_CONNECTED:
			if (NC2(tcp->sport) != _NetTerm.peerPort)
				return 0;		/* port incorrect, ignore it */

			if (seqNum != _NetTerm.ackNum)
			{	/* incorrect sequence number, retransmit the last packet */
				return 0;
			}

			if (code & TCP_ACK)
			{
				_NetTerm.seqNum = ackNum;
				if (data_len == 0)
					return 0;
			}
		
			for (idx = 0; idx < data_len; idx++)
			{				
				_NetTerm.rx_buff[_NetTerm.rx_tail] = data[idx];
				_NetTerm.rx_tail = (_NetTerm.rx_tail+1) % TCP_RX_BUF_SIZE;
			}
			_NetTerm.ackNum += data_len;
			//TCP_SendPacket(NULL, 0, TCP_ACK | TCP_PSH, 1);
			return 0;		
		
		case TCP_CLSOING:
			if (seqNum != _NetTerm.ackNum)
			{	/* incorrect sequence number, discard it */
				return 0;
			}
	}
	return 0;
}



void  ARP_Reply(UCHAR *target_ip, UCHAR *target_mac)
{
	ARP_PACKET  *arp;
	NETBUF      *txbuf;

	//uHALr_printf("ARP reply, %d\n", _NetBufferAvailableCount);

	if ((txbuf = NetBuf_AllocateIR()) == NULL)
	{
		//uHALr_printf("Fail to allocate a net buffer...\n");
		return;
	}

	/*- prepare and send ARP reply packet -*/
	txbuf->len = sizeof(ARP_PACKET);
	arp = (ARP_PACKET *)txbuf->packet; 
	memcpy((CHAR *)arp->tMAC, (CHAR *)target_mac, 6);
	memcpy((CHAR *)arp->sMAC, (CHAR *)_HostMAC, 6);
	arp->protocol  = NC2(PROTOCOL_ARP);
	arp->htype     = NC2(HT_ETHERNET);
	arp->ptype     = NC2(ARP_PTYPE);
	arp->hlen      = 6;
	arp->plen      = 4;
	arp->operation = NC2(ARP_REPLY);
	memcpy((CHAR *)arp->sender_ha, (CHAR *)_HostMAC, 6);
	memcpy((CHAR *)arp->sender_ip, (CHAR *)_HostIP, 4);
	memcpy((CHAR *)arp->target_ha, (CHAR *)target_mac, 6);
	memcpy((CHAR *)arp->target_ip, (CHAR *)target_ip, 4);
	NIC_SendPacket(txbuf);
}



INT  PacketProcessor(UCHAR *packet, INT len)
{
	ARP_PACKET	*arp = (ARP_PACKET *)packet;
	IP_PACKET	*ip  = (IP_PACKET *)packet;
	UDP_PACKET	*udp = (UDP_PACKET *)packet;
	
	//uHALr_printf("[%d]\n", _NetBufferAvailableCount);
	if (packet[0] == 0xFF)   	/* this is a broadcast packet */
	{
		/* 
		 *  We manage the ARP reply process here. 
		 *  In the following code, if we have received a ARP request,
		 *  we send ARP reply immediately.
		 */
		if ((!CompareIP(arp->target_ip, _HostIP)) &&
			(arp->protocol == NC2(PROTOCOL_ARP)) && (arp->operation == NC2(ARP_REQUEST)))
		{                            
			ARP_Reply(arp->sender_ip, arp->sender_ha);
			return 0;
		}

		if ((ip->ippro == IP_PRO_UDP) && (udp->sport == NC2(67)))
			return -1;			/* DHCP packet */

		return 0;
	}
	else                    	/* this is a multicast or unicast packet */
	{
		/*
		 *  This is a unicast packet to us. We are only interested
		 *  in the TCP packets. If this is a TCP packet and we are
		 *  the target host, we will pass this packet to the TCP processor.
		 */
		if ((ip->ippro == IP_PRO_TCP) && (!CompareIP(ip->destIP, _HostIP)))
		{
			TCP_Core(packet, len);
			return 0;
		}
				
		/*
		 * Check ICMP Echo Request packet -
		 * if matched, we reply it right here
		 */
		if ((ip->ippro == IP_PRO_ICMP) && (!CompareIP(ip->destIP, _HostIP)) &&
			(packet[34] == 0x08))
		{
			NETBUF		*txbuf;
			IP_PACKET	*tx_ip;

			//uHALr_printf("ICMP reply, %d\n", _NetBufferAvailableCount);
			
			if ((txbuf = NetBuf_AllocateIR()) == NULL)
				return -1;

			/* duplicate packet then modify it */
			memcpy((CHAR *)&txbuf->packet[0], (CHAR *)&packet[0], len);
			txbuf->len = len;
				
			tx_ip = (IP_PACKET *)txbuf->packet; 
			memcpy((CHAR *)tx_ip->tMAC, (CHAR *)ip->sMAC, 6);
			memcpy((CHAR *)tx_ip->sMAC, (CHAR *)_HostMAC, 6);
			tx_ip->protocol = NC2(PROTOCOL_IP);
			tx_ip->vers_hlen = 0x45; 		/* fixed value, do not change it */
			tx_ip->stype = 0;            	/* no special priority */
			tx_ip->tlen = NC2(60);
			tx_ip->id = NC2(_IP_packet_ID);
			tx_ip->ffrag = 0;
			tx_ip->ttl = 64;
			tx_ip->ippro = IP_PRO_ICMP;
			tx_ip->hdrchksum = 0;
			memcpy((CHAR *)tx_ip->srcIP, (CHAR *)_HostIP, 4);
			memcpy((CHAR *)tx_ip->destIP, (CHAR *)ip->srcIP, 4);
			tx_ip->hdrchksum = ~Nchksum((UINT16 *)&tx_ip->vers_hlen, 10);  /* 20 bytes */

			_IP_packet_ID++;
				
			/* ICMP reply */
			txbuf->packet[34] = 0;
			
			/* ICMP checksum */
			txbuf->packet[36] = 0;
			txbuf->packet[37] = 0;
			*(UINT16 *)&txbuf->packet[36] = ~Nchksum((UINT16 *)&txbuf->packet[34], (txbuf->len - 34) / 2);
			
   			NIC_SendPacket(txbuf);
   			
   			return 0;
		}

		if ((ip->ippro == IP_PRO_UDP) && (udp->sport == NC2(67)))
			return -1;		/* DHCP packet */

⌨️ 快捷键说明

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