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

icmp.c File Reference

ICMP (Internet Control Message Protocol) layer. More...

#include <const.h>
#include <errno.h>
#include <stdlib.h>
#include <arch/i386.h>
#include <arch/mem.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/kmalloc.h>
#include <net/ip.h>
#include <net/network.h>
#include <net/icmp.h>

Go to the source code of this file.

Functions

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


int send_icmp_packet (in_addr_t ip_to, uint8_t message, uint8_t *data, size_t len)
 Send an ICMP packet.
Parameters:
ip_to  The IP destination address (in network format).
message  The ICMP message to send.
data  The data buffer to send into the ICMP packet.
len  The size of the data buffer.
Returns:
  • The number of bytes sent in case of success;
  • a negative value if an error occurs.


int recv_icmp_packet (icmp_t *buf, size_t len)
 Receive an ICMP 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.


void ping (char *ip_dot)
 Send a ping to a destination host
Parameters:
ip_dot  The host IP destination expressed in numbers-and-dot notation.



Detailed Description

ICMP (Internet Control Message Protocol) layer.

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

Definition in file icmp.c.


Function Documentation

void ping char *    ip_dot
 

Send a ping to a destination host

Parameters:
ip_dot  The host IP destination expressed in numbers-and-dot notation.

Definition at line 205 of file icmp.c.

00206 {
00207         struct
00208         {
00209                 uint16_t ping_id;
00210                 uint16_t ping_seq;
00211                 uint8_t data[128 - sizeof(ip_t) + sizeof(icmp_ping_t)];
00212         } packet;
00213         int tot_sent, i;
00214         in_addr_t ip, host_ip = ntohl( get_host_ip() );
00215 
00216         // Translate the IP address from numbers-and-dot notation into  //
00217         // binary network order byte number.                            //
00218         if ( !inet_aton(ip_dot, &ip) )
00219         {
00220                 kprintf("\n\rUsage: ping <IP address>\n\r");
00221                 return;
00222         }
00223 
00224         // Fill the packet                                              //
00225         for (i = 0; i < _countof(packet.data); i++)
00226                 packet.data[i] = 'a' + i % 26;
00227 
00228         // Fill the header of the ping                                  //
00229         packet.ping_id = 3636;
00230         packet.ping_seq = 0;
00231 
00232         kprintf("\n\rPING: %u(%u) bytes %u.%u.%u.%u from %u.%u.%u.%u",
00233 
00234                 sizeof(packet)-sizeof(icmp_ping_t),
00235                 sizeof(packet),
00236 
00237                 IP_A(ntohl(ip)), IP_B(ntohl(ip)), IP_C(ntohl(ip)), IP_D(ntohl(ip)),
00238                 IP_A(host_ip), IP_B(host_ip), IP_C(host_ip), IP_D(host_ip)
00239         );
00240 
00241         tot_sent = send_icmp_packet(
00242                         ip,
00243                         ICMP_ECHO,
00244                         (uint8_t *)&packet,
00245                         sizeof(packet)
00246         );
00247         if ( tot_sent < 0 )
00248         {
00249                 switch( tot_sent )
00250                 {
00251                         case (-ENETUNREACH):
00252                                 kprintf("\n\rHost unreachable!");
00253                         break;
00254 
00255                         kprintf("\n\rCannot send data to ip layer!");
00256                         break;
00257                 }
00258                 kprintf("\n\r");
00259                 return;
00260         }
00261         // Wait 500ms for the answer                                    //
00262         delay(500);
00263         // Well done!                                                   //
00264         kprintf("\n\r");
00265 }

int recv_icmp_packet icmp_t   buf,
size_t    len
 

Receive an ICMP 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 197 of file icmp.c.

00198 {
00199         return( -ENOPROTOOPT );
00200 }

int send_icmp_packet in_addr_t    ip_to,
uint8_t    message,
uint8_t   data,
size_t    len
 

Send an ICMP packet.

Parameters:
ip_to  The IP destination address (in network format).
message  The ICMP message to send.
data  The data buffer to send into the ICMP packet.
len  The size of the data buffer.
Returns:
  • The number of bytes sent in case of success;
  • a negative value if an error occurs.

Definition at line 149 of file icmp.c.

00150 {
00151         icmp_t *packet;
00152         int tot_len;
00153 
00154         packet = kmalloc(len + sizeof(icmp_t));
00155         if (packet == NULL)
00156                 // Out of memory!                                       //
00157                 return(-ENOMEM);
00158 
00159         // Create the ICMP header                                       //
00160         packet->icmp_type = message;
00161         packet->icmp_code = 0;
00162         packet->icmp_chk = 0;
00163 
00164         // Copy the data into the packet                                //
00165         memcpy(packet + 1, data, len);
00166         len += sizeof(icmp_t);
00167 
00168         // Calculate the checksum of the ICMP message                   //
00169         packet->icmp_chk = ip_checksum(packet, len);
00170 
00171         // Send the IP packet                                           //
00172         tot_len = send_ip_packet(ip_to, packet, len, IP_DEFAULT_TTL, IPPROTO_ICMP);
00173 
00174         #ifdef DEBUG
00175         kprintf("\n\r%u bytes sent from ip layer", tot_len);
00176         #endif
00177 
00178         // Free the memory of the packet                                //
00179         kfree(packet);
00180 
00181         if ( tot_len < 0 )
00182                 // Something wrong from at the IP layer                 //
00183                 return(tot_len);
00184 
00185         return(len);
00186 }

void to_icmp_layer ip_t   packet
 

Process an ICMP packet received from the IP layer.

Parameters:
packet  The ICMP packet received.

Definition at line 26 of file icmp.c.

00027 {
00028         int size = ntohs(packet->ip_len) - (packet->ip_hdr_len)*sizeof(uint32_t);
00029         icmp_t *icmp_packet = (icmp_t *)((void *)packet + (packet->ip_hdr_len)*sizeof(uint32_t));
00030 #if 0
00031         kprintf(        "\n\ricmp_type:%02X, icmp_code:%02X, icmp_chk:%04X"
00032                 "\n\rping_id:%04X, ping_seq:%u"
00033                 "\n\rping %u bytes",
00034                 icmp_packet->icmp_type,
00035                 icmp_packet->icmp_code,
00036                 icmp_packet->icmp_chk,
00037                 ((icmp_ping_t *)icmp_packet)->ping_id,
00038                 ((icmp_ping_t *)icmp_packet)->ping_seq,
00039                 size-sizeof(icmp_ping_t)
00040         );
00041         kprintf( "\n\rlocal checksum = %04X", ip_checksum(icmp_packet, size) );
00042 #endif
00043         // Calculate the header checksum                                //
00044         if ( ip_checksum(icmp_packet, size) )
00045         {
00046                 kprintf("\n\ricmp: header checksum error!!!");
00047                 return;
00048         }
00049         // Identify the message type                                    //
00050         switch( icmp_packet->icmp_type )
00051         {
00052                 case ICMP_ECHO:
00053                         // Print the echo request to stdout             //
00054                         #ifdef ICMP_DEBUG
00055                         kprintf(        "\n\recho request %u(%u) bytes "
00056                                 "%u.%u.%u.%u > %u.%u.%u.%u id=%u seq=%u ttl=%u",
00057                                 size,
00058                                 size - sizeof(icmp_ping_t),
00059 
00060                                 IP_A(ntohl(packet->ip_src)), IP_B(ntohl(packet->ip_src)),
00061                                 IP_C(ntohl(packet->ip_src)), IP_D(ntohl(packet->ip_src)),
00062 
00063                                 IP_A(ntohl(packet->ip_dst)), IP_B(ntohl(packet->ip_dst)),
00064                                 IP_C(ntohl(packet->ip_dst)), IP_D(ntohl(packet->ip_dst)),
00065 
00066                                 ((icmp_ping_t *)icmp_packet)->ping_id,
00067                                 ((icmp_ping_t *)icmp_packet)->ping_seq,
00068                                 packet->ip_ttl
00069                         );
00070                         #endif
00071                         // Check if we must send the echo reply message //
00072                         if (
00073                                 (packet->ip_dst==get_host_ip()) ||
00074                                 (packet->ip_dst==get_host_bcast()) ||
00075                                 (packet->ip_dst==INADDR_BROADCAST)
00076                         )
00077                         {
00078                                 #ifdef ICMP_DEBUG
00079                                 // Notify that we're sending the reply  //
00080                                 kprintf(        "\n\recho reply %u(%u) bytes "
00081                                         "%u.%u.%u.%u > %u.%u.%u.%u id=%u seq=%u ttl=%u",
00082                                         size,
00083                                         size - sizeof(icmp_ping_t),
00084 
00085                                         IP_A(ntohl(get_host_ip())), IP_B(ntohl(get_host_ip())),
00086                                         IP_C(ntohl(get_host_ip())), IP_D(ntohl(get_host_ip())),
00087 
00088                                         IP_A(ntohl(packet->ip_src)), IP_B(ntohl(packet->ip_src)),
00089                                         IP_C(ntohl(packet->ip_src)), IP_D(ntohl(packet->ip_src)),
00090 
00091                                         ((icmp_ping_t *)icmp_packet)->ping_id,
00092                                         ((icmp_ping_t *)icmp_packet)->ping_seq,
00093                                         IP_DEFAULT_TTL
00094                                 );
00095                                 #endif
00096                                 // Send the echo reply                  //
00097                                 send_icmp_packet(
00098                                         packet->ip_src,
00099                                         ICMP_ECHOREPLY,
00100                                         (void *)icmp_packet + sizeof(icmp_t),
00101                                         size-sizeof(icmp_t)
00102                                 );
00103                         }
00104                 break;
00105 
00106                 case ICMP_ECHOREPLY:
00107                         // Show the echo reply message                  //
00108                         kprintf("\n\recho reply %u.%u.%u.%u > %u.%u.%u.%u id=%u seq=%u ttl=%u",
00109 
00110                                 IP_A(ntohl(packet->ip_src)), IP_B(ntohl(packet->ip_src)),
00111                                 IP_C(ntohl(packet->ip_src)), IP_D(ntohl(packet->ip_src)),
00112 
00113                                 IP_A(ntohl(packet->ip_dst)), IP_B(ntohl(packet->ip_dst)),
00114                                 IP_C(ntohl(packet->ip_dst)), IP_D(ntohl(packet->ip_dst)),
00115 
00116                                 ((icmp_ping_t *)icmp_packet)->ping_id,
00117                                 ((icmp_ping_t *)icmp_packet)->ping_seq,
00118                                 packet->ip_ttl
00119                         );
00120                         // TODO:                                        //
00121                         // Insert the message into the icmp recv buffer //
00122                 break;
00123 
00124                 default:
00125                         kprintf("\n\ricmp: ??? %u.%u.%u.%u > %u.%u.%u.%u id=%u seq=%u ttl=%u",
00126 
00127                                 IP_A(ntohl(packet->ip_src)), IP_B(ntohl(packet->ip_src)),
00128                                 IP_C(ntohl(packet->ip_src)), IP_D(ntohl(packet->ip_src)),
00129 
00130                                 IP_A(ntohl(packet->ip_dst)), IP_B(ntohl(packet->ip_dst)),
00131                                 IP_C(ntohl(packet->ip_dst)), IP_D(ntohl(packet->ip_dst)),
00132 
00133                                 ((icmp_ping_t *)icmp_packet)->ping_id,
00134                                 ((icmp_ping_t *)icmp_packet)->ping_seq,
00135                                 packet->ip_ttl
00136                         );
00137                 break;
00138         }
00139 }


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