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

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

Integrate net_err.h into the standard library's err.h.

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