Subversion Repositories HelenOS

Rev

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