Subversion Repositories HelenOS

Rev

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