Subversion Repositories HelenOS

Rev

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