Subversion Repositories HelenOS

Rev

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