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

📄 ip.c

📁 开发工具用EMBEST IDE进行开发,该程序是一个S3C44B0直接驱动网卡的程序,包括8019初始化,物理层收包发包,UDP的接收和发送,IP的发送和接收.已及ARM的地址解板,整个程序是自顶而下
💻 C
字号:
//-----------------------------------------------------------------------------
// Net IP.C
// This module is the IP layer
// Refer to RFC 791, 1122, and RFC 815 (fragmentation)
//-----------------------------------------------------------------------------
#include "44b.h"
#include "44blib.h"
#include "def.h"
#include "option.h"
#include "ethernet.h"
#include "arp.h"
#include "string.h"
//#include "stdlib.h"
#include "stdio.h"
#include "ip.h"
#include "lib.h"
#include "icmp.h"
#include "udp.h"
extern unsigned char debug;
extern unsigned long my_ipaddr;
struct WAIT  waitq;
char maddr[6] = { 0x00,0x0a,0xe6,0x84,0x2c,0x21};
char * itoa(unsigned short value, char * buf, unsigned char radix)
{
	unsigned short i;
	char * ptr;
	char * temphold;

  	temphold = buf;
	ptr = buf + 12;
	*--ptr = 0;		// Insert NULL char
	do
	{
	   // First create string in reverse order
	   i = (value % radix) + 0x30;
		if(i > 0x39) i += 7;
		*--ptr = i;
      value = value / radix;
  	} while(value != 0);

	// Next, move the string 6 places to the left
	// Include NULL character
	for( ; (*buf++ = *ptr++); );	
	return(temphold);
}


//------------------------------------------------------------------------
// This handles outgoing IP datagrams.  It adds the 20 byte IP header
// and checksum then forwards the IP datagram to the Ethernet layer
// for sending. See "TCP/IP Illustrated, Volume 1" Sect 3.2
//------------------------------------------------------------------------
void ip_send(unsigned char * outbuf, unsigned long ipaddr, unsigned char proto_id, unsigned short len)
{
   struct IP_HEADER  * ip;
   unsigned char  * hwaddr;
   static unsigned short ip_ident = 0;
   
   ip = (struct IP_HEADER  *)(outbuf + 14);
   ip->ver_len = 0x45;          // IPv4 with 20 byte header
   ip->type_of_service = 0;
   ip->total_length = ntohs(20 + len);
   ip->identifier = ntohs(ip_ident++);     // sequential identifier
   ip->fragment_info = 0;           // not fragmented
   ip->time_to_live = 32;           // max hops
   ip->protocol_id = proto_id;      // type of payload
   ip->header_cksum = 0;
   ip->source_ipaddr = htonl(my_ipaddr);
   
   // Outgoing IP address
   ip->dest_ipaddr = ntohl(ipaddr);

   // Compute and insert complement of checksum of ip header
   // Outgoing ip header length is always 20 bytes
   ip->header_cksum = ntohs(~cksum(outbuf + 14, 20));
   
   // Use ARP to get hardware address to send this to
   
   hwaddr = arp_resolve(ntohl(ip->dest_ipaddr));
	
	// Null means that the ARP resolver did not find the IP address
	// in its cache so had to send an ARP request
	
//hwaddr=maddr;
	if (hwaddr == NULL)
	{
		// Fill in the destination information so ehrn the ARP response
		// arrives we can identify it and know what to do when we get it
      waitq.buf = outbuf;
		waitq.ipaddr = ip->dest_ipaddr;
		waitq.proto_id = proto_id;
		waitq.len = len;
		waitq.timer = ARP_TIMEOUT; 
      return;
	}	
	
	eth_send(outbuf, hwaddr, IP_PACKET, 20 + len);
	// EtherOutput(hwaddr, outbuf, 20 + len);
	
//		printf("IP:send  IP packet.\n");
}



//------------------------------------------------------------------------
// This handles incoming IP datagrams from the Ethernet layer
// See "TCP/IP Illustrated, Volume 1" Sect 3.2
//------------------------------------------------------------------------
void ip_rcve(unsigned char  * inbuf)
{
	struct IP_HEADER  * ip;
	unsigned short  header_len, payload_len;
		
   ip = (struct IP_HEADER  *)(inbuf + 14);
            
   // Make sure it is addressed to my IP address
 // 	Uart_Printf("\n  IP->DEST_IPADDR======   %x\n ",ntohl(ip->dest_ipaddr));
 // 		Uart_Printf("\n  my_ipaddr======   %x\n ",my_ipaddr);
   if (ntohl(ip->dest_ipaddr) != my_ipaddr) return;

   // Validate checksum of ip header
	header_len = 4 * (0x0F & ip->ver_len);
//	Uart_Printf("\n  ip  process header_len  %d\n ",header_len);
	payload_len = ntohs(ip->total_length) - header_len;
//	Uart_Printf("\n  ip  payload data len_len  %d\n ",payload_len);
   if (cksum(inbuf + 14, header_len) != 0xFFFF)
	{
//	Uart_Printf(" IP:  Error, cksum bad\n");
	   return; 
   }
//	Uart_Printf("\n IP:  ok, cksum right\n");
	// Make sure incoming message is IP version 4
	if ((ip->ver_len >> 4) != 0x04)
	{
//		if (debug) printf("IP:  Error, not IPv4\n");
//	Uart_Printf("IP:  Error, not IPv4\n");
   	return;
	}
//	Uart_Printf("IP:  right, is IPv4\n");
	// Make sure incoming message is not fragmented because
   // we cannot handle fragmented messages
   if ((ntohl(ip->fragment_info) & 0x3FFF) != 0)
   {
 //     if (debug) printf("IP:  Error, fragmented msg rcvd\n");
 //	Uart_Printf("IP:  Error, fragmented msg rcvd\n");
	   return; 
   }

   // At this point we have received a valid IP datagram addressed
   // to me.  We do not use header options, and do not forward
   // messages, so in the unlikely event there are header options,
   // delete them and shift the data down. The advantage is that
   // layers such as UDP and TCP know where their data starts
	if (header_len > 20)
	{
//		if (debug) printf("IP: Rcvd header > 20 bytes\n");
   			
      // Use memmove because of overlap
      memmove(inbuf + 34, inbuf + 14 + header_len, payload_len);

		// Adjust info to reflect the move
		header_len = 20;
		ip->ver_len = 0x45;
		ip->total_length = 20 + payload_len;
	}
	
	
	// Look at protocol ID byte and call the appropriate
   // function to handle the received message.  See 
   // "TCP/IP Illustrated, Volume 1" Sect 1.7 and RFC 791
   // for values for various protocols
   switch (ip->protocol_id)
	{
	   case ICMP_TYPE:
 //	Uart_Printf("IP:  ICMP pkt rcvd\n");
      icmp_rcve(inbuf, payload_len);
		break;

     case IGMP_TYPE:
		// We cannot handle IGMP messages
//		if (debug) printf("IP:  Error, IGMP pkt rcvd\n");
		break;
		  
		case UDP_TYPE:
		Uart_Printf("IP:  UDP pkt rcvd\n");
	      udp_rcve(inbuf, payload_len);
		break;


      default:
 //     if (debug) printf("IP:  Unknown IP proto id rcvd\n");
      break;
   }
}



⌨️ 快捷键说明

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