Subversion Repositories HelenOS

Rev

Rev 4724 | Rev 4731 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3466 mejdrech 1
/*
3912 mejdrech 2
 * Copyright (c) 2009 Lukas Mejdrech
3466 mejdrech 3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
3912 mejdrech 29
/** @addtogroup ip
30
 *  @{
3466 mejdrech 31
 */
32
 
33
/** @file
4702 mejdrech 34
 *  IP module implementation.
35
 *  @see arp.h
36
 *  \todo
3466 mejdrech 37
 */
3666 mejdrech 38
 
3466 mejdrech 39
#include <async.h>
40
#include <errno.h>
4582 mejdrech 41
#include <fibril_sync.h>
3466 mejdrech 42
#include <stdio.h>
4327 mejdrech 43
#include <string.h>
3846 mejdrech 44
 
3466 mejdrech 45
#include <ipc/ipc.h>
46
#include <ipc/services.h>
47
 
4505 mejdrech 48
#include <sys/types.h>
49
 
3886 mejdrech 50
#include "../../err.h"
51
#include "../../messages.h"
52
#include "../../modules.h"
3466 mejdrech 53
 
4720 mejdrech 54
#include "../../include/arp_interface.h"
4505 mejdrech 55
#include "../../include/byteorder.h"
56
#include "../../include/crc.h"
4243 mejdrech 57
#include "../../include/device.h"
4720 mejdrech 58
#include "../../include/icmp_client.h"
59
#include "../../include/icmp_codes.h"
60
#include "../../include/icmp_interface.h"
4307 mejdrech 61
#include "../../include/il_interface.h"
4720 mejdrech 62
#include "../../include/in.h"
63
#include "../../include/in6.h"
64
#include "../../include/inet.h"
4505 mejdrech 65
#include "../../include/ip_client.h"
4307 mejdrech 66
#include "../../include/ip_interface.h"
4720 mejdrech 67
#include "../../include/net_interface.h"
68
#include "../../include/nil_interface.h"
4505 mejdrech 69
#include "../../include/tl_interface.h"
4720 mejdrech 70
#include "../../include/socket_codes.h"
71
#include "../../include/socket_errno.h"
3886 mejdrech 72
#include "../../structures/measured_strings.h"
4192 mejdrech 73
#include "../../structures/module_map.h"
3901 mejdrech 74
#include "../../structures/packet/packet_client.h"
3846 mejdrech 75
 
4307 mejdrech 76
#include "../../nil/nil_messages.h"
77
 
78
#include "../il_messages.h"
79
 
3466 mejdrech 80
#include "ip.h"
4505 mejdrech 81
#include "ip_header.h"
82
#include "ip_messages.h"
3846 mejdrech 83
#include "ip_module.h"
3466 mejdrech 84
 
4722 mejdrech 85
/** IP version 4.
4702 mejdrech 86
 */
4722 mejdrech 87
#define IPV4                4
4702 mejdrech 88
 
4722 mejdrech 89
/** Default network interface IP version.
90
 */
91
#define NET_DEFAULT_IPV     IPV4
92
 
93
/** Default network interface IP routing.
94
 */
95
#define NET_DEFAULT_IP_ROUTING  false
96
 
4702 mejdrech 97
/** Minimum IP packet content.
98
 */
4505 mejdrech 99
#define IP_MIN_CONTENT  576
3685 mejdrech 100
 
4702 mejdrech 101
/** ARP module name.
102
 */
4192 mejdrech 103
#define ARP_NAME                "arp"
4702 mejdrech 104
 
105
/** ARP module filename.
106
 */
4192 mejdrech 107
#define ARP_FILENAME            "/srv/arp"
108
 
4702 mejdrech 109
/** IP packet address length.
110
 */
4720 mejdrech 111
#define IP_ADDR                         sizeof( struct sockaddr_in6 )
4702 mejdrech 112
 
113
/** IP packet prefix length.
114
 */
4505 mejdrech 115
#define IP_PREFIX                       sizeof( ip_header_t )
4702 mejdrech 116
 
117
/** IP packet suffix length.
118
 */
4505 mejdrech 119
#define IP_SUFFIX                       0
4702 mejdrech 120
 
121
/** IP packet maximum content length.
122
 */
4505 mejdrech 123
#define IP_MAX_CONTENT                  65535
4702 mejdrech 124
 
4724 mejdrech 125
/** The IP localhost address.
126
 */
127
#define IPV4_LOCALHOST_ADDRESS  htonl(( 127 << 24 ) + 1 )
128
 
4702 mejdrech 129
/** IP global data.
130
 */
3666 mejdrech 131
ip_globals_t    ip_globals;
3466 mejdrech 132
 
3666 mejdrech 133
DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
134
 
3846 mejdrech 135
INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
3685 mejdrech 136
 
4505 mejdrech 137
GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
138
 
4702 mejdrech 139
/** Updates the device content length according to the new MTU value.
140
 *  @param device_id The device identifier. Input parameter.
141
 *  @param mtu The new mtu value. Input parameter.
142
 *  @returns EOK on success.
143
 *  @returns ENOENT if device is not found.
144
 */
145
int ip_mtu_changed_message( device_id_t device_id, size_t mtu );
146
 
147
/** Updates the device state.
148
 *  @param device_id The device identifier. Input parameter.
149
 *  @param state The new state value. Input parameter.
150
 *  @returns EOK on success.
151
 *  @returns ENOENT if device is not found.
152
 */
153
int ip_device_state_message( device_id_t device_id, device_state_t state );
154
 
4505 mejdrech 155
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
4702 mejdrech 156
 
157
/** Initializes a new network interface specific data.
158
 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
159
 *  The device identifier and the nil service has to be set.
160
 *  @param ip_netif Network interface specific data. Input/output parameter.
161
 *  @returns EOK on success.
162
 *  @returns ENOTSUP if DHCP is configured.
163
 *  @returns ENOTSUP if IPv6 is configured.
164
 *  @returns EINVAL if any of the addresses is invalid.
165
 *  @returns EINVAL if the used ARP module is not known.
166
 *  @returns ENOMEM if there is not enough memory left.
167
 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
168
 *  @returns Other error codes as defined for the bind_service() function.
169
 *  @returns Other error codes as defined for the specific arp_device_req() function.
170
 *  @returns Other error codes as defined for the nil_packet_size_req() function.
171
 */
4505 mejdrech 172
int ip_netif_initialize( ip_netif_ref ip_netif );
3846 mejdrech 173
 
4707 mejdrech 174
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error );
4575 mejdrech 175
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
4505 mejdrech 176
 
4720 mejdrech 177
packet_t    ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error );
178
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len );
179
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen );
4505 mejdrech 180
ip_header_ref   ip_create_middle_header( packet_t packet, ip_header_ref last );
4589 mejdrech 181
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
4505 mejdrech 182
 
4707 mejdrech 183
in_addr_t * ip_netif_address( ip_netif_ref netif );
4505 mejdrech 184
ip_route_ref    ip_find_route( in_addr_t destination );
185
ip_route_ref    ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
186
 
4702 mejdrech 187
/** Processes the received IP packet.
188
 *  @param device_id The source device identifier. Input parameter.
189
 *  @param packet The received packet. Input/output parameter.
190
 *  @returns EOK on success and the packet is no longer needed.
191
 *  @returns EINVAL if the packet is too small to carry the IP packet.
192
 *  @returns EINVAL if the received address lengths differs from the registered values.
193
 *  @returns ENOENT if the device is not found in the cache.
194
 *  @returns ENOENT if the protocol for the device is not found in the cache.
195
 *  @returns ENOMEM if there is not enough memory left.
196
 */
197
int ip_receive_message( device_id_t device_id, packet_t packet );
198
 
4505 mejdrech 199
int ip_process_packet( device_id_t device_id, packet_t packet );
200
in_addr_t   ip_get_destination( ip_header_ref header );
4707 mejdrech 201
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
4505 mejdrech 202
 
4707 mejdrech 203
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
204
int ip_get_icmp_phone( void );
205
int ip_prepare_icmp( packet_t packet, ip_header_ref header );
206
 
4711 mejdrech 207
int ip_release_and_return( packet_t packet, int result );
4707 mejdrech 208
 
4351 mejdrech 209
int ip_initialize( async_client_conn_t client_connection ){
4192 mejdrech 210
    ERROR_DECLARE;
211
 
4582 mejdrech 212
    fibril_rwlock_initialize( & ip_globals.lock );
213
    fibril_rwlock_write_lock( & ip_globals.lock );
214
    fibril_rwlock_initialize( & ip_globals.protos_lock );
215
    fibril_rwlock_initialize( & ip_globals.netifs_lock );
4505 mejdrech 216
    ip_globals.packet_counter = 0;
217
    ip_globals.gateway.address.s_addr = 0;
218
    ip_globals.gateway.netmask.s_addr = 0;
219
    ip_globals.gateway.gateway.s_addr = 0;
220
    ip_globals.gateway.netif = NULL;
4192 mejdrech 221
    ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
222
    ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
4351 mejdrech 223
    ip_globals.client_connection = client_connection;
4192 mejdrech 224
    ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
4307 mejdrech 225
    ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
4582 mejdrech 226
    fibril_rwlock_write_unlock( & ip_globals.lock );
3466 mejdrech 227
    return EOK;
228
}
229
 
4350 mejdrech 230
int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
3666 mejdrech 231
    ERROR_DECLARE;
232
 
4505 mejdrech 233
    ip_netif_ref    ip_netif;
234
    ip_route_ref    route;
235
    int             index;
236
    char *          data;
237
 
238
    ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
239
    if( ! ip_netif ) return ENOMEM;
240
    if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
241
        free( ip_netif );
242
        return ERROR_CODE;
243
    }
244
    ip_netif->device_id = device_id;
245
    ip_netif->service = netif;
246
    ip_netif->state = NETIF_STOPPED;
4582 mejdrech 247
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 248
    if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
4582 mejdrech 249
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 250
        ip_routes_destroy( & ip_netif->routes );
251
        free( ip_netif );
252
        return ERROR_CODE;
253
    }
254
    if( ip_netif->arp ) ++ ip_netif->arp->usage;
255
    // print the settings
256
    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 );
257
    printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
258
    // TODO ipv6 addresses
259
    data = ( char * ) malloc( INET_ADDRSTRLEN );
260
    if( data ){
261
        for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
262
            route = ip_routes_get_index( & ip_netif->routes, index );
263
            if( route ){
264
                printf( "\tRouting %d:\n", index );
265
                inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
266
                printf( "\t\taddress\t= %s\n", data );
267
                inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
268
                printf( "\t\tnetmask\t= %s\n", data );
269
                inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
270
                printf( "\t\tgateway\t= %s\n", data );
271
            }
272
        }
273
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
274
        printf( "\tbroadcast\t= %s\n", data );
275
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
276
        printf( "\tdns1\t= %s\n", data );
277
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
278
        printf( "\tdns2\t= %s\n", data );
279
        free( data );
280
    }
4582 mejdrech 281
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 282
    return EOK;
283
}
284
 
285
int ip_netif_initialize( ip_netif_ref ip_netif ){
286
    ERROR_DECLARE;
287
 
4695 mejdrech 288
    measured_string_t   names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
4307 mejdrech 289
    measured_string_ref configuration;
4505 mejdrech 290
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
4307 mejdrech 291
    char *              data;
4717 mejdrech 292
    measured_string_t   address;
4307 mejdrech 293
    int                 index;
4505 mejdrech 294
    ip_route_ref        route;
295
    in_addr_t           gateway;
3666 mejdrech 296
 
4702 mejdrech 297
    ip_netif->arp = NULL;
4506 mejdrech 298
    route = NULL;
4722 mejdrech 299
    ip_netif->ipv = NET_DEFAULT_IPV;
300
    ip_netif->dhcp = false;
301
    ip_netif->routing = NET_DEFAULT_IP_ROUTING;
4307 mejdrech 302
    configuration = & names[ 0 ];
3846 mejdrech 303
    // get configuration
4307 mejdrech 304
    ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
305
    if( configuration ){
306
        if( configuration[ 0 ].value ){
307
            ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
3846 mejdrech 308
        }
4332 mejdrech 309
        ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
3846 mejdrech 310
        if( ip_netif->dhcp ){
311
            // TODO dhcp
4307 mejdrech 312
            net_free_settings( configuration, data );
3846 mejdrech 313
            return ENOTSUP;
4722 mejdrech 314
        }else if( ip_netif->ipv == IPV4 ){
4505 mejdrech 315
            route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
316
            if( ! route ){
317
                net_free_settings( configuration, data );
318
                return ENOMEM;
319
            }
320
            route->address.s_addr = 0;
321
            route->netmask.s_addr = 0;
322
            route->gateway.s_addr = 0;
323
            route->netif = ip_netif;
324
            index = ip_routes_add( & ip_netif->routes, route );
325
            if( index < 0 ){
326
                net_free_settings( configuration, data );
327
                free( route );
328
                return index;
329
            }
330
            if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
331
            || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
332
            || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
333
            || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
4307 mejdrech 334
            || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
335
            || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
336
                net_free_settings( configuration, data );
3846 mejdrech 337
                return EINVAL;
338
            }
339
        }else{
4505 mejdrech 340
            // TODO ipv6 in separate module
4307 mejdrech 341
            net_free_settings( configuration, data );
3846 mejdrech 342
            return ENOTSUP;
343
        }
4307 mejdrech 344
        if( configuration[ 8 ].value ){
345
            ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
4192 mejdrech 346
            if( ! ip_netif->arp ){
4307 mejdrech 347
                printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
348
                net_free_settings( configuration, data );
4192 mejdrech 349
                return EINVAL;
350
            }
351
        }
4722 mejdrech 352
        if( configuration[ 9 ].value ){
353
            ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' );
354
        }
4307 mejdrech 355
        net_free_settings( configuration, data );
3846 mejdrech 356
    }
4717 mejdrech 357
    // binds the netif service which also initializes the device
4558 mejdrech 358
    ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
4192 mejdrech 359
    if( ip_netif->phone < 0 ){
4505 mejdrech 360
        printf( "Failed to contact the nil service %d\n", ip_netif->service );
4192 mejdrech 361
        return ip_netif->phone;
362
    }
4717 mejdrech 363
    // has to be after the device netif module initialization
4192 mejdrech 364
    if( ip_netif->arp ){
4506 mejdrech 365
        if( route ){
4717 mejdrech 366
            address.value = ( char * ) & route->address.s_addr;
367
            address.length = CONVERT_SIZE( in_addr_t, char, 1 );
368
            ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address ));
4506 mejdrech 369
        }else{
370
            ip_netif->arp = 0;
371
        }
4192 mejdrech 372
    }
4505 mejdrech 373
    // get packet dimensions
374
    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 ));
375
    if( ip_netif->content < IP_MIN_CONTENT ){
376
        printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
377
        ip_netif->content = IP_MIN_CONTENT;
378
    }
4192 mejdrech 379
    index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
4505 mejdrech 380
    if( index < 0 ) return index;
381
    if( gateway.s_addr ){
382
        // the default gateway
383
        ip_globals.gateway.address.s_addr = 0;
384
        ip_globals.gateway.netmask.s_addr = 0;
385
        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
386
        ip_globals.gateway.netif = ip_netif;
4192 mejdrech 387
    }
3846 mejdrech 388
    return EOK;
389
}
390
 
4702 mejdrech 391
int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
4695 mejdrech 392
    ip_netif_ref    netif;
393
 
394
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
395
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
396
    if( ! netif ){
397
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
398
        return ENOENT;
399
    }
400
    netif->content = mtu;
401
    printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
402
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
403
    return EOK;
404
}
405
 
4702 mejdrech 406
int ip_device_state_message( device_id_t device_id, device_state_t state ){
4506 mejdrech 407
//  ERROR_DECLARE;
4243 mejdrech 408
 
4505 mejdrech 409
/*  measured_string_t   address;
410
    measured_string_ref translation;
411
    char *              data;
412
*/
4506 mejdrech 413
/*  packet_t        packet;
4505 mejdrech 414
    in_addr_t       destination;
4506 mejdrech 415
*/
4243 mejdrech 416
    ip_netif_ref    netif;
417
 
4582 mejdrech 418
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4243 mejdrech 419
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 420
    if( ! netif ){
4582 mejdrech 421
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 422
        return ENOENT;
423
    }
4505 mejdrech 424
    netif->state = state;
3846 mejdrech 425
    // TODO state
4307 mejdrech 426
    printf( "ip - device %d changed state to %d\n\n", device_id, state );
4582 mejdrech 427
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4506 mejdrech 428
//  if( netif->arp ){
4505 mejdrech 429
/*      address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
430
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
4327 mejdrech 431
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4505 mejdrech 432
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
433
        }
434
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
435
        free( translation );
436
        free( data );
437
        address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
438
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
439
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4327 mejdrech 440
            sleep( 2 );
441
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
442
        }
4307 mejdrech 443
        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 444
        free( translation );
445
        free( data );
4506 mejdrech 446
*//*        printf( "IP - testing to send packet:\n" );
4505 mejdrech 447
        ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
448
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
449
        if( ! packet ) return ENOMEM;
450
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
451
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
452
        if( ! packet ) return ENOMEM;
453
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
454
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
455
        if( ! packet ) return ENOMEM;
456
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
457
        packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
458
        if( ! packet ) return ENOMEM;
459
        // try this long version
460
//      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 ))
461
        if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
462
        || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
463
        || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
464
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
465
        }
466
        ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
467
        printf( "send returned %d\n", ERROR_CODE );
4243 mejdrech 468
    }
4506 mejdrech 469
*/  return EOK;
4307 mejdrech 470
}
471
 
472
int ip_connect_module( services_t service ){
473
    return EOK;
474
}
475
 
4558 mejdrech 476
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
477
    return ip_register( protocol, me, 0, received_msg );
4505 mejdrech 478
}
479
 
4558 mejdrech 480
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
3846 mejdrech 481
    ip_proto_ref    proto;
4192 mejdrech 482
    int             index;
3846 mejdrech 483
 
4558 mejdrech 484
    if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
3846 mejdrech 485
    proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
486
    if( ! proto ) return ENOMEM;
487
    proto->protocol = protocol;
4505 mejdrech 488
    proto->service = service;
3846 mejdrech 489
    proto->phone = phone;
4558 mejdrech 490
    proto->received_msg = received_msg;
4582 mejdrech 491
    fibril_rwlock_write_lock( & ip_globals.protos_lock );
4192 mejdrech 492
    index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
493
    if( index < 0 ){
4582 mejdrech 494
        fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 495
        free( proto );
4192 mejdrech 496
        return index;
3846 mejdrech 497
    }
4307 mejdrech 498
    printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
4582 mejdrech 499
    fibril_rwlock_write_unlock( & ip_globals.protos_lock );
3846 mejdrech 500
    return EOK;
501
}
502
 
4707 mejdrech 503
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
4505 mejdrech 504
    ERROR_DECLARE;
505
 
4720 mejdrech 506
    int                 addrlen;
4505 mejdrech 507
    ip_netif_ref        netif;
508
    ip_route_ref        route;
4720 mejdrech 509
    struct sockaddr *       addr;
510
    struct sockaddr_in *    address_in;
511
//  struct sockaddr_in6 *   address_in6;
4575 mejdrech 512
    in_addr_t *         dest;
4505 mejdrech 513
    in_addr_t *         src;
4707 mejdrech 514
    int                 phone;
4505 mejdrech 515
 
516
    // addresses in the host byte order
517
    // should be the next hop address or the target destination address
4720 mejdrech 518
    addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr );
519
    if( addrlen < 0 ){
520
        return ip_release_and_return( packet, addrlen );
4505 mejdrech 521
    }
4720 mejdrech 522
    if( addrlen < sizeof( struct sockaddr )){
4711 mejdrech 523
        return ip_release_and_return( packet, EINVAL );
4505 mejdrech 524
    }
4720 mejdrech 525
    switch( addr->sa_family ){
526
        case AF_INET:
527
            if( addrlen != sizeof( struct sockaddr_in )){
528
                return ip_release_and_return( packet, EINVAL );
529
            }
530
            address_in = ( struct sockaddr_in * ) addr;
531
            dest = & address_in->sin_addr;
532
            break;
533
        // TODO IPv6
534
/*      case AF_INET6:
535
            if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
536
            address_in6 = ( struct sockaddr_in6 * ) dest;
537
            address_in6.sin6_addr.s6_addr;
538
*/      default:
539
            return ip_release_and_return( packet, EAFNOSUPPORT );
540
    }
4582 mejdrech 541
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4505 mejdrech 542
    // device specified?
4575 mejdrech 543
    if( device_id > 0 ){
4505 mejdrech 544
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
4575 mejdrech 545
        route = ip_netif_find_route( netif, * dest );
4505 mejdrech 546
    }else{
4575 mejdrech 547
        route = ip_find_route( * dest );
4505 mejdrech 548
        netif = route ? route->netif : NULL;
549
    }
550
    if( !( netif && route )){
4582 mejdrech 551
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4707 mejdrech 552
        phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
553
        if( phone >= 0 ){
554
            // unreachable ICMP if no routing
4724 mejdrech 555
            icmp_destination_unreachable_msg( phone, ICMP_NET_UNREACH, 0, packet );
4707 mejdrech 556
        }
4505 mejdrech 557
        return ENOENT;
558
    }
4707 mejdrech 559
    if( error ){
560
        // do not send for broadcast, anycast packets or network broadcast
561
        if(( ! dest->s_addr )
562
        || ( !( ~ dest->s_addr ))
563
        || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
564
        || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
4711 mejdrech 565
            return ip_release_and_return( packet, EINVAL );
4707 mejdrech 566
        }
567
    }
4724 mejdrech 568
    if( route->address.s_addr == dest->s_addr ){
569
        // find the loopback device to deliver
570
        dest->s_addr = IPV4_LOCALHOST_ADDRESS;
571
        route = ip_find_route( * dest );
572
        netif = route ? route->netif : NULL;
573
        if( !( netif && route )){
574
            fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
575
            phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
576
            if( phone >= 0 ){
577
                // unreachable ICMP if no routing
578
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
579
            }
580
            return ENOENT;
581
        }
582
    }
4707 mejdrech 583
    src = ip_netif_address( netif );
4505 mejdrech 584
    if( ! src ){
4582 mejdrech 585
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4711 mejdrech 586
        return ip_release_and_return( packet, ENOENT );
4505 mejdrech 587
    }
4720 mejdrech 588
    ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error );
4582 mejdrech 589
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 590
    return ERROR_CODE;
591
}
592
 
4707 mejdrech 593
in_addr_t * ip_netif_address( ip_netif_ref netif ){
4505 mejdrech 594
    ip_route_ref    route;
595
 
596
    route = ip_routes_get_index( & netif->routes, 0 );
597
    return route ? & route->address : NULL;
598
}
599
 
4707 mejdrech 600
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ){
4505 mejdrech 601
    ERROR_DECLARE;
602
 
603
    measured_string_t   destination;
604
    measured_string_ref translation;
605
    char *              data;
4707 mejdrech 606
    int                 phone;
4505 mejdrech 607
 
608
    // get destination hardware address
4722 mejdrech 609
    if( netif->arp && ( route->address.s_addr != dest.s_addr )){
4575 mejdrech 610
        destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
4505 mejdrech 611
        destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
612
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
4720 mejdrech 613
//          sleep( 1 );
614
//          ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
615
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
616
            return ERROR_CODE;
4505 mejdrech 617
        }
4707 mejdrech 618
        if( !( translation && translation->value )){
619
            if( translation ){
620
                free( translation );
621
                free( data );
622
            }
623
            phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
624
            if( phone >= 0 ){
625
                // unreachable ICMP if no routing
626
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
627
            }
4505 mejdrech 628
            return EINVAL;
629
        }
630
    }else translation = NULL;
4589 mejdrech 631
    if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
632
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
633
    }else{
4707 mejdrech 634
        packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
4589 mejdrech 635
        if( packet ){
636
            nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
4505 mejdrech 637
        }
4589 mejdrech 638
    }
4505 mejdrech 639
    if( translation ){
640
        free( translation );
641
        free( data );
642
    }
4589 mejdrech 643
    return ERROR_CODE;
3846 mejdrech 644
}
645
 
4575 mejdrech 646
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
4505 mejdrech 647
    ERROR_DECLARE;
648
 
4558 mejdrech 649
    size_t              length;
4505 mejdrech 650
    ip_header_ref       header;
4589 mejdrech 651
    ip_header_ref       last_header;
652
    ip_header_ref       middle_header;
653
    packet_t            next;
4505 mejdrech 654
 
655
    length = packet_get_data_length( packet );
656
    if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
657
    header = ( ip_header_ref ) packet_get_data( packet );
658
    if( destination ){
659
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
4722 mejdrech 660
    }else{
661
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
4505 mejdrech 662
    }
4722 mejdrech 663
    header->version = IPV4;
4505 mejdrech 664
    header->fragment_offset = 0;
4589 mejdrech 665
    header->header_checksum = 0;
4575 mejdrech 666
    if( source ) header->source_address = source->s_addr;
667
    header->destination_address = dest.s_addr;
4582 mejdrech 668
    fibril_rwlock_write_lock( & ip_globals.lock );
4505 mejdrech 669
    ++ ip_globals.packet_counter;
670
    header->identification = htons( ip_globals.packet_counter );
4582 mejdrech 671
    fibril_rwlock_write_unlock( & ip_globals.lock );
4589 mejdrech 672
    length = packet_get_data_length( packet );
673
    if( pq_next( packet )){
674
        last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
675
        if( ! last_header ) return ENOMEM;
676
        ip_create_last_header( last_header, header );
677
        next = pq_next( packet );
678
        while( pq_next( next )){
679
            middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
680
            if( ! middle_header ) return ENOMEM;
681
            memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
682
            header->flags |= IPFLAG_MORE_FRAGMENTS;
683
            middle_header->total_length = htons( packet_get_data_length( next ));
4728 mejdrech 684
            middle_header->fragment_offset = IP_COMPUTE_FRAGMENT_OFFSET( length );
4589 mejdrech 685
            middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
686
            if( destination ){
687
                ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
688
            }
689
            length += packet_get_data_length( next );
690
            next = pq_next( next );
691
        }
692
        middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
693
        if( ! middle_header ) return ENOMEM;
694
        memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
695
        middle_header->total_length = htons( packet_get_data_length( next ));
4728 mejdrech 696
        middle_header->fragment_offset = IP_COMPUTE_FRAGMENT_OFFSET( length );
4589 mejdrech 697
        middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
698
        if( destination ){
699
            ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
700
        }
701
        length += packet_get_data_length( next );
702
        free( last_header );
703
        header->flags |= IPFLAG_MORE_FRAGMENTS;
704
    }
705
    header->total_length = htons( length );
4505 mejdrech 706
    // unnecessary for all protocols
707
    header->header_checksum = IP_HEADER_CHECKSUM( header );
708
    return EOK;
709
}
710
 
3846 mejdrech 711
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
712
    ERROR_DECLARE;
713
 
4722 mejdrech 714
    packet_t                packet;
715
    struct sockaddr *       addr;
716
    size_t                  addrlen;
717
    ip_pseudo_header_ref    header;
718
    size_t                  headerlen;
3846 mejdrech 719
 
720
    * answer_count = 0;
721
    switch( IPC_GET_METHOD( * call )){
3466 mejdrech 722
        case IPC_M_PHONE_HUNGUP:
723
            return EOK;
3666 mejdrech 724
        case NET_IL_DEVICE:
4307 mejdrech 725
            return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 726
        case IPC_M_CONNECT_TO_ME:
4505 mejdrech 727
            return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 728
        case NET_IL_SEND:
729
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4707 mejdrech 730
            return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
4351 mejdrech 731
        case NET_IL_DEVICE_STATE:
4702 mejdrech 732
            return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
4351 mejdrech 733
        case NET_IL_RECEIVED:
734
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4702 mejdrech 735
            return ip_receive_message( IPC_GET_DEVICE( call ), packet );
4707 mejdrech 736
        case NET_IP_RECEIVED_ERROR:
737
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
738
            return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
4505 mejdrech 739
        case NET_IP_ADD_ROUTE:
740
            return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
741
        case NET_IP_SET_GATEWAY:
742
            return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
4722 mejdrech 743
        case NET_IP_GET_ROUTE:
744
            ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
745
            ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
746
            * IP_SET_HEADERLEN( answer ) = headerlen;
747
            if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
748
                ERROR_CODE = data_reply( header, headerlen );
749
            }
750
            free( header );
751
            return ERROR_CODE;
4505 mejdrech 752
        case NET_IL_PACKET_SPACE:
753
            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 )));
754
            * answer_count = 3;
755
            return EOK;
4695 mejdrech 756
        case NET_IL_MTU_CHANGED:
4702 mejdrech 757
            return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
3466 mejdrech 758
    }
759
    return ENOTSUP;
760
}
761
 
4505 mejdrech 762
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 ){
763
    ip_netif_ref    netif;
4575 mejdrech 764
    int             index;
4505 mejdrech 765
 
766
    if( !( addr_len && prefix && content && suffix )) return EBADMEM;
4575 mejdrech 767
    * content = IP_MAX_CONTENT - IP_PREFIX;
4582 mejdrech 768
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
4575 mejdrech 769
    if( device_id < 0 ){
770
        * addr_len = IP_ADDR;
771
        * prefix = 0;
772
        * suffix = 0;
773
        for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
774
            netif = ip_netifs_get_index( & ip_globals.netifs, index );
775
            if( netif ){
776
                if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
777
                if( netif->prefix > * prefix ) * prefix = netif->prefix;
778
                if( netif->suffix > * suffix ) * suffix = netif->suffix;
779
            }
780
        }
781
        * prefix = * prefix + IP_PREFIX;
782
        * suffix = * suffix + IP_SUFFIX;
783
    }else{
784
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
785
        if( ! netif ){
4582 mejdrech 786
            fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4575 mejdrech 787
            return ENOENT;
788
        }
789
        * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
790
        * prefix = netif->prefix + IP_PREFIX;
791
        * suffix = netif->suffix + IP_SUFFIX;
4505 mejdrech 792
    }
4582 mejdrech 793
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 794
    return EOK;
795
}
796
 
797
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 ){
798
    ip_route_ref    route;
799
    ip_netif_ref    netif;
800
    int             index;
801
 
4582 mejdrech 802
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 803
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 804
    if( ! netif ){
4582 mejdrech 805
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 806
        return ENOENT;
807
    }
4505 mejdrech 808
    route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
4558 mejdrech 809
    if( ! route ){
4582 mejdrech 810
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 811
        return ENOMEM;
812
    }
4505 mejdrech 813
    route->address.s_addr = address.s_addr;
814
    route->netmask.s_addr = netmask.s_addr;
815
    route->gateway.s_addr = gateway.s_addr;
816
    route->netif = netif;
817
    index = ip_routes_add( & netif->routes, route );
818
    if( index < 0 ) free( route );
4582 mejdrech 819
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 820
    return index;
821
}
822
 
823
ip_route_ref ip_find_route( in_addr_t destination ){
824
    int             index;
825
    ip_route_ref    route;
826
    ip_netif_ref    netif;
827
 
828
    // start with the last netif - the newest one
829
    index = ip_netifs_count( & ip_globals.netifs ) - 1;
830
    while( index >= 0 ){
831
        netif = ip_netifs_get_index( & ip_globals.netifs, index );
832
        if( netif && ( netif->state == NETIF_ACTIVE )){
833
            route = ip_netif_find_route( netif, destination );
834
            if( route ) return route;
835
        }
836
        -- index;
837
    }
838
    return & ip_globals.gateway;
839
}
840
 
841
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
842
    int             index;
843
    ip_route_ref    route;
844
 
845
    if( netif ){
846
        // start with the first one - the direct route
847
        for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
848
            route = ip_routes_get_index( & netif->routes, index );
849
            if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
850
                return route;
851
            }
852
        }
853
    }
854
    return NULL;
855
}
856
 
857
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
858
    ip_netif_ref    netif;
859
 
4582 mejdrech 860
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 861
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 862
    if( ! netif ){
4582 mejdrech 863
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4558 mejdrech 864
        return ENOENT;
865
    }
4505 mejdrech 866
    ip_globals.gateway.address.s_addr = 0;
867
    ip_globals.gateway.netmask.s_addr = 0;
868
    ip_globals.gateway.gateway.s_addr = gateway.s_addr;
869
    ip_globals.gateway.netif = netif;
4582 mejdrech 870
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 871
    return EOK;
872
}
873
 
4720 mejdrech 874
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){
4505 mejdrech 875
    size_t          length;
876
    packet_t        next;
877
    packet_t        new_packet;
4707 mejdrech 878
    int             result;
879
    int             phone;
4505 mejdrech 880
 
881
    next = packet;
882
    // check all packets
883
    while( next ){
884
        length = packet_get_data_length( next );
885
        // too long?
886
        if( length > content ){
4707 mejdrech 887
            result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
888
            if( result != EOK ){
4505 mejdrech 889
                new_packet = pq_detach( next );
890
                if( next == packet ){
4707 mejdrech 891
                    // the new first packet of the queue
4505 mejdrech 892
                    packet = new_packet;
893
                }
4707 mejdrech 894
                // fragmentation needed?
895
                if( result == EPERM ){
896
                    phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
897
                    if( phone >= 0 ){
898
                        // fragmentation necessary ICMP
899
                        icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
900
                    }
901
                }else{
902
                    pq_release( ip_globals.net_phone, packet_get_id( next ));
903
                }
4505 mejdrech 904
                next = new_packet;
905
                continue;
906
            }
907
        }
908
        next = pq_next( next );
909
    }
910
    return packet;
911
}
912
 
4720 mejdrech 913
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){
4505 mejdrech 914
    ERROR_DECLARE;
915
 
916
    packet_t        new_packet;
917
    ip_header_ref   header;
918
    ip_header_ref   middle_header;
919
    ip_header_ref   last_header;
4720 mejdrech 920
    struct sockaddr *       src;
921
    struct sockaddr *       dest;
922
    socklen_t       addrlen;
4708 mejdrech 923
    int             result;
4505 mejdrech 924
 
4720 mejdrech 925
    result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
4708 mejdrech 926
    if( result <= 0 ) return EINVAL;
4720 mejdrech 927
    addrlen = ( socklen_t ) result;
4505 mejdrech 928
    if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
929
    // get header
930
    header = ( ip_header_ref ) packet_get_data( packet );
931
    if( ! header ) return EINVAL;
932
    // fragmentation forbidden?
933
    if( header->flags & IPFLAG_DONT_FRAGMENT ){
934
        return EPERM;
935
    }
936
    // create the last fragment
4720 mejdrech 937
    new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len ));
4505 mejdrech 938
    if( ! new_packet ) return ENOMEM;
4589 mejdrech 939
    // allocate as much as originally
940
    last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
4505 mejdrech 941
    if( ! last_header ){
4711 mejdrech 942
        return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 943
    }
4589 mejdrech 944
    ip_create_last_header( last_header, header );
945
    // trim the unused space
946
    if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
4711 mejdrech 947
        return ip_release_and_return( packet, ERROR_CODE );
4589 mejdrech 948
    }
4505 mejdrech 949
    // biggest multiple of 8 lower than content
950
    // TODO even fragmentation?
951
    length = length & ( ~ 0x7 );// ( content / 8 ) * 8
4720 mejdrech 952
    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, addrlen ))){
4711 mejdrech 953
        return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 954
    }
955
    // mark the first as fragmented
956
    header->flags |= IPFLAG_MORE_FRAGMENTS;
957
    // create middle framgents
958
    while( IP_TOTAL_LENGTH( header ) > length ){
4720 mejdrech 959
        new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len ));
4505 mejdrech 960
        if( ! new_packet ) return ENOMEM;
961
        middle_header = ip_create_middle_header( new_packet, last_header );
962
        if( ! middle_header ){
4711 mejdrech 963
            return ip_release_and_return( packet, ENOMEM );
4505 mejdrech 964
        }
4720 mejdrech 965
        if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){
4711 mejdrech 966
            return ip_release_and_return( packet, ERROR_CODE );
4505 mejdrech 967
        }
968
    }
969
    // finish the first fragment
970
    header->header_checksum = IP_HEADER_CHECKSUM( header );
971
    return EOK;
972
}
973
 
4720 mejdrech 974
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ){
4505 mejdrech 975
    ERROR_DECLARE;
976
 
977
    void *          data;
978
 
979
    data = packet_suffix( new_packet, length );
980
    if( ! data ) return ENOMEM;
981
    memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
982
    ERROR_PROPAGATE( packet_trim( packet, 0, length ));
983
    header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
984
    new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
985
    new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
986
    new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
4720 mejdrech 987
    ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
4505 mejdrech 988
    return pq_insert_after( packet, new_packet );
989
}
990
 
991
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
992
    ip_header_ref   middle;
993
 
994
    middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
995
    if( ! middle ) return NULL;
996
    memcpy( middle, last, IP_HEADER_LENGTH( last ));
997
    middle->flags |= IPFLAG_MORE_FRAGMENTS;
998
    return middle;
999
}
1000
 
4589 mejdrech 1001
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
4505 mejdrech 1002
    ip_option_ref   option;
1003
    size_t          next;
1004
    size_t          length;
1005
 
1006
    // copy first itself
1007
    memcpy( last, first, sizeof( ip_header_t ));
1008
    length = sizeof( ip_header_t );
1009
    next = sizeof( ip_header_t );
1010
    // process all ip options
4728 mejdrech 1011
    while( next < first->header_length ){
4708 mejdrech 1012
        option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
4505 mejdrech 1013
        // skip end or noop
1014
        if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
1015
            ++ next;
1016
        }else{
1017
            // copy if said so or skip
1018
            if( IPOPT_COPIED( option->type )){
4708 mejdrech 1019
                memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
4505 mejdrech 1020
                length += option->length;
1021
            }
1022
            // next option
1023
            next += option->length;
1024
        }
1025
    }
1026
    // align 4 byte boundary
1027
    if( length % 4 ){
4708 mejdrech 1028
        bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
4728 mejdrech 1029
        last->header_length = length / 4 + 1;
4505 mejdrech 1030
    }else{
4728 mejdrech 1031
        last->header_length = length / 4;
4505 mejdrech 1032
    }
4589 mejdrech 1033
    last->header_checksum = 0;
4505 mejdrech 1034
}
1035
 
4702 mejdrech 1036
int ip_receive_message( device_id_t device_id, packet_t packet ){
4505 mejdrech 1037
    packet_t        next;
1038
 
1039
    do{
1040
        next = pq_detach( packet );
4707 mejdrech 1041
        ip_process_packet( device_id, packet );
4505 mejdrech 1042
        packet = next;
1043
    }while( packet );
1044
    return EOK;
1045
}
1046
 
1047
int ip_process_packet( device_id_t device_id, packet_t packet ){
1048
    ERROR_DECLARE;
1049
 
1050
    ip_header_ref   header;
1051
    in_addr_t       dest;
1052
    ip_route_ref    route;
4707 mejdrech 1053
    int             phone;
4720 mejdrech 1054
    struct sockaddr *   addr;
1055
    struct sockaddr_in  addr_in;
1056
//  struct sockaddr_in  addr_in6;
1057
    socklen_t       addrlen;
4505 mejdrech 1058
 
1059
    header = ( ip_header_ref ) packet_get_data( packet );
4707 mejdrech 1060
    if( ! header ){
4711 mejdrech 1061
        return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1062
    }
4505 mejdrech 1063
    // checksum
1064
    if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
1065
        // TODO checksum error ICMP?
4711 mejdrech 1066
        return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1067
    }
1068
    if( header->ttl <= 1 ){
1069
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1070
        if( phone >= 0 ){
1071
            // ttl oxceeded ICMP
1072
            icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
1073
        }
4505 mejdrech 1074
        return EINVAL;
1075
    }
1076
    // process ipopt and get destination
1077
    dest = ip_get_destination( header );
4720 mejdrech 1078
    // set the addrination address
1079
    switch( header->version ){
1080
        case IPVERSION:
1081
            addrlen = sizeof( addr_in );
1082
            bzero( & addr_in, addrlen );
1083
            addr_in.sin_family = AF_INET;
1084
            memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest ));
1085
            addr = ( struct sockaddr * ) & addr_in;
1086
            break;
1087
/*      case IPv6VERSION:
1088
            addrlen = sizeof( dest_in6 );
1089
            bzero( & dest_in6, addrlen );
1090
            dest_in6.sin6_family = AF_INET6;
1091
            memcpy( & dest_in6.sin6_addr.s6_addr, );
1092
            dest = ( struct sockaddr * ) & dest_in;
1093
            break;
1094
*/      default:
1095
            return EAFNOSUPPORT;
1096
    }
1097
    ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen ));
4505 mejdrech 1098
    route = ip_find_route( dest );
4707 mejdrech 1099
    if( ! route ){
1100
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1101
        if( phone >= 0 ){
1102
            // unreachable ICMP
1103
            icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1104
        }
1105
        return ENOENT;
1106
    }
4505 mejdrech 1107
    if( route->address.s_addr == dest.s_addr ){
1108
        // local delivery
4707 mejdrech 1109
        return ip_deliver_local( device_id, packet, header, 0 );
4505 mejdrech 1110
    }else{
4695 mejdrech 1111
        // only if routing enabled
1112
        if( route->netif->routing ){
4707 mejdrech 1113
            -- header->ttl;
1114
            return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
1115
        }else{
1116
            phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1117
            if( phone >= 0 ){
1118
                // unreachable ICMP if no routing
1119
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1120
            }
4695 mejdrech 1121
            return ENOENT;
1122
        }
4505 mejdrech 1123
    }
1124
}
1125
 
4707 mejdrech 1126
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
1127
    uint8_t *           data;
1128
    int                 offset;
1129
    icmp_type_t         type;
1130
    icmp_code_t         code;
1131
    ip_netif_ref        netif;
1132
    measured_string_t   address;
1133
    ip_route_ref        route;
1134
    ip_header_ref       header;
1135
 
1136
    switch( error ){
1137
        case SERVICE_ICMP:
1138
            offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
1139
            if( offset < 0 ){
4711 mejdrech 1140
                return ip_release_and_return( packet, ENOMEM );
4707 mejdrech 1141
            }
1142
            data = packet_get_data( packet );
4720 mejdrech 1143
            header = ( ip_header_ref )( data + offset );
4707 mejdrech 1144
            // destination host unreachable?
1145
            if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
1146
                fibril_rwlock_read_lock( & ip_globals.netifs_lock );
1147
                netif = ip_netifs_find( & ip_globals.netifs, device_id );
1148
                if( netif && netif->arp ){
1149
                    route = ip_routes_get_index( & netif->routes, 0 );
1150
                    // from the same network?
1151
                    if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
1152
                        // clear the ARP mapping if any
1153
                        address.value = ( char * ) & header->destination_address;
1154
                        address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
1155
                        arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
1156
                    }
1157
                }
1158
                fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
1159
            }
1160
            break;
1161
        default:
4711 mejdrech 1162
            return ip_release_and_return( packet, ENOTSUP );
4707 mejdrech 1163
    }
1164
    return ip_deliver_local( device_id, packet, header, error );
1165
}
1166
 
1167
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
4505 mejdrech 1168
    ERROR_DECLARE;
1169
 
1170
    ip_proto_ref    proto;
4707 mejdrech 1171
    int             phone;
4720 mejdrech 1172
    services_t      service;
1173
    tl_received_msg_t   received_msg;
1174
    struct sockaddr *   src;
1175
    struct sockaddr *   dest;
1176
    struct sockaddr_in  src_in;
1177
    struct sockaddr_in  dest_in;
1178
//  struct sockaddr_in  src_in6;
1179
//  struct sockaddr_in  dest_in6;
1180
    socklen_t       addrlen;
4505 mejdrech 1181
 
1182
    if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
1183
        // TODO fragmented
1184
        return ENOTSUP;
1185
    }else{
4720 mejdrech 1186
        switch( header->version ){
1187
            case IPVERSION:
1188
                addrlen = sizeof( src_in );
1189
                bzero( & src_in, addrlen );
1190
                src_in.sin_family = AF_INET;
1191
                memcpy( & dest_in, & src_in, addrlen );
1192
                memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
1193
                memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address ));
1194
                src = ( struct sockaddr * ) & src_in;
1195
                dest = ( struct sockaddr * ) & dest_in;
1196
                break;
1197
/*          case IPv6VERSION:
1198
                addrlen = sizeof( src_in6 );
1199
                bzero( & src_in6, addrlen );
1200
                src_in6.sin6_family = AF_INET6;
1201
                memcpy( & dest_in6, & src_in6, addrlen );
1202
                memcpy( & src_in6.sin6_addr.s6_addr, );
1203
                memcpy( & dest_in6.sin6_addr.s6_addr, );
1204
                src = ( struct sockaddr * ) & src_in;
1205
                dest = ( struct sockaddr * ) & dest_in;
1206
                break;
1207
*/          default:
1208
                return EAFNOSUPPORT;
1209
        }
1210
        ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen ));
4582 mejdrech 1211
        fibril_rwlock_read_lock( & ip_globals.protos_lock );
4505 mejdrech 1212
        proto = ip_protos_find( & ip_globals.protos, header->protocol );
4558 mejdrech 1213
        if( ! proto ){
4582 mejdrech 1214
            fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4707 mejdrech 1215
            phone = ip_prepare_icmp_and_get_phone( error, packet, header );
1216
            if( phone >= 0 ){
1217
                // unreachable ICMP
1218
                icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
1219
            }
4558 mejdrech 1220
            return ENOENT;
1221
        }
1222
        if( proto->received_msg ){
4720 mejdrech 1223
            service = proto->service;
1224
            received_msg = proto->received_msg;
1225
            fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1226
            ERROR_CODE = received_msg( device_id, packet, service, error );
4505 mejdrech 1227
        }else{
4707 mejdrech 1228
            ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
4720 mejdrech 1229
            fibril_rwlock_read_unlock( & ip_globals.protos_lock );
4505 mejdrech 1230
        }
4558 mejdrech 1231
        return ERROR_CODE;
4505 mejdrech 1232
    }
1233
}
1234
 
1235
in_addr_t ip_get_destination( ip_header_ref header ){
1236
    in_addr_t   destination;
1237
 
1238
    // TODO search set ipopt route?
4707 mejdrech 1239
    destination.s_addr = header->destination_address;
4505 mejdrech 1240
    return destination;
1241
}
1242
 
4707 mejdrech 1243
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
1244
    packet_t    next;
4720 mejdrech 1245
    struct sockaddr *   dest;
1246
    struct sockaddr_in  dest_in;
1247
//  struct sockaddr_in  dest_in6;
1248
    socklen_t       addrlen;
4707 mejdrech 1249
 
1250
    // detach the first packet and release the others
1251
    next = pq_detach( packet );
1252
    if( next ){
1253
        pq_release( ip_globals.net_phone, packet_get_id( next ));
1254
    }
1255
    if( ! header ){
1256
        if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
1257
        // get header
1258
        header = ( ip_header_ref ) packet_get_data( packet );
1259
        if( ! header ) return EINVAL;
1260
    }
1261
    // only for the first fragment
1262
    if( header->fragment_offset ) return EINVAL;
1263
    // set the destination address
4720 mejdrech 1264
    switch( header->version ){
1265
        case IPVERSION:
1266
            addrlen = sizeof( dest_in );
1267
            bzero( & dest_in, addrlen );
1268
            dest_in.sin_family = AF_INET;
1269
            memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
1270
            dest = ( struct sockaddr * ) & dest_in;
1271
            break;
1272
/*      case IPv6VERSION:
1273
            addrlen = sizeof( dest_in6 );
1274
            bzero( & dest_in6, addrlen );
1275
            dest_in6.sin6_family = AF_INET6;
1276
            memcpy( & dest_in6.sin6_addr.s6_addr, );
1277
            dest = ( struct sockaddr * ) & dest_in;
1278
            break;
1279
*/      default:
1280
            return EAFNOSUPPORT;
1281
    }
1282
    return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen );
4707 mejdrech 1283
}
1284
 
1285
int ip_get_icmp_phone( void ){
1286
    ip_proto_ref    proto;
1287
    int             phone;
1288
 
1289
    fibril_rwlock_read_lock( & ip_globals.protos_lock );
1290
    proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
1291
    phone = proto ? proto->phone : ENOENT;
1292
    fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1293
    return phone;
1294
}
1295
 
1296
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
1297
    int phone;
1298
 
1299
    phone = ip_get_icmp_phone();
1300
    if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
4711 mejdrech 1301
        return ip_release_and_return( packet, EINVAL );
4707 mejdrech 1302
    }
1303
    return phone;
1304
}
1305
 
4711 mejdrech 1306
int ip_release_and_return( packet_t packet, int result ){
4707 mejdrech 1307
    pq_release( ip_globals.net_phone, packet_get_id( packet ));
1308
    return result;
1309
}
1310
 
4722 mejdrech 1311
int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
1312
    struct sockaddr_in *    address_in;
1313
//  struct sockaddr_in6 *   address_in6;
1314
    in_addr_t *             dest;
1315
    in_addr_t *             src;
1316
    ip_route_ref            route;
1317
    ipv4_pseudo_header_ref  header_in;
1318
 
1319
    if( !( destination && ( addrlen > 0 ))) return EINVAL;
1320
    if( !( device_id && header && headerlen )) return EBADMEM;
1321
    if( addrlen < sizeof( struct sockaddr )){
1322
        return EINVAL;
1323
    }
1324
    switch( destination->sa_family ){
1325
        case AF_INET:
1326
            if( addrlen != sizeof( struct sockaddr_in )){
1327
                return EINVAL;
1328
            }
1329
            address_in = ( struct sockaddr_in * ) destination;
1330
            dest = & address_in->sin_addr;
1331
            break;
1332
        // TODO IPv6
1333
/*      case AF_INET6:
1334
            if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
1335
            address_in6 = ( struct sockaddr_in6 * ) dest;
1336
            address_in6.sin6_addr.s6_addr;
1337
*/      default:
1338
            return EAFNOSUPPORT;
1339
    }
1340
    fibril_rwlock_read_lock( & ip_globals.lock );
1341
    route = ip_find_route( * dest );
1342
    if( !( route && route->netif )){
1343
        fibril_rwlock_read_unlock( & ip_globals.lock );
1344
        return ENOENT;
1345
    }
1346
    * device_id = route->netif->device_id;
1347
    src = ip_netif_address( route->netif );
1348
    fibril_rwlock_read_unlock( & ip_globals.lock );
1349
    * headerlen = sizeof( * header_in );
1350
    header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
1351
    if( ! header_in ) return ENOMEM;
1352
    bzero( header_in, * headerlen );
1353
    header_in->destination_address = dest->s_addr;
1354
    header_in->source_address = src->s_addr;
1355
    header_in->protocol = protocol;
1356
    header_in->data_length = 0;
1357
    * header = ( ip_pseudo_header_ref ) header_in;
1358
    return EOK;
1359
}
1360
 
3466 mejdrech 1361
/** @}
1362
 */