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

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

Move net_device.h to standard library.

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