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

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

Do not leak last_header on failure.

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