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

📄 network.c

📁 embedded ethernet code for pic18F
💻 C
字号:
// module implementing IP, ICMP and ARP

#include <p18cxxx.h>
#include "nic.h"
#include "network.h"
#include <usart.h>

unsigned char myMACAddress[6];
unsigned char myIPAddress[4];
unsigned char myIPSubnetBroadcast[4];
unsigned char broadcastIP[4]={255,255,255,255};

//******************************************************************
//*	Ethernet Header Layout
//******************************************************************
#define	enetpacketDest0	   0x00  //destination mac address
#define	enetpacketDest1	   0x01
#define	enetpacketDest2	   0x02
#define	enetpacketDest3	   0x03
#define	enetpacketDest4	   0x04
#define	enetpacketDest5	   0x05
#define	enetpacketSrc0		   0x06  //source mac address
#define	enetpacketSrc1		   0x07
#define	enetpacketSrc2		   0x08
#define	enetpacketSrc3		   0x09
#define	enetpacketSrc4		   0x0A
#define	enetpacketSrc5		   0x0B
#define	enetpacketType0	   0x0C  //type/length field
#define	enetpacketType1	   0x0D
#define  enetpacketData       0x0E  //IP data area begins here
//******************************************************************
//*	ARP Layout
//******************************************************************
#define	arp_hwtype			   0x0E
#define	arp_prtype			   0x10
#define	arp_hwlen			   0x12
#define	arp_prlen			   0x13
#define	arp_op				   0x14
#define	arp_shaddr			   0x16   //arp source mac address
#define	arp_sipaddr			   0x1C   //arp source ip address
#define	arp_thaddr			   0x20   //arp target mac address
#define	arp_tipaddr			   0x26   //arp target ip address
//******************************************************************
//*	IP Header Layout
//******************************************************************
#define	ip_vers_len			   0x0E	//IP version and header length
#define	ip_tos				   0x0F	//IP type of service
#define	ip_pktlen			   0x10	//packet length
#define	ip_id				      0x12	//datagram id
#define	ip_frag_offset			0x14	//fragment offset
#define	ip_ttl				   0x16	//time to live
#define	ip_proto			      0x17	//protocol (ICMP=1, TCP=6, UDP=11)
#define	ip_hdr_cksum			0x18	//header checksum
#define	ip_srcaddr			   0x1A	//IP address of source
#define	ip_destaddr			   0x1E	//IP address of destination
#define	ip_data				   0x22	//IP data area
//******************************************************************
//*	ICMP Header
//******************************************************************
#define	ICMP_type			   ip_data
#define	ICMP_code			   ICMP_type+1
#define	ICMP_cksum			   ICMP_code+1
#define	ICMP_id				   ICMP_cksum+2
#define	ICMP_seqnum			   ICMP_id+2
#define  ICMP_data            ICMP_seqnum+2
//******************************************************************
//*	IP Protocol Types
//******************************************************************
#define	PROT_ICMP			   0x01
#define	PROT_TCP			      0x06
#define	PROT_UDP			      0x11

#define ARP_PACKET 1
#define IP_PACKET 2
#define INVALID_PACKET 0



// Network layer.
//
// Handles IP, ARP and ICMP.  
//

/* initialise the network layer */




void initNetworkLayer(const rom unsigned char *mac,const rom unsigned char *ip,const rom unsigned char *netmask)
{
	unsigned char i;
	
	for(i=0;i<6;i++) myMACAddress[i]=mac[i];
	initNIC(mac);
	
	for(i=0;i<4;i++)
	{
		myIPAddress[i]=ip[i];
		myIPSubnetBroadcast[i]=ip[i]|(0xff^netmask[i]);
	}
	//putrsUSART("MY IP is ");
	//for(i=0;i<4;i++) printByte(myIPAddress[i]);
	//putrsUSART("\r\n");
	//putrsUSART("MY netmask is ");
	//for(i=0;i<4;i++) printByte(myIPSubnetBroadcast[i]);
	//putrsUSART("\r\n");
	//putrsUSART("MY MAC is ");
	//for(i=0;i<6;i++) printByte(myMACAddress[i]);
	//putrsUSART("\r\n");
}

void getIPDatagramSourceAddr(unsigned char *packet,unsigned char *sourceMAC,unsigned char *sourceIP)
{
	unsigned char i;
	
	for(i=0;i<6;i++) sourceMAC[i]=packet[enetpacketSrc0+i];
	for(i=0;i<4;i++) sourceIP[i]=packet[ip_srcaddr+i];
}



void buildEthernetHeader(unsigned char *packet,unsigned char *destMAC,unsigned char type)
{
	unsigned char i;
	
	for(i=0;i<6;i++) 
	{
		packet[enetpacketDest0+i]=destMAC[i];
		packet[enetpacketSrc0+i]=myMACAddress[i];
	}
	packet[enetpacketType0]=0x08;
	if(type==ARP_PACKET) packet[enetpacketType1]=0x06;
	else if(type==IP_PACKET) packet[enetpacketType1]=0x00;
}


//******************************************************************
//*	CHECKSUM CALCULATION ROUTINE
//******************************************************************
unsigned long computeIPChecksum(unsigned char *addr,unsigned long hdr_chksum,unsigned int h)
{
	unsigned int chksum16;
	unsigned char data_H,data_L;
	
      while(h > 1)
      {
         data_H=*addr++;
         data_L=*addr++;
         chksum16=(((unsigned int)data_H)<<8)|data_L;
         hdr_chksum = hdr_chksum + chksum16;
         h -=2;
      }
      if(h > 0)
      {
         data_H=*addr;
         data_L=0x00;
         chksum16=(((unsigned int)data_H)<<8)|data_L;
         hdr_chksum = hdr_chksum + chksum16;
      }
      
      return hdr_chksum;
}

 
void buildIPDatagramHeader(unsigned char *packet,unsigned char *destMAC,unsigned char *destIP,unsigned char type)
{
	unsigned char i;
	unsigned long hdr_chksum;
	unsigned int chksum16;
	
	buildEthernetHeader(packet,destMAC,IP_PACKET);
	for(i=0;i<4;i++)
	{
		packet[ip_destaddr+i]=destIP[i];
		packet[ip_srcaddr+i]=myIPAddress[i];
	}
	if(type==ICMP) packet[ip_proto]=PROT_ICMP;
	else if(type==TCP) packet[ip_proto]=PROT_TCP;
	else if(type==UDP) packet[ip_proto]=PROT_UDP;
	
	packet[ip_hdr_cksum]=0x00;
    packet[ip_hdr_cksum+1]=0x00;
	hdr_chksum=computeIPChecksum(packet+ip_vers_len,0,(packet[ip_vers_len] & 0x0F) * 4);
    chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
    packet[ip_hdr_cksum] = (chksum16>>8)&0xff;
    packet[ip_hdr_cksum+1] = chksum16&0xff;
}



	
unsigned char matchIP(unsigned char *IP1,unsigned char *IP2)
{
	unsigned char i;
	
	for(i=0;i<4;i++) if(IP1[i]!=IP2[i]) return 0;
	return 1;
}



unsigned char getIPDatagramType(unsigned char *packet)
{
	//putrsUSART("Discriminating on protocol type ");printByte(packet[ip_proto]);putrsUSART(" ");
	switch(packet[ip_proto])
	{
		case PROT_UDP:
			return UDP;
			break;
		case PROT_TCP:
			return TCP;
			break;
		default:
			return INVALID;
			break;
	}
}





unsigned char matchIPDatagramAddress(unsigned char *packet)
{
	if(matchIP(packet+ip_destaddr,myIPAddress)) return UNICAST;
	if(matchIP(packet+ip_destaddr,myIPSubnetBroadcast)) return BROADCAST_SUBNET;
	if(matchIP(packet+ip_destaddr,broadcastIP)) return BROADCAST;
	return NO_MATCH;
}


unsigned int getIPDatagramLength(unsigned char *packet)
{
	return (((unsigned int)packet[ip_pktlen])<<8)|packet[ip_pktlen+1];
}

void setIPDatagramLength(unsigned char *packet,unsigned int ip_packet_len)
{
	packet[ip_pktlen] = (ip_packet_len>>8)&0xff;
    packet[ip_pktlen+1] = ip_packet_len&0xff;
}

unsigned int getIPDatagramPayloadLength(unsigned char *packet)
{
	return getIPDatagramLength(packet) - ((packet[ip_vers_len] & 0x0F) * 4);
}

unsigned long computeIPContributionToChecksum(unsigned char *packet)
{
	return computeIPChecksum(packet+ip_srcaddr,0,0x08)+packet[ip_proto];
}


    
   
   
	
	
      
      
      
	
//******************************************************************
//*	SEND ARP RESPONSE
//******************************************************************

void handleARP(unsigned char *packet)
{
	unsigned char i;
	
	buildEthernetHeader(packet,packet+enetpacketSrc0,ARP_PACKET);
	//setMAC(MYMAC,packet+enetpacketSrc0);
	//packet[enetpacketType0]=0x08;
	//packet[enetpacketType1]=0x06;
	
	packet[arp_hwtype]=0x00;
    packet[arp_hwtype+1]=0x01;

    packet[arp_prtype]=0x08;
    packet[arp_prtype+1]=0x00;

    packet[arp_hwlen]=0x06;
    packet[arp_prlen]=0x04;

    packet[arp_op]=0x00;
    packet[arp_op+1]=0x02;
   
    for(i=0;i<6;i++)
    {
	   packet[arp_shaddr+i]=myMACAddress[i];
	   packet[arp_thaddr+i]=packet[enetpacketDest0+i];
    }
    for(i=0;i<4;i++) 
    {
	    packet[arp_tipaddr+i]=packet[arp_sipaddr+i];
        packet[arp_sipaddr+i]=myIPAddress[i];
    }
    echo_packet((unsigned int)34,packet);
}

//******************************************************************
//*	PING (Tiger Woods' putter)
//******************************************************************
void handleICMP(unsigned char *packet,signed int rxlen)
{
	unsigned long hdr_chksum;
	unsigned int chksum16;
	
   //set echo reply
   packet[ICMP_type]=0x00;
   packet[ICMP_code]=0x00;

   //clear the ICMP checksum
   packet[ICMP_cksum ]=0x00;
   packet[ICMP_cksum+1]=0x00;

   //setup the IP header
   buildIPDatagramHeader(packet,packet+enetpacketSrc0,packet+ip_srcaddr,ICMP);

   //calculate the ICMP checksum
   
   //hdrlen = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) - ((packet[ip_vers_len] & 0x0F) * 4);
   //addr = &packet[ICMP_type];
   hdr_chksum=computeIPChecksum(packet+ICMP_type,0,((((unsigned int)packet[ip_pktlen])<<8)|packet[ip_pktlen+1]) - ((packet[ip_vers_len] & 0x0F) * 4));
   chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
   packet[ICMP_cksum] = (chksum16>>8)&0xff;
   packet[ICMP_cksum+1] = chksum16&0xff;

   echo_packet(rxlen,packet);
   
   //if(debug) putrsUSART("PING - sent response\r\n");
}
#define MAX_PACKET_LENGTH 512
		
		
signed int handleNetworkLayer(unsigned char *packet)
{
    signed int rxlen;
    unsigned char lenH,lenL,c,type;
    
    rxlen=getPacket(MAX_PACKET_LENGTH,packet);
   
   // ARP - handle internally
   
   if(packet[enetpacketType0] == 0x08 && packet[enetpacketType1] == 0x06)
   {
      if(packet[arp_hwtype+1] == 0x01 &&
      packet[arp_prtype] == 0x08 && packet[arp_prtype+1] == 0x00 &&
      packet[arp_hwlen] == 0x06 && packet[arp_prlen] == 0x04 &&
      packet[arp_op+1] == 0x01 && matchIP(myIPAddress,packet+arp_tipaddr))
      {
	      //putrsUSART("ARP broadcast - matched & responding\r\n");
	      handleARP(packet);
      }
      //else putrsUSART("ARP broadcast\r\n");
	  return 0;
	}
   
   // IP - do ICMP internally, hand off TCP and UDP to higher layers
   
   else if((packet[enetpacketType0] == 0x08 && packet[enetpacketType1] == 0x00) && (matchIPDatagramAddress(packet)!=NO_MATCH))
   {
	  if(packet[ip_proto]==PROT_ICMP)
	  {
		  //putrsUSART("ICMP\r\n");
		  handleICMP(packet,rxlen);
		  return 0;
	  }
	  else return rxlen;
   }

   //trash the frame
   else
   {
	   //putrsUSART("Unknown\r\n");
	   ignoreFrame();
	   return 0;
	}
   
}

⌨️ 快捷键说明

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