Subversion Repositories HelenOS

Rev

Rev 4708 | Rev 4717 | 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;
297
	int					index;
4505 mejdrech 298
	ip_route_ref		route;
299
	in_addr_t			gateway;
3666 mejdrech 300
 
4702 mejdrech 301
	ip_netif->arp = NULL;
4506 mejdrech 302
	route = NULL;
4307 mejdrech 303
	configuration = & names[ 0 ];
3846 mejdrech 304
	// get configuration
4307 mejdrech 305
	ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
306
	if( configuration ){
307
		if( configuration[ 0 ].value ){
308
			ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
3846 mejdrech 309
		}else{
310
			ip_netif->ipv = DEFAULT_IPV;
311
		}
4332 mejdrech 312
		ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
3846 mejdrech 313
		if( ip_netif->dhcp ){
314
			// TODO dhcp
4307 mejdrech 315
			net_free_settings( configuration, data );
3846 mejdrech 316
			return ENOTSUP;
317
		}else if( ip_netif->ipv == 4 ){
4505 mejdrech 318
			route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
319
			if( ! route ){
320
				net_free_settings( configuration, data );
321
				return ENOMEM;
322
			}
323
			route->address.s_addr = 0;
324
			route->netmask.s_addr = 0;
325
			route->gateway.s_addr = 0;
326
			route->netif = ip_netif;
327
			index = ip_routes_add( & ip_netif->routes, route );
328
			if( index < 0 ){
329
				net_free_settings( configuration, data );
330
				free( route );
331
				return index;
332
			}
333
			if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
334
			|| ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
335
			|| ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
336
			|| ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
4307 mejdrech 337
			|| ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
338
			|| ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
339
				net_free_settings( configuration, data );
3846 mejdrech 340
				return EINVAL;
341
			}
342
		}else{
4505 mejdrech 343
			// TODO ipv6 in separate module
4307 mejdrech 344
			net_free_settings( configuration, data );
3846 mejdrech 345
			return ENOTSUP;
346
		}
4307 mejdrech 347
		if( configuration[ 8 ].value ){
348
			ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
4192 mejdrech 349
			if( ! ip_netif->arp ){
4307 mejdrech 350
				printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
351
				net_free_settings( configuration, data );
4192 mejdrech 352
				return EINVAL;
353
			}
354
		}else{
355
			ip_netif->arp = NULL;
356
		}
4695 mejdrech 357
		ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' );
4307 mejdrech 358
		net_free_settings( configuration, data );
3846 mejdrech 359
	}
4558 mejdrech 360
	ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
4192 mejdrech 361
	if( ip_netif->phone < 0 ){
4505 mejdrech 362
		printf( "Failed to contact the nil service %d\n", ip_netif->service );
4192 mejdrech 363
		return ip_netif->phone;
364
	}
4505 mejdrech 365
	// MUST BE AFTER the bind_service up there!
4192 mejdrech 366
	if( ip_netif->arp ){
4506 mejdrech 367
		if( route ){
368
			configuration[ 0 ].value = ( char * ) & route->address.s_addr;
369
			configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 );
370
			ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & configuration[ 0 ] ));
371
		}else{
372
			ip_netif->arp = 0;
373
		}
4192 mejdrech 374
	}
4505 mejdrech 375
	// get packet dimensions
376
	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 ));
377
	if( ip_netif->content < IP_MIN_CONTENT ){
378
		printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
379
		ip_netif->content = IP_MIN_CONTENT;
380
	}
4192 mejdrech 381
	index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
4505 mejdrech 382
	if( index < 0 ) return index;
383
	if( gateway.s_addr ){
384
		// the default gateway
385
		ip_globals.gateway.address.s_addr = 0;
386
		ip_globals.gateway.netmask.s_addr = 0;
387
		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
388
		ip_globals.gateway.netif = ip_netif;
4192 mejdrech 389
	}
3846 mejdrech 390
	return EOK;
391
}
392
 
4702 mejdrech 393
int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
4695 mejdrech 394
	ip_netif_ref	netif;
395
 
396
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
397
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
398
	if( ! netif ){
399
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
400
		return ENOENT;
401
	}
402
	netif->content = mtu;
403
	printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
404
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
405
	return EOK;
406
}
407
 
4702 mejdrech 408
int ip_device_state_message( device_id_t device_id, device_state_t state ){
4506 mejdrech 409
//	ERROR_DECLARE;
4243 mejdrech 410
 
4505 mejdrech 411
/*	measured_string_t	address;
412
	measured_string_ref	translation;
413
	char *				data;
414
*/
4506 mejdrech 415
/*	packet_t		packet;
4505 mejdrech 416
	in_addr_t		destination;
4506 mejdrech 417
*/
4243 mejdrech 418
	ip_netif_ref	netif;
419
 
4582 mejdrech 420
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4243 mejdrech 421
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 422
	if( ! netif ){
4582 mejdrech 423
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 424
		return ENOENT;
425
	}
4505 mejdrech 426
	netif->state = state;
3846 mejdrech 427
	// TODO state
4307 mejdrech 428
	printf( "ip - device %d changed state to %d\n\n", device_id, state );
4582 mejdrech 429
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4506 mejdrech 430
//	if( netif->arp ){
4505 mejdrech 431
/*		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
432
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
4327 mejdrech 433
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4505 mejdrech 434
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
435
		}
436
		printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
437
		free( translation );
438
		free( data );
439
		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
440
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
441
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4327 mejdrech 442
			sleep( 2 );
443
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
444
		}
4307 mejdrech 445
		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 446
		free( translation );
447
		free( data );
4506 mejdrech 448
*//*		printf( "IP - testing to send packet:\n" );
4505 mejdrech 449
		ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
450
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
451
		if( ! packet ) return ENOMEM;
452
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
453
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
454
		if( ! packet ) return ENOMEM;
455
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
456
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
457
		if( ! packet ) return ENOMEM;
458
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
459
		packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
460
		if( ! packet ) return ENOMEM;
461
		// try this long version
462
//		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 ))
463
		if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
464
		|| ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
465
		|| ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
466
			pq_release( ip_globals.net_phone, packet_get_id( packet ));
467
		}
468
		ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
469
		printf( "send returned %d\n", ERROR_CODE );
4243 mejdrech 470
	}
4506 mejdrech 471
*/	return EOK;
4307 mejdrech 472
}
473
 
474
int ip_connect_module( services_t service ){
475
	return EOK;
476
}
477
 
4558 mejdrech 478
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
479
	return ip_register( protocol, me, 0, received_msg );
4505 mejdrech 480
}
481
 
4558 mejdrech 482
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
3846 mejdrech 483
	ip_proto_ref	proto;
4192 mejdrech 484
	int				index;
3846 mejdrech 485
 
4558 mejdrech 486
	if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
3846 mejdrech 487
	proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
488
	if( ! proto ) return ENOMEM;
489
	proto->protocol = protocol;
4505 mejdrech 490
	proto->service = service;
3846 mejdrech 491
	proto->phone = phone;
4558 mejdrech 492
	proto->received_msg = received_msg;
4582 mejdrech 493
	fibril_rwlock_write_lock( & ip_globals.protos_lock );
4192 mejdrech 494
	index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
495
	if( index < 0 ){
4582 mejdrech 496
		fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 497
		free( proto );
4192 mejdrech 498
		return index;
3846 mejdrech 499
	}
4307 mejdrech 500
	printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
4582 mejdrech 501
	fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 502
	return EOK;
503
}
504
 
4707 mejdrech 505
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
4505 mejdrech 506
	ERROR_DECLARE;
507
 
508
	int					length;
509
	ip_netif_ref		netif;
510
	ip_route_ref		route;
4575 mejdrech 511
	in_addr_t *			dest;
4505 mejdrech 512
	in_addr_t *			src;
4707 mejdrech 513
	int					phone;
4505 mejdrech 514
 
515
	// addresses in the host byte order
516
	// should be the next hop address or the target destination address
4575 mejdrech 517
	length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest );
4505 mejdrech 518
	if( length < 0 ){
4711 mejdrech 519
		return ip_release_and_return( packet, length );
4505 mejdrech 520
	}
521
	// TODO IPv6
522
	if( length != IP_ADDR ){
4711 mejdrech 523
		return ip_release_and_return( packet, EINVAL );
4505 mejdrech 524
	}
4582 mejdrech 525
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4505 mejdrech 526
	// device specified?
4575 mejdrech 527
	if( device_id > 0 ){
4505 mejdrech 528
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
4575 mejdrech 529
		route = ip_netif_find_route( netif, * dest );
4505 mejdrech 530
	}else{
531
		// TODO IPv6
4575 mejdrech 532
		route = ip_find_route( * dest );
4505 mejdrech 533
		netif = route ? route->netif : NULL;
534
	}
535
	if( !( netif && route )){
4582 mejdrech 536
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4707 mejdrech 537
		phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
538
		if( phone >= 0 ){
539
			// unreachable ICMP if no routing
540
			icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
541
		}
4505 mejdrech 542
		return ENOENT;
543
	}
4707 mejdrech 544
	if( error ){
545
		// do not send for broadcast, anycast packets or network broadcast
546
		if(( ! dest->s_addr )
547
		|| ( !( ~ dest->s_addr ))
548
		|| ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
549
		|| ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
4711 mejdrech 550
			return ip_release_and_return( packet, EINVAL );
4707 mejdrech 551
		}
552
	}
4505 mejdrech 553
	// to me?
4575 mejdrech 554
	if( route->address.s_addr == dest->s_addr ){
4505 mejdrech 555
		// TODO loopback deliver
4582 mejdrech 556
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4707 mejdrech 557
		return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error );
4505 mejdrech 558
	}
559
 
4707 mejdrech 560
	src = ip_netif_address( netif );
4505 mejdrech 561
	if( ! src ){
4582 mejdrech 562
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4711 mejdrech 563
		return ip_release_and_return( packet, ENOENT );
4505 mejdrech 564
	}
4707 mejdrech 565
	if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){
4505 mejdrech 566
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
567
	}
4582 mejdrech 568
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 569
	return ERROR_CODE;
570
}
571
 
4707 mejdrech 572
in_addr_t * ip_netif_address( ip_netif_ref netif ){
4505 mejdrech 573
	ip_route_ref	route;
574
 
575
	route = ip_routes_get_index( & netif->routes, 0 );
576
	return route ? & route->address : NULL;
577
}
578
 
4707 mejdrech 579
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 580
	ERROR_DECLARE;
581
 
582
	measured_string_t	destination;
583
	measured_string_ref	translation;
584
	char *				data;
4707 mejdrech 585
	int					phone;
4505 mejdrech 586
 
587
	// get destination hardware address
588
	if( netif->arp ){
4575 mejdrech 589
		destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
4505 mejdrech 590
		destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
591
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
4582 mejdrech 592
			sleep( 1 );
4505 mejdrech 593
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
594
		}
4707 mejdrech 595
		if( !( translation && translation->value )){
596
			if( translation ){
597
				free( translation );
598
				free( data );
599
			}
600
			phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
601
			if( phone >= 0 ){
602
				// unreachable ICMP if no routing
603
				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
604
			}
4505 mejdrech 605
			return EINVAL;
606
		}
607
	}else translation = NULL;
4589 mejdrech 608
	if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
609
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
610
	}else{
4707 mejdrech 611
		packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
4589 mejdrech 612
		if( packet ){
613
			nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
4505 mejdrech 614
		}
4589 mejdrech 615
	}
4505 mejdrech 616
	if( translation ){
617
		free( translation );
618
		free( data );
619
	}
4589 mejdrech 620
	return ERROR_CODE;
3846 mejdrech 621
}
622
 
4575 mejdrech 623
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
4505 mejdrech 624
	ERROR_DECLARE;
625
 
4558 mejdrech 626
	size_t				length;
4505 mejdrech 627
	ip_header_ref		header;
4589 mejdrech 628
	ip_header_ref		last_header;
629
	ip_header_ref		middle_header;
630
	packet_t			next;
4505 mejdrech 631
 
632
	length = packet_get_data_length( packet );
633
	if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
634
	header = ( ip_header_ref ) packet_get_data( packet );
635
	if( destination ){
636
		ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
637
	}
638
	header->version = 4;
639
	header->fragment_offset = 0;
4589 mejdrech 640
	header->header_checksum = 0;
4575 mejdrech 641
	if( source ) header->source_address = source->s_addr;
642
	header->destination_address = dest.s_addr;
4582 mejdrech 643
	fibril_rwlock_write_lock( & ip_globals.lock );
4505 mejdrech 644
	++ ip_globals.packet_counter;
645
	header->identification = htons( ip_globals.packet_counter );
4582 mejdrech 646
	fibril_rwlock_write_unlock( & ip_globals.lock );
4589 mejdrech 647
	length = packet_get_data_length( packet );
648
	if( pq_next( packet )){
649
		last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
650
		if( ! last_header ) return ENOMEM;
651
		ip_create_last_header( last_header, header );
652
		next = pq_next( packet );
653
		while( pq_next( next )){
654
			middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
655
			if( ! middle_header ) return ENOMEM;
656
			memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
657
			header->flags |= IPFLAG_MORE_FRAGMENTS;
658
			middle_header->total_length = htons( packet_get_data_length( next ));
659
			middle_header->fragment_offset = length / 8;
660
			middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
661
			if( destination ){
662
				ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
663
			}
664
			length += packet_get_data_length( next );
665
			next = pq_next( next );
666
		}
667
		middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
668
		if( ! middle_header ) return ENOMEM;
669
		memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
670
		middle_header->total_length = htons( packet_get_data_length( next ));
671
		middle_header->fragment_offset = length / 8;
672
		middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
673
		if( destination ){
674
			ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
675
		}
676
		length += packet_get_data_length( next );
677
		free( last_header );
678
		header->flags |= IPFLAG_MORE_FRAGMENTS;
679
	}
680
	header->total_length = htons( length );
4505 mejdrech 681
	// unnecessary for all protocols
682
	header->header_checksum = IP_HEADER_CHECKSUM( header );
683
	return EOK;
684
}
685
 
3846 mejdrech 686
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
687
	ERROR_DECLARE;
688
 
689
	packet_t	packet;
690
 
691
	* answer_count = 0;
692
	switch( IPC_GET_METHOD( * call )){
3466 mejdrech 693
		case IPC_M_PHONE_HUNGUP:
694
			return EOK;
3666 mejdrech 695
		case NET_IL_DEVICE:
4307 mejdrech 696
			return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 697
		case IPC_M_CONNECT_TO_ME:
4505 mejdrech 698
			return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 699
		case NET_IL_SEND:
700
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4707 mejdrech 701
			return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
4351 mejdrech 702
		case NET_IL_DEVICE_STATE:
4702 mejdrech 703
			return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
4351 mejdrech 704
		case NET_IL_RECEIVED:
705
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4702 mejdrech 706
			return ip_receive_message( IPC_GET_DEVICE( call ), packet );
4707 mejdrech 707
		case NET_IP_RECEIVED_ERROR:
708
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
709
			return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
4505 mejdrech 710
		case NET_IP_ADD_ROUTE:
711
			return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
712
		case NET_IP_SET_GATEWAY:
713
			return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
714
		case NET_IL_PACKET_SPACE:
715
			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 )));
716
			* answer_count = 3;
717
			return EOK;
4695 mejdrech 718
		case NET_IL_MTU_CHANGED:
4702 mejdrech 719
			return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
3466 mejdrech 720
	}
721
	return ENOTSUP;
722
}
723
 
4505 mejdrech 724
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 ){
725
	ip_netif_ref	netif;
4575 mejdrech 726
	int				index;
4505 mejdrech 727
 
728
	if( !( addr_len && prefix && content && suffix )) return EBADMEM;
4575 mejdrech 729
	* content = IP_MAX_CONTENT - IP_PREFIX;
4582 mejdrech 730
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4575 mejdrech 731
	if( device_id < 0 ){
732
		* addr_len = IP_ADDR;
733
		* prefix = 0;
734
		* suffix = 0;
735
		for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
736
			netif = ip_netifs_get_index( & ip_globals.netifs, index );
737
			if( netif ){
738
				if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
739
				if( netif->prefix > * prefix ) * prefix = netif->prefix;
740
				if( netif->suffix > * suffix ) * suffix = netif->suffix;
741
			}
742
		}
743
		* prefix = * prefix + IP_PREFIX;
744
		* suffix = * suffix + IP_SUFFIX;
745
	}else{
746
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
747
		if( ! netif ){
4582 mejdrech 748
			fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4575 mejdrech 749
			return ENOENT;
750
		}
751
		* addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
752
		* prefix = netif->prefix + IP_PREFIX;
753
		* suffix = netif->suffix + IP_SUFFIX;
4505 mejdrech 754
	}
4582 mejdrech 755
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 756
	return EOK;
757
}
758
 
759
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 ){
760
	ip_route_ref	route;
761
	ip_netif_ref	netif;
762
	int				index;
763
 
4582 mejdrech 764
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 765
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 766
	if( ! netif ){
4582 mejdrech 767
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 768
		return ENOENT;
769
	}
4505 mejdrech 770
	route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
4558 mejdrech 771
	if( ! route ){
4582 mejdrech 772
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 773
		return ENOMEM;
774
	}
4505 mejdrech 775
	route->address.s_addr = address.s_addr;
776
	route->netmask.s_addr = netmask.s_addr;
777
	route->gateway.s_addr = gateway.s_addr;
778
	route->netif = netif;
779
	index = ip_routes_add( & netif->routes, route );
780
	if( index < 0 ) free( route );
4582 mejdrech 781
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 782
	return index;
783
}
784
 
785
ip_route_ref ip_find_route( in_addr_t destination ){
786
	int				index;
787
	ip_route_ref	route;
788
	ip_netif_ref	netif;
789
 
790
	// start with the last netif - the newest one
791
	index = ip_netifs_count( & ip_globals.netifs ) - 1;
792
	while( index >= 0 ){
793
		netif = ip_netifs_get_index( & ip_globals.netifs, index );
794
		if( netif && ( netif->state == NETIF_ACTIVE )){
795
			route = ip_netif_find_route( netif, destination );
796
			if( route ) return route;
797
		}
798
		-- index;
799
	}
800
	return & ip_globals.gateway;
801
}
802
 
803
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
804
	int				index;
805
	ip_route_ref	route;
806
 
807
	if( netif ){
808
		// start with the first one - the direct route
809
		for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
810
			route = ip_routes_get_index( & netif->routes, index );
811
			if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
812
				return route;
813
			}
814
		}
815
	}
816
	return NULL;
817
}
818
 
819
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
820
	ip_netif_ref	netif;
821
 
4582 mejdrech 822
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 823
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 824
	if( ! netif ){
4582 mejdrech 825
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 826
		return ENOENT;
827
	}
4505 mejdrech 828
	ip_globals.gateway.address.s_addr = 0;
829
	ip_globals.gateway.netmask.s_addr = 0;
830
	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
831
	ip_globals.gateway.netif = netif;
4582 mejdrech 832
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 833
	return EOK;
834
}
835
 
4707 mejdrech 836
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 837
	size_t			length;
838
	packet_t		next;
839
	packet_t		new_packet;
4707 mejdrech 840
	int				result;
841
	int				phone;
4505 mejdrech 842
 
843
	next = packet;
844
	// check all packets
845
	while( next ){
846
		length = packet_get_data_length( next );
847
		// too long?
848
		if( length > content ){
4707 mejdrech 849
			result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
850
			if( result != EOK ){
4505 mejdrech 851
				new_packet = pq_detach( next );
852
				if( next == packet ){
4707 mejdrech 853
					// the new first packet of the queue
4505 mejdrech 854
					packet = new_packet;
855
				}
4707 mejdrech 856
				// fragmentation needed?
857
				if( result == EPERM ){
858
					phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
859
					if( phone >= 0 ){
860
						// fragmentation necessary ICMP
861
						icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
862
					}
863
				}else{
864
					pq_release( ip_globals.net_phone, packet_get_id( next ));
865
				}
4505 mejdrech 866
				next = new_packet;
867
				continue;
868
			}
869
		}
870
		next = pq_next( next );
871
	}
872
	return packet;
873
}
874
 
875
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
876
	ERROR_DECLARE;
877
 
878
	packet_t		new_packet;
879
	ip_header_ref	header;
880
	ip_header_ref	middle_header;
881
	ip_header_ref	last_header;
882
	uint8_t *		src;
883
	uint8_t *		dest;
4708 mejdrech 884
	size_t			address_length;
885
	int				result;
4505 mejdrech 886
 
4708 mejdrech 887
	result = packet_get_addr( packet, & src, & dest );
888
	if( result <= 0 ) return EINVAL;
889
	address_length = ( size_t ) result;
4505 mejdrech 890
	if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
891
	// get header
892
	header = ( ip_header_ref ) packet_get_data( packet );
893
	if( ! header ) return EINVAL;
894
	// fragmentation forbidden?
895
	if( header->flags & IPFLAG_DONT_FRAGMENT ){
896
		return EPERM;
897
	}
898
	// create the last fragment
4558 mejdrech 899
	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 900
	if( ! new_packet ) return ENOMEM;
4589 mejdrech 901
	// allocate as much as originally
902
	last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
4505 mejdrech 903
	if( ! last_header ){
4711 mejdrech 904
		return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 905
	}
4589 mejdrech 906
	ip_create_last_header( last_header, header );
907
	// trim the unused space
908
	if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
4711 mejdrech 909
		return ip_release_and_return( packet, ERROR_CODE );
4589 mejdrech 910
	}
4505 mejdrech 911
	// biggest multiple of 8 lower than content
912
	// TODO even fragmentation?
913
	length = length & ( ~ 0x7 );// ( content / 8 ) * 8
914
	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 915
		return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 916
	}
917
	// mark the first as fragmented
918
	header->flags |= IPFLAG_MORE_FRAGMENTS;
919
	// create middle framgents
920
	while( IP_TOTAL_LENGTH( header ) > length ){
921
		new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
922
		if( ! new_packet ) return ENOMEM;
923
		middle_header = ip_create_middle_header( new_packet, last_header );
924
		if( ! middle_header ){
4711 mejdrech 925
			return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 926
		}
927
		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 928
			return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 929
		}
930
	}
931
	// finish the first fragment
932
	header->header_checksum = IP_HEADER_CHECKSUM( header );
933
	return EOK;
934
}
935
 
936
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 ){
937
	ERROR_DECLARE;
938
 
939
	void *			data;
940
 
941
	data = packet_suffix( new_packet, length );
942
	if( ! data ) return ENOMEM;
943
	memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
944
	ERROR_PROPAGATE( packet_trim( packet, 0, length ));
945
	header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
946
	new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
947
	new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
948
	new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
949
	ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
950
	return pq_insert_after( packet, new_packet );
951
}
952
 
953
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
954
	ip_header_ref	middle;
955
 
956
	middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
957
	if( ! middle ) return NULL;
958
	memcpy( middle, last, IP_HEADER_LENGTH( last ));
959
	middle->flags |= IPFLAG_MORE_FRAGMENTS;
960
	return middle;
961
}
962
 
4589 mejdrech 963
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
4505 mejdrech 964
	ip_option_ref	option;
965
	size_t			next;
966
	size_t			length;
967
 
968
	// copy first itself
969
	memcpy( last, first, sizeof( ip_header_t ));
970
	length = sizeof( ip_header_t );
971
	next = sizeof( ip_header_t );
972
	// process all ip options
973
	while( next < first->ihl ){
4708 mejdrech 974
		option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
4505 mejdrech 975
		// skip end or noop
976
		if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
977
			++ next;
978
		}else{
979
			// copy if said so or skip
980
			if( IPOPT_COPIED( option->type )){
4708 mejdrech 981
				memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
4505 mejdrech 982
				length += option->length;
983
			}
984
			// next option
985
			next += option->length;
986
		}
987
	}
988
	// align 4 byte boundary
989
	if( length % 4 ){
4708 mejdrech 990
		bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
4505 mejdrech 991
		last->ihl = length / 4 + 1;
992
	}else{
993
		last->ihl = length / 4;
994
	}
4589 mejdrech 995
	last->header_checksum = 0;
4505 mejdrech 996
}
997
 
4702 mejdrech 998
int ip_receive_message( device_id_t device_id, packet_t packet ){
4505 mejdrech 999
	packet_t		next;
1000
 
1001
	do{
1002
		next = pq_detach( packet );
4707 mejdrech 1003
		ip_process_packet( device_id, packet );
4505 mejdrech 1004
		packet = next;
1005
	}while( packet );
1006
	return EOK;
1007
}
1008
 
1009
int ip_process_packet( device_id_t device_id, packet_t packet ){
1010
	ERROR_DECLARE;
1011
 
1012
	ip_header_ref	header;
1013
	in_addr_t		dest;
1014
	ip_route_ref	route;
4707 mejdrech 1015
	int				phone;
4505 mejdrech 1016
 
1017
	header = ( ip_header_ref ) packet_get_data( packet );
4707 mejdrech 1018
	if( ! header ){
4711 mejdrech 1019
		return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1020
	}
4505 mejdrech 1021
	// checksum
1022
	if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
1023
		// TODO checksum error ICMP?
4711 mejdrech 1024
		return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1025
	}
1026
	if( header->ttl <= 1 ){
1027
		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1028
		if( phone >= 0 ){
1029
			// ttl oxceeded ICMP
1030
			icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
1031
		}
4505 mejdrech 1032
		return EINVAL;
1033
	}
1034
	// process ipopt and get destination
1035
	dest = ip_get_destination( header );
1036
	ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
1037
	route = ip_find_route( dest );
4707 mejdrech 1038
	if( ! route ){
1039
		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1040
		if( phone >= 0 ){
1041
			// unreachable ICMP
1042
			icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1043
		}
1044
		return ENOENT;
1045
	}
4505 mejdrech 1046
	if( route->address.s_addr == dest.s_addr ){
1047
		// local delivery
4707 mejdrech 1048
		return ip_deliver_local( device_id, packet, header, 0 );
4505 mejdrech 1049
	}else{
4695 mejdrech 1050
		// only if routing enabled
1051
		if( route->netif->routing ){
4707 mejdrech 1052
			-- header->ttl;
1053
			return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
1054
		}else{
1055
			phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1056
			if( phone >= 0 ){
1057
				// unreachable ICMP if no routing
1058
				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1059
			}
4695 mejdrech 1060
			return ENOENT;
1061
		}
4505 mejdrech 1062
	}
1063
}
1064
 
4707 mejdrech 1065
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
1066
	uint8_t *			data;
1067
	int					offset;
1068
	icmp_type_t			type;
1069
	icmp_code_t			code;
1070
	ip_netif_ref		netif;
1071
	measured_string_t	address;
1072
	ip_route_ref		route;
1073
	ip_header_ref		header;
1074
 
1075
	switch( error ){
1076
		case SERVICE_ICMP:
1077
			offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
1078
			if( offset < 0 ){
4711 mejdrech 1079
				return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1080
			}
1081
			data = packet_get_data( packet );
1082
			header = ( ip_header_ref ) data + offset;
1083
			// destination host unreachable?
1084
			if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
1085
				fibril_rwlock_read_lock( & ip_globals.netifs_lock );
1086
				netif = ip_netifs_find( & ip_globals.netifs, device_id );
1087
				if( netif && netif->arp ){
1088
					route = ip_routes_get_index( & netif->routes, 0 );
1089
					// from the same network?
1090
					if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
1091
						// clear the ARP mapping if any
1092
						address.value = ( char * ) & header->destination_address;
1093
						address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
1094
						arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
1095
					}
1096
				}
1097
				fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
1098
			}
1099
			break;
1100
		default:
4711 mejdrech 1101
			return ip_release_and_return( packet, ENOTSUP );
4707 mejdrech 1102
	}
1103
	return ip_deliver_local( device_id, packet, header, error );
1104
}
1105
 
1106
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
4505 mejdrech 1107
	ERROR_DECLARE;
1108
 
1109
	ip_proto_ref	proto;
4707 mejdrech 1110
	int				phone;
4505 mejdrech 1111
 
1112
	if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
1113
		// TODO fragmented
1114
		return ENOTSUP;
1115
	}else{
4558 mejdrech 1116
		ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
4582 mejdrech 1117
		fibril_rwlock_read_lock( & ip_globals.protos_lock );
4505 mejdrech 1118
		proto = ip_protos_find( & ip_globals.protos, header->protocol );
4558 mejdrech 1119
		if( ! proto ){
4582 mejdrech 1120
			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4707 mejdrech 1121
			phone = ip_prepare_icmp_and_get_phone( error, packet, header );
1122
			if( phone >= 0 ){
1123
				// unreachable ICMP
1124
				icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
1125
			}
4558 mejdrech 1126
			return ENOENT;
1127
		}
1128
		if( proto->received_msg ){
4707 mejdrech 1129
			ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error );
4505 mejdrech 1130
		}else{
4707 mejdrech 1131
			ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
4505 mejdrech 1132
		}
4582 mejdrech 1133
		fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4558 mejdrech 1134
		return ERROR_CODE;
4505 mejdrech 1135
	}
1136
}
1137
 
1138
in_addr_t ip_get_destination( ip_header_ref header ){
1139
	in_addr_t	destination;
1140
 
1141
	// TODO search set ipopt route?
4707 mejdrech 1142
	destination.s_addr = header->destination_address;
4505 mejdrech 1143
	return destination;
1144
}
1145
 
4707 mejdrech 1146
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
1147
	packet_t	next;
1148
 
1149
	// detach the first packet and release the others
1150
	next = pq_detach( packet );
1151
	if( next ){
1152
		pq_release( ip_globals.net_phone, packet_get_id( next ));
1153
	}
1154
	if( ! header ){
1155
		if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
1156
		// get header
1157
		header = ( ip_header_ref ) packet_get_data( packet );
1158
		if( ! header ) return EINVAL;
1159
	}
1160
	// only for the first fragment
1161
	if( header->fragment_offset ) return EINVAL;
1162
	// set the destination address
1163
	return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address ));
1164
}
1165
 
1166
int ip_get_icmp_phone( void ){
1167
	ip_proto_ref	proto;
1168
	int				phone;
1169
 
1170
	fibril_rwlock_read_lock( & ip_globals.protos_lock );
1171
	proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
1172
	phone = proto ? proto->phone : ENOENT;
1173
	fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1174
	return phone;
1175
}
1176
 
1177
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
1178
	int	phone;
1179
 
1180
	phone = ip_get_icmp_phone();
1181
	if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
4711 mejdrech 1182
		return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1183
	}
1184
	return phone;
1185
}
1186
 
4711 mejdrech 1187
int	ip_release_and_return( packet_t packet, int result ){
4707 mejdrech 1188
	pq_release( ip_globals.net_phone, packet_get_id( packet ));
1189
	return result;
1190
}
1191
 
3466 mejdrech 1192
/** @}
1193
 */