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

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

Fix packet_get_copy() and socket_destroy_core() to use the remote packet
interfaces.

Fix packet_client.h to declare the remote packet interfaces and create
packet_local.h for the use by the packet server (or later possibly also by the
bundle build).

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