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

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

networking improvements

  • start the networking stack from init
  • add loopback network interface driver (cherrypicked and sanitized from lp:~helenos-nicf/helenos/nicf)
  • add libnic and various small pieces from lp:~helenos-nicf/helenos/nicf
  • fix client side of NIC_GET_ADDRESS
  • net binary overhaul

Note: "ping 127.0.0.1" works, but the first three pings timeout for some reason

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