Subversion Repositories HelenOS

Rev

Rev 4720 | Rev 4724 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3466 mejdrech 1
/*
3912 mejdrech 2
 * Copyright (c) 2009 Lukas Mejdrech
3466 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
 
3912 mejdrech 29
/** @addtogroup ip
30
 *  @{
3466 mejdrech 31
 */
32
 
33
/** @file
4702 mejdrech 34
 *  IP module implementation.
35
 *  @see arp.h
36
 *  \todo
3466 mejdrech 37
 */
3666 mejdrech 38
 
3466 mejdrech 39
#include <async.h>
40
#include <errno.h>
4582 mejdrech 41
#include <fibril_sync.h>
3466 mejdrech 42
#include <stdio.h>
4327 mejdrech 43
#include <string.h>
3846 mejdrech 44
 
3466 mejdrech 45
#include <ipc/ipc.h>
46
#include <ipc/services.h>
47
 
4505 mejdrech 48
#include <sys/types.h>
49
 
3886 mejdrech 50
#include "../../err.h"
51
#include "../../messages.h"
52
#include "../../modules.h"
3466 mejdrech 53
 
4720 mejdrech 54
#include "../../include/arp_interface.h"
4505 mejdrech 55
#include "../../include/byteorder.h"
56
#include "../../include/crc.h"
4243 mejdrech 57
#include "../../include/device.h"
4720 mejdrech 58
#include "../../include/icmp_client.h"
59
#include "../../include/icmp_codes.h"
60
#include "../../include/icmp_interface.h"
4307 mejdrech 61
#include "../../include/il_interface.h"
4720 mejdrech 62
#include "../../include/in.h"
63
#include "../../include/in6.h"
64
#include "../../include/inet.h"
4505 mejdrech 65
#include "../../include/ip_client.h"
4307 mejdrech 66
#include "../../include/ip_interface.h"
4720 mejdrech 67
#include "../../include/net_interface.h"
68
#include "../../include/nil_interface.h"
4505 mejdrech 69
#include "../../include/tl_interface.h"
4720 mejdrech 70
#include "../../include/socket_codes.h"
71
#include "../../include/socket_errno.h"
3886 mejdrech 72
#include "../../structures/measured_strings.h"
4192 mejdrech 73
#include "../../structures/module_map.h"
3901 mejdrech 74
#include "../../structures/packet/packet_client.h"
3846 mejdrech 75
 
4307 mejdrech 76
#include "../../nil/nil_messages.h"
77
 
78
#include "../il_messages.h"
79
 
3466 mejdrech 80
#include "ip.h"
4505 mejdrech 81
#include "ip_header.h"
82
#include "ip_messages.h"
3846 mejdrech 83
#include "ip_module.h"
3466 mejdrech 84
 
4722 mejdrech 85
/** IP version 4.
4702 mejdrech 86
 */
4722 mejdrech 87
#define IPV4				4
4702 mejdrech 88
 
4722 mejdrech 89
/** Default network interface IP version.
90
 */
91
#define NET_DEFAULT_IPV		IPV4
92
 
93
/** Default network interface IP routing.
94
 */
95
#define NET_DEFAULT_IP_ROUTING	false
96
 
4702 mejdrech 97
/** Minimum IP packet content.
98
 */
4505 mejdrech 99
#define IP_MIN_CONTENT	576
3685 mejdrech 100
 
4702 mejdrech 101
/** ARP module name.
102
 */
4192 mejdrech 103
#define ARP_NAME				"arp"
4702 mejdrech 104
 
105
/** ARP module filename.
106
 */
4192 mejdrech 107
#define ARP_FILENAME			"/srv/arp"
108
 
4702 mejdrech 109
/** IP packet address length.
110
 */
4720 mejdrech 111
#define IP_ADDR							sizeof( struct sockaddr_in6 )
4702 mejdrech 112
 
113
/** IP packet prefix length.
114
 */
4505 mejdrech 115
#define IP_PREFIX						sizeof( ip_header_t )
4702 mejdrech 116
 
117
/** IP packet suffix length.
118
 */
4505 mejdrech 119
#define IP_SUFFIX						0
4702 mejdrech 120
 
121
/** IP packet maximum content length.
122
 */
4505 mejdrech 123
#define IP_MAX_CONTENT					65535
4702 mejdrech 124
 
125
/** Returns the actual IP header length.
126
 *  @param header The IP packet header. Input parameter.
127
 */
4558 mejdrech 128
#define IP_HEADER_LENGTH( header )		(( header )->ihl * 4u )
4702 mejdrech 129
 
130
/** Returns the actual IP packet total length.
131
 *  @param header The IP packet header. Input parameter.
132
 */
4505 mejdrech 133
#define IP_TOTAL_LENGTH( header )		ntohs(( header )->total_length )
4702 mejdrech 134
 
135
/** Returns the actual IP packet data length.
136
 *  @param header The IP packet header. Input parameter.
137
 */
4505 mejdrech 138
#define IP_HEADER_DATA_LENGTH( header )	( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header ))
4702 mejdrech 139
 
140
/** Returns the IP packet header checksum.
141
 *  @param header The IP packet header. Input parameter.
142
 */
4505 mejdrech 143
#define IP_HEADER_CHECKSUM( header )	( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
144
 
4722 mejdrech 145
/** Returns the fragment offest.
146
 *  @param length The prefixed data total length. Input parameter.
147
 */
148
#define IP_FRAGMENT_OFFSET( length ) (( length ) / 8 )
149
 
4702 mejdrech 150
/** IP global data.
151
 */
3666 mejdrech 152
ip_globals_t	ip_globals;
3466 mejdrech 153
 
3666 mejdrech 154
DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
155
 
3846 mejdrech 156
INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
3685 mejdrech 157
 
4505 mejdrech 158
GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
159
 
4702 mejdrech 160
/** Updates the device content length according to the new MTU value.
161
 *  @param device_id The device identifier. Input parameter.
162
 *  @param mtu The new mtu value. Input parameter.
163
 *  @returns EOK on success.
164
 *  @returns ENOENT if device is not found.
165
 */
166
int	ip_mtu_changed_message( device_id_t device_id, size_t mtu );
167
 
168
/** Updates the device state.
169
 *  @param device_id The device identifier. Input parameter.
170
 *  @param state The new state value. Input parameter.
171
 *  @returns EOK on success.
172
 *  @returns ENOENT if device is not found.
173
 */
174
int	ip_device_state_message( device_id_t device_id, device_state_t state );
175
 
4505 mejdrech 176
int	ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
4702 mejdrech 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 ip_netif Network interface specific data. Input/output parameter.
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
 */
4505 mejdrech 193
int	ip_netif_initialize( ip_netif_ref ip_netif );
3846 mejdrech 194
 
4707 mejdrech 195
int	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 );
4575 mejdrech 196
int	ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
4505 mejdrech 197
 
4720 mejdrech 198
packet_t	ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error );
199
int	ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len );
200
int	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 );
4505 mejdrech 201
ip_header_ref	ip_create_middle_header( packet_t packet, ip_header_ref last );
4589 mejdrech 202
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
4505 mejdrech 203
 
4707 mejdrech 204
in_addr_t *	ip_netif_address( ip_netif_ref netif );
4505 mejdrech 205
ip_route_ref	ip_find_route( in_addr_t destination );
206
ip_route_ref	ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
207
 
4702 mejdrech 208
/** Processes the received IP packet.
209
 *  @param device_id The source device identifier. Input parameter.
210
 *  @param packet The received packet. Input/output parameter.
211
 *  @returns EOK on success and the packet is no longer needed.
212
 *  @returns EINVAL if the packet is too small to carry the IP packet.
213
 *  @returns EINVAL if the received address lengths differs from the registered values.
214
 *  @returns ENOENT if the device is not found in the cache.
215
 *  @returns ENOENT if the protocol for the device is not found in the cache.
216
 *  @returns ENOMEM if there is not enough memory left.
217
 */
218
int	ip_receive_message( device_id_t device_id, packet_t packet );
219
 
4505 mejdrech 220
int	ip_process_packet( device_id_t device_id, packet_t packet );
221
in_addr_t	ip_get_destination( ip_header_ref header );
4707 mejdrech 222
int	ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
4505 mejdrech 223
 
4707 mejdrech 224
int	ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
225
int	ip_get_icmp_phone( void );
226
int	ip_prepare_icmp( packet_t packet, ip_header_ref header );
227
 
4711 mejdrech 228
int	ip_release_and_return( packet_t packet, int result );
4707 mejdrech 229
 
4351 mejdrech 230
int ip_initialize( async_client_conn_t client_connection ){
4192 mejdrech 231
	ERROR_DECLARE;
232
 
4582 mejdrech 233
	fibril_rwlock_initialize( & ip_globals.lock );
234
	fibril_rwlock_write_lock( & ip_globals.lock );
235
	fibril_rwlock_initialize( & ip_globals.protos_lock );
236
	fibril_rwlock_initialize( & ip_globals.netifs_lock );
4505 mejdrech 237
	ip_globals.packet_counter = 0;
238
	ip_globals.gateway.address.s_addr = 0;
239
	ip_globals.gateway.netmask.s_addr = 0;
240
	ip_globals.gateway.gateway.s_addr = 0;
241
	ip_globals.gateway.netif = NULL;
4192 mejdrech 242
	ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
243
	ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
4351 mejdrech 244
	ip_globals.client_connection = client_connection;
4192 mejdrech 245
	ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
4307 mejdrech 246
	ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
4582 mejdrech 247
	fibril_rwlock_write_unlock( & ip_globals.lock );
3466 mejdrech 248
	return EOK;
249
}
250
 
4350 mejdrech 251
int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
3666 mejdrech 252
	ERROR_DECLARE;
253
 
4505 mejdrech 254
	ip_netif_ref	ip_netif;
255
	ip_route_ref	route;
256
	int				index;
257
	char *			data;
258
 
259
	ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
260
	if( ! ip_netif ) return ENOMEM;
261
	if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
262
		free( ip_netif );
263
		return ERROR_CODE;
264
	}
265
	ip_netif->device_id = device_id;
266
	ip_netif->service = netif;
267
	ip_netif->state = NETIF_STOPPED;
4582 mejdrech 268
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 269
	if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
4582 mejdrech 270
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 271
		ip_routes_destroy( & ip_netif->routes );
272
		free( ip_netif );
273
		return ERROR_CODE;
274
	}
275
	if( ip_netif->arp ) ++ ip_netif->arp->usage;
276
	// print the settings
277
	printf( "New device registered:\n\tid\t= %d\n\tphone\t= %d\n\tIPV\t= %d\n", ip_netif->device_id, ip_netif->phone, ip_netif->ipv );
278
	printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
279
	// TODO ipv6 addresses
280
	data = ( char * ) malloc( INET_ADDRSTRLEN );
281
	if( data ){
282
		for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
283
			route = ip_routes_get_index( & ip_netif->routes, index );
284
			if( route ){
285
				printf( "\tRouting %d:\n", index );
286
				inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
287
				printf( "\t\taddress\t= %s\n", data );
288
				inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
289
				printf( "\t\tnetmask\t= %s\n", data );
290
				inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
291
				printf( "\t\tgateway\t= %s\n", data );
292
			}
293
		}
294
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
295
		printf( "\tbroadcast\t= %s\n", data );
296
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
297
		printf( "\tdns1\t= %s\n", data );
298
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
299
		printf( "\tdns2\t= %s\n", data );
300
		free( data );
301
	}
4582 mejdrech 302
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 303
	return EOK;
304
}
305
 
306
int ip_netif_initialize( ip_netif_ref ip_netif ){
307
	ERROR_DECLARE;
308
 
4695 mejdrech 309
	measured_string_t	names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
4307 mejdrech 310
	measured_string_ref	configuration;
4505 mejdrech 311
	size_t				count = sizeof( names ) / sizeof( measured_string_t );
4307 mejdrech 312
	char *				data;
4717 mejdrech 313
	measured_string_t	address;
4307 mejdrech 314
	int					index;
4505 mejdrech 315
	ip_route_ref		route;
316
	in_addr_t			gateway;
3666 mejdrech 317
 
4702 mejdrech 318
	ip_netif->arp = NULL;
4506 mejdrech 319
	route = NULL;
4722 mejdrech 320
	ip_netif->ipv = NET_DEFAULT_IPV;
321
	ip_netif->dhcp = false;
322
	ip_netif->routing = NET_DEFAULT_IP_ROUTING;
4307 mejdrech 323
	configuration = & names[ 0 ];
3846 mejdrech 324
	// get configuration
4307 mejdrech 325
	ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
326
	if( configuration ){
327
		if( configuration[ 0 ].value ){
328
			ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
3846 mejdrech 329
		}
4332 mejdrech 330
		ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
3846 mejdrech 331
		if( ip_netif->dhcp ){
332
			// TODO dhcp
4307 mejdrech 333
			net_free_settings( configuration, data );
3846 mejdrech 334
			return ENOTSUP;
4722 mejdrech 335
		}else if( ip_netif->ipv == IPV4 ){
4505 mejdrech 336
			route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
337
			if( ! route ){
338
				net_free_settings( configuration, data );
339
				return ENOMEM;
340
			}
341
			route->address.s_addr = 0;
342
			route->netmask.s_addr = 0;
343
			route->gateway.s_addr = 0;
344
			route->netif = ip_netif;
345
			index = ip_routes_add( & ip_netif->routes, route );
346
			if( index < 0 ){
347
				net_free_settings( configuration, data );
348
				free( route );
349
				return index;
350
			}
351
			if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
352
			|| ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
353
			|| ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
354
			|| ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
4307 mejdrech 355
			|| ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
356
			|| ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
357
				net_free_settings( configuration, data );
3846 mejdrech 358
				return EINVAL;
359
			}
360
		}else{
4505 mejdrech 361
			// TODO ipv6 in separate module
4307 mejdrech 362
			net_free_settings( configuration, data );
3846 mejdrech 363
			return ENOTSUP;
364
		}
4307 mejdrech 365
		if( configuration[ 8 ].value ){
366
			ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
4192 mejdrech 367
			if( ! ip_netif->arp ){
4307 mejdrech 368
				printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
369
				net_free_settings( configuration, data );
4192 mejdrech 370
				return EINVAL;
371
			}
372
		}
4722 mejdrech 373
		if( configuration[ 9 ].value ){
374
			ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' );
375
		}
4307 mejdrech 376
		net_free_settings( configuration, data );
3846 mejdrech 377
	}
4717 mejdrech 378
	// binds the netif service which also initializes the device
4558 mejdrech 379
	ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
4192 mejdrech 380
	if( ip_netif->phone < 0 ){
4505 mejdrech 381
		printf( "Failed to contact the nil service %d\n", ip_netif->service );
4192 mejdrech 382
		return ip_netif->phone;
383
	}
4717 mejdrech 384
	// has to be after the device netif module initialization
4192 mejdrech 385
	if( ip_netif->arp ){
4506 mejdrech 386
		if( route ){
4717 mejdrech 387
			address.value = ( char * ) & route->address.s_addr;
388
			address.length = CONVERT_SIZE( in_addr_t, char, 1 );
389
			ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address ));
4506 mejdrech 390
		}else{
391
			ip_netif->arp = 0;
392
		}
4192 mejdrech 393
	}
4505 mejdrech 394
	// get packet dimensions
395
	ERROR_PROPAGATE( nil_packet_size_req( ip_netif->phone, ip_netif->device_id, & ip_netif->addr_len, & ip_netif->prefix, & ip_netif->content, & ip_netif->suffix ));
396
	if( ip_netif->content < IP_MIN_CONTENT ){
397
		printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
398
		ip_netif->content = IP_MIN_CONTENT;
399
	}
4192 mejdrech 400
	index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
4505 mejdrech 401
	if( index < 0 ) return index;
402
	if( gateway.s_addr ){
403
		// the default gateway
404
		ip_globals.gateway.address.s_addr = 0;
405
		ip_globals.gateway.netmask.s_addr = 0;
406
		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
407
		ip_globals.gateway.netif = ip_netif;
4192 mejdrech 408
	}
3846 mejdrech 409
	return EOK;
410
}
411
 
4702 mejdrech 412
int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
4695 mejdrech 413
	ip_netif_ref	netif;
414
 
415
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
416
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
417
	if( ! netif ){
418
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
419
		return ENOENT;
420
	}
421
	netif->content = mtu;
422
	printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
423
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
424
	return EOK;
425
}
426
 
4702 mejdrech 427
int ip_device_state_message( device_id_t device_id, device_state_t state ){
4506 mejdrech 428
//	ERROR_DECLARE;
4243 mejdrech 429
 
4505 mejdrech 430
/*	measured_string_t	address;
431
	measured_string_ref	translation;
432
	char *				data;
433
*/
4506 mejdrech 434
/*	packet_t		packet;
4505 mejdrech 435
	in_addr_t		destination;
4506 mejdrech 436
*/
4243 mejdrech 437
	ip_netif_ref	netif;
438
 
4582 mejdrech 439
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4243 mejdrech 440
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 441
	if( ! netif ){
4582 mejdrech 442
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 443
		return ENOENT;
444
	}
4505 mejdrech 445
	netif->state = state;
3846 mejdrech 446
	// TODO state
4307 mejdrech 447
	printf( "ip - device %d changed state to %d\n\n", device_id, state );
4582 mejdrech 448
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4506 mejdrech 449
//	if( netif->arp ){
4505 mejdrech 450
/*		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
451
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
4327 mejdrech 452
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4505 mejdrech 453
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
454
		}
455
		printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
456
		free( translation );
457
		free( data );
458
		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
459
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
460
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4327 mejdrech 461
			sleep( 2 );
462
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
463
		}
4307 mejdrech 464
		printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
4243 mejdrech 465
		free( translation );
466
		free( data );
4506 mejdrech 467
*//*		printf( "IP - testing to send packet:\n" );
4505 mejdrech 468
		ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
469
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
470
		if( ! packet ) return ENOMEM;
471
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
472
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
473
		if( ! packet ) return ENOMEM;
474
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
475
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
476
		if( ! packet ) return ENOMEM;
477
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
478
		packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
479
		if( ! packet ) return ENOMEM;
480
		// try this long version
481
//		if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30", 1330 ))
482
		if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
483
		|| ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
484
		|| ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
485
			pq_release( ip_globals.net_phone, packet_get_id( packet ));
486
		}
487
		ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
488
		printf( "send returned %d\n", ERROR_CODE );
4243 mejdrech 489
	}
4506 mejdrech 490
*/	return EOK;
4307 mejdrech 491
}
492
 
493
int ip_connect_module( services_t service ){
494
	return EOK;
495
}
496
 
4558 mejdrech 497
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
498
	return ip_register( protocol, me, 0, received_msg );
4505 mejdrech 499
}
500
 
4558 mejdrech 501
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
3846 mejdrech 502
	ip_proto_ref	proto;
4192 mejdrech 503
	int				index;
3846 mejdrech 504
 
4558 mejdrech 505
	if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
3846 mejdrech 506
	proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
507
	if( ! proto ) return ENOMEM;
508
	proto->protocol = protocol;
4505 mejdrech 509
	proto->service = service;
3846 mejdrech 510
	proto->phone = phone;
4558 mejdrech 511
	proto->received_msg = received_msg;
4582 mejdrech 512
	fibril_rwlock_write_lock( & ip_globals.protos_lock );
4192 mejdrech 513
	index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
514
	if( index < 0 ){
4582 mejdrech 515
		fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 516
		free( proto );
4192 mejdrech 517
		return index;
3846 mejdrech 518
	}
4307 mejdrech 519
	printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
4582 mejdrech 520
	fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 521
	return EOK;
522
}
523
 
4707 mejdrech 524
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
4505 mejdrech 525
	ERROR_DECLARE;
526
 
4720 mejdrech 527
	int					addrlen;
4505 mejdrech 528
	ip_netif_ref		netif;
529
	ip_route_ref		route;
4720 mejdrech 530
	struct sockaddr *		addr;
531
	struct sockaddr_in *	address_in;
532
//	struct sockaddr_in6 *	address_in6;
4575 mejdrech 533
	in_addr_t *			dest;
4505 mejdrech 534
	in_addr_t *			src;
4707 mejdrech 535
	int					phone;
4505 mejdrech 536
 
537
	// addresses in the host byte order
538
	// should be the next hop address or the target destination address
4720 mejdrech 539
	addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr );
540
	if( addrlen < 0 ){
541
		return ip_release_and_return( packet, addrlen );
4505 mejdrech 542
	}
4720 mejdrech 543
	if( addrlen < sizeof( struct sockaddr )){
4711 mejdrech 544
		return ip_release_and_return( packet, EINVAL );
4505 mejdrech 545
	}
4720 mejdrech 546
	switch( addr->sa_family ){
547
		case AF_INET:
548
			if( addrlen != sizeof( struct sockaddr_in )){
549
				return ip_release_and_return( packet, EINVAL );
550
			}
551
			address_in = ( struct sockaddr_in * ) addr;
552
			dest = & address_in->sin_addr;
553
			break;
554
		// TODO IPv6
555
/*		case AF_INET6:
556
			if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
557
			address_in6 = ( struct sockaddr_in6 * ) dest;
558
			address_in6.sin6_addr.s6_addr;
559
*/		default:
560
			return ip_release_and_return( packet, EAFNOSUPPORT );
561
	}
4582 mejdrech 562
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4505 mejdrech 563
	// device specified?
4575 mejdrech 564
	if( device_id > 0 ){
4505 mejdrech 565
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
4575 mejdrech 566
		route = ip_netif_find_route( netif, * dest );
4505 mejdrech 567
	}else{
4575 mejdrech 568
		route = ip_find_route( * dest );
4505 mejdrech 569
		netif = route ? route->netif : NULL;
570
	}
571
	if( !( netif && route )){
4582 mejdrech 572
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4707 mejdrech 573
		phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
574
		if( phone >= 0 ){
575
			// unreachable ICMP if no routing
576
			icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
577
		}
4505 mejdrech 578
		return ENOENT;
579
	}
4707 mejdrech 580
	if( error ){
581
		// do not send for broadcast, anycast packets or network broadcast
582
		if(( ! dest->s_addr )
583
		|| ( !( ~ dest->s_addr ))
584
		|| ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
585
		|| ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
4711 mejdrech 586
			return ip_release_and_return( packet, EINVAL );
4707 mejdrech 587
		}
588
	}
589
	src = ip_netif_address( netif );
4505 mejdrech 590
	if( ! src ){
4582 mejdrech 591
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4711 mejdrech 592
		return ip_release_and_return( packet, ENOENT );
4505 mejdrech 593
	}
4720 mejdrech 594
	ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error );
4582 mejdrech 595
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 596
	return ERROR_CODE;
597
}
598
 
4707 mejdrech 599
in_addr_t * ip_netif_address( ip_netif_ref netif ){
4505 mejdrech 600
	ip_route_ref	route;
601
 
602
	route = ip_routes_get_index( & netif->routes, 0 );
603
	return route ? & route->address : NULL;
604
}
605
 
4707 mejdrech 606
int 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 ){
4505 mejdrech 607
	ERROR_DECLARE;
608
 
609
	measured_string_t	destination;
610
	measured_string_ref	translation;
611
	char *				data;
4707 mejdrech 612
	int					phone;
4505 mejdrech 613
 
614
	// get destination hardware address
4722 mejdrech 615
	if( netif->arp && ( route->address.s_addr != dest.s_addr )){
4575 mejdrech 616
		destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
4505 mejdrech 617
		destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
618
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
4720 mejdrech 619
//			sleep( 1 );
620
//			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
621
			pq_release( ip_globals.net_phone, packet_get_id( packet ));
622
			return ERROR_CODE;
4505 mejdrech 623
		}
4707 mejdrech 624
		if( !( translation && translation->value )){
625
			if( translation ){
626
				free( translation );
627
				free( data );
628
			}
629
			phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
630
			if( phone >= 0 ){
631
				// unreachable ICMP if no routing
632
				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
633
			}
4505 mejdrech 634
			return EINVAL;
635
		}
636
	}else translation = NULL;
4589 mejdrech 637
	if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
638
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
639
	}else{
4707 mejdrech 640
		packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
4589 mejdrech 641
		if( packet ){
642
			nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
4505 mejdrech 643
		}
4589 mejdrech 644
	}
4505 mejdrech 645
	if( translation ){
646
		free( translation );
647
		free( data );
648
	}
4589 mejdrech 649
	return ERROR_CODE;
3846 mejdrech 650
}
651
 
4575 mejdrech 652
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
4505 mejdrech 653
	ERROR_DECLARE;
654
 
4558 mejdrech 655
	size_t				length;
4505 mejdrech 656
	ip_header_ref		header;
4589 mejdrech 657
	ip_header_ref		last_header;
658
	ip_header_ref		middle_header;
659
	packet_t			next;
4505 mejdrech 660
 
661
	length = packet_get_data_length( packet );
662
	if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
663
	header = ( ip_header_ref ) packet_get_data( packet );
664
	if( destination ){
665
		ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
4722 mejdrech 666
	}else{
667
		ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
4505 mejdrech 668
	}
4722 mejdrech 669
	header->version = IPV4;
4505 mejdrech 670
	header->fragment_offset = 0;
4589 mejdrech 671
	header->header_checksum = 0;
4575 mejdrech 672
	if( source ) header->source_address = source->s_addr;
673
	header->destination_address = dest.s_addr;
4582 mejdrech 674
	fibril_rwlock_write_lock( & ip_globals.lock );
4505 mejdrech 675
	++ ip_globals.packet_counter;
676
	header->identification = htons( ip_globals.packet_counter );
4582 mejdrech 677
	fibril_rwlock_write_unlock( & ip_globals.lock );
4589 mejdrech 678
	length = packet_get_data_length( packet );
679
	if( pq_next( packet )){
680
		last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
681
		if( ! last_header ) return ENOMEM;
682
		ip_create_last_header( last_header, header );
683
		next = pq_next( packet );
684
		while( pq_next( next )){
685
			middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
686
			if( ! middle_header ) return ENOMEM;
687
			memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
688
			header->flags |= IPFLAG_MORE_FRAGMENTS;
689
			middle_header->total_length = htons( packet_get_data_length( next ));
4722 mejdrech 690
			middle_header->fragment_offset = IP_FRAGMENT_OFFSET( length );
4589 mejdrech 691
			middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
692
			if( destination ){
693
				ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
694
			}
695
			length += packet_get_data_length( next );
696
			next = pq_next( next );
697
		}
698
		middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
699
		if( ! middle_header ) return ENOMEM;
700
		memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
701
		middle_header->total_length = htons( packet_get_data_length( next ));
4722 mejdrech 702
		middle_header->fragment_offset = IP_FRAGMENT_OFFSET( length );
4589 mejdrech 703
		middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
704
		if( destination ){
705
			ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
706
		}
707
		length += packet_get_data_length( next );
708
		free( last_header );
709
		header->flags |= IPFLAG_MORE_FRAGMENTS;
710
	}
711
	header->total_length = htons( length );
4505 mejdrech 712
	// unnecessary for all protocols
713
	header->header_checksum = IP_HEADER_CHECKSUM( header );
714
	return EOK;
715
}
716
 
3846 mejdrech 717
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
718
	ERROR_DECLARE;
719
 
4722 mejdrech 720
	packet_t				packet;
721
	struct sockaddr *		addr;
722
	size_t					addrlen;
723
	ip_pseudo_header_ref	header;
724
	size_t					headerlen;
3846 mejdrech 725
 
726
	* answer_count = 0;
727
	switch( IPC_GET_METHOD( * call )){
3466 mejdrech 728
		case IPC_M_PHONE_HUNGUP:
729
			return EOK;
3666 mejdrech 730
		case NET_IL_DEVICE:
4307 mejdrech 731
			return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 732
		case IPC_M_CONNECT_TO_ME:
4505 mejdrech 733
			return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 734
		case NET_IL_SEND:
735
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4707 mejdrech 736
			return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
4351 mejdrech 737
		case NET_IL_DEVICE_STATE:
4702 mejdrech 738
			return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
4351 mejdrech 739
		case NET_IL_RECEIVED:
740
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4702 mejdrech 741
			return ip_receive_message( IPC_GET_DEVICE( call ), packet );
4707 mejdrech 742
		case NET_IP_RECEIVED_ERROR:
743
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
744
			return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
4505 mejdrech 745
		case NET_IP_ADD_ROUTE:
746
			return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
747
		case NET_IP_SET_GATEWAY:
748
			return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
4722 mejdrech 749
		case NET_IP_GET_ROUTE:
750
			ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
751
			ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
752
			* IP_SET_HEADERLEN( answer ) = headerlen;
753
			if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
754
				ERROR_CODE = data_reply( header, headerlen );
755
			}
756
			free( header );
757
			return ERROR_CODE;
4505 mejdrech 758
		case NET_IL_PACKET_SPACE:
759
			ERROR_PROPAGATE( ip_packet_size_req( 0, IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
760
			* answer_count = 3;
761
			return EOK;
4695 mejdrech 762
		case NET_IL_MTU_CHANGED:
4702 mejdrech 763
			return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
3466 mejdrech 764
	}
765
	return ENOTSUP;
766
}
767
 
4505 mejdrech 768
int ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
769
	ip_netif_ref	netif;
4575 mejdrech 770
	int				index;
4505 mejdrech 771
 
772
	if( !( addr_len && prefix && content && suffix )) return EBADMEM;
4575 mejdrech 773
	* content = IP_MAX_CONTENT - IP_PREFIX;
4582 mejdrech 774
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4575 mejdrech 775
	if( device_id < 0 ){
776
		* addr_len = IP_ADDR;
777
		* prefix = 0;
778
		* suffix = 0;
779
		for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
780
			netif = ip_netifs_get_index( & ip_globals.netifs, index );
781
			if( netif ){
782
				if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
783
				if( netif->prefix > * prefix ) * prefix = netif->prefix;
784
				if( netif->suffix > * suffix ) * suffix = netif->suffix;
785
			}
786
		}
787
		* prefix = * prefix + IP_PREFIX;
788
		* suffix = * suffix + IP_SUFFIX;
789
	}else{
790
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
791
		if( ! netif ){
4582 mejdrech 792
			fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4575 mejdrech 793
			return ENOENT;
794
		}
795
		* addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
796
		* prefix = netif->prefix + IP_PREFIX;
797
		* suffix = netif->suffix + IP_SUFFIX;
4505 mejdrech 798
	}
4582 mejdrech 799
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 800
	return EOK;
801
}
802
 
803
int ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway ){
804
	ip_route_ref	route;
805
	ip_netif_ref	netif;
806
	int				index;
807
 
4582 mejdrech 808
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 809
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 810
	if( ! netif ){
4582 mejdrech 811
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 812
		return ENOENT;
813
	}
4505 mejdrech 814
	route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
4558 mejdrech 815
	if( ! route ){
4582 mejdrech 816
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 817
		return ENOMEM;
818
	}
4505 mejdrech 819
	route->address.s_addr = address.s_addr;
820
	route->netmask.s_addr = netmask.s_addr;
821
	route->gateway.s_addr = gateway.s_addr;
822
	route->netif = netif;
823
	index = ip_routes_add( & netif->routes, route );
824
	if( index < 0 ) free( route );
4582 mejdrech 825
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 826
	return index;
827
}
828
 
829
ip_route_ref ip_find_route( in_addr_t destination ){
830
	int				index;
831
	ip_route_ref	route;
832
	ip_netif_ref	netif;
833
 
834
	// start with the last netif - the newest one
835
	index = ip_netifs_count( & ip_globals.netifs ) - 1;
836
	while( index >= 0 ){
837
		netif = ip_netifs_get_index( & ip_globals.netifs, index );
838
		if( netif && ( netif->state == NETIF_ACTIVE )){
839
			route = ip_netif_find_route( netif, destination );
840
			if( route ) return route;
841
		}
842
		-- index;
843
	}
844
	return & ip_globals.gateway;
845
}
846
 
847
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
848
	int				index;
849
	ip_route_ref	route;
850
 
851
	if( netif ){
852
		// start with the first one - the direct route
853
		for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
854
			route = ip_routes_get_index( & netif->routes, index );
855
			if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
856
				return route;
857
			}
858
		}
859
	}
860
	return NULL;
861
}
862
 
863
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
864
	ip_netif_ref	netif;
865
 
4582 mejdrech 866
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 867
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 868
	if( ! netif ){
4582 mejdrech 869
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 870
		return ENOENT;
871
	}
4505 mejdrech 872
	ip_globals.gateway.address.s_addr = 0;
873
	ip_globals.gateway.netmask.s_addr = 0;
874
	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
875
	ip_globals.gateway.netif = netif;
4582 mejdrech 876
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 877
	return EOK;
878
}
879
 
4720 mejdrech 880
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){
4505 mejdrech 881
	size_t			length;
882
	packet_t		next;
883
	packet_t		new_packet;
4707 mejdrech 884
	int				result;
885
	int				phone;
4505 mejdrech 886
 
887
	next = packet;
888
	// check all packets
889
	while( next ){
890
		length = packet_get_data_length( next );
891
		// too long?
892
		if( length > content ){
4707 mejdrech 893
			result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
894
			if( result != EOK ){
4505 mejdrech 895
				new_packet = pq_detach( next );
896
				if( next == packet ){
4707 mejdrech 897
					// the new first packet of the queue
4505 mejdrech 898
					packet = new_packet;
899
				}
4707 mejdrech 900
				// fragmentation needed?
901
				if( result == EPERM ){
902
					phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
903
					if( phone >= 0 ){
904
						// fragmentation necessary ICMP
905
						icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
906
					}
907
				}else{
908
					pq_release( ip_globals.net_phone, packet_get_id( next ));
909
				}
4505 mejdrech 910
				next = new_packet;
911
				continue;
912
			}
913
		}
914
		next = pq_next( next );
915
	}
916
	return packet;
917
}
918
 
4720 mejdrech 919
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){
4505 mejdrech 920
	ERROR_DECLARE;
921
 
922
	packet_t		new_packet;
923
	ip_header_ref	header;
924
	ip_header_ref	middle_header;
925
	ip_header_ref	last_header;
4720 mejdrech 926
	struct sockaddr *		src;
927
	struct sockaddr *		dest;
928
	socklen_t		addrlen;
4708 mejdrech 929
	int				result;
4505 mejdrech 930
 
4720 mejdrech 931
	result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
4708 mejdrech 932
	if( result <= 0 ) return EINVAL;
4720 mejdrech 933
	addrlen = ( socklen_t ) result;
4505 mejdrech 934
	if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
935
	// get header
936
	header = ( ip_header_ref ) packet_get_data( packet );
937
	if( ! header ) return EINVAL;
938
	// fragmentation forbidden?
939
	if( header->flags & IPFLAG_DONT_FRAGMENT ){
940
		return EPERM;
941
	}
942
	// create the last fragment
4720 mejdrech 943
	new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len ));
4505 mejdrech 944
	if( ! new_packet ) return ENOMEM;
4589 mejdrech 945
	// allocate as much as originally
946
	last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
4505 mejdrech 947
	if( ! last_header ){
4711 mejdrech 948
		return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 949
	}
4589 mejdrech 950
	ip_create_last_header( last_header, header );
951
	// trim the unused space
952
	if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
4711 mejdrech 953
		return ip_release_and_return( packet, ERROR_CODE );
4589 mejdrech 954
	}
4505 mejdrech 955
	// biggest multiple of 8 lower than content
956
	// TODO even fragmentation?
957
	length = length & ( ~ 0x7 );// ( content / 8 ) * 8
4720 mejdrech 958
	if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, addrlen ))){
4711 mejdrech 959
		return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 960
	}
961
	// mark the first as fragmented
962
	header->flags |= IPFLAG_MORE_FRAGMENTS;
963
	// create middle framgents
964
	while( IP_TOTAL_LENGTH( header ) > length ){
4720 mejdrech 965
		new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len ));
4505 mejdrech 966
		if( ! new_packet ) return ENOMEM;
967
		middle_header = ip_create_middle_header( new_packet, last_header );
968
		if( ! middle_header ){
4711 mejdrech 969
			return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 970
		}
4720 mejdrech 971
		if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){
4711 mejdrech 972
			return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 973
		}
974
	}
975
	// finish the first fragment
976
	header->header_checksum = IP_HEADER_CHECKSUM( header );
977
	return EOK;
978
}
979
 
4720 mejdrech 980
int 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 ){
4505 mejdrech 981
	ERROR_DECLARE;
982
 
983
	void *			data;
984
 
985
	data = packet_suffix( new_packet, length );
986
	if( ! data ) return ENOMEM;
987
	memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
988
	ERROR_PROPAGATE( packet_trim( packet, 0, length ));
989
	header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
990
	new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
991
	new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
992
	new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
4720 mejdrech 993
	ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
4505 mejdrech 994
	return pq_insert_after( packet, new_packet );
995
}
996
 
997
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
998
	ip_header_ref	middle;
999
 
1000
	middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
1001
	if( ! middle ) return NULL;
1002
	memcpy( middle, last, IP_HEADER_LENGTH( last ));
1003
	middle->flags |= IPFLAG_MORE_FRAGMENTS;
1004
	return middle;
1005
}
1006
 
4589 mejdrech 1007
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
4505 mejdrech 1008
	ip_option_ref	option;
1009
	size_t			next;
1010
	size_t			length;
1011
 
1012
	// copy first itself
1013
	memcpy( last, first, sizeof( ip_header_t ));
1014
	length = sizeof( ip_header_t );
1015
	next = sizeof( ip_header_t );
1016
	// process all ip options
1017
	while( next < first->ihl ){
4708 mejdrech 1018
		option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
4505 mejdrech 1019
		// skip end or noop
1020
		if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
1021
			++ next;
1022
		}else{
1023
			// copy if said so or skip
1024
			if( IPOPT_COPIED( option->type )){
4708 mejdrech 1025
				memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
4505 mejdrech 1026
				length += option->length;
1027
			}
1028
			// next option
1029
			next += option->length;
1030
		}
1031
	}
1032
	// align 4 byte boundary
1033
	if( length % 4 ){
4708 mejdrech 1034
		bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
4505 mejdrech 1035
		last->ihl = length / 4 + 1;
1036
	}else{
1037
		last->ihl = length / 4;
1038
	}
4589 mejdrech 1039
	last->header_checksum = 0;
4505 mejdrech 1040
}
1041
 
4702 mejdrech 1042
int ip_receive_message( device_id_t device_id, packet_t packet ){
4505 mejdrech 1043
	packet_t		next;
1044
 
1045
	do{
1046
		next = pq_detach( packet );
4707 mejdrech 1047
		ip_process_packet( device_id, packet );
4505 mejdrech 1048
		packet = next;
1049
	}while( packet );
1050
	return EOK;
1051
}
1052
 
1053
int ip_process_packet( device_id_t device_id, packet_t packet ){
1054
	ERROR_DECLARE;
1055
 
1056
	ip_header_ref	header;
1057
	in_addr_t		dest;
1058
	ip_route_ref	route;
4707 mejdrech 1059
	int				phone;
4720 mejdrech 1060
	struct sockaddr *	addr;
1061
	struct sockaddr_in	addr_in;
1062
//	struct sockaddr_in	addr_in6;
1063
	socklen_t		addrlen;
4505 mejdrech 1064
 
1065
	header = ( ip_header_ref ) packet_get_data( packet );
4707 mejdrech 1066
	if( ! header ){
4711 mejdrech 1067
		return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1068
	}
4505 mejdrech 1069
	// checksum
1070
	if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
1071
		// TODO checksum error ICMP?
4711 mejdrech 1072
		return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1073
	}
1074
	if( header->ttl <= 1 ){
1075
		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1076
		if( phone >= 0 ){
1077
			// ttl oxceeded ICMP
1078
			icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
1079
		}
4505 mejdrech 1080
		return EINVAL;
1081
	}
1082
	// process ipopt and get destination
1083
	dest = ip_get_destination( header );
4720 mejdrech 1084
	// set the addrination address
1085
	switch( header->version ){
1086
		case IPVERSION:
1087
			addrlen = sizeof( addr_in );
1088
			bzero( & addr_in, addrlen );
1089
			addr_in.sin_family = AF_INET;
1090
			memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest ));
1091
			addr = ( struct sockaddr * ) & addr_in;
1092
			break;
1093
/*		case IPv6VERSION:
1094
			addrlen = sizeof( dest_in6 );
1095
			bzero( & dest_in6, addrlen );
1096
			dest_in6.sin6_family = AF_INET6;
1097
			memcpy( & dest_in6.sin6_addr.s6_addr, );
1098
			dest = ( struct sockaddr * ) & dest_in;
1099
			break;
1100
*/		default:
1101
			return EAFNOSUPPORT;
1102
	}
1103
	ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen ));
4505 mejdrech 1104
	route = ip_find_route( dest );
4707 mejdrech 1105
	if( ! route ){
1106
		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1107
		if( phone >= 0 ){
1108
			// unreachable ICMP
1109
			icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1110
		}
1111
		return ENOENT;
1112
	}
4505 mejdrech 1113
	if( route->address.s_addr == dest.s_addr ){
1114
		// local delivery
4707 mejdrech 1115
		return ip_deliver_local( device_id, packet, header, 0 );
4505 mejdrech 1116
	}else{
4695 mejdrech 1117
		// only if routing enabled
1118
		if( route->netif->routing ){
4707 mejdrech 1119
			-- header->ttl;
1120
			return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
1121
		}else{
1122
			phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1123
			if( phone >= 0 ){
1124
				// unreachable ICMP if no routing
1125
				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1126
			}
4695 mejdrech 1127
			return ENOENT;
1128
		}
4505 mejdrech 1129
	}
1130
}
1131
 
4707 mejdrech 1132
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
1133
	uint8_t *			data;
1134
	int					offset;
1135
	icmp_type_t			type;
1136
	icmp_code_t			code;
1137
	ip_netif_ref		netif;
1138
	measured_string_t	address;
1139
	ip_route_ref		route;
1140
	ip_header_ref		header;
1141
 
1142
	switch( error ){
1143
		case SERVICE_ICMP:
1144
			offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
1145
			if( offset < 0 ){
4711 mejdrech 1146
				return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1147
			}
1148
			data = packet_get_data( packet );
4720 mejdrech 1149
			header = ( ip_header_ref )( data + offset );
4707 mejdrech 1150
			// destination host unreachable?
1151
			if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
1152
				fibril_rwlock_read_lock( & ip_globals.netifs_lock );
1153
				netif = ip_netifs_find( & ip_globals.netifs, device_id );
1154
				if( netif && netif->arp ){
1155
					route = ip_routes_get_index( & netif->routes, 0 );
1156
					// from the same network?
1157
					if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
1158
						// clear the ARP mapping if any
1159
						address.value = ( char * ) & header->destination_address;
1160
						address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
1161
						arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
1162
					}
1163
				}
1164
				fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
1165
			}
1166
			break;
1167
		default:
4711 mejdrech 1168
			return ip_release_and_return( packet, ENOTSUP );
4707 mejdrech 1169
	}
1170
	return ip_deliver_local( device_id, packet, header, error );
1171
}
1172
 
1173
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
4505 mejdrech 1174
	ERROR_DECLARE;
1175
 
1176
	ip_proto_ref	proto;
4707 mejdrech 1177
	int				phone;
4720 mejdrech 1178
	services_t		service;
1179
	tl_received_msg_t	received_msg;
1180
	struct sockaddr *	src;
1181
	struct sockaddr *	dest;
1182
	struct sockaddr_in	src_in;
1183
	struct sockaddr_in	dest_in;
1184
//	struct sockaddr_in	src_in6;
1185
//	struct sockaddr_in	dest_in6;
1186
	socklen_t		addrlen;
4505 mejdrech 1187
 
1188
	if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
1189
		// TODO fragmented
1190
		return ENOTSUP;
1191
	}else{
4720 mejdrech 1192
		switch( header->version ){
1193
			case IPVERSION:
1194
				addrlen = sizeof( src_in );
1195
				bzero( & src_in, addrlen );
1196
				src_in.sin_family = AF_INET;
1197
				memcpy( & dest_in, & src_in, addrlen );
1198
				memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
1199
				memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address ));
1200
				src = ( struct sockaddr * ) & src_in;
1201
				dest = ( struct sockaddr * ) & dest_in;
1202
				break;
1203
/*			case IPv6VERSION:
1204
				addrlen = sizeof( src_in6 );
1205
				bzero( & src_in6, addrlen );
1206
				src_in6.sin6_family = AF_INET6;
1207
				memcpy( & dest_in6, & src_in6, addrlen );
1208
				memcpy( & src_in6.sin6_addr.s6_addr, );
1209
				memcpy( & dest_in6.sin6_addr.s6_addr, );
1210
				src = ( struct sockaddr * ) & src_in;
1211
				dest = ( struct sockaddr * ) & dest_in;
1212
				break;
1213
*/			default:
1214
				return EAFNOSUPPORT;
1215
		}
1216
		ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen ));
4582 mejdrech 1217
		fibril_rwlock_read_lock( & ip_globals.protos_lock );
4505 mejdrech 1218
		proto = ip_protos_find( & ip_globals.protos, header->protocol );
4558 mejdrech 1219
		if( ! proto ){
4582 mejdrech 1220
			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4707 mejdrech 1221
			phone = ip_prepare_icmp_and_get_phone( error, packet, header );
1222
			if( phone >= 0 ){
1223
				// unreachable ICMP
1224
				icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
1225
			}
4558 mejdrech 1226
			return ENOENT;
1227
		}
1228
		if( proto->received_msg ){
4720 mejdrech 1229
			service = proto->service;
1230
			received_msg = proto->received_msg;
1231
			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1232
			ERROR_CODE = received_msg( device_id, packet, service, error );
4505 mejdrech 1233
		}else{
4707 mejdrech 1234
			ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
4720 mejdrech 1235
			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4505 mejdrech 1236
		}
4558 mejdrech 1237
		return ERROR_CODE;
4505 mejdrech 1238
	}
1239
}
1240
 
1241
in_addr_t ip_get_destination( ip_header_ref header ){
1242
	in_addr_t	destination;
1243
 
1244
	// TODO search set ipopt route?
4707 mejdrech 1245
	destination.s_addr = header->destination_address;
4505 mejdrech 1246
	return destination;
1247
}
1248
 
4707 mejdrech 1249
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
1250
	packet_t	next;
4720 mejdrech 1251
	struct sockaddr *	dest;
1252
	struct sockaddr_in	dest_in;
1253
//	struct sockaddr_in	dest_in6;
1254
	socklen_t		addrlen;
4707 mejdrech 1255
 
1256
	// detach the first packet and release the others
1257
	next = pq_detach( packet );
1258
	if( next ){
1259
		pq_release( ip_globals.net_phone, packet_get_id( next ));
1260
	}
1261
	if( ! header ){
1262
		if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
1263
		// get header
1264
		header = ( ip_header_ref ) packet_get_data( packet );
1265
		if( ! header ) return EINVAL;
1266
	}
1267
	// only for the first fragment
1268
	if( header->fragment_offset ) return EINVAL;
1269
	// set the destination address
4720 mejdrech 1270
	switch( header->version ){
1271
		case IPVERSION:
1272
			addrlen = sizeof( dest_in );
1273
			bzero( & dest_in, addrlen );
1274
			dest_in.sin_family = AF_INET;
1275
			memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
1276
			dest = ( struct sockaddr * ) & dest_in;
1277
			break;
1278
/*		case IPv6VERSION:
1279
			addrlen = sizeof( dest_in6 );
1280
			bzero( & dest_in6, addrlen );
1281
			dest_in6.sin6_family = AF_INET6;
1282
			memcpy( & dest_in6.sin6_addr.s6_addr, );
1283
			dest = ( struct sockaddr * ) & dest_in;
1284
			break;
1285
*/		default:
1286
			return EAFNOSUPPORT;
1287
	}
1288
	return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen );
4707 mejdrech 1289
}
1290
 
1291
int ip_get_icmp_phone( void ){
1292
	ip_proto_ref	proto;
1293
	int				phone;
1294
 
1295
	fibril_rwlock_read_lock( & ip_globals.protos_lock );
1296
	proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
1297
	phone = proto ? proto->phone : ENOENT;
1298
	fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1299
	return phone;
1300
}
1301
 
1302
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
1303
	int	phone;
1304
 
1305
	phone = ip_get_icmp_phone();
1306
	if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
4711 mejdrech 1307
		return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1308
	}
1309
	return phone;
1310
}
1311
 
4711 mejdrech 1312
int	ip_release_and_return( packet_t packet, int result ){
4707 mejdrech 1313
	pq_release( ip_globals.net_phone, packet_get_id( packet ));
1314
	return result;
1315
}
1316
 
4722 mejdrech 1317
int 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 ){
1318
	struct sockaddr_in *	address_in;
1319
//	struct sockaddr_in6 *	address_in6;
1320
	in_addr_t *				dest;
1321
	in_addr_t *				src;
1322
	ip_route_ref			route;
1323
	ipv4_pseudo_header_ref	header_in;
1324
 
1325
	if( !( destination && ( addrlen > 0 ))) return EINVAL;
1326
	if( !( device_id && header && headerlen )) return EBADMEM;
1327
	if( addrlen < sizeof( struct sockaddr )){
1328
		return EINVAL;
1329
	}
1330
	switch( destination->sa_family ){
1331
		case AF_INET:
1332
			if( addrlen != sizeof( struct sockaddr_in )){
1333
				return EINVAL;
1334
			}
1335
			address_in = ( struct sockaddr_in * ) destination;
1336
			dest = & address_in->sin_addr;
1337
			break;
1338
		// TODO IPv6
1339
/*		case AF_INET6:
1340
			if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
1341
			address_in6 = ( struct sockaddr_in6 * ) dest;
1342
			address_in6.sin6_addr.s6_addr;
1343
*/		default:
1344
			return EAFNOSUPPORT;
1345
	}
1346
	fibril_rwlock_read_lock( & ip_globals.lock );
1347
	route = ip_find_route( * dest );
1348
	if( !( route && route->netif )){
1349
		fibril_rwlock_read_unlock( & ip_globals.lock );
1350
		return ENOENT;
1351
	}
1352
	* device_id = route->netif->device_id;
1353
	src = ip_netif_address( route->netif );
1354
	fibril_rwlock_read_unlock( & ip_globals.lock );
1355
	* headerlen = sizeof( * header_in );
1356
	header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
1357
	if( ! header_in ) return ENOMEM;
1358
	bzero( header_in, * headerlen );
1359
	header_in->destination_address = dest->s_addr;
1360
	header_in->source_address = src->s_addr;
1361
	header_in->protocol = protocol;
1362
	header_in->data_length = 0;
1363
	* header = ( ip_pseudo_header_ref ) header_in;
1364
	return EOK;
1365
}
1366
 
3466 mejdrech 1367
/** @}
1368
 */