source: mainline/uspace/srv/net/il/ip/ip.c@ ab6f2507

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ab6f2507 was 014dd57b, checked in by Martin Decky <martin@…>, 14 years ago

streamline and create a common skeleton for the transport layer
(in the line of the previous updates to the lower layers)

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