Subversion Repositories HelenOS

Rev

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