Subversion Repositories HelenOS

Rev

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

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