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

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

Move IP module messages definitions to standard library.

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