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

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

networking stack: convert to the new async framework

  • Property mode set to 100644
File size: 54.2 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 *, void *);
123
124/** Release the packet and returns the result.
125 *
126 * @param[in] packet Packet queue to be released.
127 * @param[in] result Result to be returned.
128 *
129 * @return Result parameter.
130 *
131 */
132static int ip_release_and_return(packet_t *packet, int result)
133{
134 pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
135 return result;
136}
137
138/** Return the ICMP session.
139 *
140 * Search the registered protocols.
141 *
142 * @return Found ICMP session.
143 * @return NULL if the ICMP is not registered.
144 *
145 */
146static async_sess_t *ip_get_icmp_session(void)
147{
148 fibril_rwlock_read_lock(&ip_globals.protos_lock);
149 ip_proto_t *proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
150 async_sess_t *sess = proto ? proto->sess : NULL;
151 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
152
153 return sess;
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_sess, 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 (GET_IP_HEADER_VERSION(header)) {
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/** Prepare the ICMP notification packet.
222 *
223 * Release additional packets and keep only the first one.
224 * All packets are released on error.
225 *
226 * @param[in] error Packet error service.
227 * @param[in] packet Packet or the packet queue to be reported as faulty.
228 * @param[in] header First packet IP header. May be NULL.
229 *
230 * @return Found ICMP session.
231 * @return NULL if the error parameter is set.
232 * @return NULL if the ICMP session is not found.
233 * @return NULL if the ip_prepare_icmp() fails.
234 *
235 */
236static async_sess_t *ip_prepare_icmp_and_get_session(services_t error,
237 packet_t *packet, ip_header_t *header)
238{
239 async_sess_t *sess = ip_get_icmp_session();
240
241 if ((error) || (!sess) || (ip_prepare_icmp(packet, header))) {
242 pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
243 return NULL;
244 }
245
246 return sess;
247}
248
249int il_initialize(async_sess_t *net_sess)
250{
251 fibril_rwlock_initialize(&ip_globals.lock);
252 fibril_rwlock_write_lock(&ip_globals.lock);
253 fibril_rwlock_initialize(&ip_globals.protos_lock);
254 fibril_rwlock_initialize(&ip_globals.netifs_lock);
255
256 ip_globals.net_sess = net_sess;
257 ip_globals.packet_counter = 0;
258 ip_globals.gateway.address.s_addr = 0;
259 ip_globals.gateway.netmask.s_addr = 0;
260 ip_globals.gateway.gateway.s_addr = 0;
261 ip_globals.gateway.netif = NULL;
262
263 int rc = ip_netifs_initialize(&ip_globals.netifs);
264 if (rc != EOK)
265 goto out;
266 rc = ip_protos_initialize(&ip_globals.protos);
267 if (rc != EOK)
268 goto out;
269 rc = modules_initialize(&ip_globals.modules);
270 if (rc != EOK)
271 goto out;
272 rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
273 (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
274
275out:
276 fibril_rwlock_write_unlock(&ip_globals.lock);
277
278 return rc;
279}
280
281/** Initializes a new network interface specific data.
282 *
283 * Connects to the network interface layer module, reads the netif
284 * configuration, starts an ARP module if needed and sets the netif routing
285 * table.
286 *
287 * The device identifier and the nil service has to be set.
288 *
289 * @param[in,out] ip_netif Network interface specific data.
290 * @return EOK on success.
291 * @return ENOTSUP if DHCP is configured.
292 * @return ENOTSUP if IPv6 is configured.
293 * @return EINVAL if any of the addresses is invalid.
294 * @return EINVAL if the used ARP module is not known.
295 * @return ENOMEM if there is not enough memory left.
296 * @return Other error codes as defined for the
297 * net_get_device_conf_req() function.
298 * @return Other error codes as defined for the bind_service()
299 * function.
300 * @return Other error codes as defined for the specific
301 * arp_device_req() function.
302 * @return Other error codes as defined for the
303 * nil_packet_size_req() function.
304 */
305static int ip_netif_initialize(ip_netif_t *ip_netif)
306{
307 measured_string_t names[] = {
308 {
309 (uint8_t *) "IPV",
310 3
311 },
312 {
313 (uint8_t *) "IP_CONFIG",
314 9
315 },
316 {
317 (uint8_t *) "IP_ADDR",
318 7
319 },
320 {
321 (uint8_t *) "IP_NETMASK",
322 10
323 },
324 {
325 (uint8_t *) "IP_GATEWAY",
326 10
327 },
328 {
329 (uint8_t *) "IP_BROADCAST",
330 12
331 },
332 {
333 (uint8_t *) "ARP",
334 3
335 },
336 {
337 (uint8_t *) "IP_ROUTING",
338 10
339 }
340 };
341 measured_string_t *configuration;
342 size_t count = sizeof(names) / sizeof(measured_string_t);
343 uint8_t *data;
344 measured_string_t address;
345 ip_route_t *route;
346 in_addr_t gateway;
347 int index;
348 int rc;
349
350 ip_netif->arp = NULL;
351 route = NULL;
352 ip_netif->ipv = NET_DEFAULT_IPV;
353 ip_netif->dhcp = false;
354 ip_netif->routing = NET_DEFAULT_IP_ROUTING;
355 configuration = &names[0];
356
357 /* Get configuration */
358 rc = net_get_device_conf_req(ip_globals.net_sess, ip_netif->device_id,
359 &configuration, count, &data);
360 if (rc != EOK)
361 return rc;
362
363 if (configuration) {
364 if (configuration[0].value)
365 ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
366
367 ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
368 configuration[1].length);
369
370 if (ip_netif->dhcp) {
371 // TODO dhcp
372 net_free_settings(configuration, data);
373 return ENOTSUP;
374 } else if (ip_netif->ipv == IPV4) {
375 route = (ip_route_t *) malloc(sizeof(ip_route_t));
376 if (!route) {
377 net_free_settings(configuration, data);
378 return ENOMEM;
379 }
380 route->address.s_addr = 0;
381 route->netmask.s_addr = 0;
382 route->gateway.s_addr = 0;
383 route->netif = ip_netif;
384 index = ip_routes_add(&ip_netif->routes, route);
385 if (index < 0) {
386 net_free_settings(configuration, data);
387 free(route);
388 return index;
389 }
390
391 if ((inet_pton(AF_INET, (char *) configuration[2].value,
392 (uint8_t *) &route->address.s_addr) != EOK) ||
393 (inet_pton(AF_INET, (char *) configuration[3].value,
394 (uint8_t *) &route->netmask.s_addr) != EOK) ||
395 (inet_pton(AF_INET, (char *) configuration[4].value,
396 (uint8_t *) &gateway.s_addr) == EINVAL) ||
397 (inet_pton(AF_INET, (char *) configuration[5].value,
398 (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
399 {
400 net_free_settings(configuration, data);
401 return EINVAL;
402 }
403 } else {
404 // TODO ipv6 in separate module
405 net_free_settings(configuration, data);
406 return ENOTSUP;
407 }
408
409 if (configuration[6].value) {
410 ip_netif->arp = get_running_module(&ip_globals.modules,
411 configuration[6].value);
412 if (!ip_netif->arp) {
413 printf("Failed to start the arp %s\n",
414 configuration[6].value);
415 net_free_settings(configuration, data);
416 return EINVAL;
417 }
418 }
419 if (configuration[7].value)
420 ip_netif->routing = (configuration[7].value[0] == 'y');
421
422 net_free_settings(configuration, data);
423 }
424
425 /* Bind netif service which also initializes the device */
426 ip_netif->sess = nil_bind_service(ip_netif->service,
427 (sysarg_t) ip_netif->device_id, SERVICE_IP,
428 ip_receiver);
429 if (ip_netif->sess == NULL) {
430 printf("Failed to contact the nil service %d\n",
431 ip_netif->service);
432 return ENOENT;
433 }
434
435 /* Has to be after the device netif module initialization */
436 if (ip_netif->arp) {
437 if (route) {
438 address.value = (uint8_t *) &route->address.s_addr;
439 address.length = sizeof(in_addr_t);
440
441 rc = arp_device_req(ip_netif->arp->sess,
442 ip_netif->device_id, SERVICE_IP, ip_netif->service,
443 &address);
444 if (rc != EOK)
445 return rc;
446 } else {
447 ip_netif->arp = 0;
448 }
449 }
450
451 /* Get packet dimensions */
452 rc = nil_packet_size_req(ip_netif->sess, ip_netif->device_id,
453 &ip_netif->packet_dimension);
454 if (rc != EOK)
455 return rc;
456
457 if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
458 printf("Maximum transmission unit %zu bytes is too small, at "
459 "least %d bytes are needed\n",
460 ip_netif->packet_dimension.content, IP_MIN_CONTENT);
461 ip_netif->packet_dimension.content = IP_MIN_CONTENT;
462 }
463
464 index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
465 if (index < 0)
466 return index;
467
468 if (gateway.s_addr) {
469 /* The default gateway */
470 ip_globals.gateway.address.s_addr = 0;
471 ip_globals.gateway.netmask.s_addr = 0;
472 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
473 ip_globals.gateway.netif = ip_netif;
474
475 char defgateway[INET_ADDRSTRLEN];
476 inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
477 defgateway, INET_ADDRSTRLEN);
478 printf("%s: Default gateway (%s)\n", NAME, defgateway);
479 }
480
481 return EOK;
482}
483
484static int ip_device_req_local(device_id_t device_id, services_t netif)
485{
486 ip_netif_t *ip_netif;
487 ip_route_t *route;
488 int index;
489 int rc;
490
491 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
492 if (!ip_netif)
493 return ENOMEM;
494
495 rc = ip_routes_initialize(&ip_netif->routes);
496 if (rc != EOK) {
497 free(ip_netif);
498 return rc;
499 }
500
501 ip_netif->device_id = device_id;
502 ip_netif->service = netif;
503 ip_netif->state = NETIF_STOPPED;
504
505 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
506
507 rc = ip_netif_initialize(ip_netif);
508 if (rc != EOK) {
509 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
510 ip_routes_destroy(&ip_netif->routes, free);
511 free(ip_netif);
512 return rc;
513 }
514 if (ip_netif->arp)
515 ip_netif->arp->usage++;
516
517 /* Print the settings */
518 printf("%s: Device registered (id: %d, ipv: %d, conf: %s)\n",
519 NAME, ip_netif->device_id, ip_netif->ipv,
520 ip_netif->dhcp ? "dhcp" : "static");
521
522 // TODO ipv6 addresses
523
524 char address[INET_ADDRSTRLEN];
525 char netmask[INET_ADDRSTRLEN];
526 char gateway[INET_ADDRSTRLEN];
527
528 for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
529 route = ip_routes_get_index(&ip_netif->routes, index);
530 if (route) {
531 inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
532 address, INET_ADDRSTRLEN);
533 inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
534 netmask, INET_ADDRSTRLEN);
535 inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
536 gateway, INET_ADDRSTRLEN);
537 printf("%s: Route %d (address: %s, netmask: %s, "
538 "gateway: %s)\n", NAME, index, address, netmask,
539 gateway);
540 }
541 }
542
543 inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
544 INET_ADDRSTRLEN);
545 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
546
547 printf("%s: Broadcast (%s)\n", NAME, address);
548
549 return EOK;
550}
551
552/** Searches the network interfaces if there is a suitable route.
553 *
554 * @param[in] netif The network interface to be searched for routes. May be
555 * NULL.
556 * @param[in] destination The destination address.
557 * @return The found route.
558 * @return NULL if no route was found.
559 */
560static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
561 in_addr_t destination)
562{
563 int index;
564 ip_route_t *route;
565
566 if (!netif)
567 return NULL;
568
569 /* Start with the first one (the direct route) */
570 for (index = 0; index < ip_routes_count(&netif->routes); index++) {
571 route = ip_routes_get_index(&netif->routes, index);
572 if ((route) &&
573 ((route->address.s_addr & route->netmask.s_addr) ==
574 (destination.s_addr & route->netmask.s_addr)))
575 return route;
576 }
577
578 return NULL;
579}
580
581/** Searches all network interfaces if there is a suitable route.
582 *
583 * @param[in] destination The destination address.
584 * @return The found route.
585 * @return NULL if no route was found.
586 */
587static ip_route_t *ip_find_route(in_addr_t destination) {
588 int index;
589 ip_route_t *route;
590 ip_netif_t *netif;
591
592 /* Start with the last netif - the newest one */
593 index = ip_netifs_count(&ip_globals.netifs) - 1;
594 while (index >= 0) {
595 netif = ip_netifs_get_index(&ip_globals.netifs, index);
596 if (netif && (netif->state == NETIF_ACTIVE)) {
597 route = ip_netif_find_route(netif, destination);
598 if (route)
599 return route;
600 }
601 index--;
602 }
603
604 return &ip_globals.gateway;
605}
606
607/** Returns the network interface's IP address.
608 *
609 * @param[in] netif The network interface.
610 * @return The IP address.
611 * @return NULL if no IP address was found.
612 */
613static in_addr_t *ip_netif_address(ip_netif_t *netif)
614{
615 ip_route_t *route;
616
617 route = ip_routes_get_index(&netif->routes, 0);
618 return route ? &route->address : NULL;
619}
620
621/** Copies the fragment header.
622 *
623 * Copies only the header itself and relevant IP options.
624 *
625 * @param[out] last The created header.
626 * @param[in] first The original header to be copied.
627 */
628static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
629{
630 ip_option_t *option;
631 size_t next;
632 size_t length;
633
634 /* Copy first itself */
635 memcpy(last, first, sizeof(ip_header_t));
636 length = sizeof(ip_header_t);
637 next = sizeof(ip_header_t);
638
639 /* Process all IP options */
640 while (next < GET_IP_HEADER_LENGTH(first)) {
641 option = (ip_option_t *) (((uint8_t *) first) + next);
642 /* Skip end or noop */
643 if ((option->type == IPOPT_END) ||
644 (option->type == IPOPT_NOOP)) {
645 next++;
646 } else {
647 /* Copy if told so or skip */
648 if (IPOPT_COPIED(option->type)) {
649 memcpy(((uint8_t *) last) + length,
650 ((uint8_t *) first) + next, option->length);
651 length += option->length;
652 }
653 /* Next option */
654 next += option->length;
655 }
656 }
657
658 /* Align 4 byte boundary */
659 if (length % 4) {
660 bzero(((uint8_t *) last) + length, 4 - (length % 4));
661 SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
662 } else {
663 SET_IP_HEADER_LENGTH(last, (length / 4));
664 }
665
666 last->header_checksum = 0;
667}
668
669/** Prepares the outgoing packet or the packet queue.
670 *
671 * The packet queue is a fragmented packet
672 * Updates the first packet's IP header.
673 * Prefixes the additional packets with fragment headers.
674 *
675 * @param[in] source The source address.
676 * @param[in] dest The destination address.
677 * @param[in,out] packet The packet to be sent.
678 * @param[in] destination The destination hardware address.
679 * @return EOK on success.
680 * @return EINVAL if the packet is too small to contain the IP
681 * header.
682 * @return EINVAL if the packet is too long than the IP allows.
683 * @return ENOMEM if there is not enough memory left.
684 * @return Other error codes as defined for the packet_set_addr()
685 * function.
686 */
687static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
688 packet_t *packet, measured_string_t *destination)
689{
690 size_t length;
691 ip_header_t *header;
692 ip_header_t *last_header;
693 ip_header_t *middle_header;
694 packet_t *next;
695 int rc;
696
697 length = packet_get_data_length(packet);
698 if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
699 return EINVAL;
700
701 header = (ip_header_t *) packet_get_data(packet);
702 if (destination) {
703 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
704 destination->length);
705 } else {
706 rc = packet_set_addr(packet, NULL, NULL, 0);
707 }
708 if (rc != EOK)
709 return rc;
710
711 SET_IP_HEADER_VERSION(header, IPV4);
712 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
713 header->fragment_offset_low = 0;
714 header->header_checksum = 0;
715 if (source)
716 header->source_address = source->s_addr;
717 header->destination_address = dest.s_addr;
718
719 fibril_rwlock_write_lock(&ip_globals.lock);
720 ip_globals.packet_counter++;
721 header->identification = htons(ip_globals.packet_counter);
722 fibril_rwlock_write_unlock(&ip_globals.lock);
723
724 if (pq_next(packet)) {
725 last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
726 if (!last_header)
727 return ENOMEM;
728 ip_create_last_header(last_header, header);
729 next = pq_next(packet);
730 while (pq_next(next)) {
731 middle_header = (ip_header_t *) packet_prefix(next,
732 IP_HEADER_LENGTH(last_header));
733 if (!middle_header) {
734 free(last_header);
735 return ENOMEM;
736 }
737
738 memcpy(middle_header, last_header,
739 IP_HEADER_LENGTH(last_header));
740 SET_IP_HEADER_FLAGS(header,
741 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
742 middle_header->total_length =
743 htons(packet_get_data_length(next));
744 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
745 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
746 middle_header->fragment_offset_low =
747 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
748 middle_header->header_checksum =
749 IP_HEADER_CHECKSUM(middle_header);
750 if (destination) {
751 rc = packet_set_addr(next, NULL,
752 (uint8_t *) destination->value,
753 destination->length);
754 if (rc != EOK) {
755 free(last_header);
756 return rc;
757 }
758 }
759 length += packet_get_data_length(next);
760 next = pq_next(next);
761 }
762
763 middle_header = (ip_header_t *) packet_prefix(next,
764 IP_HEADER_LENGTH(last_header));
765 if (!middle_header) {
766 free(last_header);
767 return ENOMEM;
768 }
769
770 memcpy(middle_header, last_header,
771 IP_HEADER_LENGTH(last_header));
772 middle_header->total_length =
773 htons(packet_get_data_length(next));
774 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
775 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
776 middle_header->fragment_offset_low =
777 IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
778 middle_header->header_checksum =
779 IP_HEADER_CHECKSUM(middle_header);
780 if (destination) {
781 rc = packet_set_addr(next, NULL,
782 (uint8_t *) destination->value,
783 destination->length);
784 if (rc != EOK) {
785 free(last_header);
786 return rc;
787 }
788 }
789 length += packet_get_data_length(next);
790 free(last_header);
791 SET_IP_HEADER_FLAGS(header,
792 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
793 }
794
795 header->total_length = htons(length);
796 /* Unnecessary for all protocols */
797 header->header_checksum = IP_HEADER_CHECKSUM(header);
798
799 return EOK;
800}
801
802/** Fragments the packet from the end.
803 *
804 * @param[in] packet The packet to be fragmented.
805 * @param[in,out] new_packet The new packet fragment.
806 * @param[in,out] header The original packet header.
807 * @param[in,out] new_header The new packet fragment header.
808 * @param[in] length The new fragment length.
809 * @param[in] src The source address.
810 * @param[in] dest The destiantion address.
811 * @param[in] addrlen The address length.
812 * @return EOK on success.
813 * @return ENOMEM if the target packet is too small.
814 * @return Other error codes as defined for the packet_set_addr()
815 * function.
816 * @return Other error codes as defined for the pq_insert_after()
817 * function.
818 */
819static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
820 ip_header_t *header, ip_header_t *new_header, size_t length,
821 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
822{
823 void *data;
824 size_t offset;
825 int rc;
826
827 data = packet_suffix(new_packet, length);
828 if (!data)
829 return ENOMEM;
830
831 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
832 length);
833
834 rc = packet_trim(packet, 0, length);
835 if (rc != EOK)
836 return rc;
837
838 header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
839 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
840 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
841 SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
842 IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
843 new_header->fragment_offset_low =
844 IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
845 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
846
847 rc = packet_set_addr(new_packet, (const uint8_t *) src,
848 (const uint8_t *) dest, addrlen);
849 if (rc != EOK)
850 return rc;
851
852 return pq_insert_after(packet, new_packet);
853}
854
855/** Prefixes a middle fragment header based on the last fragment header to the
856 * packet.
857 *
858 * @param[in] packet The packet to be prefixed.
859 * @param[in] last The last header to be copied.
860 * @return The prefixed middle header.
861 * @return NULL on error.
862 */
863static ip_header_t *ip_create_middle_header(packet_t *packet,
864 ip_header_t *last)
865{
866 ip_header_t *middle;
867
868 middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
869 if (!middle)
870 return NULL;
871 memcpy(middle, last, IP_HEADER_LENGTH(last));
872 SET_IP_HEADER_FLAGS(middle,
873 (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
874 return middle;
875}
876
877/** Checks the packet length and fragments it if needed.
878 *
879 * The new fragments are queued before the original packet.
880 *
881 * @param[in,out] packet The packet to be checked.
882 * @param[in] length The maximum packet length.
883 * @param[in] prefix The minimum prefix size.
884 * @param[in] suffix The minimum suffix size.
885 * @param[in] addr_len The minimum address length.
886 * @return EOK on success.
887 * @return EINVAL if the packet_get_addr() function fails.
888 * @return EINVAL if the packet does not contain the IP header.
889 * @return EPERM if the packet needs to be fragmented and the
890 * fragmentation is not allowed.
891 * @return ENOMEM if there is not enough memory left.
892 * @return ENOMEM if there is no packet available.
893 * @return ENOMEM if the packet is too small to contain the IP
894 * header.
895 * @return Other error codes as defined for the packet_trim()
896 * function.
897 * @return Other error codes as defined for the
898 * ip_create_middle_header() function.
899 * @return Other error codes as defined for the
900 * ip_fragment_packet_data() function.
901 */
902static int
903ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
904 socklen_t addr_len)
905{
906 packet_t *new_packet;
907 ip_header_t *header;
908 ip_header_t *middle_header;
909 ip_header_t *last_header;
910 struct sockaddr *src;
911 struct sockaddr *dest;
912 socklen_t addrlen;
913 int result;
914 int rc;
915
916 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
917 if (result <= 0)
918 return EINVAL;
919
920 addrlen = (socklen_t) result;
921 if (packet_get_data_length(packet) <= sizeof(ip_header_t))
922 return ENOMEM;
923
924 /* Get header */
925 header = (ip_header_t *) packet_get_data(packet);
926 if (!header)
927 return EINVAL;
928
929 /* Fragmentation forbidden? */
930 if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
931 return EPERM;
932
933 /* Create the last fragment */
934 new_packet = packet_get_4_remote(ip_globals.net_sess, prefix, length,
935 suffix, ((addrlen > addr_len) ? addrlen : addr_len));
936 if (!new_packet)
937 return ENOMEM;
938
939 /* Allocate as much as originally */
940 last_header = (ip_header_t *) packet_suffix(new_packet,
941 IP_HEADER_LENGTH(header));
942 if (!last_header)
943 return ip_release_and_return(packet, ENOMEM);
944
945 ip_create_last_header(last_header, header);
946
947 /* Trim the unused space */
948 rc = packet_trim(new_packet, 0,
949 IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
950 if (rc != EOK)
951 return ip_release_and_return(packet, rc);
952
953 /* Greatest multiple of 8 lower than content */
954 // TODO even fragmentation?
955 length = length & ~0x7;
956
957 rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
958 ((IP_HEADER_DATA_LENGTH(header) -
959 ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
960 ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
961 src, dest, addrlen);
962 if (rc != EOK)
963 return ip_release_and_return(packet, rc);
964
965 /* Mark the first as fragmented */
966 SET_IP_HEADER_FLAGS(header,
967 (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
968
969 /* Create middle fragments */
970 while (IP_TOTAL_LENGTH(header) > length) {
971 new_packet = packet_get_4_remote(ip_globals.net_sess, prefix,
972 length, suffix,
973 ((addrlen >= addr_len) ? addrlen : addr_len));
974 if (!new_packet)
975 return ENOMEM;
976
977 middle_header = ip_create_middle_header(new_packet,
978 last_header);
979 if (!middle_header)
980 return ip_release_and_return(packet, ENOMEM);
981
982 rc = ip_fragment_packet_data(packet, new_packet, header,
983 middle_header,
984 (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
985 src, dest, addrlen);
986 if (rc != EOK)
987 return ip_release_and_return(packet, rc);
988 }
989
990 /* Finish the first fragment */
991 header->header_checksum = IP_HEADER_CHECKSUM(header);
992
993 return EOK;
994}
995
996/** Check the packet queue lengths and fragments the packets if needed.
997 *
998 * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
999 * be fragmented and the fragmentation is not allowed.
1000 *
1001 * @param[in,out] packet Packet or the packet queue to be checked.
1002 * @param[in] prefix Minimum prefix size.
1003 * @param[in] content Maximum content size.
1004 * @param[in] suffix Minimum suffix size.
1005 * @param[in] addr_len Minimum address length.
1006 * @param[in] error Error module service.
1007 *
1008 * @return The packet or the packet queue of the allowed length.
1009 * @return NULL if there are no packets left.
1010 *
1011 */
1012static packet_t *ip_split_packet(packet_t *packet, size_t prefix, size_t content,
1013 size_t suffix, socklen_t addr_len, services_t error)
1014{
1015 size_t length;
1016 packet_t *next;
1017 packet_t *new_packet;
1018 int result;
1019 async_sess_t *sess;
1020
1021 next = packet;
1022 /* Check all packets */
1023 while (next) {
1024 length = packet_get_data_length(next);
1025
1026 if (length <= content) {
1027 next = pq_next(next);
1028 continue;
1029 }
1030
1031 /* Too long */
1032 result = ip_fragment_packet(next, content, prefix,
1033 suffix, addr_len);
1034 if (result != EOK) {
1035 new_packet = pq_detach(next);
1036 if (next == packet) {
1037 /* The new first packet of the queue */
1038 packet = new_packet;
1039 }
1040 /* Fragmentation needed? */
1041 if (result == EPERM) {
1042 sess = ip_prepare_icmp_and_get_session(error, next, NULL);
1043 if (sess) {
1044 /* Fragmentation necessary ICMP */
1045 icmp_destination_unreachable_msg(sess,
1046 ICMP_FRAG_NEEDED, content, next);
1047 }
1048 } else {
1049 pq_release_remote(ip_globals.net_sess,
1050 packet_get_id(next));
1051 }
1052
1053 next = new_packet;
1054 continue;
1055 }
1056
1057 next = pq_next(next);
1058 }
1059
1060 return packet;
1061}
1062
1063/** Send the packet or the packet queue via the specified route.
1064 *
1065 * The ICMP_HOST_UNREACH error notification may be sent if route hardware
1066 * destination address is found.
1067 *
1068 * @param[in,out] packet Packet to be sent.
1069 * @param[in] netif Target network interface.
1070 * @param[in] route Target route.
1071 * @param[in] src Source address.
1072 * @param[in] dest Destination address.
1073 * @param[in] error Error module service.
1074 *
1075 * @return EOK on success.
1076 * @return Other error codes as defined for arp_translate_req().
1077 * @return Other error codes as defined for ip_prepare_packet().
1078 *
1079 */
1080static int ip_send_route(packet_t *packet, ip_netif_t *netif,
1081 ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
1082{
1083 measured_string_t destination;
1084 measured_string_t *translation;
1085 uint8_t *data;
1086 async_sess_t *sess;
1087 int rc;
1088
1089 /* Get destination hardware address */
1090 if (netif->arp && (route->address.s_addr != dest.s_addr)) {
1091 destination.value = route->gateway.s_addr ?
1092 (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
1093 destination.length = sizeof(dest.s_addr);
1094
1095 rc = arp_translate_req(netif->arp->sess, netif->device_id,
1096 SERVICE_IP, &destination, &translation, &data);
1097 if (rc != EOK) {
1098 pq_release_remote(ip_globals.net_sess,
1099 packet_get_id(packet));
1100 return rc;
1101 }
1102
1103 if (!translation || !translation->value) {
1104 if (translation) {
1105 free(translation);
1106 free(data);
1107 }
1108 sess = ip_prepare_icmp_and_get_session(error, packet,
1109 NULL);
1110 if (sess) {
1111 /* Unreachable ICMP if no routing */
1112 icmp_destination_unreachable_msg(sess,
1113 ICMP_HOST_UNREACH, 0, packet);
1114 }
1115 return EINVAL;
1116 }
1117
1118 } else {
1119 translation = NULL;
1120 }
1121
1122 rc = ip_prepare_packet(src, dest, packet, translation);
1123 if (rc != EOK) {
1124 pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
1125 } else {
1126 packet = ip_split_packet(packet, netif->packet_dimension.prefix,
1127 netif->packet_dimension.content,
1128 netif->packet_dimension.suffix,
1129 netif->packet_dimension.addr_len, error);
1130 if (packet) {
1131 nil_send_msg(netif->sess, netif->device_id, packet,
1132 SERVICE_IP);
1133 }
1134 }
1135
1136 if (translation) {
1137 free(translation);
1138 free(data);
1139 }
1140
1141 return rc;
1142}
1143
1144static int ip_send_msg_local(device_id_t device_id, packet_t *packet,
1145 services_t sender, services_t error)
1146{
1147 int addrlen;
1148 ip_netif_t *netif;
1149 ip_route_t *route;
1150 struct sockaddr *addr;
1151 struct sockaddr_in *address_in;
1152 in_addr_t *dest;
1153 in_addr_t *src;
1154 async_sess_t *sess;
1155 int rc;
1156
1157 /*
1158 * Addresses in the host byte order
1159 * Should be the next hop address or the target destination address
1160 */
1161 addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
1162 if (addrlen < 0)
1163 return ip_release_and_return(packet, addrlen);
1164 if ((size_t) addrlen < sizeof(struct sockaddr))
1165 return ip_release_and_return(packet, EINVAL);
1166
1167 switch (addr->sa_family) {
1168 case AF_INET:
1169 if (addrlen != sizeof(struct sockaddr_in))
1170 return ip_release_and_return(packet, EINVAL);
1171 address_in = (struct sockaddr_in *) addr;
1172 dest = &address_in->sin_addr;
1173 if (!dest->s_addr)
1174 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1175 break;
1176 case AF_INET6:
1177 default:
1178 return ip_release_and_return(packet, EAFNOSUPPORT);
1179 }
1180
1181 netif = NULL;
1182 route = NULL;
1183 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
1184
1185 /* Device specified? */
1186 if (device_id > 0) {
1187 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1188 route = ip_netif_find_route(netif, *dest);
1189 if (netif && !route && (ip_globals.gateway.netif == netif))
1190 route = &ip_globals.gateway;
1191 }
1192
1193 if (!route) {
1194 route = ip_find_route(*dest);
1195 netif = route ? route->netif : NULL;
1196 }
1197 if (!netif || !route) {
1198 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1199 sess = ip_prepare_icmp_and_get_session(error, packet, NULL);
1200 if (sess) {
1201 /* Unreachable ICMP if no routing */
1202 icmp_destination_unreachable_msg(sess,
1203 ICMP_NET_UNREACH, 0, packet);
1204 }
1205 return ENOENT;
1206 }
1207
1208 if (error) {
1209 /*
1210 * Do not send for broadcast, anycast packets or network
1211 * broadcast.
1212 */
1213 if (!dest->s_addr || !(~dest->s_addr) ||
1214 !(~((dest->s_addr & ~route->netmask.s_addr) |
1215 route->netmask.s_addr)) ||
1216 (!(dest->s_addr & ~route->netmask.s_addr))) {
1217 return ip_release_and_return(packet, EINVAL);
1218 }
1219 }
1220
1221 /* If the local host is the destination */
1222 if ((route->address.s_addr == dest->s_addr) &&
1223 (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
1224 /* Find the loopback device to deliver */
1225 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1226 route = ip_find_route(*dest);
1227 netif = route ? route->netif : NULL;
1228 if (!netif || !route) {
1229 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1230 sess = ip_prepare_icmp_and_get_session(error, packet,
1231 NULL);
1232 if (sess) {
1233 /* Unreachable ICMP if no routing */
1234 icmp_destination_unreachable_msg(sess,
1235 ICMP_HOST_UNREACH, 0, packet);
1236 }
1237 return ENOENT;
1238 }
1239 }
1240
1241 src = ip_netif_address(netif);
1242 if (!src) {
1243 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1244 return ip_release_and_return(packet, ENOENT);
1245 }
1246
1247 rc = ip_send_route(packet, netif, route, src, *dest, error);
1248 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1249
1250 return rc;
1251}
1252
1253/** Updates the device state.
1254 *
1255 * @param[in] device_id The device identifier.
1256 * @param[in] state The new state value.
1257 * @return EOK on success.
1258 * @return ENOENT if device is not found.
1259 */
1260static int ip_device_state_message(device_id_t device_id, device_state_t state)
1261{
1262 ip_netif_t *netif;
1263
1264 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1265 /* Find the device */
1266 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1267 if (!netif) {
1268 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1269 return ENOENT;
1270 }
1271 netif->state = state;
1272 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1273
1274 printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
1275
1276 return EOK;
1277}
1278
1279/** Returns the packet destination address from the IP header.
1280 *
1281 * @param[in] header The packet IP header to be read.
1282 * @return The packet destination address.
1283 */
1284static in_addr_t ip_get_destination(ip_header_t *header)
1285{
1286 in_addr_t destination;
1287
1288 // TODO search set ipopt route?
1289 destination.s_addr = header->destination_address;
1290 return destination;
1291}
1292
1293/** Delivers the packet to the local host.
1294 *
1295 * The packet is either passed to another module or released on error.
1296 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
1297 * found.
1298 *
1299 * @param[in] device_id The source device identifier.
1300 * @param[in] packet The packet to be delivered.
1301 * @param[in] header The first packet IP header. May be NULL.
1302 * @param[in] error The packet error service.
1303 * @return EOK on success.
1304 * @return ENOTSUP if the packet is a fragment.
1305 * @return EAFNOSUPPORT if the address family is not supported.
1306 * @return ENOENT if the target protocol is not found.
1307 * @return Other error codes as defined for the packet_set_addr()
1308 * function.
1309 * @return Other error codes as defined for the packet_trim()
1310 * function.
1311 * @return Other error codes as defined for the protocol specific
1312 * tl_received_msg() function.
1313 */
1314static int ip_deliver_local(device_id_t device_id, packet_t *packet,
1315 ip_header_t *header, services_t error)
1316{
1317 ip_proto_t *proto;
1318 async_sess_t *sess;
1319 services_t service;
1320 tl_received_msg_t received_msg;
1321 struct sockaddr *src;
1322 struct sockaddr *dest;
1323 struct sockaddr_in src_in;
1324 struct sockaddr_in dest_in;
1325 socklen_t addrlen;
1326 int rc;
1327
1328 if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
1329 IP_FRAGMENT_OFFSET(header)) {
1330 // TODO fragmented
1331 return ENOTSUP;
1332 }
1333
1334 switch (GET_IP_HEADER_VERSION(header)) {
1335 case IPVERSION:
1336 addrlen = sizeof(src_in);
1337 bzero(&src_in, addrlen);
1338 src_in.sin_family = AF_INET;
1339 memcpy(&dest_in, &src_in, addrlen);
1340 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
1341 sizeof(header->source_address));
1342 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
1343 sizeof(header->destination_address));
1344 src = (struct sockaddr *) &src_in;
1345 dest = (struct sockaddr *) &dest_in;
1346 break;
1347
1348 default:
1349 return ip_release_and_return(packet, EAFNOSUPPORT);
1350 }
1351
1352 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
1353 addrlen);
1354 if (rc != EOK)
1355 return ip_release_and_return(packet, rc);
1356
1357 /* Trim padding if present */
1358 if (!error &&
1359 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
1360 rc = packet_trim(packet, 0,
1361 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
1362 if (rc != EOK)
1363 return ip_release_and_return(packet, rc);
1364 }
1365
1366 fibril_rwlock_read_lock(&ip_globals.protos_lock);
1367
1368 proto = ip_protos_find(&ip_globals.protos, header->protocol);
1369 if (!proto) {
1370 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1371 sess = ip_prepare_icmp_and_get_session(error, packet, header);
1372 if (sess) {
1373 /* Unreachable ICMP */
1374 icmp_destination_unreachable_msg(sess,
1375 ICMP_PROT_UNREACH, 0, packet);
1376 }
1377 return ENOENT;
1378 }
1379
1380 if (proto->received_msg) {
1381 service = proto->service;
1382 received_msg = proto->received_msg;
1383 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1384 rc = received_msg(device_id, packet, service, error);
1385 } else {
1386 rc = tl_received_msg(proto->sess, device_id, packet,
1387 proto->service, error);
1388 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1389 }
1390
1391 return rc;
1392}
1393
1394/** Processes the received packet.
1395 *
1396 * The packet is either passed to another module or released on error.
1397 *
1398 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
1399 * invalid.
1400 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
1401 * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
1402 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
1403 * another host and the routing is disabled.
1404 *
1405 * @param[in] device_id The source device identifier.
1406 * @param[in] packet The received packet to be processed.
1407 * @return EOK on success.
1408 * @return EINVAL if the TTL is less than two.
1409 * @return EINVAL if the checksum is invalid.
1410 * @return EAFNOSUPPORT if the address family is not supported.
1411 * @return ENOENT if no route was found.
1412 * @return ENOENT if the packet is for another host and the routing
1413 * is disabled.
1414 */
1415static int ip_process_packet(device_id_t device_id, packet_t *packet)
1416{
1417 ip_header_t *header;
1418 in_addr_t dest;
1419 ip_route_t *route;
1420 async_sess_t *sess;
1421 struct sockaddr *addr;
1422 struct sockaddr_in addr_in;
1423 socklen_t addrlen;
1424 int rc;
1425
1426 header = (ip_header_t *) packet_get_data(packet);
1427 if (!header)
1428 return ip_release_and_return(packet, ENOMEM);
1429
1430 /* Checksum */
1431 if ((header->header_checksum) &&
1432 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
1433 sess = ip_prepare_icmp_and_get_session(0, packet, header);
1434 if (sess) {
1435 /* Checksum error ICMP */
1436 icmp_parameter_problem_msg(sess, ICMP_PARAM_POINTER,
1437 ((size_t) ((void *) &header->header_checksum)) -
1438 ((size_t) ((void *) header)), packet);
1439 }
1440 return EINVAL;
1441 }
1442
1443 if (header->ttl <= 1) {
1444 sess = ip_prepare_icmp_and_get_session(0, packet, header);
1445 if (sess) {
1446 /* TTL exceeded ICMP */
1447 icmp_time_exceeded_msg(sess, ICMP_EXC_TTL, packet);
1448 }
1449 return EINVAL;
1450 }
1451
1452 /* Process ipopt and get destination */
1453 dest = ip_get_destination(header);
1454
1455 /* Set the destination address */
1456 switch (GET_IP_HEADER_VERSION(header)) {
1457 case IPVERSION:
1458 addrlen = sizeof(addr_in);
1459 bzero(&addr_in, addrlen);
1460 addr_in.sin_family = AF_INET;
1461 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
1462 addr = (struct sockaddr *) &addr_in;
1463 break;
1464
1465 default:
1466 return ip_release_and_return(packet, EAFNOSUPPORT);
1467 }
1468
1469 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
1470 if (rc != EOK)
1471 return rc;
1472
1473 route = ip_find_route(dest);
1474 if (!route) {
1475 sess = ip_prepare_icmp_and_get_session(0, packet, header);
1476 if (sess) {
1477 /* Unreachable ICMP */
1478 icmp_destination_unreachable_msg(sess,
1479 ICMP_HOST_UNREACH, 0, packet);
1480 }
1481 return ENOENT;
1482 }
1483
1484 if (route->address.s_addr == dest.s_addr) {
1485 /* Local delivery */
1486 return ip_deliver_local(device_id, packet, header, 0);
1487 }
1488
1489 if (route->netif->routing) {
1490 header->ttl--;
1491 return ip_send_route(packet, route->netif, route, NULL, dest,
1492 0);
1493 }
1494
1495 sess = ip_prepare_icmp_and_get_session(0, packet, header);
1496 if (sess) {
1497 /* Unreachable ICMP if no routing */
1498 icmp_destination_unreachable_msg(sess, ICMP_HOST_UNREACH, 0,
1499 packet);
1500 }
1501
1502 return ENOENT;
1503}
1504
1505/** Return the device packet dimensions for sending.
1506 *
1507 * @param[in] device_id Device identifier.
1508 * @param[out] addr_len Minimum reserved address length.
1509 * @param[out] prefix Minimum reserved prefix size.
1510 * @param[out] content Maximum content size.
1511 * @param[out] suffix Minimum reserved suffix size.
1512 *
1513 * @return EOK on success.
1514 *
1515 */
1516static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
1517 size_t *prefix, size_t *content, size_t *suffix)
1518{
1519 ip_netif_t *netif;
1520 int index;
1521
1522 if (!addr_len || !prefix || !content || !suffix)
1523 return EBADMEM;
1524
1525 *content = IP_MAX_CONTENT - IP_PREFIX;
1526 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
1527 if (device_id < 0) {
1528 *addr_len = IP_ADDR;
1529 *prefix = 0;
1530 *suffix = 0;
1531
1532 for (index = ip_netifs_count(&ip_globals.netifs) - 1;
1533 index >= 0; index--) {
1534 netif = ip_netifs_get_index(&ip_globals.netifs, index);
1535 if (!netif)
1536 continue;
1537
1538 if (netif->packet_dimension.addr_len > *addr_len)
1539 *addr_len = netif->packet_dimension.addr_len;
1540
1541 if (netif->packet_dimension.prefix > *prefix)
1542 *prefix = netif->packet_dimension.prefix;
1543
1544 if (netif->packet_dimension.suffix > *suffix)
1545 *suffix = netif->packet_dimension.suffix;
1546 }
1547
1548 *prefix = *prefix + IP_PREFIX;
1549 *suffix = *suffix + IP_SUFFIX;
1550 } else {
1551 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1552 if (!netif) {
1553 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1554 return ENOENT;
1555 }
1556
1557 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
1558 netif->packet_dimension.addr_len : IP_ADDR;
1559 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
1560 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
1561 }
1562 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1563
1564 return EOK;
1565}
1566
1567/** Updates the device content length according to the new MTU value.
1568 *
1569 * @param[in] device_id The device identifier.
1570 * @param[in] mtu The new mtu value.
1571 * @return EOK on success.
1572 * @return ENOENT if device is not found.
1573 */
1574static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
1575{
1576 ip_netif_t *netif;
1577
1578 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1579 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1580 if (!netif) {
1581 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1582 return ENOENT;
1583 }
1584 netif->packet_dimension.content = mtu;
1585 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1586
1587 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
1588
1589 return EOK;
1590}
1591
1592/** Process IPC messages from the registered device driver modules
1593 *
1594 * @param[in] iid Message identifier.
1595 * @param[in,out] icall Message parameters.
1596 * @param[in] arg Local argument.
1597 *
1598 */
1599static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
1600{
1601 packet_t *packet;
1602 int rc;
1603
1604 while (true) {
1605 switch (IPC_GET_IMETHOD(*icall)) {
1606 case NET_IL_DEVICE_STATE:
1607 rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
1608 IPC_GET_STATE(*icall));
1609 async_answer_0(iid, (sysarg_t) rc);
1610 break;
1611
1612 case NET_IL_RECEIVED:
1613 rc = packet_translate_remote(ip_globals.net_sess, &packet,
1614 IPC_GET_PACKET(*icall));
1615 if (rc == EOK) {
1616 do {
1617 packet_t *next = pq_detach(packet);
1618 ip_process_packet(IPC_GET_DEVICE(*icall), packet);
1619 packet = next;
1620 } while (packet);
1621 }
1622
1623 async_answer_0(iid, (sysarg_t) rc);
1624 break;
1625
1626 case NET_IL_MTU_CHANGED:
1627 rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
1628 IPC_GET_MTU(*icall));
1629 async_answer_0(iid, (sysarg_t) rc);
1630 break;
1631
1632 default:
1633 async_answer_0(iid, (sysarg_t) ENOTSUP);
1634 }
1635
1636 iid = async_get_call(icall);
1637 }
1638}
1639
1640/** Register the transport layer protocol.
1641 *
1642 * The traffic of this protocol will be supplied using either the receive
1643 * function or IPC message.
1644 *
1645 * @param[in] protocol Transport layer module protocol.
1646 * @param[in] service Transport layer module service.
1647 * @param[in] sess Transport layer module session.
1648 * @param[in] received_msg Receiving function.
1649 *
1650 * @return EOK on success.
1651 * @return EINVAL if the protocol parameter and/or the service
1652 * parameter is zero.
1653 * @return EINVAL if the phone parameter is not a positive number
1654 * and the tl_receive_msg is NULL.
1655 * @return ENOMEM if there is not enough memory left.
1656 *
1657 */
1658static int ip_register(int protocol, services_t service, async_sess_t *sess,
1659 tl_received_msg_t received_msg)
1660{
1661 ip_proto_t *proto;
1662 int index;
1663
1664 if ((!protocol) || (!service) || ((!sess) && (!received_msg)))
1665 return EINVAL;
1666
1667 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
1668 if (!proto)
1669 return ENOMEM;
1670
1671 proto->protocol = protocol;
1672 proto->service = service;
1673 proto->sess = sess;
1674 proto->received_msg = received_msg;
1675
1676 fibril_rwlock_write_lock(&ip_globals.protos_lock);
1677 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
1678 if (index < 0) {
1679 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
1680 free(proto);
1681 return index;
1682 }
1683 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
1684
1685 printf("%s: Protocol registered (protocol: %d)\n",
1686 NAME, proto->protocol);
1687
1688 return EOK;
1689}
1690
1691static int ip_add_route_req_local(device_id_t device_id, in_addr_t address,
1692 in_addr_t netmask, in_addr_t gateway)
1693{
1694 ip_route_t *route;
1695 ip_netif_t *netif;
1696 int index;
1697
1698 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1699
1700 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1701 if (!netif) {
1702 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1703 return ENOENT;
1704 }
1705
1706 route = (ip_route_t *) malloc(sizeof(ip_route_t));
1707 if (!route) {
1708 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1709 return ENOMEM;
1710 }
1711
1712 route->address.s_addr = address.s_addr;
1713 route->netmask.s_addr = netmask.s_addr;
1714 route->gateway.s_addr = gateway.s_addr;
1715 route->netif = netif;
1716 index = ip_routes_add(&netif->routes, route);
1717 if (index < 0)
1718 free(route);
1719
1720 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1721
1722 return index;
1723}
1724
1725static int ip_set_gateway_req_local(device_id_t device_id, in_addr_t gateway)
1726{
1727 ip_netif_t *netif;
1728
1729 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1730
1731 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1732 if (!netif) {
1733 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1734 return ENOENT;
1735 }
1736
1737 ip_globals.gateway.address.s_addr = 0;
1738 ip_globals.gateway.netmask.s_addr = 0;
1739 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
1740 ip_globals.gateway.netif = netif;
1741
1742 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1743
1744 return EOK;
1745}
1746
1747/** Notify the IP module about the received error notification packet.
1748 *
1749 * @param[in] device_id Device identifier.
1750 * @param[in] packet Received packet or the received packet queue.
1751 * @param[in] target Target internetwork module service to be
1752 * delivered to.
1753 * @param[in] error Packet error reporting service. Prefixes the
1754 * received packet.
1755 *
1756 * @return EOK on success.
1757 *
1758 */
1759static int ip_received_error_msg_local(device_id_t device_id,
1760 packet_t *packet, services_t target, services_t error)
1761{
1762 uint8_t *data;
1763 int offset;
1764 icmp_type_t type;
1765 icmp_code_t code;
1766 ip_netif_t *netif;
1767 measured_string_t address;
1768 ip_route_t *route;
1769 ip_header_t *header;
1770
1771 switch (error) {
1772 case SERVICE_ICMP:
1773 offset = icmp_client_process_packet(packet, &type, &code, NULL,
1774 NULL);
1775 if (offset < 0)
1776 return ip_release_and_return(packet, ENOMEM);
1777
1778 data = packet_get_data(packet);
1779 header = (ip_header_t *)(data + offset);
1780
1781 /* Destination host unreachable? */
1782 if ((type != ICMP_DEST_UNREACH) ||
1783 (code != ICMP_HOST_UNREACH)) {
1784 /* No, something else */
1785 break;
1786 }
1787
1788 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
1789
1790 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1791 if (!netif || !netif->arp) {
1792 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1793 break;
1794 }
1795
1796 route = ip_routes_get_index(&netif->routes, 0);
1797
1798 /* From the same network? */
1799 if (route && ((route->address.s_addr & route->netmask.s_addr) ==
1800 (header->destination_address & route->netmask.s_addr))) {
1801 /* Clear the ARP mapping if any */
1802 address.value = (uint8_t *) &header->destination_address;
1803 address.length = sizeof(header->destination_address);
1804 arp_clear_address_req(netif->arp->sess,
1805 netif->device_id, SERVICE_IP, &address);
1806 }
1807
1808 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1809 break;
1810
1811 default:
1812 return ip_release_and_return(packet, ENOTSUP);
1813 }
1814
1815 return ip_deliver_local(device_id, packet, header, error);
1816}
1817
1818static int ip_get_route_req_local(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
1916 if (!IPC_GET_IMETHOD(*call))
1917 return EOK;
1918
1919 async_sess_t *callback =
1920 async_callback_receive_start(EXCHANGE_SERIALIZE, call);
1921 if (callback)
1922 return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
1923 callback, NULL);
1924
1925 switch (IPC_GET_IMETHOD(*call)) {
1926 case NET_IP_DEVICE:
1927 return ip_device_req_local(IPC_GET_DEVICE(*call),
1928 IPC_GET_SERVICE(*call));
1929
1930 case NET_IP_RECEIVED_ERROR:
1931 rc = packet_translate_remote(ip_globals.net_sess, &packet,
1932 IPC_GET_PACKET(*call));
1933 if (rc != EOK)
1934 return rc;
1935 return ip_received_error_msg_local(IPC_GET_DEVICE(*call),
1936 packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
1937
1938 case NET_IP_ADD_ROUTE:
1939 return ip_add_route_req_local(IPC_GET_DEVICE(*call),
1940 IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
1941 IP_GET_GATEWAY(*call));
1942
1943 case NET_IP_SET_GATEWAY:
1944 return ip_set_gateway_req_local(IPC_GET_DEVICE(*call),
1945 IP_GET_GATEWAY(*call));
1946
1947 case NET_IP_GET_ROUTE:
1948 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
1949 &addrlen);
1950 if (rc != EOK)
1951 return rc;
1952
1953 rc = ip_get_route_req_local(IP_GET_PROTOCOL(*call), addr,
1954 (socklen_t) addrlen, &device_id, &header, &headerlen);
1955 if (rc != EOK)
1956 return rc;
1957
1958 IPC_SET_DEVICE(*answer, device_id);
1959 IP_SET_HEADERLEN(*answer, headerlen);
1960
1961 *answer_count = 2;
1962
1963 rc = data_reply(&headerlen, sizeof(headerlen));
1964 if (rc == EOK)
1965 rc = data_reply(header, headerlen);
1966
1967 free(header);
1968 return rc;
1969
1970 case NET_IP_PACKET_SPACE:
1971 rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
1972 &prefix, &content, &suffix);
1973 if (rc != EOK)
1974 return rc;
1975
1976 IPC_SET_ADDR(*answer, addrlen);
1977 IPC_SET_PREFIX(*answer, prefix);
1978 IPC_SET_CONTENT(*answer, content);
1979 IPC_SET_SUFFIX(*answer, suffix);
1980 *answer_count = 4;
1981 return EOK;
1982
1983 case NET_IP_SEND:
1984 rc = packet_translate_remote(ip_globals.net_sess, &packet,
1985 IPC_GET_PACKET(*call));
1986 if (rc != EOK)
1987 return rc;
1988
1989 return ip_send_msg_local(IPC_GET_DEVICE(*call), packet, 0,
1990 IPC_GET_ERROR(*call));
1991 }
1992
1993 return ENOTSUP;
1994}
1995
1996int main(int argc, char *argv[])
1997{
1998 /* Start the module */
1999 return il_module_start(SERVICE_IP);
2000}
2001
2002/** @}
2003 */
Note: See TracBrowser for help on using the repository browser.