Subversion Repositories HelenOS

Rev

Rev 4589 | Rev 4702 | 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
34
 */
3666 mejdrech 35
 
3466 mejdrech 36
#include <async.h>
37
#include <errno.h>
4582 mejdrech 38
#include <fibril_sync.h>
3466 mejdrech 39
#include <stdio.h>
4327 mejdrech 40
#include <string.h>
3846 mejdrech 41
 
3466 mejdrech 42
#include <ipc/ipc.h>
43
#include <ipc/services.h>
44
 
4505 mejdrech 45
#include <sys/types.h>
46
 
3886 mejdrech 47
#include "../../err.h"
48
#include "../../messages.h"
49
#include "../../modules.h"
3466 mejdrech 50
 
4307 mejdrech 51
#include "../../include/net_interface.h"
4558 mejdrech 52
#include "../../include/inet.h"
3886 mejdrech 53
#include "../../include/socket.h"
4505 mejdrech 54
#include "../../include/byteorder.h"
55
#include "../../include/crc.h"
4243 mejdrech 56
#include "../../include/device.h"
4307 mejdrech 57
#include "../../include/arp_interface.h"
58
#include "../../include/nil_interface.h"
59
#include "../../include/il_interface.h"
4505 mejdrech 60
#include "../../include/ip_client.h"
4307 mejdrech 61
#include "../../include/ip_interface.h"
4505 mejdrech 62
#include "../../include/tl_interface.h"
3886 mejdrech 63
#include "../../structures/measured_strings.h"
4192 mejdrech 64
#include "../../structures/module_map.h"
3901 mejdrech 65
#include "../../structures/packet/packet_client.h"
3846 mejdrech 66
 
4307 mejdrech 67
#include "../../nil/nil_messages.h"
68
 
69
#include "../il_messages.h"
70
 
3466 mejdrech 71
#include "ip.h"
4505 mejdrech 72
#include "ip_header.h"
73
#include "ip_messages.h"
3846 mejdrech 74
#include "ip_module.h"
3466 mejdrech 75
 
3846 mejdrech 76
#define DEFAULT_IPV		4
4505 mejdrech 77
#define IP_MIN_CONTENT	576
3685 mejdrech 78
 
4192 mejdrech 79
#define ARP_NAME				"arp"
80
#define ARP_FILENAME			"/srv/arp"
81
 
4505 mejdrech 82
#define IP_ADDR							sizeof( in_addr_t )
83
#define IP_PREFIX						sizeof( ip_header_t )
84
#define IP_SUFFIX						0
85
#define IP_MAX_CONTENT					65535
4558 mejdrech 86
#define IP_HEADER_LENGTH( header )		(( header )->ihl * 4u )
4505 mejdrech 87
#define IP_TOTAL_LENGTH( header )		ntohs(( header )->total_length )
88
#define IP_HEADER_DATA_LENGTH( header )	( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header ))
89
#define IP_HEADER_CHECKSUM( header )	( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
90
 
91
//zero is returned as 0xFFFF (not flipped)
4558 mejdrech 92
#define IP_HEADER_CHECKSUM_ZERO			0xFFFFu
4505 mejdrech 93
 
3666 mejdrech 94
ip_globals_t	ip_globals;
3466 mejdrech 95
 
3666 mejdrech 96
DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
97
 
3846 mejdrech 98
INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
3685 mejdrech 99
 
4505 mejdrech 100
GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
101
 
4695 mejdrech 102
int	ip_mtu_changed_msg( device_id_t device_id, size_t mtu );
4307 mejdrech 103
int	ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state );
4505 mejdrech 104
int	ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
105
int	ip_netif_initialize( ip_netif_ref ip_netif );
3846 mejdrech 106
 
4505 mejdrech 107
int	ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest );
4575 mejdrech 108
int	ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
4505 mejdrech 109
 
110
packet_t	ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len );
111
int	ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len );
112
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 );
113
ip_header_ref	ip_create_middle_header( packet_t packet, ip_header_ref last );
4589 mejdrech 114
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
4505 mejdrech 115
 
116
in_addr_t *	ip_netif_addr( ip_netif_ref netif );
117
ip_route_ref	ip_find_route( in_addr_t destination );
118
ip_route_ref	ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
119
 
120
int	ip_received_msg( device_id_t device_id, packet_t packet );
121
int	ip_process_packet( device_id_t device_id, packet_t packet );
122
in_addr_t	ip_get_destination( ip_header_ref header );
123
int	ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header );
124
 
125
/** Computes the ip header checksum.
126
 *  To compute the checksum of a new packet, the checksum header field must be zero.
127
 *  To check the checksum of a received packet, the checksum may be left set.
128
 *  The zero (0) value will returned in this case if valid.
129
 *  @param data The header data. Input parameter.
130
 *  @param length The header length in bytes. Input parameter.
131
 *  @returns The internet protocol header checksum.
4558 mejdrech 132
 *  @returns 0xFFFF if the computed checksum is zero.
4505 mejdrech 133
 */
4558 mejdrech 134
uint16_t ip_checksum( uint8_t * data, size_t length );
4505 mejdrech 135
 
4558 mejdrech 136
uint16_t ip_checksum( uint8_t * data, size_t length ){
4505 mejdrech 137
	uint16_t	checksum;
138
 
139
	checksum = compact_checksum(compute_checksum( 0, data, length ));
140
 
141
	// flip, zero is returned as 0xFFFF (not flipped)
142
	return ( ~ checksum ) ? ~ checksum : IP_HEADER_CHECKSUM_ZERO;
143
}
144
 
3466 mejdrech 145
/**	Initializes the module.
146
 */
4351 mejdrech 147
int ip_initialize( async_client_conn_t client_connection ){
4192 mejdrech 148
	ERROR_DECLARE;
149
 
4582 mejdrech 150
	fibril_rwlock_initialize( & ip_globals.lock );
151
	fibril_rwlock_write_lock( & ip_globals.lock );
152
	fibril_rwlock_initialize( & ip_globals.protos_lock );
153
	fibril_rwlock_initialize( & ip_globals.netifs_lock );
4505 mejdrech 154
	ip_globals.packet_counter = 0;
155
	ip_globals.gateway.address.s_addr = 0;
156
	ip_globals.gateway.netmask.s_addr = 0;
157
	ip_globals.gateway.gateway.s_addr = 0;
158
	ip_globals.gateway.netif = NULL;
4192 mejdrech 159
	ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
160
	ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
4351 mejdrech 161
	ip_globals.client_connection = client_connection;
4192 mejdrech 162
	ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
4307 mejdrech 163
	ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
4582 mejdrech 164
	fibril_rwlock_write_unlock( & ip_globals.lock );
3466 mejdrech 165
	return EOK;
166
}
167
 
4350 mejdrech 168
int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
3666 mejdrech 169
	ERROR_DECLARE;
170
 
4505 mejdrech 171
	ip_netif_ref	ip_netif;
172
	ip_route_ref	route;
173
	int				index;
174
	char *			data;
175
 
176
	ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
177
	if( ! ip_netif ) return ENOMEM;
178
	if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
179
		free( ip_netif );
180
		return ERROR_CODE;
181
	}
182
	ip_netif->device_id = device_id;
183
	ip_netif->service = netif;
184
	ip_netif->state = NETIF_STOPPED;
4582 mejdrech 185
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 186
	if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
4582 mejdrech 187
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 188
		ip_routes_destroy( & ip_netif->routes );
189
		free( ip_netif );
190
		return ERROR_CODE;
191
	}
192
	if( ip_netif->arp ) ++ ip_netif->arp->usage;
193
	// print the settings
194
	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 );
195
	printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
196
	// TODO ipv6 addresses
197
	data = ( char * ) malloc( INET_ADDRSTRLEN );
198
	if( data ){
199
		for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
200
			route = ip_routes_get_index( & ip_netif->routes, index );
201
			if( route ){
202
				printf( "\tRouting %d:\n", index );
203
				inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
204
				printf( "\t\taddress\t= %s\n", data );
205
				inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
206
				printf( "\t\tnetmask\t= %s\n", data );
207
				inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
208
				printf( "\t\tgateway\t= %s\n", data );
209
			}
210
		}
211
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
212
		printf( "\tbroadcast\t= %s\n", data );
213
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
214
		printf( "\tdns1\t= %s\n", data );
215
		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
216
		printf( "\tdns2\t= %s\n", data );
217
		free( data );
218
	}
4582 mejdrech 219
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 220
	return EOK;
221
}
222
 
223
int ip_netif_initialize( ip_netif_ref ip_netif ){
224
	ERROR_DECLARE;
225
 
4695 mejdrech 226
	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 227
	measured_string_ref	configuration;
4505 mejdrech 228
	size_t				count = sizeof( names ) / sizeof( measured_string_t );
4307 mejdrech 229
	char *				data;
230
	int					index;
4505 mejdrech 231
	ip_route_ref		route;
232
	in_addr_t			gateway;
3666 mejdrech 233
 
4506 mejdrech 234
	ip_netif->arp = 0;
235
	route = NULL;
4307 mejdrech 236
	configuration = & names[ 0 ];
3846 mejdrech 237
	// get configuration
4307 mejdrech 238
	ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
239
	if( configuration ){
240
		if( configuration[ 0 ].value ){
241
			ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
3846 mejdrech 242
		}else{
243
			ip_netif->ipv = DEFAULT_IPV;
244
		}
4332 mejdrech 245
		ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
3846 mejdrech 246
		if( ip_netif->dhcp ){
247
			// TODO dhcp
4307 mejdrech 248
			net_free_settings( configuration, data );
3846 mejdrech 249
			return ENOTSUP;
250
		}else if( ip_netif->ipv == 4 ){
4505 mejdrech 251
			route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
252
			if( ! route ){
253
				net_free_settings( configuration, data );
254
				return ENOMEM;
255
			}
256
			route->address.s_addr = 0;
257
			route->netmask.s_addr = 0;
258
			route->gateway.s_addr = 0;
259
			route->netif = ip_netif;
260
			index = ip_routes_add( & ip_netif->routes, route );
261
			if( index < 0 ){
262
				net_free_settings( configuration, data );
263
				free( route );
264
				return index;
265
			}
266
			if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
267
			|| ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
268
			|| ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
269
			|| ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
4307 mejdrech 270
			|| ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
271
			|| ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
272
				net_free_settings( configuration, data );
3846 mejdrech 273
				return EINVAL;
274
			}
275
		}else{
4505 mejdrech 276
			// TODO ipv6 in separate module
4307 mejdrech 277
			net_free_settings( configuration, data );
3846 mejdrech 278
			return ENOTSUP;
279
		}
4307 mejdrech 280
		if( configuration[ 8 ].value ){
281
			ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
4192 mejdrech 282
			if( ! ip_netif->arp ){
4307 mejdrech 283
				printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
284
				net_free_settings( configuration, data );
4192 mejdrech 285
				return EINVAL;
286
			}
287
		}else{
288
			ip_netif->arp = NULL;
289
		}
4695 mejdrech 290
		ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' );
4307 mejdrech 291
		net_free_settings( configuration, data );
3846 mejdrech 292
	}
4558 mejdrech 293
	ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
4192 mejdrech 294
	if( ip_netif->phone < 0 ){
4505 mejdrech 295
		printf( "Failed to contact the nil service %d\n", ip_netif->service );
4192 mejdrech 296
		return ip_netif->phone;
297
	}
4505 mejdrech 298
	// MUST BE AFTER the bind_service up there!
4192 mejdrech 299
	if( ip_netif->arp ){
4506 mejdrech 300
		if( route ){
301
			configuration[ 0 ].value = ( char * ) & route->address.s_addr;
302
			configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 );
303
			ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & configuration[ 0 ] ));
304
		}else{
305
			ip_netif->arp = 0;
306
		}
4192 mejdrech 307
	}
4505 mejdrech 308
	// get packet dimensions
309
	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 ));
310
	if( ip_netif->content < IP_MIN_CONTENT ){
311
		printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
312
		ip_netif->content = IP_MIN_CONTENT;
313
	}
4192 mejdrech 314
	index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
4505 mejdrech 315
	if( index < 0 ) return index;
316
	if( gateway.s_addr ){
317
		// the default gateway
318
		ip_globals.gateway.address.s_addr = 0;
319
		ip_globals.gateway.netmask.s_addr = 0;
320
		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
321
		ip_globals.gateway.netif = ip_netif;
4192 mejdrech 322
	}
3846 mejdrech 323
	return EOK;
324
}
325
 
4695 mejdrech 326
int ip_mtu_changed_msg( device_id_t device_id, size_t mtu ){
327
	ip_netif_ref	netif;
328
 
329
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
330
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
331
	if( ! netif ){
332
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
333
		return ENOENT;
334
	}
335
	netif->content = mtu;
336
	printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
337
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
338
	return EOK;
339
}
340
 
4307 mejdrech 341
int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ){
4506 mejdrech 342
//	ERROR_DECLARE;
4243 mejdrech 343
 
4505 mejdrech 344
/*	measured_string_t	address;
345
	measured_string_ref	translation;
346
	char *				data;
347
*/
4506 mejdrech 348
/*	packet_t		packet;
4505 mejdrech 349
	in_addr_t		destination;
4506 mejdrech 350
*/
4243 mejdrech 351
	ip_netif_ref	netif;
352
 
4582 mejdrech 353
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4243 mejdrech 354
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 355
	if( ! netif ){
4582 mejdrech 356
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 357
		return ENOENT;
358
	}
4505 mejdrech 359
	netif->state = state;
3846 mejdrech 360
	// TODO state
4307 mejdrech 361
	printf( "ip - device %d changed state to %d\n\n", device_id, state );
4582 mejdrech 362
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4506 mejdrech 363
//	if( netif->arp ){
4505 mejdrech 364
/*		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
365
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
4327 mejdrech 366
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4505 mejdrech 367
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
368
		}
369
		printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
370
		free( translation );
371
		free( data );
372
		address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
373
		address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
374
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4327 mejdrech 375
			sleep( 2 );
376
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
377
		}
4307 mejdrech 378
		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 379
		free( translation );
380
		free( data );
4506 mejdrech 381
*//*		printf( "IP - testing to send packet:\n" );
4505 mejdrech 382
		ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
383
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
384
		if( ! packet ) return ENOMEM;
385
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
386
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
387
		if( ! packet ) return ENOMEM;
388
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
389
		packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
390
		if( ! packet ) return ENOMEM;
391
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
392
		packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
393
		if( ! packet ) return ENOMEM;
394
		// try this long version
395
//		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 ))
396
		if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
397
		|| ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
398
		|| ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
399
			pq_release( ip_globals.net_phone, packet_get_id( packet ));
400
		}
401
		ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
402
		printf( "send returned %d\n", ERROR_CODE );
4243 mejdrech 403
	}
4506 mejdrech 404
*/	return EOK;
4307 mejdrech 405
}
406
 
407
int ip_connect_module( services_t service ){
408
	return EOK;
409
}
410
 
4558 mejdrech 411
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
412
	return ip_register( protocol, me, 0, received_msg );
4505 mejdrech 413
}
414
 
4558 mejdrech 415
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
3846 mejdrech 416
	ip_proto_ref	proto;
4192 mejdrech 417
	int				index;
3846 mejdrech 418
 
4558 mejdrech 419
	if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
3846 mejdrech 420
	proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
421
	if( ! proto ) return ENOMEM;
422
	proto->protocol = protocol;
4505 mejdrech 423
	proto->service = service;
3846 mejdrech 424
	proto->phone = phone;
4558 mejdrech 425
	proto->received_msg = received_msg;
4582 mejdrech 426
	fibril_rwlock_write_lock( & ip_globals.protos_lock );
4192 mejdrech 427
	index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
428
	if( index < 0 ){
4582 mejdrech 429
		fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 430
		free( proto );
4192 mejdrech 431
		return index;
3846 mejdrech 432
	}
4307 mejdrech 433
	printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
4582 mejdrech 434
	fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 435
	return EOK;
436
}
437
 
4505 mejdrech 438
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender ){
439
	ERROR_DECLARE;
440
 
441
	int					length;
442
	ip_netif_ref		netif;
443
	ip_route_ref		route;
4575 mejdrech 444
	in_addr_t *			dest;
4505 mejdrech 445
	in_addr_t *			src;
446
 
447
	// addresses in the host byte order
448
	// should be the next hop address or the target destination address
4575 mejdrech 449
	length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest );
4505 mejdrech 450
	if( length < 0 ){
451
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
452
		return length;
453
	}
454
	// TODO IPv6
455
	if( length != IP_ADDR ){
456
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
457
		return EINVAL;
458
	}
4582 mejdrech 459
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4505 mejdrech 460
	// device specified?
461
//	dest.s_addr = ntohl( dest.s_addr );
4575 mejdrech 462
	if( device_id > 0 ){
4505 mejdrech 463
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
4575 mejdrech 464
		route = ip_netif_find_route( netif, * dest );
4505 mejdrech 465
	}else{
466
		// TODO IPv6
4575 mejdrech 467
		route = ip_find_route( * dest );
4505 mejdrech 468
		netif = route ? route->netif : NULL;
469
	}
470
	if( !( netif && route )){
4582 mejdrech 471
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 472
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
473
		return ENOENT;
474
	}
475
	// to me?
4575 mejdrech 476
	if( route->address.s_addr == dest->s_addr ){
4505 mejdrech 477
		// TODO loopback deliver
4582 mejdrech 478
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4558 mejdrech 479
		return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ));
4505 mejdrech 480
	}
481
 
482
	src = ip_netif_addr( netif );
483
	if( ! src ){
4582 mejdrech 484
		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 485
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
486
		return ENOENT;
487
	}
4575 mejdrech 488
	if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest ))){
4505 mejdrech 489
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
490
	}
4582 mejdrech 491
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 492
	return ERROR_CODE;
493
}
494
 
495
in_addr_t * ip_netif_addr( ip_netif_ref netif ){
496
	ip_route_ref	route;
497
 
498
	route = ip_routes_get_index( & netif->routes, 0 );
499
	return route ? & route->address : NULL;
500
}
501
 
502
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){
503
	ERROR_DECLARE;
504
 
505
	measured_string_t	destination;
506
	measured_string_ref	translation;
507
	char *				data;
508
 
509
	// get destination hardware address
510
	if( netif->arp ){
4575 mejdrech 511
		destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
4505 mejdrech 512
		destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
513
		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
4582 mejdrech 514
			sleep( 1 );
4505 mejdrech 515
			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
516
		}
517
		// TODO unreachable
518
		if( ! translation ) return EINVAL;
519
		if( ! translation->value ){
520
			// TODO unreachable
521
			free( translation );
522
			free( data );
523
			return EINVAL;
524
		}
525
	}else translation = NULL;
4589 mejdrech 526
	if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
527
		pq_release( ip_globals.net_phone, packet_get_id( packet ));
528
	}else{
529
		packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len );
530
		if( packet ){
531
			nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
4505 mejdrech 532
		}
4589 mejdrech 533
	}
4505 mejdrech 534
	if( translation ){
535
		free( translation );
536
		free( data );
537
	}
4589 mejdrech 538
	return ERROR_CODE;
3846 mejdrech 539
}
540
 
4575 mejdrech 541
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
4505 mejdrech 542
	ERROR_DECLARE;
543
 
4558 mejdrech 544
	size_t				length;
4505 mejdrech 545
	ip_header_ref		header;
4589 mejdrech 546
	ip_header_ref		last_header;
547
	ip_header_ref		middle_header;
548
	packet_t			next;
4505 mejdrech 549
 
550
	length = packet_get_data_length( packet );
551
	if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
552
	header = ( ip_header_ref ) packet_get_data( packet );
553
	if( destination ){
554
		ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
555
	}
556
	header->version = 4;
557
	header->fragment_offset = 0;
4589 mejdrech 558
	header->header_checksum = 0;
4575 mejdrech 559
	if( source ) header->source_address = source->s_addr;
560
	header->destination_address = dest.s_addr;
4582 mejdrech 561
	fibril_rwlock_write_lock( & ip_globals.lock );
4505 mejdrech 562
	++ ip_globals.packet_counter;
563
	header->identification = htons( ip_globals.packet_counter );
4582 mejdrech 564
	fibril_rwlock_write_unlock( & ip_globals.lock );
4589 mejdrech 565
	length = packet_get_data_length( packet );
566
	if( pq_next( packet )){
567
		last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
568
		if( ! last_header ) return ENOMEM;
569
		ip_create_last_header( last_header, header );
570
		next = pq_next( packet );
571
		while( pq_next( next )){
572
			middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
573
			if( ! middle_header ) return ENOMEM;
574
			memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
575
			header->flags |= IPFLAG_MORE_FRAGMENTS;
576
			middle_header->total_length = htons( packet_get_data_length( next ));
577
			middle_header->fragment_offset = length / 8;
578
			middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
579
			if( destination ){
580
				ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
581
			}
582
			length += packet_get_data_length( next );
583
			next = pq_next( next );
584
		}
585
		middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
586
		if( ! middle_header ) return ENOMEM;
587
		memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
588
		middle_header->total_length = htons( packet_get_data_length( next ));
589
		middle_header->fragment_offset = length / 8;
590
		middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
591
		if( destination ){
592
			ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
593
		}
594
		length += packet_get_data_length( next );
595
		free( last_header );
596
		header->flags |= IPFLAG_MORE_FRAGMENTS;
597
	}
598
	header->total_length = htons( length );
4505 mejdrech 599
	// unnecessary for all protocols
600
	header->header_checksum = IP_HEADER_CHECKSUM( header );
601
	return EOK;
602
}
603
 
3846 mejdrech 604
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
605
	ERROR_DECLARE;
606
 
607
	packet_t	packet;
608
 
609
	* answer_count = 0;
610
	switch( IPC_GET_METHOD( * call )){
3466 mejdrech 611
		case IPC_M_PHONE_HUNGUP:
612
			return EOK;
3666 mejdrech 613
		case NET_IL_DEVICE:
4307 mejdrech 614
			return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 615
		case IPC_M_CONNECT_TO_ME:
4505 mejdrech 616
			return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 617
		case NET_IL_SEND:
618
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
619
			return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 );
4351 mejdrech 620
		case NET_IL_DEVICE_STATE:
621
			return ip_device_state_msg( 0, IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
622
		case NET_IL_RECEIVED:
623
			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4505 mejdrech 624
			return ip_received_msg( IPC_GET_DEVICE( call ), packet );
625
		case NET_IP_ADD_ROUTE:
626
			return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
627
		case NET_IP_SET_GATEWAY:
628
			return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
629
		case NET_IL_PACKET_SPACE:
630
			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 )));
631
			* answer_count = 3;
632
			return EOK;
4695 mejdrech 633
		case NET_IL_MTU_CHANGED:
634
			return ip_mtu_changed_msg( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
3466 mejdrech 635
	}
636
	return ENOTSUP;
637
}
638
 
4505 mejdrech 639
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 ){
640
	ip_netif_ref	netif;
4575 mejdrech 641
	int				index;
4505 mejdrech 642
 
643
	if( !( addr_len && prefix && content && suffix )) return EBADMEM;
4575 mejdrech 644
	* content = IP_MAX_CONTENT - IP_PREFIX;
4582 mejdrech 645
	fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4575 mejdrech 646
	if( device_id < 0 ){
647
		* addr_len = IP_ADDR;
648
		* prefix = 0;
649
		* suffix = 0;
650
		for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
651
			netif = ip_netifs_get_index( & ip_globals.netifs, index );
652
			if( netif ){
653
				if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
654
				if( netif->prefix > * prefix ) * prefix = netif->prefix;
655
				if( netif->suffix > * suffix ) * suffix = netif->suffix;
656
			}
657
		}
658
		* prefix = * prefix + IP_PREFIX;
659
		* suffix = * suffix + IP_SUFFIX;
660
	}else{
661
		netif = ip_netifs_find( & ip_globals.netifs, device_id );
662
		if( ! netif ){
4582 mejdrech 663
			fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4575 mejdrech 664
			return ENOENT;
665
		}
666
		* addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
667
		* prefix = netif->prefix + IP_PREFIX;
668
		* suffix = netif->suffix + IP_SUFFIX;
4505 mejdrech 669
	}
4582 mejdrech 670
	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 671
	return EOK;
672
}
673
 
674
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 ){
675
	ip_route_ref	route;
676
	ip_netif_ref	netif;
677
	int				index;
678
 
4582 mejdrech 679
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 680
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 681
	if( ! netif ){
4582 mejdrech 682
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 683
		return ENOENT;
684
	}
4505 mejdrech 685
	route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
4558 mejdrech 686
	if( ! route ){
4582 mejdrech 687
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 688
		return ENOMEM;
689
	}
4505 mejdrech 690
	route->address.s_addr = address.s_addr;
691
	route->netmask.s_addr = netmask.s_addr;
692
	route->gateway.s_addr = gateway.s_addr;
693
	route->netif = netif;
694
	index = ip_routes_add( & netif->routes, route );
695
	if( index < 0 ) free( route );
4582 mejdrech 696
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 697
	return index;
698
}
699
 
700
ip_route_ref ip_find_route( in_addr_t destination ){
701
	int				index;
702
	ip_route_ref	route;
703
	ip_netif_ref	netif;
704
 
705
	// start with the last netif - the newest one
706
	index = ip_netifs_count( & ip_globals.netifs ) - 1;
707
	while( index >= 0 ){
708
		netif = ip_netifs_get_index( & ip_globals.netifs, index );
709
		if( netif && ( netif->state == NETIF_ACTIVE )){
710
			route = ip_netif_find_route( netif, destination );
711
			if( route ) return route;
712
		}
713
		-- index;
714
	}
715
	return & ip_globals.gateway;
716
}
717
 
718
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
719
	int				index;
720
	ip_route_ref	route;
721
 
722
	if( netif ){
723
		// start with the first one - the direct route
724
		for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
725
			route = ip_routes_get_index( & netif->routes, index );
726
			if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
727
				return route;
728
			}
729
		}
730
	}
731
	return NULL;
732
}
733
 
734
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
735
	ip_netif_ref	netif;
736
 
4582 mejdrech 737
	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 738
	netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 739
	if( ! netif ){
4582 mejdrech 740
		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 741
		return ENOENT;
742
	}
4505 mejdrech 743
	ip_globals.gateway.address.s_addr = 0;
744
	ip_globals.gateway.netmask.s_addr = 0;
745
	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
746
	ip_globals.gateway.netif = netif;
4582 mejdrech 747
	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 748
	return EOK;
749
}
750
 
751
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ){
752
	size_t			length;
753
	packet_t		next;
754
	packet_t		new_packet;
755
 
756
	next = packet;
757
	// check all packets
758
	while( next ){
759
		length = packet_get_data_length( next );
760
		// too long?
761
		if( length > content ){
762
			if( ip_fragment_packet( next, content, prefix, suffix, addr_len ) != EOK ){
763
				new_packet = pq_detach( next );
764
				if( next == packet ){
765
					packet = new_packet;
766
				}
767
				pq_release( ip_globals.net_phone, packet_get_id( next ));
768
				next = new_packet;
769
				continue;
770
			}
771
		}
772
		next = pq_next( next );
773
	}
774
	return packet;
775
}
776
 
777
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
778
	ERROR_DECLARE;
779
 
780
	packet_t		new_packet;
781
	ip_header_ref	header;
782
	ip_header_ref	middle_header;
783
	ip_header_ref	last_header;
784
	uint8_t *		src;
785
	uint8_t *		dest;
786
	int				address_length;
787
 
788
	address_length = packet_get_addr( packet, & src, & dest );
789
	if( address_length <= 0 ) return EINVAL;
790
	if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
791
	// get header
792
	header = ( ip_header_ref ) packet_get_data( packet );
793
	if( ! header ) return EINVAL;
794
	// fragmentation forbidden?
795
	if( header->flags & IPFLAG_DONT_FRAGMENT ){
796
		// TODO fragmentation necessary ICMP
797
		return EPERM;
798
	}
799
	// create the last fragment
4558 mejdrech 800
	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 801
	if( ! new_packet ) return ENOMEM;
4589 mejdrech 802
	// allocate as much as originally
803
	last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
4505 mejdrech 804
	if( ! last_header ){
805
		pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
806
		return ENOMEM;
807
	}
4589 mejdrech 808
	ip_create_last_header( last_header, header );
809
	// trim the unused space
810
	if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
811
		pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
812
		return ERROR_CODE;
813
	}
4505 mejdrech 814
	// biggest multiple of 8 lower than content
815
	// TODO even fragmentation?
816
	length = length & ( ~ 0x7 );// ( content / 8 ) * 8
817
	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 ))){
818
		pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
819
		return ERROR_CODE;
820
	}
821
	// mark the first as fragmented
822
	header->flags |= IPFLAG_MORE_FRAGMENTS;
823
	// create middle framgents
824
	while( IP_TOTAL_LENGTH( header ) > length ){
825
		new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
826
		if( ! new_packet ) return ENOMEM;
827
		middle_header = ip_create_middle_header( new_packet, last_header );
828
		if( ! middle_header ){
829
			pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
830
			return ENOMEM;
831
		}
832
		if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){
833
			pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
834
			return ERROR_CODE;
835
		}
836
	}
837
	// finish the first fragment
838
	header->header_checksum = IP_HEADER_CHECKSUM( header );
839
	printf( "ok\n" );
840
	return EOK;
841
}
842
 
843
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 ){
844
	ERROR_DECLARE;
845
 
846
	void *			data;
847
 
848
	data = packet_suffix( new_packet, length );
849
	if( ! data ) return ENOMEM;
850
	memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
851
	ERROR_PROPAGATE( packet_trim( packet, 0, length ));
852
	header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
853
	new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
854
	new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
855
	new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
856
	ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
857
	return pq_insert_after( packet, new_packet );
858
}
859
 
860
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
861
	ip_header_ref	middle;
862
 
863
	middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
864
	if( ! middle ) return NULL;
865
	memcpy( middle, last, IP_HEADER_LENGTH( last ));
866
	middle->flags |= IPFLAG_MORE_FRAGMENTS;
867
	return middle;
868
}
869
 
4589 mejdrech 870
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
4505 mejdrech 871
	ip_option_ref	option;
872
	size_t			next;
873
	size_t			length;
874
 
875
	// copy first itself
876
	memcpy( last, first, sizeof( ip_header_t ));
877
	length = sizeof( ip_header_t );
878
	next = sizeof( ip_header_t );
879
	// process all ip options
880
	while( next < first->ihl ){
881
		option = ( ip_option_ref ) ((( void * ) first ) + next );
882
		// skip end or noop
883
		if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
884
			++ next;
885
		}else{
886
			// copy if said so or skip
887
			if( IPOPT_COPIED( option->type )){
888
				memcpy((( void * ) last ) + length, (( void * ) first ) + next, option->length );
889
				length += option->length;
890
			}
891
			// next option
892
			next += option->length;
893
		}
894
	}
895
	// align 4 byte boundary
896
	if( length % 4 ){
897
		bzero((( void * ) last ) + length, 4 - ( length % 4 ));
898
		last->ihl = length / 4 + 1;
899
	}else{
900
		last->ihl = length / 4;
901
	}
4589 mejdrech 902
	last->header_checksum = 0;
4505 mejdrech 903
}
904
 
905
int ip_received_msg( device_id_t device_id, packet_t packet ){
906
	packet_t		next;
907
 
908
	do{
909
		next = pq_detach( packet );
910
		if( ip_process_packet( device_id, packet ) != EOK ){
911
			pq_release( ip_globals.net_phone, packet_get_id( packet ));
912
		}
913
		packet = next;
914
	}while( packet );
915
	return EOK;
916
}
917
 
918
int ip_process_packet( device_id_t device_id, packet_t packet ){
919
	ERROR_DECLARE;
920
 
921
	ip_header_ref	header;
922
	in_addr_t		dest;
923
	ip_route_ref	route;
924
 
925
	header = ( ip_header_ref ) packet_get_data( packet );
926
	if( ! header ) return ENOMEM;
927
	// checksum
928
	if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
929
		// TODO checksum error ICMP?
930
		return EINVAL;
931
	}
932
	// TODO ttl oxceeded ICMP?
933
	if( !( -- header->ttl )) return EINVAL;
934
	// process ipopt and get destination
935
	dest = ip_get_destination( header );
936
	ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
937
	route = ip_find_route( dest );
938
	// TODO unreachable ICMP?
939
	if( ! route ) return ENOENT;
940
	if( route->address.s_addr == dest.s_addr ){
941
		// local delivery
942
		return ip_deliver_local( device_id, packet, header );
943
	}else{
4695 mejdrech 944
		// only if routing enabled
945
		if( route->netif->routing ){
946
			return ip_send_route( packet, route->netif, route, NULL, dest );
947
		}
948
		else
949
		{
950
			// TODO icmp unreachable?
951
			return ENOENT;
952
		}
4505 mejdrech 953
	}
954
}
955
 
956
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ){
957
	ERROR_DECLARE;
958
 
959
	ip_proto_ref	proto;
960
 
961
	if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
962
		// TODO fragmented
963
		return ENOTSUP;
964
	}else{
4558 mejdrech 965
		ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
4582 mejdrech 966
		fibril_rwlock_read_lock( & ip_globals.protos_lock );
4505 mejdrech 967
		proto = ip_protos_find( & ip_globals.protos, header->protocol );
4558 mejdrech 968
		if( ! proto ){
4582 mejdrech 969
			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4558 mejdrech 970
			return ENOENT;
971
		}
972
		if( proto->received_msg ){
973
			ERROR_CODE = proto->received_msg( device_id, packet, SERVICE_IP );
4505 mejdrech 974
		}else{
4558 mejdrech 975
			ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service );
4505 mejdrech 976
		}
4582 mejdrech 977
		fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4558 mejdrech 978
		return ERROR_CODE;
4505 mejdrech 979
	}
980
}
981
 
982
in_addr_t ip_get_destination( ip_header_ref header ){
983
	in_addr_t	destination;
984
 
985
	// TODO search set ipopt route?
986
	destination.s_addr = header->destination_address; //ntohl( header->destination_address );
987
	return destination;
988
}
989
 
3466 mejdrech 990
/** @}
991
 */