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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7bf12387 was 7bf12387, checked in by Jakub Jermar <jakub@…>, 14 years ago

ip: Rename the defines so they don't conflict with similar TCP changes

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