added debug output

This commit is contained in:
Markus Fröschle
2013-12-24 16:40:23 +00:00
parent ca041d331b
commit 75677cf1a7
4 changed files with 315 additions and 299 deletions

View File

@@ -1,100 +1,83 @@
/* /*
* File: ip.h * File: ip.h
* Purpose: Definitions for the Internet Protocol, IP. * Purpose: Definitions for the Internet Protocol, IP.
* *
* Notes: See RFC 791 "DARPA Internet Program Protocol * Notes: See RFC 791 "DARPA Internet Program Protocol
* Specification" for more details. * Specification" for more details.
*/ */
#ifndef _IP_H #ifndef _IP_H
#define _IP_H #define _IP_H
/********************************************************************/ /********************************************************************/
/* 32-bit IP Addresses */ /* 32-bit IP Addresses */
typedef uint8_t IP_ADDR[4]; typedef uint8_t IP_ADDR[4];
/* Pointer to an IP Address */ /* Pointer to an IP Address */
typedef uint8_t IP_ADDR_P[]; typedef uint8_t IP_ADDR_P[];
/* Definition of an IP packet header */ /* Definition of an IP packet header */
typedef struct typedef struct
{ {
uint8_t version_ihl; uint8_t version_ihl;
uint8_t service_type; uint8_t service_type;
uint16_t total_length; uint16_t total_length;
uint16_t identification; uint16_t identification;
uint16_t flags_frag_offset; uint16_t flags_frag_offset;
uint8_t ttl; uint8_t ttl;
uint8_t protocol; uint8_t protocol;
uint16_t checksum; uint16_t checksum;
IP_ADDR source_addr; IP_ADDR source_addr;
IP_ADDR dest_addr; IP_ADDR dest_addr;
uint8_t options; /* actually an array of undetermined length */ uint8_t options; /* actually an array of undetermined length */
} ip_frame_hdr; } ip_frame_hdr;
/* Macros for accessing an IP datagram. */ /* Macros for accessing an IP datagram. */
#define IP_VERSION(a) ((a->version_ihl & 0x00F0) >> 4) #define IP_VERSION(a) ((a->version_ihl & 0x00F0) >> 4)
#define IP_IHL(a) ((a->version_ihl & 0x000F)) #define IP_IHL(a) ((a->version_ihl & 0x000F))
#define IP_SERVICE(a) (a->service_type) #define IP_SERVICE(a) (a->service_type)
#define IP_LENGTH(a) (a->total_length) #define IP_LENGTH(a) (a->total_length)
#define IP_IDENT(a) (a->identification) #define IP_IDENT(a) (a->identification)
#define IP_FLAGS(a) ((a->flags_frag_offset & 0x0000E000) >> 13) #define IP_FLAGS(a) ((a->flags_frag_offset & 0x0000E000) >> 13)
#define IP_FRAGMENT(a) ((a->flags_frag_offset & 0x00001FFF)) #define IP_FRAGMENT(a) ((a->flags_frag_offset & 0x00001FFF))
#define IP_TTL(a) (a->ttl) #define IP_TTL(a) (a->ttl)
#define IP_PROTOCOL(a) (a->protocol) #define IP_PROTOCOL(a) (a->protocol)
#define IP_CHKSUM(a) (a->checksum) #define IP_CHKSUM(a) (a->checksum)
#define IP_SRC(a) (&a->source_addr[0]) #define IP_SRC(a) (&a->source_addr[0])
#define IP_DEST(a) (&a->dest_addr[0]) #define IP_DEST(a) (&a->dest_addr[0])
#define IP_OPTIONS(a) (&a->options) #define IP_OPTIONS(a) (&a->options)
#define IP_DATA(a) (&((uint8_t *)a)[IP_IHL(a) * 4]) #define IP_DATA(a) (&((uint8_t *)a)[IP_IHL(a) * 4])
/* Defined IP protocols */ /* Defined IP protocols */
#define IP_PROTO_ICMP (1) #define IP_PROTO_ICMP (1)
#define IP_PROTO_UDP (17) #define IP_PROTO_UDP (17)
/* Protocol Header information */ /* Protocol Header information */
#define IP_HDR_OFFSET ETH_HDR_LEN #define IP_HDR_OFFSET ETH_HDR_LEN
#define IP_HDR_SIZE 20 /* no options */ #define IP_HDR_SIZE 20 /* no options */
/********************************************************************/ /********************************************************************/
typedef struct typedef struct
{ {
IP_ADDR myip; IP_ADDR myip;
IP_ADDR gateway; IP_ADDR gateway;
IP_ADDR netmask; IP_ADDR netmask;
IP_ADDR broadcast; IP_ADDR broadcast;
unsigned int rx; unsigned int rx;
unsigned int rx_unsup; unsigned int rx_unsup;
unsigned int tx; unsigned int tx;
unsigned int err; unsigned int err;
} IP_INFO; } IP_INFO;
/********************************************************************/ /********************************************************************/
void extern void ip_handler(NIF *nif, NBUF *nbf);
ip_handler (NIF *, NBUF *); uint16_t ip_chksum(uint16_t *data, int num);
extern int ip_send(NIF *nif, uint8_t *dest_addr, uint8_t *src_addr, uint8_t protocol, NBUF *nbf);
uint16_t extern void ip_init(IP_INFO *, IP_ADDR_P, IP_ADDR_P, IP_ADDR_P);
ip_chksum (uint16_t *, int); extern uint8_t *ip_get_myip(IP_INFO *);
extern uint8_t *ip_resolve_route(NIF *, IP_ADDR_P);
int
ip_send (NIF *, #endif /* _IP_H */
uint8_t *, /* destination IP */
uint8_t *, /* source IP */
uint8_t, /* protocol */
NBUF * /* buffer descriptor */);
void
ip_init (IP_INFO *, IP_ADDR_P, IP_ADDR_P, IP_ADDR_P);
uint8_t *
ip_get_myip (IP_INFO *);
uint8_t *
ip_resolve_route (NIF *, IP_ADDR_P);
/********************************************************************/
#endif /* _IP_H */

View File

@@ -50,6 +50,7 @@ void bootp_request(NIF *nif, uint8_t *pa)
p->yi_addr = 0x0; p->yi_addr = 0x0;
p->gi_addr = 0x0; p->gi_addr = 0x0;
connection.nif = nif;
addr = &nif->hwa[0]; addr = &nif->hwa[0];
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
p->ch_addr[i] = addr[i]; p->ch_addr[i] = addr[i];

417
net/ip.c
View File

@@ -11,284 +11,303 @@
#include <stddef.h> #include <stddef.h>
#define IP_DEBUG
#if defined(IP_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg); } while (0)
#else
#define dbg(format, arg...) do { ; } while (0)
#endif
void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask) void ip_init(IP_INFO *info, IP_ADDR_P myip, IP_ADDR_P gateway, IP_ADDR_P netmask)
{ {
int index; int index;
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
{ {
info->myip[index] = myip[index]; info->myip[index] = myip[index];
info->gateway[index] = gateway[index]; info->gateway[index] = gateway[index];
info->netmask[index] = netmask[index]; info->netmask[index] = netmask[index];
info->broadcast[index] = 0xFF; info->broadcast[index] = 0xFF;
} }
info->rx = 0; info->rx = 0;
info->rx_unsup = 0; info->rx_unsup = 0;
info->tx = 0; info->tx = 0;
info->err = 0; info->err = 0;
} }
uint8_t *ip_get_myip(IP_INFO *info) uint8_t *ip_get_myip(IP_INFO *info)
{ {
if (info != 0) if (info != 0)
{ {
return (uint8_t *) &info->myip[0]; return (uint8_t *) &info->myip[0];
} }
return 0; dbg("%s: info is NULL!\n\t", __FUNCTION__);
return 0;
} }
int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2) int ip_addr_compare(IP_ADDR_P addr1, IP_ADDR_P addr2)
{ {
int i; int i;
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
if (addr1[i] != addr2[i]) if (addr1[i] != addr2[i])
return 0; return 0;
} }
return 1; return 1;
} }
uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip) uint8_t *ip_resolve_route(NIF *nif, IP_ADDR_P destip)
{ {
/* /*
* This function determines whether or not an outgoing IP * This function determines whether or not an outgoing IP
* packet needs to be transmitted on the local net or sent * packet needs to be transmitted on the local net or sent
* to the router for transmission. * to the router for transmission.
*/ */
IP_INFO *info; IP_INFO *info;
IP_ADDR mask, result; IP_ADDR mask, result;
int i; IP_ADDR bc = { 255, 255, 255, 255 };
int i;
info = nif_get_protocol_info(nif, ETH_FRM_IP); info = nif_get_protocol_info(nif, ETH_FRM_IP);
/* create mask for local IP */ if (memcmp(destip, bc) == 0)
for (i = 0; i < sizeof(IP_ADDR); i++) {
{ dbg("%s: destip is broadcast address, no gateway needed\r\n", __FUNCTION__);
mask[i] = info->myip[i] & info->netmask[i]; return destip;
} }
/* apply mask to the destination IP */ /* create mask for local IP */
for (i = 0; i < sizeof(IP_ADDR); i++) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
result[i] = mask[i] & destip[i]; mask[i] = info->myip[i] & info->netmask[i];
} }
/* See if destination IP is local or not */ /* apply mask to the destination IP */
if (ip_addr_compare(mask, result)) for (i = 0; i < sizeof(IP_ADDR); i++)
{ {
/* The destination IP is on the local net */ result[i] = mask[i] & destip[i];
return arp_resolve(nif, ETH_FRM_IP, destip); }
}
else /* See if destination IP is local or not */
{ if (ip_addr_compare(mask, result))
/* The destination IP is not on the local net */ {
return arp_resolve(nif, ETH_FRM_IP, info->gateway); /* The destination IP is on the local net */
} return arp_resolve(nif, ETH_FRM_IP, destip);
}
else
{
/* The destination IP is not on the local net */
return arp_resolve(nif, ETH_FRM_IP, info->gateway);
}
} }
int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf) int ip_send(NIF *nif, uint8_t *dest, uint8_t *src, uint8_t protocol, NBUF *pNbuf)
{ {
/* /*
* This function assembles an IP datagram and passes it * This function assembles an IP datagram and passes it
* onto the hardware to be sent over the network. * onto the hardware to be sent over the network.
*/ */
uint8_t *route; uint8_t *route;
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
/* /*
* Construct the IP header * Construct the IP header
*/ */
ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET]; ipframe = (ip_frame_hdr*) &pNbuf->data[IP_HDR_OFFSET];
/* IP version 4, Internet Header Length of 5 32-bit words */ /* IP version 4, Internet Header Length of 5 32-bit words */
ipframe->version_ihl = 0x45; ipframe->version_ihl = 0x45;
/* Type of Service == 0, normal and routine */ /* Type of Service == 0, normal and routine */
ipframe->service_type = 0x00; ipframe->service_type = 0x00;
/* Total length of data */ /* Total length of data */
ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE); ipframe->total_length = (uint16_t) (pNbuf->length + IP_HDR_SIZE);
/* User defined identification */ /* User defined identification */
ipframe->identification = 0x0000; ipframe->identification = 0x0000;
/* Fragment Flags and Offset -- Don't fragment, last frag */ /* Fragment Flags and Offset -- Don't fragment, last frag */
ipframe->flags_frag_offset = 0x0000; ipframe->flags_frag_offset = 0x0000;
/* Time To Live */ /* Time To Live */
ipframe->ttl = 0xFF; ipframe->ttl = 0xFF;
/* Protocol */ /* Protocol */
ipframe->protocol = protocol; ipframe->protocol = protocol;
/* Checksum, computed later, zeroed for computation */ /* Checksum, computed later, zeroed for computation */
ipframe->checksum = 0x0000; ipframe->checksum = 0x0000;
/* source IP address */ /* source IP address */
ipframe->source_addr[0] = src[0]; ipframe->source_addr[0] = src[0];
ipframe->source_addr[1] = src[1]; ipframe->source_addr[1] = src[1];
ipframe->source_addr[2] = src[2]; ipframe->source_addr[2] = src[2];
ipframe->source_addr[3] = src[3]; ipframe->source_addr[3] = src[3];
/* dest IP address */ /* dest IP address */
ipframe->dest_addr[0] = dest[0]; ipframe->dest_addr[0] = dest[0];
ipframe->dest_addr[1] = dest[1]; ipframe->dest_addr[1] = dest[1];
ipframe->dest_addr[2] = dest[2]; ipframe->dest_addr[2] = dest[2];
ipframe->dest_addr[3] = dest[3]; ipframe->dest_addr[3] = dest[3];
/* Compute checksum */ /* Compute checksum */
ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE); ipframe->checksum = ip_chksum((uint16_t *) ipframe, IP_HDR_SIZE);
/* Increment the packet length by the size of the IP header */ /* Increment the packet length by the size of the IP header */
pNbuf->length += IP_HDR_SIZE; pNbuf->length += IP_HDR_SIZE;
/* /*
* Determine the hardware address of the recipient * Determine the hardware address of the recipient
*/ */
IP_ADDR bc = { 255, 255, 255, 255}; IP_ADDR bc = { 255, 255, 255, 255};
if (memcmp(bc, dest, 4) != 0) if (memcmp(bc, dest, 4) != 0)
{ {
route = ip_resolve_route(nif, dest); route = ip_resolve_route(nif, dest);
if (route == NULL) if (route == NULL)
{ {
xprintf("Unable to locate %d.%d.%d.%d\n", dbg("Unable to locate %d.%d.%d.%d\n",
dest[0], dest[1], dest[2], dest[3]); dest[0], dest[1], dest[2], dest[3]);
return 0; return 0;
} }
} }
else else
{
route = bc; route = bc;
dbg("%s: route = broadcast\r\n", __FUNCTION__);
dbg("%s: nif = %p\r\n", __FUNCTION__, nif);
dbg("%s: nif->send = %p\n\t", __FUNCTION__, nif->send);
}
return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf); return nif->send(nif, route, &nif->hwa[0], ETH_FRM_IP, pNbuf);
} }
#if defined(DEBUG_PRINT) #if defined(DEBUG_PRINT)
void void dump_ip_frame(ip_frame_hdr *ipframe)
dump_ip_frame (ip_frame_hdr *ipframe)
{ {
printf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4)); xprintf("Version: %02X\n", ((ipframe->version_ihl & 0x00f0) >> 4));
printf("IHL: %02X\n", ipframe->version_ihl & 0x000f); xprintf("IHL: %02X\n", ipframe->version_ihl & 0x000f);
printf("Service: %02X\n", ipframe->service_type); xprintf("Service: %02X\n", ipframe->service_type);
printf("Length: %04X\n", ipframe->total_length); xprintf("Length: %04X\n", ipframe->total_length);
printf("Ident: %04X\n", ipframe->identification); xprintf("Ident: %04X\n", ipframe->identification);
printf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14)); xprintf("Flags: %02X\n", ((ipframe->flags_frag_offset & 0xC000) >> 14));
printf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF); xprintf("Frag: %04X\n", ipframe->flags_frag_offset & 0x3FFF);
printf("TTL: %02X\n", ipframe->ttl); xprintf("TTL: %02X\n", ipframe->ttl);
printf("Protocol: %02X\n", ipframe->protocol); xprintf("Protocol: %02X\n", ipframe->protocol);
printf("Chksum: %04X\n", ipframe->checksum); xprintf("Chksum: %04X\n", ipframe->checksum);
printf("Source : %d.%d.%d.%d\n", xprintf("Source : %d.%d.%d.%d\n",
ipframe->source_addr[0], ipframe->source_addr[0],
ipframe->source_addr[1], ipframe->source_addr[1],
ipframe->source_addr[2], ipframe->source_addr[2],
ipframe->source_addr[3]); ipframe->source_addr[3]);
printf("Dest : %d.%d.%d.%d\n", xprintf("Dest : %d.%d.%d.%d\n",
ipframe->dest_addr[0], ipframe->dest_addr[0],
ipframe->dest_addr[1], ipframe->dest_addr[1],
ipframe->dest_addr[2], ipframe->dest_addr[2],
ipframe->dest_addr[3]); ipframe->dest_addr[3]);
printf("Options: %08X\n", ipframe->options); xprintf("Options: %08X\n", ipframe->options);
} }
#endif #endif
uint16_t ip_chksum(uint16_t *data, int num) uint16_t ip_chksum(uint16_t *data, int num)
{ {
int chksum, ichksum; int chksum, ichksum;
uint16_t temp; uint16_t temp;
chksum = 0; chksum = 0;
num = num >> 1; /* from bytes to words */ num = num >> 1; /* from bytes to words */
for (; num; num--, data++) for (; num; num--, data++)
{ {
temp = *data; temp = *data;
ichksum = chksum + temp; ichksum = chksum + temp;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
if ((ichksum < temp) || (ichksum < chksum)) if ((ichksum < temp) || (ichksum < chksum))
{ {
ichksum += 1; ichksum += 1;
ichksum = ichksum & 0x0000FFFF; ichksum = ichksum & 0x0000FFFF;
} }
chksum = ichksum; chksum = ichksum;
} }
return (uint16_t) ~chksum; return (uint16_t) ~chksum;
} }
static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe) static int validate_ip_hdr(NIF *nif, ip_frame_hdr *ipframe)
{ {
int index, chksum; int index, chksum;
IP_INFO *info; IP_INFO *info;
/* /*
* Check the IP Version * Check the IP Version
*/ */
if (IP_VERSION(ipframe) != 4) if (IP_VERSION(ipframe) != 4)
return 0; return 0;
/* /*
* Check Internet Header Length * Check Internet Header Length
*/ */
if (IP_IHL(ipframe) < 5) if (IP_IHL(ipframe) < 5)
return 0; return 0;
/* /*
* Check the destination IP address * Check the destination IP address
*/ */
info = nif_get_protocol_info(nif,ETH_FRM_IP); info = nif_get_protocol_info(nif,ETH_FRM_IP);
for (index = 0; index < sizeof(IP_ADDR); index++) for (index = 0; index < sizeof(IP_ADDR); index++)
if (info->myip[index] != ipframe->dest_addr[index]) if (info->myip[index] != ipframe->dest_addr[index])
return 0; return 0;
/* /*
* Check the checksum * Check the checksum
*/ */
chksum = (int)((uint16_t) IP_CHKSUM(ipframe)); chksum = (int)((uint16_t) IP_CHKSUM(ipframe));
IP_CHKSUM(ipframe) = 0; IP_CHKSUM(ipframe) = 0;
if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum) if (ip_chksum((uint16_t *) ipframe, IP_IHL(ipframe) * 4) != chksum)
return 0; return 0;
IP_CHKSUM(ipframe) = (uint16_t) chksum; IP_CHKSUM(ipframe) = (uint16_t) chksum;
return 1; return 1;
} }
void ip_handler(NIF *nif, NBUF *pNbuf) void ip_handler(NIF *nif, NBUF *pNbuf)
{ {
/* /*
* IP packet handler * IP packet handler
*/ */
ip_frame_hdr *ipframe; ip_frame_hdr *ipframe;
ipframe = (ip_frame_hdr *)&pNbuf->data[pNbuf->offset]; ipframe = (ip_frame_hdr *) &pNbuf->data[pNbuf->offset];
/* /*
* Verify valid IP header and destination IP * Verify valid IP header and destination IP
*/ */
if (!validate_ip_hdr(nif, ipframe)) if (!validate_ip_hdr(nif, ipframe))
{ {
nbuf_free(pNbuf); nbuf_free(pNbuf);
return; return;
} }
pNbuf->offset += (IP_IHL(ipframe) * 4); pNbuf->offset += (IP_IHL(ipframe) * 4);
pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4)); pNbuf->length = (uint16_t)(IP_LENGTH(ipframe) - (IP_IHL(ipframe) * 4));
/* /*
* Call the appriopriate handler * Call the appriopriate handler
*/ */
switch (IP_PROTOCOL(ipframe)) switch (IP_PROTOCOL(ipframe))
{ {
case IP_PROTO_ICMP: case IP_PROTO_ICMP:
// FIXME: icmp_handler(nif,pNbuf); // FIXME: icmp_handler(nif,pNbuf);
break; break;
case IP_PROTO_UDP: case IP_PROTO_UDP:
udp_handler(nif,pNbuf); udp_handler(nif,pNbuf);
break; break;
default: default:
nbuf_free(pNbuf); nbuf_free(pNbuf);
break; break;
} }
return; return;
} }

View File

@@ -11,6 +11,13 @@
#include "net.h" #include "net.h"
#include <stddef.h> #include <stddef.h>
#define UDP_DEBUG
#if defined(UDP_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg); } while (0)
#else
#define dbg(format, arg...) do { ; } while (0)
#endif
typedef struct typedef struct
{ {
uint16_t port; uint16_t port;
@@ -99,6 +106,12 @@ uint16_t udp_obtain_free_port(void)
int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf) int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
{ {
if (nif == NULL)
{
dbg("%s: nif is NULL\r\n", __FUNCTION__);
return 0;
}
/* /*
* This function takes data and creates a UDP frame and * This function takes data and creates a UDP frame and
* passes it onto the IP layer * passes it onto the IP layer