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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 24ab58b3 was 24ab58b3, checked in by Martin Decky <martin@…>, 15 years ago

more compact network startup messages (usually one line instead of multiple lines)
pass module name as an argument to nil_message() and friends
deeper cstyle changes (replace forward prototypes with proper extern declarations and static functions, change doxygen comments, stick more closely to the 80-column rule, no argument names in header files, spacing, comments, etc.)

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