Changes in uspace/srv/net/il/ip/ip.c [ccca251:fd8e8e1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/ip/ip.c
rccca251 rfd8e8e1 36 36 */ 37 37 38 #include "ip.h" 39 #include "ip_module.h" 40 38 41 #include <async.h> 39 42 #include <errno.h> 43 #include <err.h> 40 44 #include <fibril_synch.h> 41 45 #include <stdio.h> 42 46 #include <str.h> 47 #include <ipc/ipc.h> 43 48 #include <ipc/services.h> 44 49 #include <ipc/net.h> … … 48 53 #include <sys/types.h> 49 54 #include <byteorder.h> 50 #include "ip.h"51 55 52 56 #include <adt/measured_strings.h> … … 66 70 #include <net_checksum.h> 67 71 #include <icmp_client.h> 68 #include <icmp_remote.h> 72 #include <icmp_interface.h> 73 #include <il_interface.h> 69 74 #include <ip_client.h> 70 75 #include <ip_interface.h> 71 76 #include <ip_header.h> 72 77 #include <net_interface.h> 73 #include <nil_ remote.h>74 #include <tl_ remote.h>78 #include <nil_interface.h> 79 #include <tl_interface.h> 75 80 #include <packet_remote.h> 76 #include <il_remote.h> 77 #include <il_skel.h> 81 #include <il_local.h> 78 82 79 83 /** IP module name. */ … … 120 124 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t); 121 125 122 static void ip_receiver(ipc_callid_t, ipc_call_t *);123 124 126 /** Releases the packet and returns the result. 125 127 * … … 128 130 * @return The result parameter. 129 131 */ 130 static int ip_release_and_return(packet_t *packet, int result)132 static int ip_release_and_return(packet_t packet, int result) 131 133 { 132 134 pq_release_remote(ip_globals.net_phone, packet_get_id(packet)); … … 138 140 * Searches the registered protocols. 139 141 * 140 * @return The found ICMP phone.141 * @return ENOENT if the ICMP is not registered.142 * @returns The found ICMP phone. 143 * @returns ENOENT if the ICMP is not registered. 142 144 */ 143 145 static int ip_get_icmp_phone(void) 144 146 { 145 ip_proto_ t *proto;147 ip_proto_ref proto; 146 148 int phone; 147 149 … … 159 161 * @param[in] packet The packet or the packet queue to be reported as faulty. 160 162 * @param[in] header The first packet IP header. May be NULL. 161 * @return EOK on success.162 * @return EINVAL if there are no data in the packet.163 * @return EINVAL if the packet is a fragment.164 * @return ENOMEM if the packet is too short to contain the IP163 * @returns EOK on success. 164 * @returns EINVAL if there are no data in the packet. 165 * @returns EINVAL if the packet is a fragment. 166 * @returns ENOMEM if the packet is too short to contain the IP 165 167 * header. 166 * @return EAFNOSUPPORT if the address family is not supported.167 * @return EPERM if the protocol is not allowed to send ICMP168 * @returns EAFNOSUPPORT if the address family is not supported. 169 * @returns EPERM if the protocol is not allowed to send ICMP 168 170 * notifications. The ICMP protocol itself. 169 * @return Other error codes as defined for the packet_set_addr().170 */ 171 static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)172 { 173 packet_t *next;171 * @returns Other error codes as defined for the packet_set_addr(). 172 */ 173 static int ip_prepare_icmp(packet_t packet, ip_header_ref header) 174 { 175 packet_t next; 174 176 struct sockaddr *dest; 175 177 struct sockaddr_in dest_in; 176 178 socklen_t addrlen; 177 179 178 / * Detach the first packet and release the others */180 // detach the first packet and release the others 179 181 next = pq_detach(packet); 180 182 if (next) … … 185 187 return ENOMEM; 186 188 187 / * Get header */188 header = (ip_header_ t *) packet_get_data(packet);189 // get header 190 header = (ip_header_ref) packet_get_data(packet); 189 191 if (!header) 190 192 return EINVAL; … … 192 194 } 193 195 194 / * Only for the first fragment */196 // only for the first fragment 195 197 if (IP_FRAGMENT_OFFSET(header)) 196 198 return EINVAL; 197 199 198 / * Not for the ICMP protocol */200 // not for the ICMP protocol 199 201 if (header->protocol == IPPROTO_ICMP) 200 202 return EPERM; 201 203 202 / * Set the destination address */204 // set the destination address 203 205 switch (header->version) { 204 206 case IPVERSION: … … 226 228 * @param[in] packet The packet or the packet queue to be reported as faulty. 227 229 * @param[in] header The first packet IP header. May be NULL. 228 * @return The found ICMP phone.229 * @return EINVAL if the error parameter is set.230 * @return EINVAL if the ICMP phone is not found.231 * @return EINVAL if the ip_prepare_icmp() fails.230 * @returns The found ICMP phone. 231 * @returns EINVAL if the error parameter is set. 232 * @returns EINVAL if the ICMP phone is not found. 233 * @returns EINVAL if the ip_prepare_icmp() fails. 232 234 */ 233 235 static int 234 ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,235 ip_header_ t *header)236 ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, 237 ip_header_ref header) 236 238 { 237 239 int phone; … … 243 245 } 244 246 245 int il_initialize(int net_phone) 246 { 247 /** Initializes the IP module. 248 * 249 * @param[in] client_connection The client connection processing function. The 250 * module skeleton propagates its own one. 251 * @returns EOK on success. 252 * @returns ENOMEM if there is not enough memory left. 253 */ 254 int ip_initialize(async_client_conn_t client_connection) 255 { 256 ERROR_DECLARE; 257 247 258 fibril_rwlock_initialize(&ip_globals.lock); 248 259 fibril_rwlock_write_lock(&ip_globals.lock); 249 260 fibril_rwlock_initialize(&ip_globals.protos_lock); 250 261 fibril_rwlock_initialize(&ip_globals.netifs_lock); 251 252 ip_globals.net_phone = net_phone;253 262 ip_globals.packet_counter = 0; 254 263 ip_globals.gateway.address.s_addr = 0; … … 256 265 ip_globals.gateway.gateway.s_addr = 0; 257 266 ip_globals.gateway.netif = NULL; 258 259 int rc = ip_netifs_initialize(&ip_globals.netifs); 260 if (rc != EOK) 261 goto out; 262 rc = ip_protos_initialize(&ip_globals.protos); 263 if (rc != EOK) 264 goto out; 265 rc = modules_initialize(&ip_globals.modules); 266 if (rc != EOK) 267 goto out; 268 rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME, 269 (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module); 270 271 out: 267 ERROR_PROPAGATE(ip_netifs_initialize(&ip_globals.netifs)); 268 ERROR_PROPAGATE(ip_protos_initialize(&ip_globals.protos)); 269 ip_globals.client_connection = client_connection; 270 ERROR_PROPAGATE(modules_initialize(&ip_globals.modules)); 271 ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME, 272 ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module)); 272 273 fibril_rwlock_write_unlock(&ip_globals.lock); 273 274 274 return rc;275 return EOK; 275 276 } 276 277 … … 284 285 * 285 286 * @param[in,out] ip_netif Network interface specific data. 286 * @return EOK on success.287 * @return ENOTSUP if DHCP is configured.288 * @return ENOTSUP if IPv6 is configured.289 * @return EINVAL if any of the addresses is invalid.290 * @return EINVAL if the used ARP module is not known.291 * @return ENOMEM if there is not enough memory left.292 * @return Other error codes as defined for the287 * @returns EOK on success. 288 * @returns ENOTSUP if DHCP is configured. 289 * @returns ENOTSUP if IPv6 is configured. 290 * @returns EINVAL if any of the addresses is invalid. 291 * @returns EINVAL if the used ARP module is not known. 292 * @returns ENOMEM if there is not enough memory left. 293 * @returns Other error codes as defined for the 293 294 * net_get_device_conf_req() function. 294 * @return Other error codes as defined for the bind_service()295 * @returns Other error codes as defined for the bind_service() 295 296 * function. 296 * @return Other error codes as defined for the specific297 * @returns Other error codes as defined for the specific 297 298 * arp_device_req() function. 298 * @return Other error codes as defined for the299 * @returns Other error codes as defined for the 299 300 * nil_packet_size_req() function. 300 301 */ 301 static int ip_netif_initialize(ip_netif_t *ip_netif) 302 { 302 static int ip_netif_initialize(ip_netif_ref ip_netif) 303 { 304 ERROR_DECLARE; 305 303 306 measured_string_t names[] = { 304 307 { 305 ( uint8_t*) "IPV",308 (char *) "IPV", 306 309 3 307 310 }, 308 311 { 309 ( uint8_t*) "IP_CONFIG",312 (char *) "IP_CONFIG", 310 313 9 311 314 }, 312 315 { 313 ( uint8_t*) "IP_ADDR",316 (char *) "IP_ADDR", 314 317 7 315 318 }, 316 319 { 317 ( uint8_t*) "IP_NETMASK",320 (char *) "IP_NETMASK", 318 321 10 319 322 }, 320 323 { 321 ( uint8_t*) "IP_GATEWAY",324 (char *) "IP_GATEWAY", 322 325 10 323 326 }, 324 327 { 325 ( uint8_t*) "IP_BROADCAST",328 (char *) "IP_BROADCAST", 326 329 12 327 330 }, 328 331 { 329 ( uint8_t*) "ARP",332 (char *) "ARP", 330 333 3 331 334 }, 332 335 { 333 ( uint8_t*) "IP_ROUTING",336 (char *) "IP_ROUTING", 334 337 10 335 338 } 336 339 }; 337 measured_string_ t *configuration;340 measured_string_ref configuration; 338 341 size_t count = sizeof(names) / sizeof(measured_string_t); 339 uint8_t*data;342 char *data; 340 343 measured_string_t address; 341 ip_route_t *route; 344 int index; 345 ip_route_ref route; 342 346 in_addr_t gateway; 343 int index;344 int rc;345 347 346 348 ip_netif->arp = NULL; … … 351 353 configuration = &names[0]; 352 354 353 /* Get configuration */ 354 rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id, 355 &configuration, count, &data); 356 if (rc != EOK) 357 return rc; 358 355 // get configuration 356 ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone, 357 ip_netif->device_id, &configuration, count, &data)); 359 358 if (configuration) { 360 359 if (configuration[0].value) 361 ip_netif->ipv = strtol( (char *)configuration[0].value, NULL, 0);362 363 ip_netif->dhcp = !str_lcmp( (char *)configuration[1].value, "dhcp",360 ip_netif->ipv = strtol(configuration[0].value, NULL, 0); 361 362 ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp", 364 363 configuration[1].length); 365 364 … … 369 368 return ENOTSUP; 370 369 } else if (ip_netif->ipv == IPV4) { 371 route = (ip_route_ t *) malloc(sizeof(ip_route_t));370 route = (ip_route_ref) malloc(sizeof(ip_route_t)); 372 371 if (!route) { 373 372 net_free_settings(configuration, data); … … 384 383 return index; 385 384 } 386 387 if ((inet_pton(AF_INET, (char *) configuration[2].value, 388 (uint8_t *) &route->address.s_addr) != EOK) || 389 (inet_pton(AF_INET, (char *) configuration[3].value, 390 (uint8_t *) &route->netmask.s_addr) != EOK) || 391 (inet_pton(AF_INET, (char *) configuration[4].value, 385 if (ERROR_OCCURRED(inet_pton(AF_INET, 386 configuration[2].value, 387 (uint8_t *) &route->address.s_addr)) || 388 ERROR_OCCURRED(inet_pton(AF_INET, 389 configuration[3].value, 390 (uint8_t *) &route->netmask.s_addr)) || 391 (inet_pton(AF_INET, configuration[4].value, 392 392 (uint8_t *) &gateway.s_addr) == EINVAL) || 393 (inet_pton(AF_INET, (char *)configuration[5].value,393 (inet_pton(AF_INET, configuration[5].value, 394 394 (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)) 395 395 { … … 419 419 } 420 420 421 / * Bind netif service which also initializes the device */421 // binds the netif service which also initializes the device 422 422 ip_netif->phone = nil_bind_service(ip_netif->service, 423 ( sysarg_t) ip_netif->device_id, SERVICE_IP,424 ip_ receiver);423 (ipcarg_t) ip_netif->device_id, SERVICE_IP, 424 ip_globals.client_connection); 425 425 if (ip_netif->phone < 0) { 426 426 printf("Failed to contact the nil service %d\n", … … 429 429 } 430 430 431 / * Has to be after the device netif module initialization */431 // has to be after the device netif module initialization 432 432 if (ip_netif->arp) { 433 433 if (route) { 434 address.value = (uint8_t *) &route->address.s_addr; 435 address.length = sizeof(in_addr_t); 436 437 rc = arp_device_req(ip_netif->arp->phone, 434 address.value = (char *) &route->address.s_addr; 435 address.length = CONVERT_SIZE(in_addr_t, char, 1); 436 ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone, 438 437 ip_netif->device_id, SERVICE_IP, ip_netif->service, 439 &address); 440 if (rc != EOK) 441 return rc; 438 &address)); 442 439 } else { 443 440 ip_netif->arp = 0; … … 445 442 } 446 443 447 /* Get packet dimensions */ 448 rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id, 449 &ip_netif->packet_dimension); 450 if (rc != EOK) 451 return rc; 452 444 // get packet dimensions 445 ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone, 446 ip_netif->device_id, &ip_netif->packet_dimension)); 453 447 if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) { 454 printf("Maximum transmission unit % zubytes is too small, at "448 printf("Maximum transmission unit %d bytes is too small, at " 455 449 "least %d bytes are needed\n", 456 450 ip_netif->packet_dimension.content, IP_MIN_CONTENT); … … 463 457 464 458 if (gateway.s_addr) { 465 / * The default gateway */459 // the default gateway 466 460 ip_globals.gateway.address.s_addr = 0; 467 461 ip_globals.gateway.netmask.s_addr = 0; 468 462 ip_globals.gateway.gateway.s_addr = gateway.s_addr; 469 463 ip_globals.gateway.netif = ip_netif; 464 } 465 466 return EOK; 467 } 468 469 /** Updates the device content length according to the new MTU value. 470 * 471 * @param[in] device_id The device identifier. 472 * @param[in] mtu The new mtu value. 473 * @returns EOK on success. 474 * @returns ENOENT if device is not found. 475 */ 476 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu) 477 { 478 ip_netif_ref netif; 479 480 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 481 netif = ip_netifs_find(&ip_globals.netifs, device_id); 482 if (!netif) { 483 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 484 return ENOENT; 485 } 486 netif->packet_dimension.content = mtu; 487 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 488 489 printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu); 490 491 return EOK; 492 } 493 494 /** Updates the device state. 495 * 496 * @param[in] device_id The device identifier. 497 * @param[in] state The new state value. 498 * @returns EOK on success. 499 * @returns ENOENT if device is not found. 500 */ 501 static int ip_device_state_message(device_id_t device_id, device_state_t state) 502 { 503 ip_netif_ref netif; 504 505 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 506 // find the device 507 netif = ip_netifs_find(&ip_globals.netifs, device_id); 508 if (!netif) { 509 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 510 return ENOENT; 511 } 512 netif->state = state; 513 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 514 515 printf("%s: Device %d changed state to %d\n", NAME, device_id, state); 516 517 return EOK; 518 } 519 520 521 /** Prefixes a middle fragment header based on the last fragment header to the 522 * packet. 523 * 524 * @param[in] packet The packet to be prefixed. 525 * @param[in] last The last header to be copied. 526 * @returns The prefixed middle header. 527 * @returns NULL on error. 528 */ 529 static ip_header_ref 530 ip_create_middle_header(packet_t packet, ip_header_ref last) 531 { 532 ip_header_ref middle; 533 534 middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last)); 535 if (!middle) 536 return NULL; 537 memcpy(middle, last, IP_HEADER_LENGTH(last)); 538 middle->flags |= IPFLAG_MORE_FRAGMENTS; 539 return middle; 540 } 541 542 /** Copies the fragment header. 543 * 544 * Copies only the header itself and relevant IP options. 545 * 546 * @param[out] last The created header. 547 * @param[in] first The original header to be copied. 548 */ 549 static void ip_create_last_header(ip_header_ref last, ip_header_ref first) 550 { 551 ip_option_ref option; 552 size_t next; 553 size_t length; 554 555 // copy first itself 556 memcpy(last, first, sizeof(ip_header_t)); 557 length = sizeof(ip_header_t); 558 next = sizeof(ip_header_t); 559 560 // process all ip options 561 while (next < first->header_length) { 562 option = (ip_option_ref) (((uint8_t *) first) + next); 563 // skip end or noop 564 if ((option->type == IPOPT_END) || 565 (option->type == IPOPT_NOOP)) { 566 next++; 567 } else { 568 // copy if told so or skip 569 if (IPOPT_COPIED(option->type)) { 570 memcpy(((uint8_t *) last) + length, 571 ((uint8_t *) first) + next, option->length); 572 length += option->length; 573 } 574 // next option 575 next += option->length; 576 } 577 } 578 579 // align 4 byte boundary 580 if (length % 4) { 581 bzero(((uint8_t *) last) + length, 4 - (length % 4)); 582 last->header_length = length / 4 + 1; 583 } else { 584 last->header_length = length / 4; 585 } 586 587 last->header_checksum = 0; 588 } 589 590 /** Prepares the outgoing packet or the packet queue. 591 * 592 * The packet queue is a fragmented packet 593 * Updates the first packet's IP header. 594 * Prefixes the additional packets with fragment headers. 595 * 596 * @param[in] source The source address. 597 * @param[in] dest The destination address. 598 * @param[in,out] packet The packet to be sent. 599 * @param[in] destination The destination hardware address. 600 * @returns EOK on success. 601 * @returns EINVAL if the packet is too small to contain the IP 602 * header. 603 * @returns EINVAL if the packet is too long than the IP allows. 604 * @returns ENOMEM if there is not enough memory left. 605 * @returns Other error codes as defined for the packet_set_addr() 606 * function. 607 */ 608 static int 609 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t packet, 610 measured_string_ref destination) 611 { 612 ERROR_DECLARE; 613 614 size_t length; 615 ip_header_ref header; 616 ip_header_ref last_header; 617 ip_header_ref middle_header; 618 packet_t next; 619 620 length = packet_get_data_length(packet); 621 if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)) 622 return EINVAL; 623 624 header = (ip_header_ref) packet_get_data(packet); 625 if (destination) { 626 ERROR_PROPAGATE(packet_set_addr(packet, NULL, 627 (uint8_t *) destination->value, 628 CONVERT_SIZE(char, uint8_t, destination->length))); 629 } else { 630 ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0)); 631 } 632 header->version = IPV4; 633 header->fragment_offset_high = 0; 634 header->fragment_offset_low = 0; 635 header->header_checksum = 0; 636 if (source) 637 header->source_address = source->s_addr; 638 header->destination_address = dest.s_addr; 639 640 fibril_rwlock_write_lock(&ip_globals.lock); 641 ip_globals.packet_counter++; 642 header->identification = htons(ip_globals.packet_counter); 643 fibril_rwlock_write_unlock(&ip_globals.lock); 644 645 if (pq_next(packet)) { 646 last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header)); 647 if (!last_header) 648 return ENOMEM; 649 ip_create_last_header(last_header, header); 650 next = pq_next(packet); 651 while (pq_next(next)) { 652 middle_header = (ip_header_ref) packet_prefix(next, 653 IP_HEADER_LENGTH(last_header)); 654 if (!middle_header) { 655 free(last_header); 656 return ENOMEM; 657 } 658 659 memcpy(middle_header, last_header, 660 IP_HEADER_LENGTH(last_header)); 661 header->flags |= IPFLAG_MORE_FRAGMENTS; 662 middle_header->total_length = 663 htons(packet_get_data_length(next)); 664 middle_header->fragment_offset_high = 665 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length); 666 middle_header->fragment_offset_low = 667 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length); 668 middle_header->header_checksum = 669 IP_HEADER_CHECKSUM(middle_header); 670 if (destination) { 671 if (ERROR_OCCURRED(packet_set_addr(next, NULL, 672 (uint8_t *) destination->value, 673 CONVERT_SIZE(char, uint8_t, 674 destination->length)))) { 675 free(last_header); 676 return ERROR_CODE; 677 } 678 } 679 length += packet_get_data_length(next); 680 next = pq_next(next); 681 } 682 683 middle_header = (ip_header_ref) packet_prefix(next, 684 IP_HEADER_LENGTH(last_header)); 685 if (!middle_header) { 686 free(last_header); 687 return ENOMEM; 688 } 689 690 memcpy(middle_header, last_header, 691 IP_HEADER_LENGTH(last_header)); 692 middle_header->total_length = 693 htons(packet_get_data_length(next)); 694 middle_header->fragment_offset_high = 695 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length); 696 middle_header->fragment_offset_low = 697 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length); 698 middle_header->header_checksum = 699 IP_HEADER_CHECKSUM(middle_header); 700 if (destination) { 701 if (ERROR_OCCURRED(packet_set_addr(next, NULL, 702 (uint8_t *) destination->value, 703 CONVERT_SIZE(char, uint8_t, 704 destination->length)))) { 705 free(last_header); 706 return ERROR_CODE; 707 } 708 } 709 length += packet_get_data_length(next); 710 free(last_header); 711 header->flags |= IPFLAG_MORE_FRAGMENTS; 712 } 713 714 header->total_length = htons(length); 715 // unnecessary for all protocols 716 header->header_checksum = IP_HEADER_CHECKSUM(header); 717 718 return EOK; 719 } 720 721 /** Fragments the packet from the end. 722 * 723 * @param[in] packet The packet to be fragmented. 724 * @param[in,out] new_packet The new packet fragment. 725 * @param[in,out] header The original packet header. 726 * @param[in,out] new_header The new packet fragment header. 727 * @param[in] length The new fragment length. 728 * @param[in] src The source address. 729 * @param[in] dest The destiantion address. 730 * @param[in] addrlen The address length. 731 * @returns EOK on success. 732 * @returns ENOMEM if the target packet is too small. 733 * @returns Other error codes as defined for the packet_set_addr() 734 * function. 735 * @returns Other error codes as defined for the pq_insert_after() 736 * function. 737 */ 738 static int 739 ip_fragment_packet_data(packet_t packet, packet_t new_packet, 740 ip_header_ref header, ip_header_ref new_header, size_t length, 741 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen) 742 { 743 ERROR_DECLARE; 744 745 void *data; 746 size_t offset; 747 748 data = packet_suffix(new_packet, length); 749 if (!data) 750 return ENOMEM; 751 752 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, 753 length); 754 ERROR_PROPAGATE(packet_trim(packet, 0, length)); 755 header->total_length = htons(IP_TOTAL_LENGTH(header) - length); 756 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length); 757 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header); 758 new_header->fragment_offset_high = 759 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset); 760 new_header->fragment_offset_low = 761 IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset); 762 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header); 763 ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, 764 (const uint8_t *) dest, addrlen)); 765 766 return pq_insert_after(packet, new_packet); 767 } 768 769 /** Checks the packet length and fragments it if needed. 770 * 771 * The new fragments are queued before the original packet. 772 * 773 * @param[in,out] packet The packet to be checked. 774 * @param[in] length The maximum packet length. 775 * @param[in] prefix The minimum prefix size. 776 * @param[in] suffix The minimum suffix size. 777 * @param[in] addr_len The minimum address length. 778 * @returns EOK on success. 779 * @returns EINVAL if the packet_get_addr() function fails. 780 * @returns EINVAL if the packet does not contain the IP header. 781 * @returns EPERM if the packet needs to be fragmented and the 782 * fragmentation is not allowed. 783 * @returns ENOMEM if there is not enough memory left. 784 * @returns ENOMEM if there is no packet available. 785 * @returns ENOMEM if the packet is too small to contain the IP 786 * header. 787 * @returns Other error codes as defined for the packet_trim() 788 * function. 789 * @returns Other error codes as defined for the 790 * ip_create_middle_header() function. 791 * @returns Other error codes as defined for the 792 * ip_fragment_packet_data() function. 793 */ 794 static int 795 ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, 796 socklen_t addr_len) 797 { 798 ERROR_DECLARE; 799 800 packet_t new_packet; 801 ip_header_ref header; 802 ip_header_ref middle_header; 803 ip_header_ref last_header; 804 struct sockaddr *src; 805 struct sockaddr *dest; 806 socklen_t addrlen; 807 int result; 808 809 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 810 if (result <= 0) 811 return EINVAL; 812 813 addrlen = (socklen_t) result; 814 if (packet_get_data_length(packet) <= sizeof(ip_header_t)) 815 return ENOMEM; 816 817 // get header 818 header = (ip_header_ref) packet_get_data(packet); 819 if (!header) 820 return EINVAL; 821 822 // fragmentation forbidden? 823 if(header->flags & IPFLAG_DONT_FRAGMENT) 824 return EPERM; 825 826 // create the last fragment 827 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, 828 suffix, ((addrlen > addr_len) ? addrlen : addr_len)); 829 if (!new_packet) 830 return ENOMEM; 831 832 // allocate as much as originally 833 last_header = (ip_header_ref) packet_suffix(new_packet, 834 IP_HEADER_LENGTH(header)); 835 if (!last_header) 836 return ip_release_and_return(packet, ENOMEM); 837 838 ip_create_last_header(last_header, header); 839 840 // trim the unused space 841 if (ERROR_OCCURRED(packet_trim(new_packet, 0, 842 IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))) { 843 return ip_release_and_return(packet, ERROR_CODE); 844 } 845 846 // biggest multiple of 8 lower than content 847 // TODO even fragmentation? 848 length = length & ~0x7; 849 if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, 850 last_header, 851 ((IP_HEADER_DATA_LENGTH(header) - 852 ((length - IP_HEADER_LENGTH(header)) & ~0x7)) % 853 ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)), src, dest, 854 addrlen))) { 855 return ip_release_and_return(packet, ERROR_CODE); 856 } 857 858 // mark the first as fragmented 859 header->flags |= IPFLAG_MORE_FRAGMENTS; 860 861 // create middle framgents 862 while (IP_TOTAL_LENGTH(header) > length) { 863 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, 864 length, suffix, 865 ((addrlen >= addr_len) ? addrlen : addr_len)); 866 if (!new_packet) 867 return ENOMEM; 868 869 middle_header = ip_create_middle_header(new_packet, 870 last_header); 871 if (!middle_header) 872 return ip_release_and_return(packet, ENOMEM); 873 874 if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, 875 header, middle_header, 876 (length - IP_HEADER_LENGTH(middle_header)) & ~0x7, src, 877 dest, addrlen))) { 878 return ip_release_and_return(packet, ERROR_CODE); 879 } 880 } 881 882 // finish the first fragment 883 header->header_checksum = IP_HEADER_CHECKSUM(header); 884 885 return EOK; 886 } 887 888 /** Checks the packet queue lengths and fragments the packets if needed. 889 * 890 * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to 891 * be fragmented and the fragmentation is not allowed. 892 * 893 * @param[in,out] packet The packet or the packet queue to be checked. 894 * @param[in] prefix The minimum prefix size. 895 * @param[in] content The maximum content size. 896 * @param[in] suffix The minimum suffix size. 897 * @param[in] addr_len The minimum address length. 898 * @param[in] error The error module service. 899 * @returns The packet or the packet queue of the allowed length. 900 * @returns NULL if there are no packets left. 901 */ 902 static packet_t 903 ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, 904 socklen_t addr_len, services_t error) 905 { 906 size_t length; 907 packet_t next; 908 packet_t new_packet; 909 int result; 910 int phone; 911 912 next = packet; 913 // check all packets 914 while (next) { 915 length = packet_get_data_length(next); 470 916 471 char defgateway[INET_ADDRSTRLEN]; 472 inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr, 473 defgateway, INET_ADDRSTRLEN); 474 printf("%s: Default gateway (%s)\n", NAME, defgateway); 475 } 917 if (length <= content) { 918 next = pq_next(next); 919 continue; 920 } 921 922 // too long 923 result = ip_fragment_packet(next, content, prefix, 924 suffix, addr_len); 925 if (result != EOK) { 926 new_packet = pq_detach(next); 927 if (next == packet) { 928 // the new first packet of the queue 929 packet = new_packet; 930 } 931 // fragmentation needed? 932 if (result == EPERM) { 933 phone = ip_prepare_icmp_and_get_phone( 934 error, next, NULL); 935 if (phone >= 0) { 936 // fragmentation necessary ICMP 937 icmp_destination_unreachable_msg(phone, 938 ICMP_FRAG_NEEDED, content, next); 939 } 940 } else { 941 pq_release_remote(ip_globals.net_phone, 942 packet_get_id(next)); 943 } 944 945 next = new_packet; 946 continue; 947 } 948 949 next = pq_next(next); 950 } 951 952 return packet; 953 } 954 955 /** Sends the packet or the packet queue via the specified route. 956 * 957 * The ICMP_HOST_UNREACH error notification may be sent if route hardware 958 * destination address is found. 959 * 960 * @param[in,out] packet The packet to be sent. 961 * @param[in] netif The target network interface. 962 * @param[in] route The target route. 963 * @param[in] src The source address. 964 * @param[in] dest The destination address. 965 * @param[in] error The error module service. 966 * @returns EOK on success. 967 * @returns Other error codes as defined for the arp_translate_req() 968 * function. 969 * @returns Other error codes as defined for the ip_prepare_packet() 970 * function. 971 */ 972 static int 973 ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route, 974 in_addr_t *src, in_addr_t dest, services_t error) 975 { 976 ERROR_DECLARE; 977 978 measured_string_t destination; 979 measured_string_ref translation; 980 char *data; 981 int phone; 982 983 // get destination hardware address 984 if (netif->arp && (route->address.s_addr != dest.s_addr)) { 985 destination.value = route->gateway.s_addr ? 986 (char *) &route->gateway.s_addr : (char *) &dest.s_addr; 987 destination.length = CONVERT_SIZE(dest.s_addr, char, 1); 988 989 if (ERROR_OCCURRED(arp_translate_req(netif->arp->phone, 990 netif->device_id, SERVICE_IP, &destination, &translation, 991 &data))) { 992 pq_release_remote(ip_globals.net_phone, 993 packet_get_id(packet)); 994 return ERROR_CODE; 995 } 996 997 if (!translation || !translation->value) { 998 if (translation) { 999 free(translation); 1000 free(data); 1001 } 1002 phone = ip_prepare_icmp_and_get_phone(error, packet, 1003 NULL); 1004 if (phone >= 0) { 1005 // unreachable ICMP if no routing 1006 icmp_destination_unreachable_msg(phone, 1007 ICMP_HOST_UNREACH, 0, packet); 1008 } 1009 return EINVAL; 1010 } 1011 1012 } else { 1013 translation = NULL; 1014 } 1015 1016 if (ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))) { 1017 pq_release_remote(ip_globals.net_phone, packet_get_id(packet)); 1018 } else { 1019 packet = ip_split_packet(packet, netif->packet_dimension.prefix, 1020 netif->packet_dimension.content, 1021 netif->packet_dimension.suffix, 1022 netif->packet_dimension.addr_len, error); 1023 if (packet) { 1024 nil_send_msg(netif->phone, netif->device_id, packet, 1025 SERVICE_IP); 1026 } 1027 } 1028 1029 if (translation) { 1030 free(translation); 1031 free(data); 1032 } 1033 1034 return ERROR_CODE; 1035 } 1036 1037 /** Searches the network interfaces if there is a suitable route. 1038 * 1039 * @param[in] netif The network interface to be searched for routes. May be 1040 * NULL. 1041 * @param[in] destination The destination address. 1042 * @returns The found route. 1043 * @returns NULL if no route was found. 1044 */ 1045 static ip_route_ref 1046 ip_netif_find_route(ip_netif_ref netif, in_addr_t destination) 1047 { 1048 int index; 1049 ip_route_ref route; 1050 1051 if (!netif) 1052 return NULL; 1053 1054 // start with the first one - the direct route 1055 for (index = 0; index < ip_routes_count(&netif->routes); index++) { 1056 route = ip_routes_get_index(&netif->routes, index); 1057 if (route && 1058 ((route->address.s_addr & route->netmask.s_addr) == 1059 (destination.s_addr & route->netmask.s_addr))) { 1060 return route; 1061 } 1062 } 1063 1064 return NULL; 1065 } 1066 1067 /** Searches all network interfaces if there is a suitable route. 1068 * 1069 * @param[in] destination The destination address. 1070 * @returns The found route. 1071 * @returns NULL if no route was found. 1072 */ 1073 static ip_route_ref ip_find_route(in_addr_t destination) { 1074 int index; 1075 ip_route_ref route; 1076 ip_netif_ref netif; 1077 1078 // start with the last netif - the newest one 1079 index = ip_netifs_count(&ip_globals.netifs) - 1; 1080 while (index >= 0) { 1081 netif = ip_netifs_get_index(&ip_globals.netifs, index); 1082 if (netif && (netif->state == NETIF_ACTIVE)) { 1083 route = ip_netif_find_route(netif, destination); 1084 if (route) 1085 return route; 1086 } 1087 index--; 1088 } 1089 1090 return &ip_globals.gateway; 1091 } 1092 1093 /** Returns the network interface's IP address. 1094 * 1095 * @param[in] netif The network interface. 1096 * @returns The IP address. 1097 * @returns NULL if no IP address was found. 1098 */ 1099 static in_addr_t *ip_netif_address(ip_netif_ref netif) 1100 { 1101 ip_route_ref route; 1102 1103 route = ip_routes_get_index(&netif->routes, 0); 1104 return route ? &route->address : NULL; 1105 } 1106 1107 /** Registers the transport layer protocol. 1108 * 1109 * The traffic of this protocol will be supplied using either the receive 1110 * function or IPC message. 1111 * 1112 * @param[in] protocol The transport layer module protocol. 1113 * @param[in] service The transport layer module service. 1114 * @param[in] phone The transport layer module phone. 1115 * @param[in] received_msg The receiving function. 1116 * @returns EOK on success. 1117 * @returns EINVAL if the protocol parameter and/or the service 1118 * parameter is zero. 1119 * @returns EINVAL if the phone parameter is not a positive number 1120 * and the tl_receive_msg is NULL. 1121 * @returns ENOMEM if there is not enough memory left. 1122 */ 1123 static int 1124 ip_register(int protocol, services_t service, int phone, 1125 tl_received_msg_t received_msg) 1126 { 1127 ip_proto_ref proto; 1128 int index; 1129 1130 if (!protocol || !service || ((phone < 0) && !received_msg)) 1131 return EINVAL; 1132 1133 proto = (ip_proto_ref) malloc(sizeof(ip_protos_t)); 1134 if (!proto) 1135 return ENOMEM; 1136 1137 proto->protocol = protocol; 1138 proto->service = service; 1139 proto->phone = phone; 1140 proto->received_msg = received_msg; 1141 1142 fibril_rwlock_write_lock(&ip_globals.protos_lock); 1143 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto); 1144 if (index < 0) { 1145 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1146 free(proto); 1147 return index; 1148 } 1149 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1150 1151 printf("%s: Protocol registered (protocol: %d, phone: %d)\n", 1152 NAME, proto->protocol, proto->phone); 476 1153 477 1154 return EOK; 478 1155 } 479 1156 480 static int ip_device_req_local(int il_phone, device_id_t device_id, 481 services_t netif) 482 { 483 ip_netif_t *ip_netif; 484 ip_route_t *route; 1157 static int 1158 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif) 1159 { 1160 ERROR_DECLARE; 1161 1162 ip_netif_ref ip_netif; 1163 ip_route_ref route; 485 1164 int index; 486 int rc; 487 488 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t)); 1165 1166 ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t)); 489 1167 if (!ip_netif) 490 1168 return ENOMEM; 491 1169 492 rc = ip_routes_initialize(&ip_netif->routes); 493 if (rc != EOK) { 1170 if (ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))) { 494 1171 free(ip_netif); 495 return rc;1172 return ERROR_CODE; 496 1173 } 497 1174 … … 501 1178 502 1179 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 503 504 rc = ip_netif_initialize(ip_netif); 505 if (rc != EOK) { 1180 if (ERROR_OCCURRED(ip_netif_initialize(ip_netif))) { 506 1181 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 507 ip_routes_destroy(&ip_netif->routes , free);1182 ip_routes_destroy(&ip_netif->routes); 508 1183 free(ip_netif); 509 return rc;1184 return ERROR_CODE; 510 1185 } 511 1186 if (ip_netif->arp) 512 1187 ip_netif->arp->usage++; 513 1188 514 / * Print the settings */1189 // print the settings 515 1190 printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n", 516 1191 NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv, … … 547 1222 } 548 1223 549 /** Searches the network interfaces if there is a suitable route.550 *551 * @param[in] netif The network interface to be searched for routes. May be552 * NULL.553 * @param[in] destination The destination address.554 * @return The found route.555 * @return NULL if no route was found.556 */557 static ip_route_t *ip_netif_find_route(ip_netif_t *netif,558 in_addr_t destination)559 {560 int index;561 ip_route_t *route;562 563 if (!netif)564 return NULL;565 566 /* Start with the first one (the direct route) */567 for (index = 0; index < ip_routes_count(&netif->routes); index++) {568 route = ip_routes_get_index(&netif->routes, index);569 if ((route) &&570 ((route->address.s_addr & route->netmask.s_addr) ==571 (destination.s_addr & route->netmask.s_addr)))572 return route;573 }574 575 return NULL;576 }577 578 /** Searches all network interfaces if there is a suitable route.579 *580 * @param[in] destination The destination address.581 * @return The found route.582 * @return NULL if no route was found.583 */584 static ip_route_t *ip_find_route(in_addr_t destination) {585 int index;586 ip_route_t *route;587 ip_netif_t *netif;588 589 /* Start with the last netif - the newest one */590 index = ip_netifs_count(&ip_globals.netifs) - 1;591 while (index >= 0) {592 netif = ip_netifs_get_index(&ip_globals.netifs, index);593 if (netif && (netif->state == NETIF_ACTIVE)) {594 route = ip_netif_find_route(netif, destination);595 if (route)596 return route;597 }598 index--;599 }600 601 return &ip_globals.gateway;602 }603 604 /** Returns the network interface's IP address.605 *606 * @param[in] netif The network interface.607 * @return The IP address.608 * @return NULL if no IP address was found.609 */610 static in_addr_t *ip_netif_address(ip_netif_t *netif)611 {612 ip_route_t *route;613 614 route = ip_routes_get_index(&netif->routes, 0);615 return route ? &route->address : NULL;616 }617 618 /** Copies the fragment header.619 *620 * Copies only the header itself and relevant IP options.621 *622 * @param[out] last The created header.623 * @param[in] first The original header to be copied.624 */625 static void ip_create_last_header(ip_header_t *last, ip_header_t *first)626 {627 ip_option_t *option;628 size_t next;629 size_t length;630 631 /* Copy first itself */632 memcpy(last, first, sizeof(ip_header_t));633 length = sizeof(ip_header_t);634 next = sizeof(ip_header_t);635 636 /* Process all IP options */637 while (next < first->header_length) {638 option = (ip_option_t *) (((uint8_t *) first) + next);639 /* Skip end or noop */640 if ((option->type == IPOPT_END) ||641 (option->type == IPOPT_NOOP)) {642 next++;643 } else {644 /* Copy if told so or skip */645 if (IPOPT_COPIED(option->type)) {646 memcpy(((uint8_t *) last) + length,647 ((uint8_t *) first) + next, option->length);648 length += option->length;649 }650 /* Next option */651 next += option->length;652 }653 }654 655 /* Align 4 byte boundary */656 if (length % 4) {657 bzero(((uint8_t *) last) + length, 4 - (length % 4));658 last->header_length = length / 4 + 1;659 } else {660 last->header_length = length / 4;661 }662 663 last->header_checksum = 0;664 }665 666 /** Prepares the outgoing packet or the packet queue.667 *668 * The packet queue is a fragmented packet669 * Updates the first packet's IP header.670 * Prefixes the additional packets with fragment headers.671 *672 * @param[in] source The source address.673 * @param[in] dest The destination address.674 * @param[in,out] packet The packet to be sent.675 * @param[in] destination The destination hardware address.676 * @return EOK on success.677 * @return EINVAL if the packet is too small to contain the IP678 * header.679 * @return EINVAL if the packet is too long than the IP allows.680 * @return ENOMEM if there is not enough memory left.681 * @return Other error codes as defined for the packet_set_addr()682 * function.683 */684 static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,685 packet_t *packet, measured_string_t *destination)686 {687 size_t length;688 ip_header_t *header;689 ip_header_t *last_header;690 ip_header_t *middle_header;691 packet_t *next;692 int rc;693 694 length = packet_get_data_length(packet);695 if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))696 return EINVAL;697 698 header = (ip_header_t *) packet_get_data(packet);699 if (destination) {700 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,701 destination->length);702 } else {703 rc = packet_set_addr(packet, NULL, NULL, 0);704 }705 if (rc != EOK)706 return rc;707 708 header->version = IPV4;709 header->fragment_offset_high = 0;710 header->fragment_offset_low = 0;711 header->header_checksum = 0;712 if (source)713 header->source_address = source->s_addr;714 header->destination_address = dest.s_addr;715 716 fibril_rwlock_write_lock(&ip_globals.lock);717 ip_globals.packet_counter++;718 header->identification = htons(ip_globals.packet_counter);719 fibril_rwlock_write_unlock(&ip_globals.lock);720 721 if (pq_next(packet)) {722 last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));723 if (!last_header)724 return ENOMEM;725 ip_create_last_header(last_header, header);726 next = pq_next(packet);727 while (pq_next(next)) {728 middle_header = (ip_header_t *) packet_prefix(next,729 IP_HEADER_LENGTH(last_header));730 if (!middle_header) {731 free(last_header);732 return ENOMEM;733 }734 735 memcpy(middle_header, last_header,736 IP_HEADER_LENGTH(last_header));737 header->flags |= IPFLAG_MORE_FRAGMENTS;738 middle_header->total_length =739 htons(packet_get_data_length(next));740 middle_header->fragment_offset_high =741 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);742 middle_header->fragment_offset_low =743 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);744 middle_header->header_checksum =745 IP_HEADER_CHECKSUM(middle_header);746 if (destination) {747 rc = packet_set_addr(next, NULL,748 (uint8_t *) destination->value,749 destination->length);750 if (rc != EOK) {751 free(last_header);752 return rc;753 }754 }755 length += packet_get_data_length(next);756 next = pq_next(next);757 }758 759 middle_header = (ip_header_t *) packet_prefix(next,760 IP_HEADER_LENGTH(last_header));761 if (!middle_header) {762 free(last_header);763 return ENOMEM;764 }765 766 memcpy(middle_header, last_header,767 IP_HEADER_LENGTH(last_header));768 middle_header->total_length =769 htons(packet_get_data_length(next));770 middle_header->fragment_offset_high =771 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);772 middle_header->fragment_offset_low =773 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);774 middle_header->header_checksum =775 IP_HEADER_CHECKSUM(middle_header);776 if (destination) {777 rc = packet_set_addr(next, NULL,778 (uint8_t *) destination->value,779 destination->length);780 if (rc != EOK) {781 free(last_header);782 return rc;783 }784 }785 length += packet_get_data_length(next);786 free(last_header);787 header->flags |= IPFLAG_MORE_FRAGMENTS;788 }789 790 header->total_length = htons(length);791 /* Unnecessary for all protocols */792 header->header_checksum = IP_HEADER_CHECKSUM(header);793 794 return EOK;795 }796 797 /** Fragments the packet from the end.798 *799 * @param[in] packet The packet to be fragmented.800 * @param[in,out] new_packet The new packet fragment.801 * @param[in,out] header The original packet header.802 * @param[in,out] new_header The new packet fragment header.803 * @param[in] length The new fragment length.804 * @param[in] src The source address.805 * @param[in] dest The destiantion address.806 * @param[in] addrlen The address length.807 * @return EOK on success.808 * @return ENOMEM if the target packet is too small.809 * @return Other error codes as defined for the packet_set_addr()810 * function.811 * @return Other error codes as defined for the pq_insert_after()812 * function.813 */814 static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,815 ip_header_t *header, ip_header_t *new_header, size_t length,816 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)817 {818 void *data;819 size_t offset;820 int rc;821 822 data = packet_suffix(new_packet, length);823 if (!data)824 return ENOMEM;825 826 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,827 length);828 829 rc = packet_trim(packet, 0, length);830 if (rc != EOK)831 return rc;832 833 header->total_length = htons(IP_TOTAL_LENGTH(header) - length);834 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);835 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);836 new_header->fragment_offset_high =837 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);838 new_header->fragment_offset_low =839 IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);840 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);841 842 rc = packet_set_addr(new_packet, (const uint8_t *) src,843 (const uint8_t *) dest, addrlen);844 if (rc != EOK)845 return rc;846 847 return pq_insert_after(packet, new_packet);848 }849 850 /** Prefixes a middle fragment header based on the last fragment header to the851 * packet.852 *853 * @param[in] packet The packet to be prefixed.854 * @param[in] last The last header to be copied.855 * @return The prefixed middle header.856 * @return NULL on error.857 */858 static ip_header_t *ip_create_middle_header(packet_t *packet,859 ip_header_t *last)860 {861 ip_header_t *middle;862 863 middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));864 if (!middle)865 return NULL;866 memcpy(middle, last, IP_HEADER_LENGTH(last));867 middle->flags |= IPFLAG_MORE_FRAGMENTS;868 return middle;869 }870 871 /** Checks the packet length and fragments it if needed.872 *873 * The new fragments are queued before the original packet.874 *875 * @param[in,out] packet The packet to be checked.876 * @param[in] length The maximum packet length.877 * @param[in] prefix The minimum prefix size.878 * @param[in] suffix The minimum suffix size.879 * @param[in] addr_len The minimum address length.880 * @return EOK on success.881 * @return EINVAL if the packet_get_addr() function fails.882 * @return EINVAL if the packet does not contain the IP header.883 * @return EPERM if the packet needs to be fragmented and the884 * fragmentation is not allowed.885 * @return ENOMEM if there is not enough memory left.886 * @return ENOMEM if there is no packet available.887 * @return ENOMEM if the packet is too small to contain the IP888 * header.889 * @return Other error codes as defined for the packet_trim()890 * function.891 * @return Other error codes as defined for the892 * ip_create_middle_header() function.893 * @return Other error codes as defined for the894 * ip_fragment_packet_data() function.895 */896 1224 static int 897 ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix, 898 socklen_t addr_len) 899 { 900 packet_t *new_packet; 901 ip_header_t *header; 902 ip_header_t *middle_header; 903 ip_header_t *last_header; 904 struct sockaddr *src; 905 struct sockaddr *dest; 906 socklen_t addrlen; 907 int result; 908 int rc; 909 910 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 911 if (result <= 0) 912 return EINVAL; 913 914 addrlen = (socklen_t) result; 915 if (packet_get_data_length(packet) <= sizeof(ip_header_t)) 916 return ENOMEM; 917 918 /* Get header */ 919 header = (ip_header_t *) packet_get_data(packet); 920 if (!header) 921 return EINVAL; 922 923 /* Fragmentation forbidden? */ 924 if(header->flags & IPFLAG_DONT_FRAGMENT) 925 return EPERM; 926 927 /* Create the last fragment */ 928 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, 929 suffix, ((addrlen > addr_len) ? addrlen : addr_len)); 930 if (!new_packet) 931 return ENOMEM; 932 933 /* Allocate as much as originally */ 934 last_header = (ip_header_t *) packet_suffix(new_packet, 935 IP_HEADER_LENGTH(header)); 936 if (!last_header) 937 return ip_release_and_return(packet, ENOMEM); 938 939 ip_create_last_header(last_header, header); 940 941 /* Trim the unused space */ 942 rc = packet_trim(new_packet, 0, 943 IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)); 944 if (rc != EOK) 945 return ip_release_and_return(packet, rc); 946 947 /* Greatest multiple of 8 lower than content */ 948 // TODO even fragmentation? 949 length = length & ~0x7; 950 951 rc = ip_fragment_packet_data(packet, new_packet, header, last_header, 952 ((IP_HEADER_DATA_LENGTH(header) - 953 ((length - IP_HEADER_LENGTH(header)) & ~0x7)) % 954 ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)), 955 src, dest, addrlen); 956 if (rc != EOK) 957 return ip_release_and_return(packet, rc); 958 959 /* Mark the first as fragmented */ 960 header->flags |= IPFLAG_MORE_FRAGMENTS; 961 962 /* Create middle fragments */ 963 while (IP_TOTAL_LENGTH(header) > length) { 964 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, 965 length, suffix, 966 ((addrlen >= addr_len) ? addrlen : addr_len)); 967 if (!new_packet) 968 return ENOMEM; 969 970 middle_header = ip_create_middle_header(new_packet, 971 last_header); 972 if (!middle_header) 973 return ip_release_and_return(packet, ENOMEM); 974 975 rc = ip_fragment_packet_data(packet, new_packet, header, 976 middle_header, 977 (length - IP_HEADER_LENGTH(middle_header)) & ~0x7, 978 src, dest, addrlen); 979 if (rc != EOK) 980 return ip_release_and_return(packet, rc); 981 } 982 983 /* Finish the first fragment */ 984 header->header_checksum = IP_HEADER_CHECKSUM(header); 985 986 return EOK; 987 } 988 989 /** Checks the packet queue lengths and fragments the packets if needed. 990 * 991 * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to 992 * be fragmented and the fragmentation is not allowed. 993 * 994 * @param[in,out] packet The packet or the packet queue to be checked. 995 * @param[in] prefix The minimum prefix size. 996 * @param[in] content The maximum content size. 997 * @param[in] suffix The minimum suffix size. 998 * @param[in] addr_len The minimum address length. 999 * @param[in] error The error module service. 1000 * @return The packet or the packet queue of the allowed length. 1001 * @return NULL if there are no packets left. 1002 */ 1003 static packet_t * 1004 ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix, 1005 socklen_t addr_len, services_t error) 1006 { 1007 size_t length; 1008 packet_t *next; 1009 packet_t *new_packet; 1010 int result; 1011 int phone; 1012 1013 next = packet; 1014 /* Check all packets */ 1015 while (next) { 1016 length = packet_get_data_length(next); 1017 1018 if (length <= content) { 1019 next = pq_next(next); 1020 continue; 1021 } 1022 1023 /* Too long */ 1024 result = ip_fragment_packet(next, content, prefix, 1025 suffix, addr_len); 1026 if (result != EOK) { 1027 new_packet = pq_detach(next); 1028 if (next == packet) { 1029 /* The new first packet of the queue */ 1030 packet = new_packet; 1031 } 1032 /* Fragmentation needed? */ 1033 if (result == EPERM) { 1034 phone = ip_prepare_icmp_and_get_phone( 1035 error, next, NULL); 1036 if (phone >= 0) { 1037 /* Fragmentation necessary ICMP */ 1038 icmp_destination_unreachable_msg(phone, 1039 ICMP_FRAG_NEEDED, content, next); 1040 } 1041 } else { 1042 pq_release_remote(ip_globals.net_phone, 1043 packet_get_id(next)); 1044 } 1045 1046 next = new_packet; 1047 continue; 1048 } 1049 1050 next = pq_next(next); 1051 } 1052 1053 return packet; 1054 } 1055 1056 /** Sends the packet or the packet queue via the specified route. 1057 * 1058 * The ICMP_HOST_UNREACH error notification may be sent if route hardware 1059 * destination address is found. 1060 * 1061 * @param[in,out] packet The packet to be sent. 1062 * @param[in] netif The target network interface. 1063 * @param[in] route The target route. 1064 * @param[in] src The source address. 1065 * @param[in] dest The destination address. 1066 * @param[in] error The error module service. 1067 * @return EOK on success. 1068 * @return Other error codes as defined for the arp_translate_req() 1069 * function. 1070 * @return Other error codes as defined for the ip_prepare_packet() 1071 * function. 1072 */ 1073 static int ip_send_route(packet_t *packet, ip_netif_t *netif, 1074 ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error) 1075 { 1076 measured_string_t destination; 1077 measured_string_t *translation; 1078 uint8_t *data; 1079 int phone; 1080 int rc; 1081 1082 /* Get destination hardware address */ 1083 if (netif->arp && (route->address.s_addr != dest.s_addr)) { 1084 destination.value = route->gateway.s_addr ? 1085 (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr; 1086 destination.length = sizeof(dest.s_addr); 1087 1088 rc = arp_translate_req(netif->arp->phone, netif->device_id, 1089 SERVICE_IP, &destination, &translation, &data); 1090 if (rc != EOK) { 1091 pq_release_remote(ip_globals.net_phone, 1092 packet_get_id(packet)); 1093 return rc; 1094 } 1095 1096 if (!translation || !translation->value) { 1097 if (translation) { 1098 free(translation); 1099 free(data); 1100 } 1101 phone = ip_prepare_icmp_and_get_phone(error, packet, 1102 NULL); 1103 if (phone >= 0) { 1104 /* Unreachable ICMP if no routing */ 1105 icmp_destination_unreachable_msg(phone, 1106 ICMP_HOST_UNREACH, 0, packet); 1107 } 1108 return EINVAL; 1109 } 1110 1111 } else { 1112 translation = NULL; 1113 } 1114 1115 rc = ip_prepare_packet(src, dest, packet, translation); 1116 if (rc != EOK) { 1117 pq_release_remote(ip_globals.net_phone, packet_get_id(packet)); 1118 } else { 1119 packet = ip_split_packet(packet, netif->packet_dimension.prefix, 1120 netif->packet_dimension.content, 1121 netif->packet_dimension.suffix, 1122 netif->packet_dimension.addr_len, error); 1123 if (packet) { 1124 nil_send_msg(netif->phone, netif->device_id, packet, 1125 SERVICE_IP); 1126 } 1127 } 1128 1129 if (translation) { 1130 free(translation); 1131 free(data); 1132 } 1133 1134 return rc; 1135 } 1136 1137 static int ip_send_msg_local(int il_phone, device_id_t device_id, 1138 packet_t *packet, services_t sender, services_t error) 1139 { 1225 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, 1226 services_t sender, services_t error) 1227 { 1228 ERROR_DECLARE; 1229 1140 1230 int addrlen; 1141 ip_netif_ t *netif;1142 ip_route_ t *route;1231 ip_netif_ref netif; 1232 ip_route_ref route; 1143 1233 struct sockaddr *addr; 1144 1234 struct sockaddr_in *address_in; … … 1146 1236 in_addr_t *src; 1147 1237 int phone; 1148 int rc; 1149 1150 /* 1151 * Addresses in the host byte order 1152 * Should be the next hop address or the target destination address 1153 */ 1238 1239 // addresses in the host byte order 1240 // should be the next hop address or the target destination address 1154 1241 addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr); 1155 1242 if (addrlen < 0) … … 1176 1263 fibril_rwlock_read_lock(&ip_globals.netifs_lock); 1177 1264 1178 / * Device specified? */1265 // device specified? 1179 1266 if (device_id > 0) { 1180 1267 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1181 route = ip_netif_find_route(netif, * dest);1268 route = ip_netif_find_route(netif, * dest); 1182 1269 if (netif && !route && (ip_globals.gateway.netif == netif)) 1183 1270 route = &ip_globals.gateway; … … 1192 1279 phone = ip_prepare_icmp_and_get_phone(error, packet, NULL); 1193 1280 if (phone >= 0) { 1194 / * Unreachable ICMP if no routing */1281 // unreachable ICMP if no routing 1195 1282 icmp_destination_unreachable_msg(phone, 1196 1283 ICMP_NET_UNREACH, 0, packet); … … 1200 1287 1201 1288 if (error) { 1202 /* 1203 * Do not send for broadcast, anycast packets or network 1204 * broadcast. 1205 */ 1289 // do not send for broadcast, anycast packets or network 1290 // broadcast 1206 1291 if (!dest->s_addr || !(~dest->s_addr) || 1207 1292 !(~((dest->s_addr & ~route->netmask.s_addr) | … … 1211 1296 } 1212 1297 } 1213 1214 / * If the local host is the destination */1298 1299 // if the local host is the destination 1215 1300 if ((route->address.s_addr == dest->s_addr) && 1216 1301 (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) { 1217 / * Find the loopback device to deliver */1302 // find the loopback device to deliver 1218 1303 dest->s_addr = IPV4_LOCALHOST_ADDRESS; 1219 1304 route = ip_find_route(*dest); … … 1224 1309 NULL); 1225 1310 if (phone >= 0) { 1226 / * Unreachable ICMP if no routing */1311 // unreachable ICMP if no routing 1227 1312 icmp_destination_unreachable_msg(phone, 1228 1313 ICMP_HOST_UNREACH, 0, packet); … … 1238 1323 } 1239 1324 1240 rc= ip_send_route(packet, netif, route, src, *dest, error);1325 ERROR_CODE = ip_send_route(packet, netif, route, src, *dest, error); 1241 1326 fibril_rwlock_read_unlock(&ip_globals.netifs_lock); 1242 1327 1243 return rc; 1244 } 1245 1246 /** Updates the device state. 1247 * 1248 * @param[in] device_id The device identifier. 1249 * @param[in] state The new state value. 1250 * @return EOK on success. 1251 * @return ENOENT if device is not found. 1252 */ 1253 static int ip_device_state_message(device_id_t device_id, device_state_t state) 1254 { 1255 ip_netif_t *netif; 1256 1257 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1258 /* Find the device */ 1259 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1260 if (!netif) { 1261 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1262 return ENOENT; 1263 } 1264 netif->state = state; 1265 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1266 1267 printf("%s: Device %d changed state to %d\n", NAME, device_id, state); 1268 1269 return EOK; 1270 } 1271 1272 /** Returns the packet destination address from the IP header. 1273 * 1274 * @param[in] header The packet IP header to be read. 1275 * @return The packet destination address. 1276 */ 1277 static in_addr_t ip_get_destination(ip_header_t *header) 1278 { 1279 in_addr_t destination; 1280 1281 // TODO search set ipopt route? 1282 destination.s_addr = header->destination_address; 1283 return destination; 1284 } 1285 1286 /** Delivers the packet to the local host. 1287 * 1288 * The packet is either passed to another module or released on error. 1289 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not 1290 * found. 1291 * 1292 * @param[in] device_id The source device identifier. 1293 * @param[in] packet The packet to be delivered. 1294 * @param[in] header The first packet IP header. May be NULL. 1295 * @param[in] error The packet error service. 1296 * @return EOK on success. 1297 * @return ENOTSUP if the packet is a fragment. 1298 * @return EAFNOSUPPORT if the address family is not supported. 1299 * @return ENOENT if the target protocol is not found. 1300 * @return Other error codes as defined for the packet_set_addr() 1301 * function. 1302 * @return Other error codes as defined for the packet_trim() 1303 * function. 1304 * @return Other error codes as defined for the protocol specific 1305 * tl_received_msg() function. 1306 */ 1307 static int ip_deliver_local(device_id_t device_id, packet_t *packet, 1308 ip_header_t *header, services_t error) 1309 { 1310 ip_proto_t *proto; 1311 int phone; 1312 services_t service; 1313 tl_received_msg_t received_msg; 1314 struct sockaddr *src; 1315 struct sockaddr *dest; 1316 struct sockaddr_in src_in; 1317 struct sockaddr_in dest_in; 1318 socklen_t addrlen; 1319 int rc; 1320 1321 if ((header->flags & IPFLAG_MORE_FRAGMENTS) || 1322 IP_FRAGMENT_OFFSET(header)) { 1323 // TODO fragmented 1324 return ENOTSUP; 1325 } 1326 1327 switch (header->version) { 1328 case IPVERSION: 1329 addrlen = sizeof(src_in); 1330 bzero(&src_in, addrlen); 1331 src_in.sin_family = AF_INET; 1332 memcpy(&dest_in, &src_in, addrlen); 1333 memcpy(&src_in.sin_addr.s_addr, &header->source_address, 1334 sizeof(header->source_address)); 1335 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, 1336 sizeof(header->destination_address)); 1337 src = (struct sockaddr *) &src_in; 1338 dest = (struct sockaddr *) &dest_in; 1339 break; 1340 1341 default: 1342 return ip_release_and_return(packet, EAFNOSUPPORT); 1343 } 1344 1345 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, 1346 addrlen); 1347 if (rc != EOK) 1348 return ip_release_and_return(packet, rc); 1349 1350 /* Trim padding if present */ 1351 if (!error && 1352 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) { 1353 rc = packet_trim(packet, 0, 1354 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)); 1355 if (rc != EOK) 1356 return ip_release_and_return(packet, rc); 1357 } 1358 1359 fibril_rwlock_read_lock(&ip_globals.protos_lock); 1360 1361 proto = ip_protos_find(&ip_globals.protos, header->protocol); 1362 if (!proto) { 1363 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1364 phone = ip_prepare_icmp_and_get_phone(error, packet, header); 1365 if (phone >= 0) { 1366 /* Unreachable ICMP */ 1367 icmp_destination_unreachable_msg(phone, 1368 ICMP_PROT_UNREACH, 0, packet); 1369 } 1370 return ENOENT; 1371 } 1372 1373 if (proto->received_msg) { 1374 service = proto->service; 1375 received_msg = proto->received_msg; 1376 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1377 rc = received_msg(device_id, packet, service, error); 1378 } else { 1379 rc = tl_received_msg(proto->phone, device_id, packet, 1380 proto->service, error); 1381 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1382 } 1383 1384 return rc; 1385 } 1386 1387 /** Processes the received packet. 1388 * 1389 * The packet is either passed to another module or released on error. 1390 * 1391 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is 1392 * invalid. 1393 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two. 1394 * The ICMP_HOST_UNREACH error notification may be sent if no route was found. 1395 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for 1396 * another host and the routing is disabled. 1397 * 1398 * @param[in] device_id The source device identifier. 1399 * @param[in] packet The received packet to be processed. 1400 * @return EOK on success. 1401 * @return EINVAL if the TTL is less than two. 1402 * @return EINVAL if the checksum is invalid. 1403 * @return EAFNOSUPPORT if the address family is not supported. 1404 * @return ENOENT if no route was found. 1405 * @return ENOENT if the packet is for another host and the routing 1406 * is disabled. 1407 */ 1408 static int ip_process_packet(device_id_t device_id, packet_t *packet) 1409 { 1410 ip_header_t *header; 1411 in_addr_t dest; 1412 ip_route_t *route; 1413 int phone; 1414 struct sockaddr *addr; 1415 struct sockaddr_in addr_in; 1416 socklen_t addrlen; 1417 int rc; 1418 1419 header = (ip_header_t *) packet_get_data(packet); 1420 if (!header) 1421 return ip_release_and_return(packet, ENOMEM); 1422 1423 /* Checksum */ 1424 if ((header->header_checksum) && 1425 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) { 1426 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1427 if (phone >= 0) { 1428 /* Checksum error ICMP */ 1429 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, 1430 ((size_t) ((void *) &header->header_checksum)) - 1431 ((size_t) ((void *) header)), packet); 1432 } 1433 return EINVAL; 1434 } 1435 1436 if (header->ttl <= 1) { 1437 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1438 if (phone >= 0) { 1439 /* TTL exceeded ICMP */ 1440 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet); 1441 } 1442 return EINVAL; 1443 } 1444 1445 /* Process ipopt and get destination */ 1446 dest = ip_get_destination(header); 1447 1448 /* Set the destination address */ 1449 switch (header->version) { 1450 case IPVERSION: 1451 addrlen = sizeof(addr_in); 1452 bzero(&addr_in, addrlen); 1453 addr_in.sin_family = AF_INET; 1454 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest)); 1455 addr = (struct sockaddr *) &addr_in; 1456 break; 1457 1458 default: 1459 return ip_release_and_return(packet, EAFNOSUPPORT); 1460 } 1461 1462 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen); 1463 if (rc != EOK) 1464 return rc; 1465 1466 route = ip_find_route(dest); 1467 if (!route) { 1468 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1469 if (phone >= 0) { 1470 /* Unreachable ICMP */ 1471 icmp_destination_unreachable_msg(phone, 1472 ICMP_HOST_UNREACH, 0, packet); 1473 } 1474 return ENOENT; 1475 } 1476 1477 if (route->address.s_addr == dest.s_addr) { 1478 /* Local delivery */ 1479 return ip_deliver_local(device_id, packet, header, 0); 1480 } 1481 1482 if (route->netif->routing) { 1483 header->ttl--; 1484 return ip_send_route(packet, route->netif, route, NULL, dest, 1485 0); 1486 } 1487 1488 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1489 if (phone >= 0) { 1490 /* Unreachable ICMP if no routing */ 1491 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, 1492 packet); 1493 } 1494 1495 return ENOENT; 1328 return ERROR_CODE; 1496 1329 } 1497 1330 … … 1505 1338 * @param[out] content The maximum content size. 1506 1339 * @param[out] suffix The minimum reserved suffix size. 1507 * @return EOK on success. 1508 */ 1509 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len, 1510 size_t *prefix, size_t *content, size_t *suffix) 1511 { 1512 ip_netif_t *netif; 1340 * @returns EOK on success. 1341 */ 1342 static int 1343 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix, 1344 size_t *content, size_t *suffix) 1345 { 1346 ip_netif_ref netif; 1513 1347 int index; 1514 1348 … … 1558 1392 } 1559 1393 1560 /** Updates the device content length according to the new MTU value. 1561 * 1562 * @param[in] device_id The device identifier. 1563 * @param[in] mtu The new mtu value. 1564 * @return EOK on success. 1565 * @return ENOENT if device is not found. 1566 */ 1567 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu) 1568 { 1569 ip_netif_t *netif; 1394 /** Returns the packet destination address from the IP header. 1395 * 1396 * @param[in] header The packet IP header to be read. 1397 * @returns The packet destination address. 1398 */ 1399 static in_addr_t ip_get_destination(ip_header_ref header) 1400 { 1401 in_addr_t destination; 1402 1403 // TODO search set ipopt route? 1404 destination.s_addr = header->destination_address; 1405 return destination; 1406 } 1407 1408 /** Delivers the packet to the local host. 1409 * 1410 * The packet is either passed to another module or released on error. 1411 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not 1412 * found. 1413 * 1414 * @param[in] device_id The source device identifier. 1415 * @param[in] packet The packet to be delivered. 1416 * @param[in] header The first packet IP header. May be NULL. 1417 * @param[in] error The packet error service. 1418 * @returns EOK on success. 1419 * @returns ENOTSUP if the packet is a fragment. 1420 * @returns EAFNOSUPPORT if the address family is not supported. 1421 * @returns ENOENT if the target protocol is not found. 1422 * @returns Other error codes as defined for the packet_set_addr() 1423 * function. 1424 * @returns Other error codes as defined for the packet_trim() 1425 * function. 1426 * @returns Other error codes as defined for the protocol specific 1427 * tl_received_msg() function. 1428 */ 1429 static int 1430 ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, 1431 services_t error) 1432 { 1433 ERROR_DECLARE; 1434 1435 ip_proto_ref proto; 1436 int phone; 1437 services_t service; 1438 tl_received_msg_t received_msg; 1439 struct sockaddr *src; 1440 struct sockaddr *dest; 1441 struct sockaddr_in src_in; 1442 struct sockaddr_in dest_in; 1443 socklen_t addrlen; 1444 1445 if ((header->flags & IPFLAG_MORE_FRAGMENTS) || 1446 IP_FRAGMENT_OFFSET(header)) { 1447 // TODO fragmented 1448 return ENOTSUP; 1449 } 1450 1451 switch (header->version) { 1452 case IPVERSION: 1453 addrlen = sizeof(src_in); 1454 bzero(&src_in, addrlen); 1455 src_in.sin_family = AF_INET; 1456 memcpy(&dest_in, &src_in, addrlen); 1457 memcpy(&src_in.sin_addr.s_addr, &header->source_address, 1458 sizeof(header->source_address)); 1459 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, 1460 sizeof(header->destination_address)); 1461 src = (struct sockaddr *) &src_in; 1462 dest = (struct sockaddr *) &dest_in; 1463 break; 1464 1465 default: 1466 return ip_release_and_return(packet, EAFNOSUPPORT); 1467 } 1468 1469 if (ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, 1470 (uint8_t *) dest, addrlen))) { 1471 return ip_release_and_return(packet, ERROR_CODE); 1472 } 1473 1474 // trim padding if present 1475 if (!error && 1476 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) { 1477 if (ERROR_OCCURRED(packet_trim(packet, 0, 1478 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))) 1479 return ip_release_and_return(packet, ERROR_CODE); 1480 } 1481 1482 fibril_rwlock_read_lock(&ip_globals.protos_lock); 1483 1484 proto = ip_protos_find(&ip_globals.protos, header->protocol); 1485 if (!proto) { 1486 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1487 phone = ip_prepare_icmp_and_get_phone(error, packet, header); 1488 if (phone >= 0) { 1489 // unreachable ICMP 1490 icmp_destination_unreachable_msg(phone, 1491 ICMP_PROT_UNREACH, 0, packet); 1492 } 1493 return ENOENT; 1494 } 1495 1496 if (proto->received_msg) { 1497 service = proto->service; 1498 received_msg = proto->received_msg; 1499 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1500 ERROR_CODE = received_msg(device_id, packet, service, error); 1501 } else { 1502 ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, 1503 proto->service, error); 1504 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1505 } 1506 1507 return ERROR_CODE; 1508 } 1509 1510 /** Processes the received packet. 1511 * 1512 * The packet is either passed to another module or released on error. 1513 * 1514 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is 1515 * invalid. 1516 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two. 1517 * The ICMP_HOST_UNREACH error notification may be sent if no route was found. 1518 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for 1519 * another host and the routing is disabled. 1520 * 1521 * @param[in] device_id The source device identifier. 1522 * @param[in] packet The received packet to be processed. 1523 * @returns EOK on success. 1524 * @returns EINVAL if the TTL is less than two. 1525 * @returns EINVAL if the checksum is invalid. 1526 * @returns EAFNOSUPPORT if the address family is not supported. 1527 * @returns ENOENT if no route was found. 1528 * @returns ENOENT if the packet is for another host and the routing 1529 * is disabled. 1530 */ 1531 static int 1532 ip_process_packet(device_id_t device_id, packet_t packet) 1533 { 1534 ERROR_DECLARE; 1535 1536 ip_header_ref header; 1537 in_addr_t dest; 1538 ip_route_ref route; 1539 int phone; 1540 struct sockaddr *addr; 1541 struct sockaddr_in addr_in; 1542 socklen_t addrlen; 1543 1544 header = (ip_header_ref) packet_get_data(packet); 1545 if (!header) 1546 return ip_release_and_return(packet, ENOMEM); 1547 1548 // checksum 1549 if ((header->header_checksum) && 1550 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) { 1551 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1552 if (phone >= 0) { 1553 // checksum error ICMP 1554 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, 1555 ((size_t) ((void *) &header->header_checksum)) - 1556 ((size_t) ((void *) header)), packet); 1557 } 1558 return EINVAL; 1559 } 1560 1561 if (header->ttl <= 1) { 1562 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1563 if (phone >= 0) { 1564 // ttl exceeded ICMP 1565 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet); 1566 } 1567 return EINVAL; 1568 } 1569 1570 // process ipopt and get destination 1571 dest = ip_get_destination(header); 1572 1573 // set the addrination address 1574 switch (header->version) { 1575 case IPVERSION: 1576 addrlen = sizeof(addr_in); 1577 bzero(&addr_in, addrlen); 1578 addr_in.sin_family = AF_INET; 1579 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest)); 1580 addr = (struct sockaddr *) &addr_in; 1581 break; 1582 1583 default: 1584 return ip_release_and_return(packet, EAFNOSUPPORT); 1585 } 1586 1587 ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, 1588 addrlen)); 1589 1590 route = ip_find_route(dest); 1591 if (!route) { 1592 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1593 if (phone >= 0) { 1594 // unreachable ICMP 1595 icmp_destination_unreachable_msg(phone, 1596 ICMP_HOST_UNREACH, 0, packet); 1597 } 1598 return ENOENT; 1599 } 1600 1601 if (route->address.s_addr == dest.s_addr) { 1602 // local delivery 1603 return ip_deliver_local(device_id, packet, header, 0); 1604 } 1605 1606 if (route->netif->routing) { 1607 header->ttl--; 1608 return ip_send_route(packet, route->netif, route, NULL, dest, 1609 0); 1610 } 1611 1612 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1613 if (phone >= 0) { 1614 // unreachable ICMP if no routing 1615 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, 1616 packet); 1617 } 1618 1619 return ENOENT; 1620 } 1621 1622 static int 1623 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address, 1624 in_addr_t netmask, in_addr_t gateway) 1625 { 1626 ip_route_ref route; 1627 ip_netif_ref netif; 1628 int index; 1570 1629 1571 1630 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1631 1572 1632 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1573 1633 if (!netif) { … … 1575 1635 return ENOENT; 1576 1636 } 1577 netif->packet_dimension.content = mtu; 1578 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1579 1580 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 1581 1582 return EOK; 1583 } 1584 1585 /** Process IPC messages from the registered device driver modules 1586 * 1587 * @param[in] iid Message identifier. 1588 * @param[in,out] icall Message parameters. 1589 * 1590 */ 1591 static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall) 1592 { 1593 packet_t *packet; 1594 int rc; 1595 1596 while (true) { 1597 switch (IPC_GET_IMETHOD(*icall)) { 1598 case NET_IL_DEVICE_STATE: 1599 rc = ip_device_state_message(IPC_GET_DEVICE(*icall), 1600 IPC_GET_STATE(*icall)); 1601 async_answer_0(iid, (sysarg_t) rc); 1602 break; 1603 1604 case NET_IL_RECEIVED: 1605 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1606 IPC_GET_PACKET(*icall)); 1607 if (rc == EOK) { 1608 do { 1609 packet_t *next = pq_detach(packet); 1610 ip_process_packet(IPC_GET_DEVICE(*icall), packet); 1611 packet = next; 1612 } while (packet); 1613 } 1614 1615 async_answer_0(iid, (sysarg_t) rc); 1616 break; 1617 1618 case NET_IL_MTU_CHANGED: 1619 rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall), 1620 IPC_GET_MTU(*icall)); 1621 async_answer_0(iid, (sysarg_t) rc); 1622 break; 1623 1624 default: 1625 async_answer_0(iid, (sysarg_t) ENOTSUP); 1626 } 1627 1628 iid = async_get_call(icall); 1629 } 1630 } 1631 1632 /** Registers the transport layer protocol. 1633 * 1634 * The traffic of this protocol will be supplied using either the receive 1635 * function or IPC message. 1636 * 1637 * @param[in] protocol The transport layer module protocol. 1638 * @param[in] service The transport layer module service. 1639 * @param[in] phone The transport layer module phone. 1640 * @param[in] received_msg The receiving function. 1641 * @return EOK on success. 1642 * @return EINVAL if the protocol parameter and/or the service 1643 * parameter is zero. 1644 * @return EINVAL if the phone parameter is not a positive number 1645 * and the tl_receive_msg is NULL. 1646 * @return ENOMEM if there is not enough memory left. 1647 */ 1648 static int 1649 ip_register(int protocol, services_t service, int phone, 1650 tl_received_msg_t received_msg) 1651 { 1652 ip_proto_t *proto; 1653 int index; 1654 1655 if (!protocol || !service || ((phone < 0) && !received_msg)) 1656 return EINVAL; 1657 1658 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t)); 1659 if (!proto) 1660 return ENOMEM; 1661 1662 proto->protocol = protocol; 1663 proto->service = service; 1664 proto->phone = phone; 1665 proto->received_msg = received_msg; 1666 1667 fibril_rwlock_write_lock(&ip_globals.protos_lock); 1668 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto); 1669 if (index < 0) { 1670 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1671 free(proto); 1672 return index; 1673 } 1674 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1675 1676 printf("%s: Protocol registered (protocol: %d, phone: %d)\n", 1677 NAME, proto->protocol, proto->phone); 1678 1679 return EOK; 1680 } 1681 1682 1683 static int 1684 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address, 1685 in_addr_t netmask, in_addr_t gateway) 1686 { 1687 ip_route_t *route; 1688 ip_netif_t *netif; 1689 int index; 1690 1691 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1692 1693 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1694 if (!netif) { 1695 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1696 return ENOENT; 1697 } 1698 1699 route = (ip_route_t *) malloc(sizeof(ip_route_t)); 1637 1638 route = (ip_route_ref) malloc(sizeof(ip_route_t)); 1700 1639 if (!route) { 1701 1640 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); … … 1719 1658 ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway) 1720 1659 { 1721 ip_netif_ t *netif;1660 ip_netif_ref netif; 1722 1661 1723 1662 fibril_rwlock_write_lock(&ip_globals.netifs_lock); … … 1753 1692 static int 1754 1693 ip_received_error_msg_local(int ip_phone, device_id_t device_id, 1755 packet_t *packet, services_t target, services_t error)1694 packet_t packet, services_t target, services_t error) 1756 1695 { 1757 1696 uint8_t *data; … … 1759 1698 icmp_type_t type; 1760 1699 icmp_code_t code; 1761 ip_netif_ t *netif;1700 ip_netif_ref netif; 1762 1701 measured_string_t address; 1763 ip_route_ t *route;1764 ip_header_ t *header;1702 ip_route_ref route; 1703 ip_header_ref header; 1765 1704 1766 1705 switch (error) { … … 1772 1711 1773 1712 data = packet_get_data(packet); 1774 header = (ip_header_ t *)(data + offset);1775 1776 / * Destination host unreachable? */1713 header = (ip_header_ref)(data + offset); 1714 1715 // destination host unreachable? 1777 1716 if ((type != ICMP_DEST_UNREACH) || 1778 1717 (code != ICMP_HOST_UNREACH)) { 1779 /* No, something else */1718 // no, something else 1780 1719 break; 1781 1720 } … … 1791 1730 route = ip_routes_get_index(&netif->routes, 0); 1792 1731 1793 / * From the same network? */1732 // from the same network? 1794 1733 if (route && ((route->address.s_addr & route->netmask.s_addr) == 1795 1734 (header->destination_address & route->netmask.s_addr))) { 1796 /* Clear the ARP mapping if any */ 1797 address.value = (uint8_t *) &header->destination_address; 1798 address.length = sizeof(header->destination_address); 1735 // clear the ARP mapping if any 1736 address.value = (char *) &header->destination_address; 1737 address.length = CONVERT_SIZE(uint8_t, char, 1738 sizeof(header->destination_address)); 1799 1739 arp_clear_address_req(netif->arp->phone, 1800 1740 netif->device_id, SERVICE_IP, &address); … … 1819 1759 in_addr_t *dest; 1820 1760 in_addr_t *src; 1821 ip_route_ t *route;1822 ipv4_pseudo_header_ t *header_in;1761 ip_route_ref route; 1762 ipv4_pseudo_header_ref header_in; 1823 1763 1824 1764 if (!destination || (addrlen <= 0)) … … 1848 1788 fibril_rwlock_read_lock(&ip_globals.lock); 1849 1789 route = ip_find_route(*dest); 1850 / * If the local host is the destination */1790 // if the local host is the destination 1851 1791 if (route && (route->address.s_addr == dest->s_addr) && 1852 1792 (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) { 1853 / * Find the loopback device to deliver */1793 // find the loopback device to deliver 1854 1794 dest->s_addr = IPV4_LOCALHOST_ADDRESS; 1855 1795 route = ip_find_route(*dest); … … 1866 1806 1867 1807 *headerlen = sizeof(*header_in); 1868 header_in = (ipv4_pseudo_header_ t *) malloc(*headerlen);1808 header_in = (ipv4_pseudo_header_ref) malloc(*headerlen); 1869 1809 if (!header_in) 1870 1810 return ENOMEM; … … 1880 1820 } 1881 1821 1822 /** Processes the received IP packet or the packet queue one by one. 1823 * 1824 * The packet is either passed to another module or released on error. 1825 * 1826 * @param[in] device_id The source device identifier. 1827 * @param[in,out] packet The received packet. 1828 * @returns EOK on success and the packet is no longer needed. 1829 * @returns EINVAL if the packet is too small to carry the IP 1830 * packet. 1831 * @returns EINVAL if the received address lengths differs from the 1832 * registered values. 1833 * @returns ENOENT if the device is not found in the cache. 1834 * @returns ENOENT if the protocol for the device is not found in 1835 * the cache. 1836 * @returns ENOMEM if there is not enough memory left. 1837 */ 1838 static int ip_receive_message(device_id_t device_id, packet_t packet) 1839 { 1840 packet_t next; 1841 1842 do { 1843 next = pq_detach(packet); 1844 ip_process_packet(device_id, packet); 1845 packet = next; 1846 } while (packet); 1847 1848 return EOK; 1849 } 1850 1882 1851 /** Processes the IP message. 1883 1852 * … … 1887 1856 * @param[out] answer_count The last parameter for the actual answer in the 1888 1857 * answer parameter. 1889 * @return EOK on success.1890 * @return ENOTSUP if the message is not known.1858 * @returns EOK on success. 1859 * @returns ENOTSUP if the message is not known. 1891 1860 * 1892 1861 * @see ip_interface.h 1893 * @see il_ remote.h1862 * @see il_interface.h 1894 1863 * @see IS_NET_IP_MESSAGE() 1895 1864 */ 1896 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 1897 size_t *answer_count) 1898 { 1899 packet_t *packet; 1865 int 1866 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 1867 int *answer_count) 1868 { 1869 ERROR_DECLARE; 1870 1871 packet_t packet; 1900 1872 struct sockaddr *addr; 1901 void *header;1902 size_t headerlen;1903 1873 size_t addrlen; 1904 1874 size_t prefix; 1905 1875 size_t suffix; 1906 1876 size_t content; 1877 void *header; 1878 size_t headerlen; 1907 1879 device_id_t device_id; 1908 int rc;1909 1880 1910 1881 *answer_count = 0; 1911 switch (IPC_GET_ IMETHOD(*call)) {1882 switch (IPC_GET_METHOD(*call)) { 1912 1883 case IPC_M_PHONE_HUNGUP: 1913 1884 return EOK; 1914 1885 1915 1886 case IPC_M_CONNECT_TO_ME: 1916 return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call), 1917 IPC_GET_PHONE(*call), NULL); 1918 1919 case NET_IP_DEVICE: 1920 return ip_device_req_local(0, IPC_GET_DEVICE(*call), 1921 IPC_GET_SERVICE(*call)); 1887 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call), 1888 IPC_GET_PHONE(call), NULL); 1889 1890 case NET_IL_DEVICE: 1891 return ip_device_req_local(0, IPC_GET_DEVICE(call), 1892 IPC_GET_SERVICE(call)); 1893 1894 case NET_IL_SEND: 1895 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, 1896 &packet, IPC_GET_PACKET(call))); 1897 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0, 1898 IPC_GET_ERROR(call)); 1899 1900 case NET_IL_DEVICE_STATE: 1901 return ip_device_state_message(IPC_GET_DEVICE(call), 1902 IPC_GET_STATE(call)); 1903 1904 case NET_IL_RECEIVED: 1905 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, 1906 &packet, IPC_GET_PACKET(call))); 1907 return ip_receive_message(IPC_GET_DEVICE(call), packet); 1922 1908 1923 1909 case NET_IP_RECEIVED_ERROR: 1924 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1925 IPC_GET_PACKET(*call)); 1926 if (rc != EOK) 1927 return rc; 1928 return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call), 1929 packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call)); 1910 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, 1911 &packet, IPC_GET_PACKET(call))); 1912 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), 1913 packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call)); 1930 1914 1931 1915 case NET_IP_ADD_ROUTE: 1932 return ip_add_route_req_local(0, IPC_GET_DEVICE( *call),1933 IP_GET_ADDRESS( *call), IP_GET_NETMASK(*call),1934 IP_GET_GATEWAY( *call));1916 return ip_add_route_req_local(0, IPC_GET_DEVICE(call), 1917 IP_GET_ADDRESS(call), IP_GET_NETMASK(call), 1918 IP_GET_GATEWAY(call)); 1935 1919 1936 1920 case NET_IP_SET_GATEWAY: 1937 return ip_set_gateway_req_local(0, IPC_GET_DEVICE( *call),1938 IP_GET_GATEWAY( *call));1921 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call), 1922 IP_GET_GATEWAY(call)); 1939 1923 1940 1924 case NET_IP_GET_ROUTE: 1941 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, 1942 &addrlen); 1943 if (rc != EOK) 1944 return rc; 1945 1946 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr, 1947 (socklen_t) addrlen, &device_id, &header, &headerlen); 1948 if (rc != EOK) 1949 return rc; 1950 1951 IPC_SET_DEVICE(*answer, device_id); 1952 IP_SET_HEADERLEN(*answer, headerlen); 1925 ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen)); 1926 ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call), 1927 addr, (socklen_t) addrlen, &device_id, &header, 1928 &headerlen)); 1929 IPC_SET_DEVICE(answer, device_id); 1930 IP_SET_HEADERLEN(answer, headerlen); 1953 1931 1954 1932 *answer_count = 2; 1955 1956 rc = data_reply(&headerlen, sizeof(headerlen)); 1957 if (rc == EOK) 1958 rc = data_reply(header, headerlen); 1933 1934 if (ERROR_NONE(data_reply(&headerlen, sizeof(headerlen)))) 1935 ERROR_CODE = data_reply(header, headerlen); 1959 1936 1960 1937 free(header); 1961 return rc; 1962 1963 case NET_IP_PACKET_SPACE: 1964 rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen, 1965 &prefix, &content, &suffix); 1966 if (rc != EOK) 1967 return rc; 1968 1969 IPC_SET_ADDR(*answer, addrlen); 1970 IPC_SET_PREFIX(*answer, prefix); 1971 IPC_SET_CONTENT(*answer, content); 1972 IPC_SET_SUFFIX(*answer, suffix); 1938 return ERROR_CODE; 1939 1940 case NET_IL_PACKET_SPACE: 1941 ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call), 1942 &addrlen, &prefix, &content, &suffix)); 1943 IPC_SET_ADDR(answer, addrlen); 1944 IPC_SET_PREFIX(answer, prefix); 1945 IPC_SET_CONTENT(answer, content); 1946 IPC_SET_SUFFIX(answer, suffix); 1973 1947 *answer_count = 4; 1974 1948 return EOK; 1975 1949 1976 case NET_IP_SEND: 1977 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1978 IPC_GET_PACKET(*call)); 1979 if (rc != EOK) 1980 return rc; 1950 case NET_IL_MTU_CHANGED: 1951 return ip_mtu_changed_message(IPC_GET_DEVICE(call), 1952 IPC_GET_MTU(call)); 1953 } 1954 1955 return ENOTSUP; 1956 } 1957 1958 /** Default thread for new connections. 1959 * 1960 * @param[in] iid The initial message identifier. 1961 * @param[in] icall The initial message call structure. 1962 */ 1963 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall) 1964 { 1965 /* 1966 * Accept the connection 1967 * - Answer the first IPC_M_CONNECT_ME_TO call. 1968 */ 1969 ipc_answer_0(iid, EOK); 1970 1971 while (true) { 1972 ipc_call_t answer; 1973 int answer_count; 1981 1974 1982 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0, 1983 IPC_GET_ERROR(*call)); 1984 } 1985 1986 return ENOTSUP; 1987 } 1988 1975 /* Clear the answer structure */ 1976 refresh_answer(&answer, &answer_count); 1977 1978 /* Fetch the next message */ 1979 ipc_call_t call; 1980 ipc_callid_t callid = async_get_call(&call); 1981 1982 /* Process the message */ 1983 int res = il_module_message_standalone(callid, &call, &answer, 1984 &answer_count); 1985 1986 /* 1987 * End if told to either by the message or the processing 1988 * result. 1989 */ 1990 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 1991 (res == EHANGUP)) { 1992 return; 1993 } 1994 1995 /* Answer the message */ 1996 answer_call(callid, res, &answer, answer_count); 1997 } 1998 } 1999 2000 /** Starts the module. 2001 * 2002 * @returns EOK on success. 2003 * @returns Other error codes as defined for each specific module start function. 2004 */ 1989 2005 int main(int argc, char *argv[]) 1990 2006 { 2007 ERROR_DECLARE; 2008 1991 2009 /* Start the module */ 1992 return il_module_start(SERVICE_IP); 2010 ERROR_PROPAGATE(il_module_start_standalone(il_client_connection)); 2011 return EOK; 1993 2012 } 1994 2013
Note:
See TracChangeset
for help on using the changeset viewer.