00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <async.h>
00039 #include <errno.h>
00040 #include <fibril_synch.h>
00041 #include <stdio.h>
00042 #include <str.h>
00043 #include <ipc/services.h>
00044 #include <ipc/net.h>
00045 #include <ipc/nil.h>
00046 #include <ipc/il.h>
00047 #include <ipc/ip.h>
00048 #include <sys/types.h>
00049 #include <byteorder.h>
00050 #include "ip.h"
00051
00052 #include <adt/measured_strings.h>
00053 #include <adt/module_map.h>
00054
00055 #include <packet_client.h>
00056 #include <net/socket_codes.h>
00057 #include <net/in.h>
00058 #include <net/in6.h>
00059 #include <net/inet.h>
00060 #include <net/modules.h>
00061 #include <net/device.h>
00062 #include <net/packet.h>
00063 #include <net/icmp_codes.h>
00064
00065 #include <arp_interface.h>
00066 #include <net_checksum.h>
00067 #include <icmp_client.h>
00068 #include <icmp_remote.h>
00069 #include <ip_client.h>
00070 #include <ip_interface.h>
00071 #include <ip_header.h>
00072 #include <net_interface.h>
00073 #include <nil_remote.h>
00074 #include <tl_remote.h>
00075 #include <packet_remote.h>
00076 #include <il_remote.h>
00077 #include <il_skel.h>
00078
00080 #define NAME "ip"
00081
00083 #define IPV4 4
00084
00086 #define NET_DEFAULT_IPV IPV4
00087
00089 #define NET_DEFAULT_IP_ROUTING false
00090
00092 #define IP_MIN_CONTENT 576
00093
00095 #define ARP_NAME "arp"
00096
00098 #define ARP_FILENAME "/srv/arp"
00099
00101 #define IP_ADDR sizeof(struct sockaddr_in6)
00102
00104 #define IP_PREFIX sizeof(ip_header_t)
00105
00107 #define IP_SUFFIX 0
00108
00110 #define IP_MAX_CONTENT 65535
00111
00113 #define IPV4_LOCALHOST_ADDRESS htonl((127 << 24) + 1)
00114
00116 ip_globals_t ip_globals;
00117
00118 DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t);
00119 INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
00120 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
00121
00122 static void ip_receiver(ipc_callid_t, ipc_call_t *);
00123
00130 static int ip_release_and_return(packet_t *packet, int result)
00131 {
00132 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
00133 return result;
00134 }
00135
00143 static int ip_get_icmp_phone(void)
00144 {
00145 ip_proto_t *proto;
00146 int phone;
00147
00148 fibril_rwlock_read_lock(&ip_globals.protos_lock);
00149 proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
00150 phone = proto ? proto->phone : ENOENT;
00151 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
00152 return phone;
00153 }
00154
00171 static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)
00172 {
00173 packet_t *next;
00174 struct sockaddr *dest;
00175 struct sockaddr_in dest_in;
00176 socklen_t addrlen;
00177
00178
00179 next = pq_detach(packet);
00180 if (next)
00181 pq_release_remote(ip_globals.net_phone, packet_get_id(next));
00182
00183 if (!header) {
00184 if (packet_get_data_length(packet) <= sizeof(ip_header_t))
00185 return ENOMEM;
00186
00187
00188 header = (ip_header_t *) packet_get_data(packet);
00189 if (!header)
00190 return EINVAL;
00191
00192 }
00193
00194
00195 if (IP_FRAGMENT_OFFSET(header))
00196 return EINVAL;
00197
00198
00199 if (header->protocol == IPPROTO_ICMP)
00200 return EPERM;
00201
00202
00203 switch (GET_IP_HEADER_VERSION(header)) {
00204 case IPVERSION:
00205 addrlen = sizeof(dest_in);
00206 bzero(&dest_in, addrlen);
00207 dest_in.sin_family = AF_INET;
00208 memcpy(&dest_in.sin_addr.s_addr, &header->source_address,
00209 sizeof(header->source_address));
00210 dest = (struct sockaddr *) &dest_in;
00211 break;
00212
00213 default:
00214 return EAFNOSUPPORT;
00215 }
00216
00217 return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
00218 }
00219
00233 static int
00234 ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,
00235 ip_header_t *header)
00236 {
00237 int phone;
00238
00239 phone = ip_get_icmp_phone();
00240 if (error || (phone < 0) || ip_prepare_icmp(packet, header))
00241 return ip_release_and_return(packet, EINVAL);
00242 return phone;
00243 }
00244
00245 int il_initialize(int net_phone)
00246 {
00247 fibril_rwlock_initialize(&ip_globals.lock);
00248 fibril_rwlock_write_lock(&ip_globals.lock);
00249 fibril_rwlock_initialize(&ip_globals.protos_lock);
00250 fibril_rwlock_initialize(&ip_globals.netifs_lock);
00251
00252 ip_globals.net_phone = net_phone;
00253 ip_globals.packet_counter = 0;
00254 ip_globals.gateway.address.s_addr = 0;
00255 ip_globals.gateway.netmask.s_addr = 0;
00256 ip_globals.gateway.gateway.s_addr = 0;
00257 ip_globals.gateway.netif = NULL;
00258
00259 int rc = ip_netifs_initialize(&ip_globals.netifs);
00260 if (rc != EOK)
00261 goto out;
00262 rc = ip_protos_initialize(&ip_globals.protos);
00263 if (rc != EOK)
00264 goto out;
00265 rc = modules_initialize(&ip_globals.modules);
00266 if (rc != EOK)
00267 goto out;
00268 rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
00269 (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
00270
00271 out:
00272 fibril_rwlock_write_unlock(&ip_globals.lock);
00273
00274 return rc;
00275 }
00276
00301 static int ip_netif_initialize(ip_netif_t *ip_netif)
00302 {
00303 measured_string_t names[] = {
00304 {
00305 (uint8_t *) "IPV",
00306 3
00307 },
00308 {
00309 (uint8_t *) "IP_CONFIG",
00310 9
00311 },
00312 {
00313 (uint8_t *) "IP_ADDR",
00314 7
00315 },
00316 {
00317 (uint8_t *) "IP_NETMASK",
00318 10
00319 },
00320 {
00321 (uint8_t *) "IP_GATEWAY",
00322 10
00323 },
00324 {
00325 (uint8_t *) "IP_BROADCAST",
00326 12
00327 },
00328 {
00329 (uint8_t *) "ARP",
00330 3
00331 },
00332 {
00333 (uint8_t *) "IP_ROUTING",
00334 10
00335 }
00336 };
00337 measured_string_t *configuration;
00338 size_t count = sizeof(names) / sizeof(measured_string_t);
00339 uint8_t *data;
00340 measured_string_t address;
00341 ip_route_t *route;
00342 in_addr_t gateway;
00343 int index;
00344 int rc;
00345
00346 ip_netif->arp = NULL;
00347 route = NULL;
00348 ip_netif->ipv = NET_DEFAULT_IPV;
00349 ip_netif->dhcp = false;
00350 ip_netif->routing = NET_DEFAULT_IP_ROUTING;
00351 configuration = &names[0];
00352
00353
00354 rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
00355 &configuration, count, &data);
00356 if (rc != EOK)
00357 return rc;
00358
00359 if (configuration) {
00360 if (configuration[0].value)
00361 ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
00362
00363 ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
00364 configuration[1].length);
00365
00366 if (ip_netif->dhcp) {
00367
00368 net_free_settings(configuration, data);
00369 return ENOTSUP;
00370 } else if (ip_netif->ipv == IPV4) {
00371 route = (ip_route_t *) malloc(sizeof(ip_route_t));
00372 if (!route) {
00373 net_free_settings(configuration, data);
00374 return ENOMEM;
00375 }
00376 route->address.s_addr = 0;
00377 route->netmask.s_addr = 0;
00378 route->gateway.s_addr = 0;
00379 route->netif = ip_netif;
00380 index = ip_routes_add(&ip_netif->routes, route);
00381 if (index < 0) {
00382 net_free_settings(configuration, data);
00383 free(route);
00384 return index;
00385 }
00386
00387 if ((inet_pton(AF_INET, (char *) configuration[2].value,
00388 (uint8_t *) &route->address.s_addr) != EOK) ||
00389 (inet_pton(AF_INET, (char *) configuration[3].value,
00390 (uint8_t *) &route->netmask.s_addr) != EOK) ||
00391 (inet_pton(AF_INET, (char *) configuration[4].value,
00392 (uint8_t *) &gateway.s_addr) == EINVAL) ||
00393 (inet_pton(AF_INET, (char *) configuration[5].value,
00394 (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
00395 {
00396 net_free_settings(configuration, data);
00397 return EINVAL;
00398 }
00399 } else {
00400
00401 net_free_settings(configuration, data);
00402 return ENOTSUP;
00403 }
00404
00405 if (configuration[6].value) {
00406 ip_netif->arp = get_running_module(&ip_globals.modules,
00407 configuration[6].value);
00408 if (!ip_netif->arp) {
00409 printf("Failed to start the arp %s\n",
00410 configuration[6].value);
00411 net_free_settings(configuration, data);
00412 return EINVAL;
00413 }
00414 }
00415 if (configuration[7].value)
00416 ip_netif->routing = (configuration[7].value[0] == 'y');
00417
00418 net_free_settings(configuration, data);
00419 }
00420
00421
00422 ip_netif->phone = nil_bind_service(ip_netif->service,
00423 (sysarg_t) ip_netif->device_id, SERVICE_IP,
00424 ip_receiver);
00425 if (ip_netif->phone < 0) {
00426 printf("Failed to contact the nil service %d\n",
00427 ip_netif->service);
00428 return ip_netif->phone;
00429 }
00430
00431
00432 if (ip_netif->arp) {
00433 if (route) {
00434 address.value = (uint8_t *) &route->address.s_addr;
00435 address.length = sizeof(in_addr_t);
00436
00437 rc = arp_device_req(ip_netif->arp->phone,
00438 ip_netif->device_id, SERVICE_IP, ip_netif->service,
00439 &address);
00440 if (rc != EOK)
00441 return rc;
00442 } else {
00443 ip_netif->arp = 0;
00444 }
00445 }
00446
00447
00448 rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
00449 &ip_netif->packet_dimension);
00450 if (rc != EOK)
00451 return rc;
00452
00453 if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
00454 printf("Maximum transmission unit %zu bytes is too small, at "
00455 "least %d bytes are needed\n",
00456 ip_netif->packet_dimension.content, IP_MIN_CONTENT);
00457 ip_netif->packet_dimension.content = IP_MIN_CONTENT;
00458 }
00459
00460 index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
00461 if (index < 0)
00462 return index;
00463
00464 if (gateway.s_addr) {
00465
00466 ip_globals.gateway.address.s_addr = 0;
00467 ip_globals.gateway.netmask.s_addr = 0;
00468 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
00469 ip_globals.gateway.netif = ip_netif;
00470
00471 char defgateway[INET_ADDRSTRLEN];
00472 inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
00473 defgateway, INET_ADDRSTRLEN);
00474 printf("%s: Default gateway (%s)\n", NAME, defgateway);
00475 }
00476
00477 return EOK;
00478 }
00479
00480 static int ip_device_req_local(int il_phone, device_id_t device_id,
00481 services_t netif)
00482 {
00483 ip_netif_t *ip_netif;
00484 ip_route_t *route;
00485 int index;
00486 int rc;
00487
00488 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
00489 if (!ip_netif)
00490 return ENOMEM;
00491
00492 rc = ip_routes_initialize(&ip_netif->routes);
00493 if (rc != EOK) {
00494 free(ip_netif);
00495 return rc;
00496 }
00497
00498 ip_netif->device_id = device_id;
00499 ip_netif->service = netif;
00500 ip_netif->state = NETIF_STOPPED;
00501
00502 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
00503
00504 rc = ip_netif_initialize(ip_netif);
00505 if (rc != EOK) {
00506 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
00507 ip_routes_destroy(&ip_netif->routes, free);
00508 free(ip_netif);
00509 return rc;
00510 }
00511 if (ip_netif->arp)
00512 ip_netif->arp->usage++;
00513
00514
00515 printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
00516 NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
00517 ip_netif->dhcp ? "dhcp" : "static");
00518
00519
00520
00521 char address[INET_ADDRSTRLEN];
00522 char netmask[INET_ADDRSTRLEN];
00523 char gateway[INET_ADDRSTRLEN];
00524
00525 for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
00526 route = ip_routes_get_index(&ip_netif->routes, index);
00527 if (route) {
00528 inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
00529 address, INET_ADDRSTRLEN);
00530 inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
00531 netmask, INET_ADDRSTRLEN);
00532 inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
00533 gateway, INET_ADDRSTRLEN);
00534 printf("%s: Route %d (address: %s, netmask: %s, "
00535 "gateway: %s)\n", NAME, index, address, netmask,
00536 gateway);
00537 }
00538 }
00539
00540 inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
00541 INET_ADDRSTRLEN);
00542 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
00543
00544 printf("%s: Broadcast (%s)\n", NAME, address);
00545
00546 return EOK;
00547 }
00548
00557 static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
00558 in_addr_t destination)
00559 {
00560 int index;
00561 ip_route_t *route;
00562
00563 if (!netif)
00564 return NULL;
00565
00566
00567 for (index = 0; index < ip_routes_count(&netif->routes); index++) {
00568 route = ip_routes_get_index(&netif->routes, index);
00569 if ((route) &&
00570 ((route->address.s_addr & route->netmask.s_addr) ==
00571 (destination.s_addr & route->netmask.s_addr)))
00572 return route;
00573 }
00574
00575 return NULL;
00576 }
00577
00584 static ip_route_t *ip_find_route(in_addr_t destination) {
00585 int index;
00586 ip_route_t *route;
00587 ip_netif_t *netif;
00588
00589
00590 index = ip_netifs_count(&ip_globals.netifs) - 1;
00591 while (index >= 0) {
00592 netif = ip_netifs_get_index(&ip_globals.netifs, index);
00593 if (netif && (netif->state == NETIF_ACTIVE)) {
00594 route = ip_netif_find_route(netif, destination);
00595 if (route)
00596 return route;
00597 }
00598 index--;
00599 }
00600
00601 return &ip_globals.gateway;
00602 }
00603
00610 static in_addr_t *ip_netif_address(ip_netif_t *netif)
00611 {
00612 ip_route_t *route;
00613
00614 route = ip_routes_get_index(&netif->routes, 0);
00615 return route ? &route->address : NULL;
00616 }
00617
00625 static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
00626 {
00627 ip_option_t *option;
00628 size_t next;
00629 size_t length;
00630
00631
00632 memcpy(last, first, sizeof(ip_header_t));
00633 length = sizeof(ip_header_t);
00634 next = sizeof(ip_header_t);
00635
00636
00637 while (next < GET_IP_HEADER_LENGTH(first)) {
00638 option = (ip_option_t *) (((uint8_t *) first) + next);
00639
00640 if ((option->type == IPOPT_END) ||
00641 (option->type == IPOPT_NOOP)) {
00642 next++;
00643 } else {
00644
00645 if (IPOPT_COPIED(option->type)) {
00646 memcpy(((uint8_t *) last) + length,
00647 ((uint8_t *) first) + next, option->length);
00648 length += option->length;
00649 }
00650
00651 next += option->length;
00652 }
00653 }
00654
00655
00656 if (length % 4) {
00657 bzero(((uint8_t *) last) + length, 4 - (length % 4));
00658 SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
00659 } else {
00660 SET_IP_HEADER_LENGTH(last, (length / 4));
00661 }
00662
00663 last->header_checksum = 0;
00664 }
00665
00684 static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
00685 packet_t *packet, measured_string_t *destination)
00686 {
00687 size_t length;
00688 ip_header_t *header;
00689 ip_header_t *last_header;
00690 ip_header_t *middle_header;
00691 packet_t *next;
00692 int rc;
00693
00694 length = packet_get_data_length(packet);
00695 if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
00696 return EINVAL;
00697
00698 header = (ip_header_t *) packet_get_data(packet);
00699 if (destination) {
00700 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
00701 destination->length);
00702 } else {
00703 rc = packet_set_addr(packet, NULL, NULL, 0);
00704 }
00705 if (rc != EOK)
00706 return rc;
00707
00708 SET_IP_HEADER_VERSION(header, IPV4);
00709 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
00710 header->fragment_offset_low = 0;
00711 header->header_checksum = 0;
00712 if (source)
00713 header->source_address = source->s_addr;
00714 header->destination_address = dest.s_addr;
00715
00716 fibril_rwlock_write_lock(&ip_globals.lock);
00717 ip_globals.packet_counter++;
00718 header->identification = htons(ip_globals.packet_counter);
00719 fibril_rwlock_write_unlock(&ip_globals.lock);
00720
00721 if (pq_next(packet)) {
00722 last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
00723 if (!last_header)
00724 return ENOMEM;
00725 ip_create_last_header(last_header, header);
00726 next = pq_next(packet);
00727 while (pq_next(next)) {
00728 middle_header = (ip_header_t *) packet_prefix(next,
00729 IP_HEADER_LENGTH(last_header));
00730 if (!middle_header) {
00731 free(last_header);
00732 return ENOMEM;
00733 }
00734
00735 memcpy(middle_header, last_header,
00736 IP_HEADER_LENGTH(last_header));
00737 SET_IP_HEADER_FLAGS(header,
00738 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
00739 middle_header->total_length =
00740 htons(packet_get_data_length(next));
00741 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
00742 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
00743 middle_header->fragment_offset_low =
00744 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
00745 middle_header->header_checksum =
00746 IP_HEADER_CHECKSUM(middle_header);
00747 if (destination) {
00748 rc = packet_set_addr(next, NULL,
00749 (uint8_t *) destination->value,
00750 destination->length);
00751 if (rc != EOK) {
00752 free(last_header);
00753 return rc;
00754 }
00755 }
00756 length += packet_get_data_length(next);
00757 next = pq_next(next);
00758 }
00759
00760 middle_header = (ip_header_t *) packet_prefix(next,
00761 IP_HEADER_LENGTH(last_header));
00762 if (!middle_header) {
00763 free(last_header);
00764 return ENOMEM;
00765 }
00766
00767 memcpy(middle_header, last_header,
00768 IP_HEADER_LENGTH(last_header));
00769 middle_header->total_length =
00770 htons(packet_get_data_length(next));
00771 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
00772 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
00773 middle_header->fragment_offset_low =
00774 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
00775 middle_header->header_checksum =
00776 IP_HEADER_CHECKSUM(middle_header);
00777 if (destination) {
00778 rc = packet_set_addr(next, NULL,
00779 (uint8_t *) destination->value,
00780 destination->length);
00781 if (rc != EOK) {
00782 free(last_header);
00783 return rc;
00784 }
00785 }
00786 length += packet_get_data_length(next);
00787 free(last_header);
00788 SET_IP_HEADER_FLAGS(header,
00789 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
00790 }
00791
00792 header->total_length = htons(length);
00793
00794 header->header_checksum = IP_HEADER_CHECKSUM(header);
00795
00796 return EOK;
00797 }
00798
00816 static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
00817 ip_header_t *header, ip_header_t *new_header, size_t length,
00818 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
00819 {
00820 void *data;
00821 size_t offset;
00822 int rc;
00823
00824 data = packet_suffix(new_packet, length);
00825 if (!data)
00826 return ENOMEM;
00827
00828 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
00829 length);
00830
00831 rc = packet_trim(packet, 0, length);
00832 if (rc != EOK)
00833 return rc;
00834
00835 header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
00836 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
00837 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
00838 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
00839 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
00840 new_header->fragment_offset_low =
00841 IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
00842 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
00843
00844 rc = packet_set_addr(new_packet, (const uint8_t *) src,
00845 (const uint8_t *) dest, addrlen);
00846 if (rc != EOK)
00847 return rc;
00848
00849 return pq_insert_after(packet, new_packet);
00850 }
00851
00860 static ip_header_t *ip_create_middle_header(packet_t *packet,
00861 ip_header_t *last)
00862 {
00863 ip_header_t *middle;
00864
00865 middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
00866 if (!middle)
00867 return NULL;
00868 memcpy(middle, last, IP_HEADER_LENGTH(last));
00869 SET_IP_HEADER_FLAGS(middle,
00870 (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
00871 return middle;
00872 }
00873
00899 static int
00900 ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
00901 socklen_t addr_len)
00902 {
00903 packet_t *new_packet;
00904 ip_header_t *header;
00905 ip_header_t *middle_header;
00906 ip_header_t *last_header;
00907 struct sockaddr *src;
00908 struct sockaddr *dest;
00909 socklen_t addrlen;
00910 int result;
00911 int rc;
00912
00913 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
00914 if (result <= 0)
00915 return EINVAL;
00916
00917 addrlen = (socklen_t) result;
00918 if (packet_get_data_length(packet) <= sizeof(ip_header_t))
00919 return ENOMEM;
00920
00921
00922 header = (ip_header_t *) packet_get_data(packet);
00923 if (!header)
00924 return EINVAL;
00925
00926
00927 if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
00928 return EPERM;
00929
00930
00931 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
00932 suffix, ((addrlen > addr_len) ? addrlen : addr_len));
00933 if (!new_packet)
00934 return ENOMEM;
00935
00936
00937 last_header = (ip_header_t *) packet_suffix(new_packet,
00938 IP_HEADER_LENGTH(header));
00939 if (!last_header)
00940 return ip_release_and_return(packet, ENOMEM);
00941
00942 ip_create_last_header(last_header, header);
00943
00944
00945 rc = packet_trim(new_packet, 0,
00946 IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
00947 if (rc != EOK)
00948 return ip_release_and_return(packet, rc);
00949
00950
00951
00952 length = length & ~0x7;
00953
00954 rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
00955 ((IP_HEADER_DATA_LENGTH(header) -
00956 ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
00957 ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
00958 src, dest, addrlen);
00959 if (rc != EOK)
00960 return ip_release_and_return(packet, rc);
00961
00962
00963 SET_IP_HEADER_FLAGS(header,
00964 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
00965
00966
00967 while (IP_TOTAL_LENGTH(header) > length) {
00968 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
00969 length, suffix,
00970 ((addrlen >= addr_len) ? addrlen : addr_len));
00971 if (!new_packet)
00972 return ENOMEM;
00973
00974 middle_header = ip_create_middle_header(new_packet,
00975 last_header);
00976 if (!middle_header)
00977 return ip_release_and_return(packet, ENOMEM);
00978
00979 rc = ip_fragment_packet_data(packet, new_packet, header,
00980 middle_header,
00981 (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
00982 src, dest, addrlen);
00983 if (rc != EOK)
00984 return ip_release_and_return(packet, rc);
00985 }
00986
00987
00988 header->header_checksum = IP_HEADER_CHECKSUM(header);
00989
00990 return EOK;
00991 }
00992
01007 static packet_t *
01008 ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix,
01009 socklen_t addr_len, services_t error)
01010 {
01011 size_t length;
01012 packet_t *next;
01013 packet_t *new_packet;
01014 int result;
01015 int phone;
01016
01017 next = packet;
01018
01019 while (next) {
01020 length = packet_get_data_length(next);
01021
01022 if (length <= content) {
01023 next = pq_next(next);
01024 continue;
01025 }
01026
01027
01028 result = ip_fragment_packet(next, content, prefix,
01029 suffix, addr_len);
01030 if (result != EOK) {
01031 new_packet = pq_detach(next);
01032 if (next == packet) {
01033
01034 packet = new_packet;
01035 }
01036
01037 if (result == EPERM) {
01038 phone = ip_prepare_icmp_and_get_phone(
01039 error, next, NULL);
01040 if (phone >= 0) {
01041
01042 icmp_destination_unreachable_msg(phone,
01043 ICMP_FRAG_NEEDED, content, next);
01044 }
01045 } else {
01046 pq_release_remote(ip_globals.net_phone,
01047 packet_get_id(next));
01048 }
01049
01050 next = new_packet;
01051 continue;
01052 }
01053
01054 next = pq_next(next);
01055 }
01056
01057 return packet;
01058 }
01059
01077 static int ip_send_route(packet_t *packet, ip_netif_t *netif,
01078 ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
01079 {
01080 measured_string_t destination;
01081 measured_string_t *translation;
01082 uint8_t *data;
01083 int phone;
01084 int rc;
01085
01086
01087 if (netif->arp && (route->address.s_addr != dest.s_addr)) {
01088 destination.value = route->gateway.s_addr ?
01089 (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
01090 destination.length = sizeof(dest.s_addr);
01091
01092 rc = arp_translate_req(netif->arp->phone, netif->device_id,
01093 SERVICE_IP, &destination, &translation, &data);
01094 if (rc != EOK) {
01095 pq_release_remote(ip_globals.net_phone,
01096 packet_get_id(packet));
01097 return rc;
01098 }
01099
01100 if (!translation || !translation->value) {
01101 if (translation) {
01102 free(translation);
01103 free(data);
01104 }
01105 phone = ip_prepare_icmp_and_get_phone(error, packet,
01106 NULL);
01107 if (phone >= 0) {
01108
01109 icmp_destination_unreachable_msg(phone,
01110 ICMP_HOST_UNREACH, 0, packet);
01111 }
01112 return EINVAL;
01113 }
01114
01115 } else {
01116 translation = NULL;
01117 }
01118
01119 rc = ip_prepare_packet(src, dest, packet, translation);
01120 if (rc != EOK) {
01121 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
01122 } else {
01123 packet = ip_split_packet(packet, netif->packet_dimension.prefix,
01124 netif->packet_dimension.content,
01125 netif->packet_dimension.suffix,
01126 netif->packet_dimension.addr_len, error);
01127 if (packet) {
01128 nil_send_msg(netif->phone, netif->device_id, packet,
01129 SERVICE_IP);
01130 }
01131 }
01132
01133 if (translation) {
01134 free(translation);
01135 free(data);
01136 }
01137
01138 return rc;
01139 }
01140
01141 static int ip_send_msg_local(int il_phone, device_id_t device_id,
01142 packet_t *packet, services_t sender, services_t error)
01143 {
01144 int addrlen;
01145 ip_netif_t *netif;
01146 ip_route_t *route;
01147 struct sockaddr *addr;
01148 struct sockaddr_in *address_in;
01149 in_addr_t *dest;
01150 in_addr_t *src;
01151 int phone;
01152 int rc;
01153
01154
01155
01156
01157
01158 addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
01159 if (addrlen < 0)
01160 return ip_release_and_return(packet, addrlen);
01161 if ((size_t) addrlen < sizeof(struct sockaddr))
01162 return ip_release_and_return(packet, EINVAL);
01163
01164 switch (addr->sa_family) {
01165 case AF_INET:
01166 if (addrlen != sizeof(struct sockaddr_in))
01167 return ip_release_and_return(packet, EINVAL);
01168 address_in = (struct sockaddr_in *) addr;
01169 dest = &address_in->sin_addr;
01170 if (!dest->s_addr)
01171 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
01172 break;
01173 case AF_INET6:
01174 default:
01175 return ip_release_and_return(packet, EAFNOSUPPORT);
01176 }
01177
01178 netif = NULL;
01179 route = NULL;
01180 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
01181
01182
01183 if (device_id > 0) {
01184 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01185 route = ip_netif_find_route(netif, *dest);
01186 if (netif && !route && (ip_globals.gateway.netif == netif))
01187 route = &ip_globals.gateway;
01188 }
01189
01190 if (!route) {
01191 route = ip_find_route(*dest);
01192 netif = route ? route->netif : NULL;
01193 }
01194 if (!netif || !route) {
01195 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01196 phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
01197 if (phone >= 0) {
01198
01199 icmp_destination_unreachable_msg(phone,
01200 ICMP_NET_UNREACH, 0, packet);
01201 }
01202 return ENOENT;
01203 }
01204
01205 if (error) {
01206
01207
01208
01209
01210 if (!dest->s_addr || !(~dest->s_addr) ||
01211 !(~((dest->s_addr & ~route->netmask.s_addr) |
01212 route->netmask.s_addr)) ||
01213 (!(dest->s_addr & ~route->netmask.s_addr))) {
01214 return ip_release_and_return(packet, EINVAL);
01215 }
01216 }
01217
01218
01219 if ((route->address.s_addr == dest->s_addr) &&
01220 (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
01221
01222 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
01223 route = ip_find_route(*dest);
01224 netif = route ? route->netif : NULL;
01225 if (!netif || !route) {
01226 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01227 phone = ip_prepare_icmp_and_get_phone(error, packet,
01228 NULL);
01229 if (phone >= 0) {
01230
01231 icmp_destination_unreachable_msg(phone,
01232 ICMP_HOST_UNREACH, 0, packet);
01233 }
01234 return ENOENT;
01235 }
01236 }
01237
01238 src = ip_netif_address(netif);
01239 if (!src) {
01240 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01241 return ip_release_and_return(packet, ENOENT);
01242 }
01243
01244 rc = ip_send_route(packet, netif, route, src, *dest, error);
01245 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01246
01247 return rc;
01248 }
01249
01257 static int ip_device_state_message(device_id_t device_id, device_state_t state)
01258 {
01259 ip_netif_t *netif;
01260
01261 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
01262
01263 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01264 if (!netif) {
01265 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01266 return ENOENT;
01267 }
01268 netif->state = state;
01269 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01270
01271 printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
01272
01273 return EOK;
01274 }
01275
01281 static in_addr_t ip_get_destination(ip_header_t *header)
01282 {
01283 in_addr_t destination;
01284
01285
01286 destination.s_addr = header->destination_address;
01287 return destination;
01288 }
01289
01311 static int ip_deliver_local(device_id_t device_id, packet_t *packet,
01312 ip_header_t *header, services_t error)
01313 {
01314 ip_proto_t *proto;
01315 int phone;
01316 services_t service;
01317 tl_received_msg_t received_msg;
01318 struct sockaddr *src;
01319 struct sockaddr *dest;
01320 struct sockaddr_in src_in;
01321 struct sockaddr_in dest_in;
01322 socklen_t addrlen;
01323 int rc;
01324
01325 if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
01326 IP_FRAGMENT_OFFSET(header)) {
01327
01328 return ENOTSUP;
01329 }
01330
01331 switch (GET_IP_HEADER_VERSION(header)) {
01332 case IPVERSION:
01333 addrlen = sizeof(src_in);
01334 bzero(&src_in, addrlen);
01335 src_in.sin_family = AF_INET;
01336 memcpy(&dest_in, &src_in, addrlen);
01337 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
01338 sizeof(header->source_address));
01339 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
01340 sizeof(header->destination_address));
01341 src = (struct sockaddr *) &src_in;
01342 dest = (struct sockaddr *) &dest_in;
01343 break;
01344
01345 default:
01346 return ip_release_and_return(packet, EAFNOSUPPORT);
01347 }
01348
01349 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
01350 addrlen);
01351 if (rc != EOK)
01352 return ip_release_and_return(packet, rc);
01353
01354
01355 if (!error &&
01356 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
01357 rc = packet_trim(packet, 0,
01358 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
01359 if (rc != EOK)
01360 return ip_release_and_return(packet, rc);
01361 }
01362
01363 fibril_rwlock_read_lock(&ip_globals.protos_lock);
01364
01365 proto = ip_protos_find(&ip_globals.protos, header->protocol);
01366 if (!proto) {
01367 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
01368 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
01369 if (phone >= 0) {
01370
01371 icmp_destination_unreachable_msg(phone,
01372 ICMP_PROT_UNREACH, 0, packet);
01373 }
01374 return ENOENT;
01375 }
01376
01377 if (proto->received_msg) {
01378 service = proto->service;
01379 received_msg = proto->received_msg;
01380 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
01381 rc = received_msg(device_id, packet, service, error);
01382 } else {
01383 rc = tl_received_msg(proto->phone, device_id, packet,
01384 proto->service, error);
01385 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
01386 }
01387
01388 return rc;
01389 }
01390
01412 static int ip_process_packet(device_id_t device_id, packet_t *packet)
01413 {
01414 ip_header_t *header;
01415 in_addr_t dest;
01416 ip_route_t *route;
01417 int phone;
01418 struct sockaddr *addr;
01419 struct sockaddr_in addr_in;
01420 socklen_t addrlen;
01421 int rc;
01422
01423 header = (ip_header_t *) packet_get_data(packet);
01424 if (!header)
01425 return ip_release_and_return(packet, ENOMEM);
01426
01427
01428 if ((header->header_checksum) &&
01429 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
01430 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
01431 if (phone >= 0) {
01432
01433 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
01434 ((size_t) ((void *) &header->header_checksum)) -
01435 ((size_t) ((void *) header)), packet);
01436 }
01437 return EINVAL;
01438 }
01439
01440 if (header->ttl <= 1) {
01441 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
01442 if (phone >= 0) {
01443
01444 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
01445 }
01446 return EINVAL;
01447 }
01448
01449
01450 dest = ip_get_destination(header);
01451
01452
01453 switch (GET_IP_HEADER_VERSION(header)) {
01454 case IPVERSION:
01455 addrlen = sizeof(addr_in);
01456 bzero(&addr_in, addrlen);
01457 addr_in.sin_family = AF_INET;
01458 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
01459 addr = (struct sockaddr *) &addr_in;
01460 break;
01461
01462 default:
01463 return ip_release_and_return(packet, EAFNOSUPPORT);
01464 }
01465
01466 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
01467 if (rc != EOK)
01468 return rc;
01469
01470 route = ip_find_route(dest);
01471 if (!route) {
01472 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
01473 if (phone >= 0) {
01474
01475 icmp_destination_unreachable_msg(phone,
01476 ICMP_HOST_UNREACH, 0, packet);
01477 }
01478 return ENOENT;
01479 }
01480
01481 if (route->address.s_addr == dest.s_addr) {
01482
01483 return ip_deliver_local(device_id, packet, header, 0);
01484 }
01485
01486 if (route->netif->routing) {
01487 header->ttl--;
01488 return ip_send_route(packet, route->netif, route, NULL, dest,
01489 0);
01490 }
01491
01492 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
01493 if (phone >= 0) {
01494
01495 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
01496 packet);
01497 }
01498
01499 return ENOENT;
01500 }
01501
01513 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
01514 size_t *prefix, size_t *content, size_t *suffix)
01515 {
01516 ip_netif_t *netif;
01517 int index;
01518
01519 if (!addr_len || !prefix || !content || !suffix)
01520 return EBADMEM;
01521
01522 *content = IP_MAX_CONTENT - IP_PREFIX;
01523 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
01524 if (device_id < 0) {
01525 *addr_len = IP_ADDR;
01526 *prefix = 0;
01527 *suffix = 0;
01528
01529 for (index = ip_netifs_count(&ip_globals.netifs) - 1;
01530 index >= 0; index--) {
01531 netif = ip_netifs_get_index(&ip_globals.netifs, index);
01532 if (!netif)
01533 continue;
01534
01535 if (netif->packet_dimension.addr_len > *addr_len)
01536 *addr_len = netif->packet_dimension.addr_len;
01537
01538 if (netif->packet_dimension.prefix > *prefix)
01539 *prefix = netif->packet_dimension.prefix;
01540
01541 if (netif->packet_dimension.suffix > *suffix)
01542 *suffix = netif->packet_dimension.suffix;
01543 }
01544
01545 *prefix = *prefix + IP_PREFIX;
01546 *suffix = *suffix + IP_SUFFIX;
01547 } else {
01548 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01549 if (!netif) {
01550 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01551 return ENOENT;
01552 }
01553
01554 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
01555 netif->packet_dimension.addr_len : IP_ADDR;
01556 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
01557 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
01558 }
01559 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01560
01561 return EOK;
01562 }
01563
01571 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
01572 {
01573 ip_netif_t *netif;
01574
01575 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
01576 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01577 if (!netif) {
01578 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01579 return ENOENT;
01580 }
01581 netif->packet_dimension.content = mtu;
01582 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01583
01584 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
01585
01586 return EOK;
01587 }
01588
01595 static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
01596 {
01597 packet_t *packet;
01598 int rc;
01599
01600 while (true) {
01601 switch (IPC_GET_IMETHOD(*icall)) {
01602 case NET_IL_DEVICE_STATE:
01603 rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
01604 IPC_GET_STATE(*icall));
01605 async_answer_0(iid, (sysarg_t) rc);
01606 break;
01607
01608 case NET_IL_RECEIVED:
01609 rc = packet_translate_remote(ip_globals.net_phone, &packet,
01610 IPC_GET_PACKET(*icall));
01611 if (rc == EOK) {
01612 do {
01613 packet_t *next = pq_detach(packet);
01614 ip_process_packet(IPC_GET_DEVICE(*icall), packet);
01615 packet = next;
01616 } while (packet);
01617 }
01618
01619 async_answer_0(iid, (sysarg_t) rc);
01620 break;
01621
01622 case NET_IL_MTU_CHANGED:
01623 rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
01624 IPC_GET_MTU(*icall));
01625 async_answer_0(iid, (sysarg_t) rc);
01626 break;
01627
01628 default:
01629 async_answer_0(iid, (sysarg_t) ENOTSUP);
01630 }
01631
01632 iid = async_get_call(icall);
01633 }
01634 }
01635
01652 static int
01653 ip_register(int protocol, services_t service, int phone,
01654 tl_received_msg_t received_msg)
01655 {
01656 ip_proto_t *proto;
01657 int index;
01658
01659 if (!protocol || !service || ((phone < 0) && !received_msg))
01660 return EINVAL;
01661
01662 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
01663 if (!proto)
01664 return ENOMEM;
01665
01666 proto->protocol = protocol;
01667 proto->service = service;
01668 proto->phone = phone;
01669 proto->received_msg = received_msg;
01670
01671 fibril_rwlock_write_lock(&ip_globals.protos_lock);
01672 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
01673 if (index < 0) {
01674 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
01675 free(proto);
01676 return index;
01677 }
01678 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
01679
01680 printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
01681 NAME, proto->protocol, proto->phone);
01682
01683 return EOK;
01684 }
01685
01686
01687 static int
01688 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
01689 in_addr_t netmask, in_addr_t gateway)
01690 {
01691 ip_route_t *route;
01692 ip_netif_t *netif;
01693 int index;
01694
01695 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
01696
01697 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01698 if (!netif) {
01699 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01700 return ENOENT;
01701 }
01702
01703 route = (ip_route_t *) malloc(sizeof(ip_route_t));
01704 if (!route) {
01705 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01706 return ENOMEM;
01707 }
01708
01709 route->address.s_addr = address.s_addr;
01710 route->netmask.s_addr = netmask.s_addr;
01711 route->gateway.s_addr = gateway.s_addr;
01712 route->netif = netif;
01713 index = ip_routes_add(&netif->routes, route);
01714 if (index < 0)
01715 free(route);
01716
01717 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01718
01719 return index;
01720 }
01721
01722 static int
01723 ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
01724 {
01725 ip_netif_t *netif;
01726
01727 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
01728
01729 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01730 if (!netif) {
01731 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01732 return ENOENT;
01733 }
01734
01735 ip_globals.gateway.address.s_addr = 0;
01736 ip_globals.gateway.netmask.s_addr = 0;
01737 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
01738 ip_globals.gateway.netif = netif;
01739
01740 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
01741
01742 return EOK;
01743 }
01744
01757 static int
01758 ip_received_error_msg_local(int ip_phone, device_id_t device_id,
01759 packet_t *packet, services_t target, services_t error)
01760 {
01761 uint8_t *data;
01762 int offset;
01763 icmp_type_t type;
01764 icmp_code_t code;
01765 ip_netif_t *netif;
01766 measured_string_t address;
01767 ip_route_t *route;
01768 ip_header_t *header;
01769
01770 switch (error) {
01771 case SERVICE_ICMP:
01772 offset = icmp_client_process_packet(packet, &type, &code, NULL,
01773 NULL);
01774 if (offset < 0)
01775 return ip_release_and_return(packet, ENOMEM);
01776
01777 data = packet_get_data(packet);
01778 header = (ip_header_t *)(data + offset);
01779
01780
01781 if ((type != ICMP_DEST_UNREACH) ||
01782 (code != ICMP_HOST_UNREACH)) {
01783
01784 break;
01785 }
01786
01787 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
01788
01789 netif = ip_netifs_find(&ip_globals.netifs, device_id);
01790 if (!netif || !netif->arp) {
01791 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01792 break;
01793 }
01794
01795 route = ip_routes_get_index(&netif->routes, 0);
01796
01797
01798 if (route && ((route->address.s_addr & route->netmask.s_addr) ==
01799 (header->destination_address & route->netmask.s_addr))) {
01800
01801 address.value = (uint8_t *) &header->destination_address;
01802 address.length = sizeof(header->destination_address);
01803 arp_clear_address_req(netif->arp->phone,
01804 netif->device_id, SERVICE_IP, &address);
01805 }
01806
01807 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
01808 break;
01809
01810 default:
01811 return ip_release_and_return(packet, ENOTSUP);
01812 }
01813
01814 return ip_deliver_local(device_id, packet, header, error);
01815 }
01816
01817 static int
01818 ip_get_route_req_local(int ip_phone, ip_protocol_t protocol,
01819 const struct sockaddr *destination, socklen_t addrlen,
01820 device_id_t *device_id, void **header, size_t *headerlen)
01821 {
01822 struct sockaddr_in *address_in;
01823 in_addr_t *dest;
01824 in_addr_t *src;
01825 ip_route_t *route;
01826 ipv4_pseudo_header_t *header_in;
01827
01828 if (!destination || (addrlen <= 0))
01829 return EINVAL;
01830
01831 if (!device_id || !header || !headerlen)
01832 return EBADMEM;
01833
01834 if ((size_t) addrlen < sizeof(struct sockaddr))
01835 return EINVAL;
01836
01837 switch (destination->sa_family) {
01838 case AF_INET:
01839 if (addrlen != sizeof(struct sockaddr_in))
01840 return EINVAL;
01841 address_in = (struct sockaddr_in *) destination;
01842 dest = &address_in->sin_addr;
01843 if (!dest->s_addr)
01844 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
01845 break;
01846
01847 case AF_INET6:
01848 default:
01849 return EAFNOSUPPORT;
01850 }
01851
01852 fibril_rwlock_read_lock(&ip_globals.lock);
01853 route = ip_find_route(*dest);
01854
01855 if (route && (route->address.s_addr == dest->s_addr) &&
01856 (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
01857
01858 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
01859 route = ip_find_route(*dest);
01860 }
01861
01862 if (!route || !route->netif) {
01863 fibril_rwlock_read_unlock(&ip_globals.lock);
01864 return ENOENT;
01865 }
01866
01867 *device_id = route->netif->device_id;
01868 src = ip_netif_address(route->netif);
01869 fibril_rwlock_read_unlock(&ip_globals.lock);
01870
01871 *headerlen = sizeof(*header_in);
01872 header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
01873 if (!header_in)
01874 return ENOMEM;
01875
01876 bzero(header_in, *headerlen);
01877 header_in->destination_address = dest->s_addr;
01878 header_in->source_address = src->s_addr;
01879 header_in->protocol = protocol;
01880 header_in->data_length = 0;
01881 *header = header_in;
01882
01883 return EOK;
01884 }
01885
01900 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
01901 size_t *answer_count)
01902 {
01903 packet_t *packet;
01904 struct sockaddr *addr;
01905 void *header;
01906 size_t headerlen;
01907 size_t addrlen;
01908 size_t prefix;
01909 size_t suffix;
01910 size_t content;
01911 device_id_t device_id;
01912 int rc;
01913
01914 *answer_count = 0;
01915 switch (IPC_GET_IMETHOD(*call)) {
01916 case IPC_M_PHONE_HUNGUP:
01917 return EOK;
01918
01919 case IPC_M_CONNECT_TO_ME:
01920 return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
01921 IPC_GET_PHONE(*call), NULL);
01922
01923 case NET_IP_DEVICE:
01924 return ip_device_req_local(0, IPC_GET_DEVICE(*call),
01925 IPC_GET_SERVICE(*call));
01926
01927 case NET_IP_RECEIVED_ERROR:
01928 rc = packet_translate_remote(ip_globals.net_phone, &packet,
01929 IPC_GET_PACKET(*call));
01930 if (rc != EOK)
01931 return rc;
01932 return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
01933 packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
01934
01935 case NET_IP_ADD_ROUTE:
01936 return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
01937 IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
01938 IP_GET_GATEWAY(*call));
01939
01940 case NET_IP_SET_GATEWAY:
01941 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
01942 IP_GET_GATEWAY(*call));
01943
01944 case NET_IP_GET_ROUTE:
01945 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
01946 &addrlen);
01947 if (rc != EOK)
01948 return rc;
01949
01950 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
01951 (socklen_t) addrlen, &device_id, &header, &headerlen);
01952 if (rc != EOK)
01953 return rc;
01954
01955 IPC_SET_DEVICE(*answer, device_id);
01956 IP_SET_HEADERLEN(*answer, headerlen);
01957
01958 *answer_count = 2;
01959
01960 rc = data_reply(&headerlen, sizeof(headerlen));
01961 if (rc == EOK)
01962 rc = data_reply(header, headerlen);
01963
01964 free(header);
01965 return rc;
01966
01967 case NET_IP_PACKET_SPACE:
01968 rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
01969 &prefix, &content, &suffix);
01970 if (rc != EOK)
01971 return rc;
01972
01973 IPC_SET_ADDR(*answer, addrlen);
01974 IPC_SET_PREFIX(*answer, prefix);
01975 IPC_SET_CONTENT(*answer, content);
01976 IPC_SET_SUFFIX(*answer, suffix);
01977 *answer_count = 4;
01978 return EOK;
01979
01980 case NET_IP_SEND:
01981 rc = packet_translate_remote(ip_globals.net_phone, &packet,
01982 IPC_GET_PACKET(*call));
01983 if (rc != EOK)
01984 return rc;
01985
01986 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
01987 IPC_GET_ERROR(*call));
01988 }
01989
01990 return ENOTSUP;
01991 }
01992
01993 int main(int argc, char *argv[])
01994 {
01995
01996 return il_module_start(SERVICE_IP);
01997 }
01998