#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.
| |||||||||
int | send_icmp_packet (in_addr_t ip_to, uint8_t message, uint8_t *data, size_t len) | ||||||||
Send an ICMP packet.
| |||||||||
int | recv_icmp_packet (icmp_t *buf, size_t len) | ||||||||
Receive an ICMP packet.
| |||||||||
void | ping (char *ip_dot) | ||||||||
Send a ping to a destination host
|
Definition in file icmp.c.
|
Send a ping to a destination host
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 } |
|
Receive an ICMP packet.
Definition at line 197 of file icmp.c.
00198 { 00199 return( -ENOPROTOOPT ); 00200 } |
|
Send an ICMP packet.
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 } |
|
Process an ICMP packet received from the IP layer.
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 } |