00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009 #include <errno.h>
00010 #include <stdlib.h>
00011
00012 #include <arch/i386.h>
00013 #include <arch/mem.h>
00014
00015 #include <kernel/clock.h>
00016 #include <kernel/console.h>
00017 #include <kernel/kmalloc.h>
00018
00019 #include <net/ip.h>
00020 #include <net/network.h>
00021
00022 #include <net/icmp.h>
00023
00024
00025
00026 void to_icmp_layer(ip_t *packet)
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
00044 if ( ip_checksum(icmp_packet, size) )
00045 {
00046 kprintf("\n\ricmp: header checksum error!!!");
00047 return;
00048 }
00049
00050 switch( icmp_packet->icmp_type )
00051 {
00052 case ICMP_ECHO:
00053
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
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
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
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
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
00121
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 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 int send_icmp_packet(in_addr_t ip_to, uint8_t message, uint8_t *data, size_t len)
00150 {
00151 icmp_t *packet;
00152 int tot_len;
00153
00154 packet = kmalloc(len + sizeof(icmp_t));
00155 if (packet == NULL)
00156
00157 return(-ENOMEM);
00158
00159
00160 packet->icmp_type = message;
00161 packet->icmp_code = 0;
00162 packet->icmp_chk = 0;
00163
00164
00165 memcpy(packet + 1, data, len);
00166 len += sizeof(icmp_t);
00167
00168
00169 packet->icmp_chk = ip_checksum(packet, len);
00170
00171
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
00179 kfree(packet);
00180
00181 if ( tot_len < 0 )
00182
00183 return(tot_len);
00184
00185 return(len);
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 int recv_icmp_packet(icmp_t *buf, size_t len)
00198 {
00199 return( -ENOPROTOOPT );
00200 }
00201
00202
00203
00204
00205 void ping(char *ip_dot)
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
00217
00218 if ( !inet_aton(ip_dot, &ip) )
00219 {
00220 kprintf("\n\rUsage: ping <IP address>\n\r");
00221 return;
00222 }
00223
00224
00225 for (i = 0; i < _countof(packet.data); i++)
00226 packet.data[i] = 'a' + i % 26;
00227
00228
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
00262 delay(500);
00263
00264 kprintf("\n\r");
00265 }