Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

ip.c File Reference

IP (Internet Protocol) layer. More...

#include <const.h>
#include <ctype.h>
#include <errno.h>
#include <arch/mem.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/kmalloc.h>
#include <net/arp.h>
#include <net/eth.h>
#include <net/icmp.h>
#include <net/network.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <net/ip.h>

Go to the source code of this file.

Functions

uint16_t ip_checksum (const void *buf, size_t hdr_len)
 Calculate the IP header checksum.
Parameters:
buf  The IP header content.
hdr_len  The IP header length.
Returns:
The result of the checksum.


void dump_ip_packet (ip_t *packet)
 Dump an IP packet to the standard output.
Parameters:
packet  The IP packet.


void set_host_ip_net (in_addr_t ip, in_addr_t netmask)
 Set the IP and netmask for this host.
Parameters:
ip  The IP address in network format.
netmask  The netmask in network format.


in_addr_t get_host_ip ()
 Get the IP address of this host.
Returns:
The IP address expressed in network format.


in_addr_t get_host_netmask ()
 Get the netmask of this host.
Returns:
The netmask expressed in network format.


in_addr_t get_host_bcast ()
 Get the broadcast address of the local network.
Returns:
The broadcast address of this local network expressed in network format.


int inet_aton (const char *cp, in_addr_t *inp)
 Converts an internet IP addres from number-and-dot string notation into binary data network byte order.
Parameters:
cp  The string of the number-and-dot notation IP address.
inp  The destination where the binary network byte order address will be put.
Returns:
Nonzero if the address is valid, zero if not.


void to_ip_layer (ip_t *packet)
 Process an IP packet received from the ethernet layer.
Parameters:
packet  The IP packet.


int send_ip_packet (uint32_t ip_to, const void *data, size_t len, uint8_t ttl, uint8_t proto)
 Send an IP packet to the ethernet layer.
Parameters:
ip_to  The IP destination address in network format.
data  The buffer of data to be sent.
len  The size of the buffer to be sent.
ttl  TTL (Time To Live).
proto  The upper-layer protocol type.
Returns:
  • The number of bytes sent in case of success;
  • -EMSGSIZE the packet is too big to be sent;
  • -ENOMEM cannot allocate the packet structure;
  • -ENETUNREACH destination address not found;.


int recv_ip_packet (ip_t *buf, size_t len)
 Receive an IP packet.
Parameters:
buf  The buffer where the received packet will be copied.
len  The maximum size of the buffer.
Returns:
The size of the packet received in bytes.



Variables

in_addr_t host_ip
 This is the IP address of this host (expressed in network format).

in_addr_t host_netmask
 This is the IP netmask of this host (expressed in network format).


Detailed Description

IP (Internet Protocol) layer.

Author:
Andrea Righi <drizzt@inwind.it>
Date:
Last update: 2003-11-09
Note:
Copyright (©) 2003 Andrea Righi

Definition in file ip.c.


Function Documentation

void dump_ip_packet ip_t   packet
 

Dump an IP packet to the standard output.

Parameters:
packet  The IP packet.

Definition at line 53 of file ip.c.

00054 {
00055         int i;
00056         uint8_t *data = ((void *)packet + (packet->ip_hdr_len * sizeof(uint32_t)));
00057 
00058         // Dump the IP header                                           //
00059         kprintf(        "\n\r(ip header)"
00060                 "\n\rhdr_len:%u dwords, ip_version:%u, ToS:%#04X, tot_len:%u"
00061                 "\n\rid:%#010x, off:%#010x, TTL:%u, proto:%#04X, ip_chk:%#06X"
00062                 "\n\rip_src:%u.%u.%u.%u, ip_dst:%u.%u.%u.%u",
00063                 packet->ip_hdr_len, packet->ip_version, packet->ip_tos,
00064                 ntohs(packet->ip_len), ntohs(packet->ip_id), ntohs(packet->ip_off),
00065                 packet->ip_ttl, packet->ip_proto,
00066                 ntohs(packet->ip_chk),
00067 
00068                 IP_A(ntohl(packet->ip_src)), IP_B(ntohl(packet->ip_src)),
00069                 IP_C(ntohl(packet->ip_src)), IP_D(ntohl(packet->ip_src)),
00070 
00071                 IP_A(ntohl(packet->ip_dst)), IP_B(ntohl(packet->ip_dst)),
00072                 IP_C(ntohl(packet->ip_dst)), IP_D(ntohl(packet->ip_dst))
00073         );
00074         // Dump the IP data section                                     //
00075         kprintf("\n\r(ip data)\n\r");
00076         for (i=0; i<(ntohs(packet->ip_len) - packet->ip_hdr_len * sizeof(uint32_t)); i++)
00077                 if ( isprint(data[i]) )
00078                         kputchar(data[i]);
00079                 else
00080                         kputchar('.');
00081 }

in_addr_t get_host_bcast  
 

Get the broadcast address of the local network.

Returns:
The broadcast address of this local network expressed in network format.

Definition at line 117 of file ip.c.

00118 {
00119         return( (~host_netmask) | (host_ip & host_netmask) );
00120 }

in_addr_t get_host_ip  
 

Get the IP address of this host.

Returns:
The IP address expressed in network format.

Definition at line 100 of file ip.c.

00101 {
00102         return( host_ip );
00103 }

in_addr_t get_host_netmask  
 

Get the netmask of this host.

Returns:
The netmask expressed in network format.

Definition at line 108 of file ip.c.

00109 {
00110         return( host_netmask );
00111 }

int inet_aton const char *    cp,
in_addr_t   inp
 

Converts an internet IP addres from number-and-dot string notation into binary data network byte order.

Parameters:
cp  The string of the number-and-dot notation IP address.
inp  The destination where the binary network byte order address will be put.
Returns:
Nonzero if the address is valid, zero if not.

Definition at line 131 of file ip.c.

00132 {
00133         static const in_addr_t max[4] = { 0xFFFFFFFF, 0xFFFFFF, 0xFFFF, 0xFF };
00134         in_addr_t val;
00135         char c;
00136         union iaddr {
00137           uint8_t bytes[4];
00138           uint32_t word;
00139         } res;
00140         uint8_t *pp = res.bytes;
00141         int digit,base;
00142 
00143         res.word = 0;
00144 
00145         c = *cp;
00146         for (;;) {
00147                 // Collect number up to '.'                             //
00148                 // Values are specified as for C:                       //
00149                 // 0x=hex, 0=octal, isdigit=decimal.                    //
00150                 if (!isdigit(c)) goto ret_0;
00151                 val = 0; base = 10; digit = 0;
00152                 for (;;) {
00153                         if (isdigit(c)) {
00154                                 val = (val * base) + (c - '0');
00155                                 c = *++cp;
00156                                 digit = 1;
00157                         } else {
00158                                 break;
00159                         }
00160                 }
00161                 if (c == '.') {
00162                         // Internet format:                             //
00163                         //      a.b.c.d                                 //
00164                         //      a.b.c   (with c treated as 16 bits)     //
00165                         //      a.b     (with b treated as 24 bits)     //
00166                         if (pp > res.bytes + 2 || val > 0xff) {
00167                                 goto ret_0;
00168                         }
00169                         *pp++ = val;
00170                         c = *++cp;
00171                 } else
00172                         break;
00173         }
00174 
00175         // Check for trailing characters                                //
00176         if (c != '\0' && (!isascii(c) || !isspace(c))) {
00177                 goto ret_0;
00178         }
00179 
00180         // Did we get a valid digit?                                    //
00181         if (!digit) {
00182                 goto ret_0;
00183         }
00184 
00185         // Check whether the last part is in its limits depending on    //
00186         // the number of parts in total.                                //
00187         if (val > max[pp - res.bytes]) {
00188                 goto ret_0;
00189         }
00190 
00191         if (inp != NULL) {
00192                 *inp = res.word | htonl (val);
00193         }
00194 
00195         return (1);
00196 ret_0:
00197         return (0);
00198 }

uint16_t ip_checksum const void *    buf,
size_t    hdr_len
 

Calculate the IP header checksum.

Parameters:
buf  The IP header content.
hdr_len  The IP header length.
Returns:
The result of the checksum.

Definition at line 31 of file ip.c.

00032 {
00033         unsigned long sum = 0;
00034         const uint16_t *ip1;
00035 
00036         ip1 = buf;
00037         while (hdr_len > 1)
00038         {
00039                 sum += *ip1++;
00040                 if (sum & 0x80000000)
00041                         sum = (sum & 0xFFFF) + (sum >> 16);
00042                 hdr_len -= 2;
00043         }
00044 
00045         while (sum >> 16)
00046                 sum = (sum & 0xFFFF) + (sum >> 16);
00047 
00048         return(~sum);
00049 }

int recv_ip_packet ip_t   buf,
size_t    len
 

Receive an IP packet.

Parameters:
buf  The buffer where the received packet will be copied.
len  The maximum size of the buffer.
Returns:
The size of the packet received in bytes.

Todo:
Routine not implemented! For now return protocol not available error.

Definition at line 347 of file ip.c.

00348 {
00349         return( -ENOPROTOOPT );
00350 }

int send_ip_packet uint32_t    ip_to,
const void *    data,
size_t    len,
uint8_t    ttl,
uint8_t    proto
 

Send an IP packet to the ethernet layer.

Parameters:
ip_to  The IP destination address in network format.
data  The buffer of data to be sent.
len  The size of the buffer to be sent.
ttl  TTL (Time To Live).
proto  The upper-layer protocol type.
Returns:
  • The number of bytes sent in case of success;
  • -EMSGSIZE the packet is too big to be sent;
  • -ENOMEM cannot allocate the packet structure;
  • -ENETUNREACH destination address not found;.

Definition at line 273 of file ip.c.

00274 {
00275         uint8_t eth_to[ETH_ADDR_LEN];
00276         size_t packet_len = len + sizeof(ip_t);
00277         ip_t *packet;
00278         int tot_len;
00279 
00280         if (packet_len > IP_FRAME_LEN)
00281                 return(-EMSGSIZE);
00282 
00283         packet = kmalloc(packet_len);
00284         if (packet == NULL)
00285                 return(-ENOMEM);
00286 
00287         // Create the IP header                                         //
00288         packet->ip_version = IP_V4;
00289         packet->ip_hdr_len = sizeof(ip_t) / sizeof(dword);
00290         packet->ip_tos = 0;
00291         packet->ip_len = htons(packet_len);
00292         packet->ip_id = htons(0xDEAD);  // :-) //
00293         packet->ip_off = htons(IP_FLAG_DF | 0);
00294         packet->ip_ttl = ttl;
00295         packet->ip_proto = proto;
00296         packet->ip_chk = 0;
00297         packet->ip_dst = ip_to;
00298         packet->ip_src = get_host_ip();
00299         packet->ip_chk = ip_checksum(packet, sizeof(ip_t));
00300 
00301         // Copy the data into the packet                                //
00302         memcpy(packet + 1, data, len);
00303 
00304         // Translate the IP address into ethernet address               //
00305         // using the ARP protocol.                                      //
00306         if ( !arp_ip_to_eth(eth_to, ip_to) )
00307         {
00308                 #ifdef DEBUG
00309                 kprintf("\n\rARP fails!");
00310                 #endif
00311                 // The ethernet address was not found!                  //
00312                 return(-ENETUNREACH);
00313         }
00314         #ifdef DEBUG
00315         kprintf("\n\rsending eth packet to %02x:%02x:%02x:%02x:%02x:%02x...",
00316                 eth_to[0], eth_to[1], eth_to[2], eth_to[3], eth_to[4], eth_to[5]
00317         );
00318         #endif
00319 
00320         // Go to the ethernet layer...                                  //
00321         tot_len = send_eth_packet(eth_to, packet, packet_len, htons(ETH_FRAME_IP));
00322 
00323         #ifdef DEBUG
00324         kprintf("\n\r%u bytes sent from ethernet layer", tot_len);
00325         #endif
00326 
00327         // Free the memory of the packet                                //
00328         kfree(packet);
00329 
00330         if ( tot_len < 0 )
00331                 // Something wrong from at the ethernet layer           //
00332                 return(tot_len);
00333 
00334         // Well done!                                                   //
00335         return(packet_len);
00336 }

void set_host_ip_net in_addr_t    ip,
in_addr_t    netmask
 

Set the IP and netmask for this host.

Parameters:
ip  The IP address in network format.
netmask  The netmask in network format.

Definition at line 91 of file ip.c.

00092 {
00093         host_ip = ip;
00094         host_netmask = netmask;
00095 }

void to_ip_layer ip_t   packet
 

Process an IP packet received from the ethernet layer.

Parameters:
packet  The IP packet.

Definition at line 202 of file ip.c.

00203 {
00204         // Calculate the header checksum                                //
00205         if ( ip_checksum(packet, packet->ip_hdr_len * sizeof(dword)) )
00206         {
00207                 kprintf("\n\rip header checksum error!!!");
00208                 return;
00209         }
00210 
00211         //--------------------------------------------------------------//
00212         // Check if we can receive the packet or not                    //
00213         if (
00214                 (packet->ip_dst!=get_host_ip()) &&
00215                 (packet->ip_dst!=get_host_bcast()) &&
00216                 (packet->ip_dst!=INADDR_BROADCAST)
00217         )
00218                 return;
00219         //--------------------------------------------------------------//
00220 
00221         // Identify the right protocol                                  //
00222         switch( packet->ip_proto )
00223         {
00224                 case IPPROTO_ICMP:
00225                         // ICMP (Internet Control Message Protocol)     //
00226                         to_icmp_layer(packet);
00227                 break;
00228 
00229                 case IPPROTO_IGMP:
00230                         // Internet Group Message Protocol)             //
00231                         kprintf("\n\rIGMP protocol not yet implemented!");
00232                         dump_ip_packet(packet);
00233                 break;
00234 
00235                 case IPPROTO_TCP:
00236                         // TCP (Transmition Control Protocol)           //
00237                         to_tcp_layer(
00238                                 ((void *)packet + (packet->ip_hdr_len * sizeof(uint32_t))),
00239                                 (ntohs(packet->ip_len) - (packet->ip_hdr_len * sizeof(uint32_t))),
00240                                 packet->ip_src,
00241                                 packet->ip_dst
00242                         );
00243                         // dump_ip_packet(packet);
00244                 break;
00245 
00246                 case IPPROTO_UDP:
00247                         // UDP (User Datagram Protocol)                 //
00248                         to_udp_layer(
00249                                 ((void *)packet + (packet->ip_hdr_len * sizeof(uint32_t))),
00250                                 packet->ip_src,
00251                                 packet->ip_dst
00252                         );
00253                 break;
00254 
00255                 default:
00256                         kprintf("\n\rUnknown IP protocol!");
00257                         dump_ip_packet(packet);
00258                 break;
00259         }
00260 }


Variable Documentation

in_addr_t host_ip [static]
 

This is the IP address of this host (expressed in network format).

Definition at line 84 of file ip.c.

in_addr_t host_netmask [static]
 

This is the IP netmask of this host (expressed in network format).

Definition at line 86 of file ip.c.


Generated on Fri Feb 20 15:32:19 2004 for Minirighi by doxygen1.2.18