00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009 #include <ctype.h>
00010 #include <errno.h>
00011
00012 #include <arch/mem.h>
00013
00014 #include <kernel/clock.h>
00015 #include <kernel/console.h>
00016 #include <kernel/kmalloc.h>
00017
00018 #include <net/arp.h>
00019 #include <net/eth.h>
00020 #include <net/icmp.h>
00021 #include <net/network.h>
00022 #include <net/tcp.h>
00023 #include <net/udp.h>
00024
00025 #include <net/ip.h>
00026
00027
00028
00029
00030
00031 uint16_t ip_checksum(const void *buf, size_t hdr_len)
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 }
00050
00051
00052
00053 void dump_ip_packet(ip_t *packet)
00054 {
00055 int i;
00056 uint8_t *data = ((void *)packet + (packet->ip_hdr_len * sizeof(uint32_t)));
00057
00058
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
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 }
00082
00083
00084 static in_addr_t host_ip;
00085
00086 static in_addr_t host_netmask;
00087
00088
00089
00090
00091 void set_host_ip_net(in_addr_t ip, in_addr_t netmask)
00092 {
00093 host_ip = ip;
00094 host_netmask = netmask;
00095 }
00096
00097
00098
00099
00100 in_addr_t get_host_ip()
00101 {
00102 return( host_ip );
00103 }
00104
00105
00106
00107
00108 in_addr_t get_host_netmask()
00109 {
00110 return( host_netmask );
00111 }
00112
00113
00114
00115
00116
00117 in_addr_t get_host_bcast()
00118 {
00119 return( (~host_netmask) | (host_ip & host_netmask) );
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 int inet_aton(const char *cp, in_addr_t *inp)
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
00148
00149
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
00163
00164
00165
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
00176 if (c != '\0' && (!isascii(c) || !isspace(c))) {
00177 goto ret_0;
00178 }
00179
00180
00181 if (!digit) {
00182 goto ret_0;
00183 }
00184
00185
00186
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 }
00199
00200
00201
00202 void to_ip_layer(ip_t *packet)
00203 {
00204
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
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
00222 switch( packet->ip_proto )
00223 {
00224 case IPPROTO_ICMP:
00225
00226 to_icmp_layer(packet);
00227 break;
00228
00229 case IPPROTO_IGMP:
00230
00231 kprintf("\n\rIGMP protocol not yet implemented!");
00232 dump_ip_packet(packet);
00233 break;
00234
00235 case IPPROTO_TCP:
00236
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
00244 break;
00245
00246 case IPPROTO_UDP:
00247
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 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 int send_ip_packet(uint32_t ip_to, const void *data, size_t len, uint8_t ttl, uint8_t proto)
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
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
00302 memcpy(packet + 1, data, len);
00303
00304
00305
00306 if ( !arp_ip_to_eth(eth_to, ip_to) )
00307 {
00308 #ifdef DEBUG
00309 kprintf("\n\rARP fails!");
00310 #endif
00311
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
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
00328 kfree(packet);
00329
00330 if ( tot_len < 0 )
00331
00332 return(tot_len);
00333
00334
00335 return(packet_len);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 int recv_ip_packet(ip_t *buf, size_t len)
00348 {
00349 return( -ENOPROTOOPT );
00350 }