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

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

Fix more dangerous type casts.

  • Property mode set to 100644
File size: 55.5 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ip
30 * @{
31 */
32
33/** @file
34 * IP module implementation.
35 * @see arp.h
36 */
37
38#include <async.h>
39#include <errno.h>
40#include <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 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(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(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(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
890 ERROR_DECLARE;
891
892 packet_t packet;
893 struct sockaddr * addr;
894 size_t addrlen;
895 ip_pseudo_header_ref header;
896 size_t headerlen;
897 device_id_t device_id;
898
899 *answer_count = 0;
900 switch(IPC_GET_METHOD(*call)){
901 case IPC_M_PHONE_HUNGUP:
902 return EOK;
903 case NET_IL_DEVICE:
904 return ip_device_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call));
905 case IPC_M_CONNECT_TO_ME:
906 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call), IPC_GET_PHONE(call), NULL);
907 case NET_IL_SEND:
908 ERROR_PROPAGATE(packet_translate(ip_globals.net_phone, &packet, IPC_GET_PACKET(call)));
909 return ip_send_msg(0, IPC_GET_DEVICE(call), packet, 0, IPC_GET_ERROR(call));
910 case NET_IL_DEVICE_STATE:
911 return ip_device_state_message(IPC_GET_DEVICE(call), IPC_GET_STATE(call));
912 case NET_IL_RECEIVED:
913 ERROR_PROPAGATE(packet_translate(ip_globals.net_phone, &packet, IPC_GET_PACKET(call)));
914 return ip_receive_message(IPC_GET_DEVICE(call), packet);
915 case NET_IP_RECEIVED_ERROR:
916 ERROR_PROPAGATE(packet_translate(ip_globals.net_phone, &packet, IPC_GET_PACKET(call)));
917 return ip_received_error_msg(0, IPC_GET_DEVICE(call), packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
918 case NET_IP_ADD_ROUTE:
919 return ip_add_route_req(0, IPC_GET_DEVICE(call), IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
920 case NET_IP_SET_GATEWAY:
921 return ip_set_gateway_req(0, IPC_GET_DEVICE(call), IP_GET_GATEWAY(call));
922 case NET_IP_GET_ROUTE:
923 ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
924 ERROR_PROPAGATE(ip_get_route_req(0, IP_GET_PROTOCOL(call), addr, (socklen_t) addrlen,
925 &device_id, &header, &headerlen));
926 *IPC_SET_DEVICE(answer) = device_id;
927 *IP_SET_HEADERLEN(answer) = headerlen;
928 *answer_count = 2;
929 if(! ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen)))){
930 ERROR_CODE = data_reply(header, headerlen);
931 }
932 free(header);
933 return ERROR_CODE;
934 case NET_IL_PACKET_SPACE:
935 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)));
936 *answer_count = 3;
937 return EOK;
938 case NET_IL_MTU_CHANGED:
939 return ip_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
940 }
941 return ENOTSUP;
942}
943
944int ip_packet_size_req(int ip_phone, device_id_t device_id, packet_dimension_ref packet_dimension){
945 if(! packet_dimension){
946 return EBADMEM;
947 }
948 return ip_packet_size_message(device_id, &packet_dimension->addr_len, &packet_dimension->prefix, &packet_dimension->content, &packet_dimension->suffix);
949}
950
951int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
952 ip_netif_ref netif;
953 int index;
954
955 if(!(addr_len && prefix && content && suffix)){
956 return EBADMEM;
957 }
958 *content = IP_MAX_CONTENT - IP_PREFIX;
959 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
960 if(device_id < 0){
961 *addr_len = IP_ADDR;
962 *prefix = 0;
963 *suffix = 0;
964 for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
965 netif = ip_netifs_get_index(&ip_globals.netifs, index);
966 if(netif){
967 if(netif->packet_dimension.addr_len > * addr_len){
968 *addr_len = netif->packet_dimension.addr_len;
969 }
970 if(netif->packet_dimension.prefix > * prefix){
971 *prefix = netif->packet_dimension.prefix;
972 }
973 if(netif->packet_dimension.suffix > * suffix){
974 *suffix = netif->packet_dimension.suffix;
975 }
976 }
977 }
978 *prefix = * prefix + IP_PREFIX;
979 *suffix = * suffix + IP_SUFFIX;
980 }else{
981 netif = ip_netifs_find(&ip_globals.netifs, device_id);
982 if(! netif){
983 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
984 return ENOENT;
985 }
986 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
987 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
988 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
989 }
990 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
991 return EOK;
992}
993
994int ip_add_route_req(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
995 ip_route_ref route;
996 ip_netif_ref netif;
997 int index;
998
999 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1000 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1001 if(! netif){
1002 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1003 return ENOENT;
1004 }
1005 route = (ip_route_ref) malloc(sizeof(ip_route_t));
1006 if(! route){
1007 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1008 return ENOMEM;
1009 }
1010 route->address.s_addr = address.s_addr;
1011 route->netmask.s_addr = netmask.s_addr;
1012 route->gateway.s_addr = gateway.s_addr;
1013 route->netif = netif;
1014 index = ip_routes_add(&netif->routes, route);
1015 if(index < 0){
1016 free(route);
1017 }
1018 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1019 return index;
1020}
1021
1022ip_route_ref ip_find_route(in_addr_t destination){
1023 int index;
1024 ip_route_ref route;
1025 ip_netif_ref netif;
1026
1027 // start with the last netif - the newest one
1028 index = ip_netifs_count(&ip_globals.netifs) - 1;
1029 while(index >= 0){
1030 netif = ip_netifs_get_index(&ip_globals.netifs, index);
1031 if(netif && (netif->state == NETIF_ACTIVE)){
1032 route = ip_netif_find_route(netif, destination);
1033 if(route){
1034 return route;
1035 }
1036 }
1037 -- index;
1038 }
1039 return &ip_globals.gateway;
1040}
1041
1042ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
1043 int index;
1044 ip_route_ref route;
1045
1046 if(netif){
1047 // start with the first one - the direct route
1048 for(index = 0; index < ip_routes_count(&netif->routes); ++ index){
1049 route = ip_routes_get_index(&netif->routes, index);
1050 if(route && ((route->address.s_addr &route->netmask.s_addr) == (destination.s_addr &route->netmask.s_addr))){
1051 return route;
1052 }
1053 }
1054 }
1055 return NULL;
1056}
1057
1058int ip_set_gateway_req(int ip_phone, device_id_t device_id, in_addr_t gateway){
1059 ip_netif_ref netif;
1060
1061 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1062 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1063 if(! netif){
1064 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1065 return ENOENT;
1066 }
1067 ip_globals.gateway.address.s_addr = 0;
1068 ip_globals.gateway.netmask.s_addr = 0;
1069 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
1070 ip_globals.gateway.netif = netif;
1071 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1072 return EOK;
1073}
1074
1075packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
1076 size_t length;
1077 packet_t next;
1078 packet_t new_packet;
1079 int result;
1080 int phone;
1081
1082 next = packet;
1083 // check all packets
1084 while(next){
1085 length = packet_get_data_length(next);
1086 // too long?
1087 if(length > content){
1088 result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
1089 if(result != EOK){
1090 new_packet = pq_detach(next);
1091 if(next == packet){
1092 // the new first packet of the queue
1093 packet = new_packet;
1094 }
1095 // fragmentation needed?
1096 if(result == EPERM){
1097 phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
1098 if(phone >= 0){
1099 // fragmentation necessary ICMP
1100 icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
1101 }
1102 }else{
1103 pq_release(ip_globals.net_phone, packet_get_id(next));
1104 }
1105 next = new_packet;
1106 continue;
1107 }
1108 }
1109 next = pq_next(next);
1110 }
1111 return packet;
1112}
1113
1114int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
1115 ERROR_DECLARE;
1116
1117 packet_t new_packet;
1118 ip_header_ref header;
1119 ip_header_ref middle_header;
1120 ip_header_ref last_header;
1121 struct sockaddr * src;
1122 struct sockaddr * dest;
1123 socklen_t addrlen;
1124 int result;
1125
1126 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
1127 if(result <= 0){
1128 return EINVAL;
1129 }
1130 addrlen = (socklen_t) result;
1131 if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
1132 return ENOMEM;
1133 }
1134 // get header
1135 header = (ip_header_ref) packet_get_data(packet);
1136 if(! header){
1137 return EINVAL;
1138 }
1139 // fragmentation forbidden?
1140 if(header->flags &IPFLAG_DONT_FRAGMENT){
1141 return EPERM;
1142 }
1143 // create the last fragment
1144 new_packet = packet_get_4(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
1145 if(! new_packet){
1146 return ENOMEM;
1147 }
1148 // allocate as much as originally
1149 last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
1150 if(! last_header){
1151 return ip_release_and_return(packet, ENOMEM);
1152 }
1153 ip_create_last_header(last_header, header);
1154 // trim the unused space
1155 if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
1156 return ip_release_and_return(packet, ERROR_CODE);
1157 }
1158 // biggest multiple of 8 lower than content
1159 // TODO even fragmentation?
1160 length = length &(~ 0x7);// (content / 8) * 8
1161 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))){
1162 return ip_release_and_return(packet, ERROR_CODE);
1163 }
1164 // mark the first as fragmented
1165 header->flags |= IPFLAG_MORE_FRAGMENTS;
1166 // create middle framgents
1167 while(IP_TOTAL_LENGTH(header) > length){
1168 new_packet = packet_get_4(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
1169 if(! new_packet){
1170 return ENOMEM;
1171 }
1172 middle_header = ip_create_middle_header(new_packet, last_header);
1173 if(! middle_header){
1174 return ip_release_and_return(packet, ENOMEM);
1175 }
1176 if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
1177 return ip_release_and_return(packet, ERROR_CODE);
1178 }
1179 }
1180 // finish the first fragment
1181 header->header_checksum = IP_HEADER_CHECKSUM(header);
1182 return EOK;
1183}
1184
1185int 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){
1186 ERROR_DECLARE;
1187
1188 void * data;
1189 size_t offset;
1190
1191 data = packet_suffix(new_packet, length);
1192 if(! data){
1193 return ENOMEM;
1194 }
1195 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
1196 ERROR_PROPAGATE(packet_trim(packet, 0, length));
1197 header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
1198 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
1199 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
1200 new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
1201 new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
1202 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
1203 ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
1204 return pq_insert_after(packet, new_packet);
1205}
1206
1207ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
1208 ip_header_ref middle;
1209
1210 middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
1211 if(! middle){
1212 return NULL;
1213 }
1214 memcpy(middle, last, IP_HEADER_LENGTH(last));
1215 middle->flags |= IPFLAG_MORE_FRAGMENTS;
1216 return middle;
1217}
1218
1219void ip_create_last_header(ip_header_ref last, ip_header_ref first){
1220 ip_option_ref option;
1221 size_t next;
1222 size_t length;
1223
1224 // copy first itself
1225 memcpy(last, first, sizeof(ip_header_t));
1226 length = sizeof(ip_header_t);
1227 next = sizeof(ip_header_t);
1228 // process all ip options
1229 while(next < first->header_length){
1230 option = (ip_option_ref) (((uint8_t *) first) + next);
1231 // skip end or noop
1232 if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
1233 ++ next;
1234 }else{
1235 // copy if said so or skip
1236 if(IPOPT_COPIED(option->type)){
1237 memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
1238 length += option->length;
1239 }
1240 // next option
1241 next += option->length;
1242 }
1243 }
1244 // align 4 byte boundary
1245 if(length % 4){
1246 bzero(((uint8_t *) last) + length, 4 - (length % 4));
1247 last->header_length = length / 4 + 1;
1248 }else{
1249 last->header_length = length / 4;
1250 }
1251 last->header_checksum = 0;
1252}
1253
1254int ip_receive_message(device_id_t device_id, packet_t packet){
1255 packet_t next;
1256
1257 do{
1258 next = pq_detach(packet);
1259 ip_process_packet(device_id, packet);
1260 packet = next;
1261 }while(packet);
1262 return EOK;
1263}
1264
1265int ip_process_packet(device_id_t device_id, packet_t packet){
1266 ERROR_DECLARE;
1267
1268 ip_header_ref header;
1269 in_addr_t dest;
1270 ip_route_ref route;
1271 int phone;
1272 struct sockaddr * addr;
1273 struct sockaddr_in addr_in;
1274// struct sockaddr_in addr_in6;
1275 socklen_t addrlen;
1276
1277 header = (ip_header_ref) packet_get_data(packet);
1278 if(! header){
1279 return ip_release_and_return(packet, ENOMEM);
1280 }
1281 // checksum
1282 if((header->header_checksum) && (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)){
1283 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1284 if(phone >= 0){
1285 // checksum error ICMP
1286 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->header_checksum)) - ((size_t) ((void *) header)), packet);
1287 }
1288 return EINVAL;
1289 }
1290 if(header->ttl <= 1){
1291 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1292 if(phone >= 0){
1293 // ttl oxceeded ICMP
1294 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
1295 }
1296 return EINVAL;
1297 }
1298 // process ipopt and get destination
1299 dest = ip_get_destination(header);
1300 // set the addrination address
1301 switch(header->version){
1302 case IPVERSION:
1303 addrlen = sizeof(addr_in);
1304 bzero(&addr_in, addrlen);
1305 addr_in.sin_family = AF_INET;
1306 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
1307 addr = (struct sockaddr *) &addr_in;
1308 break;
1309/* case IPv6VERSION:
1310 addrlen = sizeof(dest_in6);
1311 bzero(&dest_in6, addrlen);
1312 dest_in6.sin6_family = AF_INET6;
1313 memcpy(&dest_in6.sin6_addr.s6_addr,);
1314 dest = (struct sockaddr *) &dest_in;
1315 break;
1316*/ default:
1317 return ip_release_and_return(packet, EAFNOSUPPORT);
1318 }
1319 ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
1320 route = ip_find_route(dest);
1321 if(! route){
1322 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1323 if(phone >= 0){
1324 // unreachable ICMP
1325 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
1326 }
1327 return ENOENT;
1328 }
1329 if(route->address.s_addr == dest.s_addr){
1330 // local delivery
1331 return ip_deliver_local(device_id, packet, header, 0);
1332 }else{
1333 // only if routing enabled
1334 if(route->netif->routing){
1335 -- header->ttl;
1336 return ip_send_route(packet, route->netif, route, NULL, dest, 0);
1337 }else{
1338 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1339 if(phone >= 0){
1340 // unreachable ICMP if no routing
1341 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
1342 }
1343 return ENOENT;
1344 }
1345 }
1346}
1347
1348int ip_received_error_msg(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
1349 uint8_t * data;
1350 int offset;
1351 icmp_type_t type;
1352 icmp_code_t code;
1353 ip_netif_ref netif;
1354 measured_string_t address;
1355 ip_route_ref route;
1356 ip_header_ref header;
1357
1358 switch(error){
1359 case SERVICE_ICMP:
1360 offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
1361 if(offset < 0){
1362 return ip_release_and_return(packet, ENOMEM);
1363 }
1364 data = packet_get_data(packet);
1365 header = (ip_header_ref)(data + offset);
1366 // destination host unreachable?
1367 if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
1368 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
1369 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1370 if(netif && netif->arp){
1371 route = ip_routes_get_index(&netif->routes, 0);
1372 // from the same network?
1373 if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
1374 // clear the ARP mapping if any
1375 address.value = (char *) &header->destination_address;
1376 address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
1377 arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
1378 }
1379 }
1380 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1381 }
1382 break;
1383 default:
1384 return ip_release_and_return(packet, ENOTSUP);
1385 }
1386 return ip_deliver_local(device_id, packet, header, error);
1387}
1388
1389int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
1390 ERROR_DECLARE;
1391
1392 ip_proto_ref proto;
1393 int phone;
1394 services_t service;
1395 tl_received_msg_t received_msg;
1396 struct sockaddr * src;
1397 struct sockaddr * dest;
1398 struct sockaddr_in src_in;
1399 struct sockaddr_in dest_in;
1400// struct sockaddr_in src_in6;
1401// struct sockaddr_in dest_in6;
1402 socklen_t addrlen;
1403
1404 if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
1405 // TODO fragmented
1406 return ENOTSUP;
1407 }else{
1408 switch(header->version){
1409 case IPVERSION:
1410 addrlen = sizeof(src_in);
1411 bzero(&src_in, addrlen);
1412 src_in.sin_family = AF_INET;
1413 memcpy(&dest_in, &src_in, addrlen);
1414 memcpy(&src_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
1415 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, sizeof(header->destination_address));
1416 src = (struct sockaddr *) &src_in;
1417 dest = (struct sockaddr *) &dest_in;
1418 break;
1419/* case IPv6VERSION:
1420 addrlen = sizeof(src_in6);
1421 bzero(&src_in6, addrlen);
1422 src_in6.sin6_family = AF_INET6;
1423 memcpy(&dest_in6, &src_in6, addrlen);
1424 memcpy(&src_in6.sin6_addr.s6_addr,);
1425 memcpy(&dest_in6.sin6_addr.s6_addr,);
1426 src = (struct sockaddr *) &src_in;
1427 dest = (struct sockaddr *) &dest_in;
1428 break;
1429*/ default:
1430 return ip_release_and_return(packet, EAFNOSUPPORT);
1431 }
1432 if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
1433 return ip_release_and_return(packet, ERROR_CODE);
1434 }
1435 // trim padding if present
1436 if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
1437 if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
1438 return ip_release_and_return(packet, ERROR_CODE);
1439 }
1440 }
1441 fibril_rwlock_read_lock(&ip_globals.protos_lock);
1442 proto = ip_protos_find(&ip_globals.protos, header->protocol);
1443 if(! proto){
1444 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1445 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
1446 if(phone >= 0){
1447 // unreachable ICMP
1448 icmp_destination_unreachable_msg(phone, ICMP_PROT_UNREACH, 0, packet);
1449 }
1450 return ENOENT;
1451 }
1452 if(proto->received_msg){
1453 service = proto->service;
1454 received_msg = proto->received_msg;
1455 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1456 ERROR_CODE = received_msg(device_id, packet, service, error);
1457 }else{
1458 ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
1459 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1460 }
1461 return ERROR_CODE;
1462 }
1463}
1464
1465in_addr_t ip_get_destination(ip_header_ref header){
1466 in_addr_t destination;
1467
1468 // TODO search set ipopt route?
1469 destination.s_addr = header->destination_address;
1470 return destination;
1471}
1472
1473int ip_prepare_icmp(packet_t packet, ip_header_ref header){
1474 packet_t next;
1475 struct sockaddr * dest;
1476 struct sockaddr_in dest_in;
1477// struct sockaddr_in dest_in6;
1478 socklen_t addrlen;
1479
1480 // detach the first packet and release the others
1481 next = pq_detach(packet);
1482 if(next){
1483 pq_release(ip_globals.net_phone, packet_get_id(next));
1484 }
1485 if(! header){
1486 if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
1487 return ENOMEM;
1488 }
1489 // get header
1490 header = (ip_header_ref) packet_get_data(packet);
1491 if(! header){
1492 return EINVAL;
1493 }
1494 }
1495 // only for the first fragment
1496 if(IP_FRAGMENT_OFFSET(header)){
1497 return EINVAL;
1498 }
1499 // not for the ICMP protocol
1500 if(header->protocol == IPPROTO_ICMP){
1501 return EPERM;
1502 }
1503 // set the destination address
1504 switch(header->version){
1505 case IPVERSION:
1506 addrlen = sizeof(dest_in);
1507 bzero(&dest_in, addrlen);
1508 dest_in.sin_family = AF_INET;
1509 memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
1510 dest = (struct sockaddr *) &dest_in;
1511 break;
1512/* case IPv6VERSION:
1513 addrlen = sizeof(dest_in6);
1514 bzero(&dest_in6, addrlen);
1515 dest_in6.sin6_family = AF_INET6;
1516 memcpy(&dest_in6.sin6_addr.s6_addr,);
1517 dest = (struct sockaddr *) &dest_in;
1518 break;
1519*/ default:
1520 return EAFNOSUPPORT;
1521 }
1522 return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
1523}
1524
1525int ip_get_icmp_phone(void){
1526 ip_proto_ref proto;
1527 int phone;
1528
1529 fibril_rwlock_read_lock(&ip_globals.protos_lock);
1530 proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
1531 phone = proto ? proto->phone : ENOENT;
1532 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1533 return phone;
1534}
1535
1536int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
1537 int phone;
1538
1539 phone = ip_get_icmp_phone();
1540 if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
1541 return ip_release_and_return(packet, EINVAL);
1542 }
1543 return phone;
1544}
1545
1546int ip_release_and_return(packet_t packet, int result){
1547 pq_release(ip_globals.net_phone, packet_get_id(packet));
1548 return result;
1549}
1550
1551int 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){
1552 struct sockaddr_in * address_in;
1553// struct sockaddr_in6 * address_in6;
1554 in_addr_t * dest;
1555 in_addr_t * src;
1556 ip_route_ref route;
1557 ipv4_pseudo_header_ref header_in;
1558
1559 if(!(destination && (addrlen > 0))){
1560 return EINVAL;
1561 }
1562 if(!(device_id && header && headerlen)){
1563 return EBADMEM;
1564 }
1565 if((size_t) addrlen < sizeof(struct sockaddr)){
1566 return EINVAL;
1567 }
1568 switch(destination->sa_family){
1569 case AF_INET:
1570 if(addrlen != sizeof(struct sockaddr_in)){
1571 return EINVAL;
1572 }
1573 address_in = (struct sockaddr_in *) destination;
1574 dest = &address_in->sin_addr;
1575 if(! dest->s_addr){
1576 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1577 }
1578 break;
1579 // TODO IPv6
1580/* case AF_INET6:
1581 if(addrlen != sizeof(struct sockaddr_in6)){
1582 return EINVAL;
1583 }
1584 address_in6 = (struct sockaddr_in6 *) dest;
1585 address_in6.sin6_addr.s6_addr;
1586*/ default:
1587 return EAFNOSUPPORT;
1588 }
1589 fibril_rwlock_read_lock(&ip_globals.lock);
1590 route = ip_find_route(*dest);
1591 // if the local host is the destination
1592 if(route && (route->address.s_addr == dest->s_addr)
1593 && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
1594 // find the loopback device to deliver
1595 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1596 route = ip_find_route(*dest);
1597 }
1598 if(!(route && route->netif)){
1599 fibril_rwlock_read_unlock(&ip_globals.lock);
1600 return ENOENT;
1601 }
1602 *device_id = route->netif->device_id;
1603 src = ip_netif_address(route->netif);
1604 fibril_rwlock_read_unlock(&ip_globals.lock);
1605 *headerlen = sizeof(*header_in);
1606 header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
1607 if(! header_in){
1608 return ENOMEM;
1609 }
1610 bzero(header_in, * headerlen);
1611 header_in->destination_address = dest->s_addr;
1612 header_in->source_address = src->s_addr;
1613 header_in->protocol = protocol;
1614 header_in->data_length = 0;
1615 *header = (ip_pseudo_header_ref) header_in;
1616 return EOK;
1617}
1618
1619/** @}
1620 */
Note: See TracBrowser for help on using the repository browser.