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

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aadf01e was aadf01e, checked in by Lukas Mejdrech <lukasmejdrech@…>, 16 years ago

Coding style (no functional change)

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