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

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

streamline internetworking layer

  • IPC method renaming

NET_IL_DEVICE → NET_IP_DEVICE
NET_IL_PACKET_SPACE → NET_IP_PACKET_SPACE
NET_IL_SEND → NET_IP_SEND

The original methods were actually not generic methods of the IL layer (used by the lower layers), but specific methods of the IP module
and used by the higher layers. The original naming was rather confusing.

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