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