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

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

Remove data_receive() in favor of standard async_data_write_accept().

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