Subversion Repositories HelenOS

Rev

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