📄 network.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 + -