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

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

Remove unused duplicit of ip_bind_service().

  • 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 <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_connect_module(services_t service){
624 return EOK;
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
650 printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
651 NAME, proto->protocol, proto->phone);
652
653 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
654 return EOK;
655}
656
657int ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
658 ERROR_DECLARE;
659
660 int addrlen;
661 ip_netif_ref netif;
662 ip_route_ref route;
663 struct sockaddr * addr;
664 struct sockaddr_in * address_in;
665// struct sockaddr_in6 * address_in6;
666 in_addr_t * dest;
667 in_addr_t * src;
668 int phone;
669
670 // addresses in the host byte order
671 // should be the next hop address or the target destination address
672 addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
673 if(addrlen < 0){
674 return ip_release_and_return(packet, addrlen);
675 }
676 if((size_t) addrlen < sizeof(struct sockaddr)){
677 return ip_release_and_return(packet, EINVAL);
678 }
679 switch(addr->sa_family){
680 case AF_INET:
681 if(addrlen != sizeof(struct sockaddr_in)){
682 return ip_release_and_return(packet, EINVAL);
683 }
684 address_in = (struct sockaddr_in *) addr;
685 dest = &address_in->sin_addr;
686 if(! dest->s_addr){
687 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
688 }
689 break;
690 // TODO IPv6
691/* case AF_INET6:
692 if(addrlen != sizeof(struct sockaddr_in6)){
693 return EINVAL;
694 }
695 address_in6 = (struct sockaddr_in6 *) dest;
696 address_in6.sin6_addr.s6_addr;
697 IPV6_LOCALHOST_ADDRESS;
698*/ default:
699 return ip_release_and_return(packet, EAFNOSUPPORT);
700 }
701 netif = NULL;
702 route = NULL;
703 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
704 // device specified?
705 if(device_id > 0){
706 netif = ip_netifs_find(&ip_globals.netifs, device_id);
707 route = ip_netif_find_route(netif, * dest);
708 if(netif && (! route) && (ip_globals.gateway.netif == netif)){
709 route = &ip_globals.gateway;
710 }
711 }
712 if(! route){
713 route = ip_find_route(*dest);
714 netif = route ? route->netif : NULL;
715 }
716 if(!(netif && route)){
717 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
718 phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
719 if(phone >= 0){
720 // unreachable ICMP if no routing
721 icmp_destination_unreachable_msg(phone, ICMP_NET_UNREACH, 0, packet);
722 }
723 return ENOENT;
724 }
725 if(error){
726 // do not send for broadcast, anycast packets or network broadcast
727 if((! dest->s_addr)
728 || (!(~ dest->s_addr))
729 || (!(~((dest->s_addr &(~ route->netmask.s_addr)) | route->netmask.s_addr)))
730 || (!(dest->s_addr &(~ route->netmask.s_addr)))){
731 return ip_release_and_return(packet, EINVAL);
732 }
733 }
734 // if the local host is the destination
735 if((route->address.s_addr == dest->s_addr)
736 && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
737 // find the loopback device to deliver
738 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
739 route = ip_find_route(*dest);
740 netif = route ? route->netif : NULL;
741 if(!(netif && route)){
742 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
743 phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
744 if(phone >= 0){
745 // unreachable ICMP if no routing
746 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
747 }
748 return ENOENT;
749 }
750 }
751 src = ip_netif_address(netif);
752 if(! src){
753 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
754 return ip_release_and_return(packet, ENOENT);
755 }
756 ERROR_CODE = ip_send_route(packet, netif, route, src, * dest, error);
757 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
758 return ERROR_CODE;
759}
760
761in_addr_t * ip_netif_address(ip_netif_ref netif){
762 ip_route_ref route;
763
764 route = ip_routes_get_index(&netif->routes, 0);
765 return route ? &route->address : NULL;
766}
767
768int 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){
769 ERROR_DECLARE;
770
771 measured_string_t destination;
772 measured_string_ref translation;
773 char * data;
774 int phone;
775
776 // get destination hardware address
777 if(netif->arp && (route->address.s_addr != dest.s_addr)){
778 destination.value = route->gateway.s_addr ? (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
779 destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
780 if(ERROR_OCCURRED(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data))){
781// sleep(1);
782// ERROR_PROPAGATE(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data));
783 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
784 return ERROR_CODE;
785 }
786 if(!(translation && translation->value)){
787 if(translation){
788 free(translation);
789 free(data);
790 }
791 phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
792 if(phone >= 0){
793 // unreachable ICMP if no routing
794 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
795 }
796 return EINVAL;
797 }
798 }else translation = NULL;
799 if(ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))){
800 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
801 }else{
802 packet = ip_split_packet(packet, netif->packet_dimension.prefix, netif->packet_dimension.content, netif->packet_dimension.suffix, netif->packet_dimension.addr_len, error);
803 if(packet){
804 nil_send_msg(netif->phone, netif->device_id, packet, SERVICE_IP);
805 }
806 }
807 if(translation){
808 free(translation);
809 free(data);
810 }
811 return ERROR_CODE;
812}
813
814int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination){
815 ERROR_DECLARE;
816
817 size_t length;
818 ip_header_ref header;
819 ip_header_ref last_header;
820 ip_header_ref middle_header;
821 packet_t next;
822
823 length = packet_get_data_length(packet);
824 if((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)){
825 return EINVAL;
826 }
827 header = (ip_header_ref) packet_get_data(packet);
828 if(destination){
829 ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
830 }else{
831 ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
832 }
833 header->version = IPV4;
834 header->fragment_offset_high = 0;
835 header->fragment_offset_low = 0;
836 header->header_checksum = 0;
837 if(source){
838 header->source_address = source->s_addr;
839 }
840 header->destination_address = dest.s_addr;
841 fibril_rwlock_write_lock(&ip_globals.lock);
842 ++ ip_globals.packet_counter;
843 header->identification = htons(ip_globals.packet_counter);
844 fibril_rwlock_write_unlock(&ip_globals.lock);
845// length = packet_get_data_length(packet);
846 if(pq_next(packet)){
847 last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
848 if(! last_header){
849 return ENOMEM;
850 }
851 ip_create_last_header(last_header, header);
852 next = pq_next(packet);
853 while(pq_next(next)){
854 middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
855 if(! middle_header){
856 return ENOMEM;
857 }
858 memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
859 header->flags |= IPFLAG_MORE_FRAGMENTS;
860 middle_header->total_length = htons(packet_get_data_length(next));
861 middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
862 middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
863 middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
864 if(destination){
865 ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
866 }
867 length += packet_get_data_length(next);
868 next = pq_next(next);
869 }
870 middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
871 if(! middle_header){
872 return ENOMEM;
873 }
874 memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
875 middle_header->total_length = htons(packet_get_data_length(next));
876 middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
877 middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
878 middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
879 if(destination){
880 ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
881 }
882 length += packet_get_data_length(next);
883 free(last_header);
884 header->flags |= IPFLAG_MORE_FRAGMENTS;
885 }
886 header->total_length = htons(length);
887 // unnecessary for all protocols
888 header->header_checksum = IP_HEADER_CHECKSUM(header);
889 return EOK;
890}
891
892int ip_message_standalone(ipc_callid_t callid, ipc_call_t *call,
893 ipc_call_t *answer, int * answer_count)
894{
895 ERROR_DECLARE;
896
897 packet_t packet;
898 struct sockaddr *addr;
899 size_t addrlen;
900 size_t prefix;
901 size_t suffix;
902 size_t content;
903 void *header;
904 size_t headerlen;
905 device_id_t device_id;
906
907 *answer_count = 0;
908 switch (IPC_GET_METHOD(*call)) {
909 case IPC_M_PHONE_HUNGUP:
910 return EOK;
911 case NET_IL_DEVICE:
912 return ip_device_req_local(0, IPC_GET_DEVICE(call),
913 IPC_GET_SERVICE(call));
914 case IPC_M_CONNECT_TO_ME:
915 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
916 IPC_GET_PHONE(call), NULL);
917 case NET_IL_SEND:
918 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
919 IPC_GET_PACKET(call)));
920 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
921 IPC_GET_ERROR(call));
922 case NET_IL_DEVICE_STATE:
923 return ip_device_state_message(IPC_GET_DEVICE(call),
924 IPC_GET_STATE(call));
925 case NET_IL_RECEIVED:
926 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
927 IPC_GET_PACKET(call)));
928 return ip_receive_message(IPC_GET_DEVICE(call), packet);
929 case NET_IP_RECEIVED_ERROR:
930 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
931 IPC_GET_PACKET(call)));
932 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), packet,
933 IPC_GET_TARGET(call), IPC_GET_ERROR(call));
934 case NET_IP_ADD_ROUTE:
935 return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
936 IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
937 case NET_IP_SET_GATEWAY:
938 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
939 IP_GET_GATEWAY(call));
940 case NET_IP_GET_ROUTE:
941 ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
942 ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
943 addr, (socklen_t) addrlen, &device_id, &header, &headerlen));
944 IPC_SET_DEVICE(answer, device_id);
945 IP_SET_HEADERLEN(answer, headerlen);
946
947 *answer_count = 2;
948
949 if (!ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen))))
950 ERROR_CODE = data_reply(header, headerlen);
951
952 free(header);
953 return ERROR_CODE;
954 case NET_IL_PACKET_SPACE:
955 ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
956 &addrlen, &prefix, &content, &suffix));
957 IPC_SET_ADDR(answer, addrlen);
958 IPC_SET_PREFIX(answer, prefix);
959 IPC_SET_CONTENT(answer, content);
960 IPC_SET_SUFFIX(answer, suffix);
961 *answer_count = 4;
962 return EOK;
963 case NET_IL_MTU_CHANGED:
964 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
965 IPC_GET_MTU(call));
966 }
967
968 return ENOTSUP;
969}
970
971int ip_packet_size_req_local(int ip_phone, device_id_t device_id,
972 packet_dimension_ref packet_dimension)
973{
974 if (!packet_dimension)
975 return EBADMEM;
976
977 return ip_packet_size_message(device_id, &packet_dimension->addr_len,
978 &packet_dimension->prefix, &packet_dimension->content,
979 &packet_dimension->suffix);
980}
981
982int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
983 ip_netif_ref netif;
984 int index;
985
986 if(!(addr_len && prefix && content && suffix)){
987 return EBADMEM;
988 }
989 *content = IP_MAX_CONTENT - IP_PREFIX;
990 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
991 if(device_id < 0){
992 *addr_len = IP_ADDR;
993 *prefix = 0;
994 *suffix = 0;
995 for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
996 netif = ip_netifs_get_index(&ip_globals.netifs, index);
997 if(netif){
998 if(netif->packet_dimension.addr_len > * addr_len){
999 *addr_len = netif->packet_dimension.addr_len;
1000 }
1001 if(netif->packet_dimension.prefix > * prefix){
1002 *prefix = netif->packet_dimension.prefix;
1003 }
1004 if(netif->packet_dimension.suffix > * suffix){
1005 *suffix = netif->packet_dimension.suffix;
1006 }
1007 }
1008 }
1009 *prefix = * prefix + IP_PREFIX;
1010 *suffix = * suffix + IP_SUFFIX;
1011 }else{
1012 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1013 if(! netif){
1014 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1015 return ENOENT;
1016 }
1017 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
1018 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
1019 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
1020 }
1021 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1022 return EOK;
1023}
1024
1025int 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){
1026 ip_route_ref route;
1027 ip_netif_ref netif;
1028 int index;
1029
1030 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1031 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1032 if(! netif){
1033 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1034 return ENOENT;
1035 }
1036 route = (ip_route_ref) malloc(sizeof(ip_route_t));
1037 if(! route){
1038 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1039 return ENOMEM;
1040 }
1041 route->address.s_addr = address.s_addr;
1042 route->netmask.s_addr = netmask.s_addr;
1043 route->gateway.s_addr = gateway.s_addr;
1044 route->netif = netif;
1045 index = ip_routes_add(&netif->routes, route);
1046 if(index < 0){
1047 free(route);
1048 }
1049 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1050 return index;
1051}
1052
1053ip_route_ref ip_find_route(in_addr_t destination){
1054 int index;
1055 ip_route_ref route;
1056 ip_netif_ref netif;
1057
1058 // start with the last netif - the newest one
1059 index = ip_netifs_count(&ip_globals.netifs) - 1;
1060 while(index >= 0){
1061 netif = ip_netifs_get_index(&ip_globals.netifs, index);
1062 if(netif && (netif->state == NETIF_ACTIVE)){
1063 route = ip_netif_find_route(netif, destination);
1064 if(route){
1065 return route;
1066 }
1067 }
1068 -- index;
1069 }
1070 return &ip_globals.gateway;
1071}
1072
1073ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
1074 int index;
1075 ip_route_ref route;
1076
1077 if(netif){
1078 // start with the first one - the direct route
1079 for(index = 0; index < ip_routes_count(&netif->routes); ++ index){
1080 route = ip_routes_get_index(&netif->routes, index);
1081 if(route && ((route->address.s_addr &route->netmask.s_addr) == (destination.s_addr &route->netmask.s_addr))){
1082 return route;
1083 }
1084 }
1085 }
1086 return NULL;
1087}
1088
1089int ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
1090{
1091 ip_netif_ref netif;
1092
1093 fibril_rwlock_write_lock(&ip_globals.netifs_lock);
1094 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1095 if(! netif){
1096 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1097 return ENOENT;
1098 }
1099 ip_globals.gateway.address.s_addr = 0;
1100 ip_globals.gateway.netmask.s_addr = 0;
1101 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
1102 ip_globals.gateway.netif = netif;
1103 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
1104 return EOK;
1105}
1106
1107packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
1108 size_t length;
1109 packet_t next;
1110 packet_t new_packet;
1111 int result;
1112 int phone;
1113
1114 next = packet;
1115 // check all packets
1116 while(next){
1117 length = packet_get_data_length(next);
1118 // too long?
1119 if(length > content){
1120 result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
1121 if(result != EOK){
1122 new_packet = pq_detach(next);
1123 if(next == packet){
1124 // the new first packet of the queue
1125 packet = new_packet;
1126 }
1127 // fragmentation needed?
1128 if(result == EPERM){
1129 phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
1130 if(phone >= 0){
1131 // fragmentation necessary ICMP
1132 icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
1133 }
1134 }else{
1135 pq_release_remote(ip_globals.net_phone, packet_get_id(next));
1136 }
1137 next = new_packet;
1138 continue;
1139 }
1140 }
1141 next = pq_next(next);
1142 }
1143 return packet;
1144}
1145
1146int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
1147 ERROR_DECLARE;
1148
1149 packet_t new_packet;
1150 ip_header_ref header;
1151 ip_header_ref middle_header;
1152 ip_header_ref last_header;
1153 struct sockaddr * src;
1154 struct sockaddr * dest;
1155 socklen_t addrlen;
1156 int result;
1157
1158 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
1159 if(result <= 0){
1160 return EINVAL;
1161 }
1162 addrlen = (socklen_t) result;
1163 if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
1164 return ENOMEM;
1165 }
1166 // get header
1167 header = (ip_header_ref) packet_get_data(packet);
1168 if(! header){
1169 return EINVAL;
1170 }
1171 // fragmentation forbidden?
1172 if(header->flags &IPFLAG_DONT_FRAGMENT){
1173 return EPERM;
1174 }
1175 // create the last fragment
1176 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
1177 if(! new_packet){
1178 return ENOMEM;
1179 }
1180 // allocate as much as originally
1181 last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
1182 if(! last_header){
1183 return ip_release_and_return(packet, ENOMEM);
1184 }
1185 ip_create_last_header(last_header, header);
1186 // trim the unused space
1187 if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
1188 return ip_release_and_return(packet, ERROR_CODE);
1189 }
1190 // biggest multiple of 8 lower than content
1191 // TODO even fragmentation?
1192 length = length &(~ 0x7);// (content / 8) * 8
1193 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))){
1194 return ip_release_and_return(packet, ERROR_CODE);
1195 }
1196 // mark the first as fragmented
1197 header->flags |= IPFLAG_MORE_FRAGMENTS;
1198 // create middle framgents
1199 while(IP_TOTAL_LENGTH(header) > length){
1200 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
1201 if(! new_packet){
1202 return ENOMEM;
1203 }
1204 middle_header = ip_create_middle_header(new_packet, last_header);
1205 if(! middle_header){
1206 return ip_release_and_return(packet, ENOMEM);
1207 }
1208 if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
1209 return ip_release_and_return(packet, ERROR_CODE);
1210 }
1211 }
1212 // finish the first fragment
1213 header->header_checksum = IP_HEADER_CHECKSUM(header);
1214 return EOK;
1215}
1216
1217int 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){
1218 ERROR_DECLARE;
1219
1220 void * data;
1221 size_t offset;
1222
1223 data = packet_suffix(new_packet, length);
1224 if(! data){
1225 return ENOMEM;
1226 }
1227 memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
1228 ERROR_PROPAGATE(packet_trim(packet, 0, length));
1229 header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
1230 new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
1231 offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
1232 new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
1233 new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
1234 new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
1235 ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
1236 return pq_insert_after(packet, new_packet);
1237}
1238
1239ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
1240 ip_header_ref middle;
1241
1242 middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
1243 if(! middle){
1244 return NULL;
1245 }
1246 memcpy(middle, last, IP_HEADER_LENGTH(last));
1247 middle->flags |= IPFLAG_MORE_FRAGMENTS;
1248 return middle;
1249}
1250
1251void ip_create_last_header(ip_header_ref last, ip_header_ref first){
1252 ip_option_ref option;
1253 size_t next;
1254 size_t length;
1255
1256 // copy first itself
1257 memcpy(last, first, sizeof(ip_header_t));
1258 length = sizeof(ip_header_t);
1259 next = sizeof(ip_header_t);
1260 // process all ip options
1261 while(next < first->header_length){
1262 option = (ip_option_ref) (((uint8_t *) first) + next);
1263 // skip end or noop
1264 if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
1265 ++ next;
1266 }else{
1267 // copy if said so or skip
1268 if(IPOPT_COPIED(option->type)){
1269 memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
1270 length += option->length;
1271 }
1272 // next option
1273 next += option->length;
1274 }
1275 }
1276 // align 4 byte boundary
1277 if(length % 4){
1278 bzero(((uint8_t *) last) + length, 4 - (length % 4));
1279 last->header_length = length / 4 + 1;
1280 }else{
1281 last->header_length = length / 4;
1282 }
1283 last->header_checksum = 0;
1284}
1285
1286int ip_receive_message(device_id_t device_id, packet_t packet){
1287 packet_t next;
1288
1289 do{
1290 next = pq_detach(packet);
1291 ip_process_packet(device_id, packet);
1292 packet = next;
1293 }while(packet);
1294 return EOK;
1295}
1296
1297int ip_process_packet(device_id_t device_id, packet_t packet){
1298 ERROR_DECLARE;
1299
1300 ip_header_ref header;
1301 in_addr_t dest;
1302 ip_route_ref route;
1303 int phone;
1304 struct sockaddr * addr;
1305 struct sockaddr_in addr_in;
1306// struct sockaddr_in addr_in6;
1307 socklen_t addrlen;
1308
1309 header = (ip_header_ref) packet_get_data(packet);
1310 if(! header){
1311 return ip_release_and_return(packet, ENOMEM);
1312 }
1313 // checksum
1314 if((header->header_checksum) && (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)){
1315 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1316 if(phone >= 0){
1317 // checksum error ICMP
1318 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->header_checksum)) - ((size_t) ((void *) header)), packet);
1319 }
1320 return EINVAL;
1321 }
1322 if(header->ttl <= 1){
1323 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1324 if(phone >= 0){
1325 // ttl oxceeded ICMP
1326 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
1327 }
1328 return EINVAL;
1329 }
1330 // process ipopt and get destination
1331 dest = ip_get_destination(header);
1332 // set the addrination address
1333 switch(header->version){
1334 case IPVERSION:
1335 addrlen = sizeof(addr_in);
1336 bzero(&addr_in, addrlen);
1337 addr_in.sin_family = AF_INET;
1338 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
1339 addr = (struct sockaddr *) &addr_in;
1340 break;
1341/* case IPv6VERSION:
1342 addrlen = sizeof(dest_in6);
1343 bzero(&dest_in6, addrlen);
1344 dest_in6.sin6_family = AF_INET6;
1345 memcpy(&dest_in6.sin6_addr.s6_addr,);
1346 dest = (struct sockaddr *) &dest_in;
1347 break;
1348*/ default:
1349 return ip_release_and_return(packet, EAFNOSUPPORT);
1350 }
1351 ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
1352 route = ip_find_route(dest);
1353 if(! route){
1354 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1355 if(phone >= 0){
1356 // unreachable ICMP
1357 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
1358 }
1359 return ENOENT;
1360 }
1361 if(route->address.s_addr == dest.s_addr){
1362 // local delivery
1363 return ip_deliver_local(device_id, packet, header, 0);
1364 }else{
1365 // only if routing enabled
1366 if(route->netif->routing){
1367 -- header->ttl;
1368 return ip_send_route(packet, route->netif, route, NULL, dest, 0);
1369 }else{
1370 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
1371 if(phone >= 0){
1372 // unreachable ICMP if no routing
1373 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
1374 }
1375 return ENOENT;
1376 }
1377 }
1378}
1379
1380/** Notify the IP module about the received error notification packet.
1381 *
1382 * @param[in] ip_phone The IP module phone used for (semi)remote calls.
1383 * @param[in] device_id The device identifier.
1384 * @param[in] packet The received packet or the received packet queue.
1385 * @param[in] target The target internetwork module service to be
1386 * delivered to.
1387 * @param[in] error The packet error reporting service. Prefixes the
1388 * received packet.
1389 *
1390 * @return EOK on success.
1391 *
1392 */
1393int ip_received_error_msg_local(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
1394 uint8_t * data;
1395 int offset;
1396 icmp_type_t type;
1397 icmp_code_t code;
1398 ip_netif_ref netif;
1399 measured_string_t address;
1400 ip_route_ref route;
1401 ip_header_ref header;
1402
1403 switch(error){
1404 case SERVICE_ICMP:
1405 offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
1406 if(offset < 0){
1407 return ip_release_and_return(packet, ENOMEM);
1408 }
1409 data = packet_get_data(packet);
1410 header = (ip_header_ref)(data + offset);
1411 // destination host unreachable?
1412 if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
1413 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
1414 netif = ip_netifs_find(&ip_globals.netifs, device_id);
1415 if(netif && netif->arp){
1416 route = ip_routes_get_index(&netif->routes, 0);
1417 // from the same network?
1418 if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
1419 // clear the ARP mapping if any
1420 address.value = (char *) &header->destination_address;
1421 address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
1422 arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
1423 }
1424 }
1425 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
1426 }
1427 break;
1428 default:
1429 return ip_release_and_return(packet, ENOTSUP);
1430 }
1431 return ip_deliver_local(device_id, packet, header, error);
1432}
1433
1434int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
1435 ERROR_DECLARE;
1436
1437 ip_proto_ref proto;
1438 int phone;
1439 services_t service;
1440 tl_received_msg_t received_msg;
1441 struct sockaddr * src;
1442 struct sockaddr * dest;
1443 struct sockaddr_in src_in;
1444 struct sockaddr_in dest_in;
1445// struct sockaddr_in src_in6;
1446// struct sockaddr_in dest_in6;
1447 socklen_t addrlen;
1448
1449 if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
1450 // TODO fragmented
1451 return ENOTSUP;
1452 }else{
1453 switch(header->version){
1454 case IPVERSION:
1455 addrlen = sizeof(src_in);
1456 bzero(&src_in, addrlen);
1457 src_in.sin_family = AF_INET;
1458 memcpy(&dest_in, &src_in, addrlen);
1459 memcpy(&src_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
1460 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, sizeof(header->destination_address));
1461 src = (struct sockaddr *) &src_in;
1462 dest = (struct sockaddr *) &dest_in;
1463 break;
1464/* case IPv6VERSION:
1465 addrlen = sizeof(src_in6);
1466 bzero(&src_in6, addrlen);
1467 src_in6.sin6_family = AF_INET6;
1468 memcpy(&dest_in6, &src_in6, addrlen);
1469 memcpy(&src_in6.sin6_addr.s6_addr,);
1470 memcpy(&dest_in6.sin6_addr.s6_addr,);
1471 src = (struct sockaddr *) &src_in;
1472 dest = (struct sockaddr *) &dest_in;
1473 break;
1474*/ default:
1475 return ip_release_and_return(packet, EAFNOSUPPORT);
1476 }
1477 if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
1478 return ip_release_and_return(packet, ERROR_CODE);
1479 }
1480 // trim padding if present
1481 if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
1482 if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
1483 return ip_release_and_return(packet, ERROR_CODE);
1484 }
1485 }
1486 fibril_rwlock_read_lock(&ip_globals.protos_lock);
1487 proto = ip_protos_find(&ip_globals.protos, header->protocol);
1488 if(! proto){
1489 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1490 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
1491 if(phone >= 0){
1492 // unreachable ICMP
1493 icmp_destination_unreachable_msg(phone, ICMP_PROT_UNREACH, 0, packet);
1494 }
1495 return ENOENT;
1496 }
1497 if(proto->received_msg){
1498 service = proto->service;
1499 received_msg = proto->received_msg;
1500 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1501 ERROR_CODE = received_msg(device_id, packet, service, error);
1502 }else{
1503 ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
1504 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1505 }
1506 return ERROR_CODE;
1507 }
1508}
1509
1510in_addr_t ip_get_destination(ip_header_ref header){
1511 in_addr_t destination;
1512
1513 // TODO search set ipopt route?
1514 destination.s_addr = header->destination_address;
1515 return destination;
1516}
1517
1518int ip_prepare_icmp(packet_t packet, ip_header_ref header){
1519 packet_t next;
1520 struct sockaddr * dest;
1521 struct sockaddr_in dest_in;
1522// struct sockaddr_in dest_in6;
1523 socklen_t addrlen;
1524
1525 // detach the first packet and release the others
1526 next = pq_detach(packet);
1527 if(next){
1528 pq_release_remote(ip_globals.net_phone, packet_get_id(next));
1529 }
1530 if(! header){
1531 if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
1532 return ENOMEM;
1533 }
1534 // get header
1535 header = (ip_header_ref) packet_get_data(packet);
1536 if(! header){
1537 return EINVAL;
1538 }
1539 }
1540 // only for the first fragment
1541 if(IP_FRAGMENT_OFFSET(header)){
1542 return EINVAL;
1543 }
1544 // not for the ICMP protocol
1545 if(header->protocol == IPPROTO_ICMP){
1546 return EPERM;
1547 }
1548 // set the destination address
1549 switch(header->version){
1550 case IPVERSION:
1551 addrlen = sizeof(dest_in);
1552 bzero(&dest_in, addrlen);
1553 dest_in.sin_family = AF_INET;
1554 memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
1555 dest = (struct sockaddr *) &dest_in;
1556 break;
1557/* case IPv6VERSION:
1558 addrlen = sizeof(dest_in6);
1559 bzero(&dest_in6, addrlen);
1560 dest_in6.sin6_family = AF_INET6;
1561 memcpy(&dest_in6.sin6_addr.s6_addr,);
1562 dest = (struct sockaddr *) &dest_in;
1563 break;
1564*/ default:
1565 return EAFNOSUPPORT;
1566 }
1567 return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
1568}
1569
1570int ip_get_icmp_phone(void){
1571 ip_proto_ref proto;
1572 int phone;
1573
1574 fibril_rwlock_read_lock(&ip_globals.protos_lock);
1575 proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
1576 phone = proto ? proto->phone : ENOENT;
1577 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
1578 return phone;
1579}
1580
1581int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
1582 int phone;
1583
1584 phone = ip_get_icmp_phone();
1585 if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
1586 return ip_release_and_return(packet, EINVAL);
1587 }
1588 return phone;
1589}
1590
1591int ip_release_and_return(packet_t packet, int result){
1592 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
1593 return result;
1594}
1595
1596int 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){
1597 struct sockaddr_in * address_in;
1598// struct sockaddr_in6 * address_in6;
1599 in_addr_t * dest;
1600 in_addr_t * src;
1601 ip_route_ref route;
1602 ipv4_pseudo_header_ref header_in;
1603
1604 if(!(destination && (addrlen > 0))){
1605 return EINVAL;
1606 }
1607 if(!(device_id && header && headerlen)){
1608 return EBADMEM;
1609 }
1610 if((size_t) addrlen < sizeof(struct sockaddr)){
1611 return EINVAL;
1612 }
1613 switch(destination->sa_family){
1614 case AF_INET:
1615 if(addrlen != sizeof(struct sockaddr_in)){
1616 return EINVAL;
1617 }
1618 address_in = (struct sockaddr_in *) destination;
1619 dest = &address_in->sin_addr;
1620 if(! dest->s_addr){
1621 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1622 }
1623 break;
1624 // TODO IPv6
1625/* case AF_INET6:
1626 if(addrlen != sizeof(struct sockaddr_in6)){
1627 return EINVAL;
1628 }
1629 address_in6 = (struct sockaddr_in6 *) dest;
1630 address_in6.sin6_addr.s6_addr;
1631*/ default:
1632 return EAFNOSUPPORT;
1633 }
1634 fibril_rwlock_read_lock(&ip_globals.lock);
1635 route = ip_find_route(*dest);
1636 // if the local host is the destination
1637 if(route && (route->address.s_addr == dest->s_addr)
1638 && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
1639 // find the loopback device to deliver
1640 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
1641 route = ip_find_route(*dest);
1642 }
1643 if(!(route && route->netif)){
1644 fibril_rwlock_read_unlock(&ip_globals.lock);
1645 return ENOENT;
1646 }
1647 *device_id = route->netif->device_id;
1648 src = ip_netif_address(route->netif);
1649 fibril_rwlock_read_unlock(&ip_globals.lock);
1650 *headerlen = sizeof(*header_in);
1651 header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
1652 if(! header_in){
1653 return ENOMEM;
1654 }
1655 bzero(header_in, * headerlen);
1656 header_in->destination_address = dest->s_addr;
1657 header_in->source_address = src->s_addr;
1658 header_in->protocol = protocol;
1659 header_in->data_length = 0;
1660 *header = header_in;
1661 return EOK;
1662}
1663
1664/** Default thread for new connections.
1665 *
1666 * @param[in] iid The initial message identifier.
1667 * @param[in] icall The initial message call structure.
1668 *
1669 */
1670static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
1671{
1672 /*
1673 * Accept the connection
1674 * - Answer the first IPC_M_CONNECT_ME_TO call.
1675 */
1676 ipc_answer_0(iid, EOK);
1677
1678 while(true) {
1679 ipc_call_t answer;
1680 int answer_count;
1681
1682 /* Clear the answer structure */
1683 refresh_answer(&answer, &answer_count);
1684
1685 /* Fetch the next message */
1686 ipc_call_t call;
1687 ipc_callid_t callid = async_get_call(&call);
1688
1689 /* Process the message */
1690 int res = il_module_message_standalone(callid, &call, &answer,
1691 &answer_count);
1692
1693 /* End if said to either by the message or the processing result */
1694 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
1695 return;
1696
1697 /* Answer the message */
1698 answer_call(callid, res, &answer, answer_count);
1699 }
1700}
1701
1702/** Starts the module.
1703 *
1704 * @param argc The count of the command line arguments. Ignored parameter.
1705 * @param argv The command line parameters. Ignored parameter.
1706 *
1707 * @returns EOK on success.
1708 * @returns Other error codes as defined for each specific module start function.
1709 *
1710 */
1711int main(int argc, char *argv[])
1712{
1713 ERROR_DECLARE;
1714
1715 /* Start the module */
1716 if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
1717 return ERROR_CODE;
1718
1719 return EOK;
1720}
1721
1722/** @}
1723 */
Note: See TracBrowser for help on using the repository browser.