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

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

Redefine packet_t to be just a type alias for struct packet.

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