Subversion Repositories HelenOS

Rev

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