Subversion Repositories HelenOS

Rev

Rev 4558 | Rev 4582 | 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 );
4575 mejdrech 107
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
4505 mejdrech 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;
4575 mejdrech 427
    in_addr_t *         dest;
4505 mejdrech 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
4575 mejdrech 432
    length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest );
4505 mejdrech 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 );
4575 mejdrech 445
    if( device_id > 0 ){
4505 mejdrech 446
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
4575 mejdrech 447
        route = ip_netif_find_route( netif, * dest );
4505 mejdrech 448
    }else{
449
        // TODO IPv6
4575 mejdrech 450
        route = ip_find_route( * dest );
4505 mejdrech 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?
4575 mejdrech 459
    if( route->address.s_addr == dest->s_addr ){
4505 mejdrech 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
    }
4575 mejdrech 471
    if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest ))){
4505 mejdrech 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
    // get destination hardware address
495
    if( netif->arp ){
4575 mejdrech 496
        destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
4505 mejdrech 497
        destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
498
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
499
            usleep( 200000 );
500
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
501
        }
502
        // TODO unreachable
503
        if( ! translation ) return EINVAL;
504
        if( ! translation->value ){
505
            // TODO unreachable
506
            free( translation );
507
            free( data );
508
            return EINVAL;
509
        }
510
    }else translation = NULL;
511
    // process packet queue
512
    next = packet;
513
    do{
4575 mejdrech 514
        if( ERROR_OCCURRED( ip_prepare_packet( src, dest, next, translation ))){
4505 mejdrech 515
            // release invalid packet
516
            tmp = pq_detach( next );
517
            if( next == packet ) packet = tmp;
518
            pq_release( ip_globals.net_phone, packet_get_id( next ));
519
            next = tmp;
520
        }else{
521
            next = pq_next( next );
522
        }
523
    }while( next );
524
    if( translation ){
525
        free( translation );
526
        free( data );
527
    }
528
    // send packet queue
529
    if( packet ){
530
        packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len );
531
        if( packet ){
532
            nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
533
        }
534
    }
3846 mejdrech 535
    return EOK;
536
}
537
 
4575 mejdrech 538
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
4505 mejdrech 539
    ERROR_DECLARE;
540
 
4558 mejdrech 541
    size_t              length;
4505 mejdrech 542
    ip_header_ref       header;
543
 
544
    length = packet_get_data_length( packet );
545
    if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
546
    header = ( ip_header_ref ) packet_get_data( packet );
547
    if( destination ){
548
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
549
    }
550
    header->version = 4;
551
    header->total_length = htons( length );
552
    header->fragment_offset = 0;
4575 mejdrech 553
    if( source ) header->source_address = source->s_addr;
554
    header->destination_address = dest.s_addr;
4558 mejdrech 555
    rwlock_write_lock( & ip_globals.lock );
4505 mejdrech 556
    ++ ip_globals.packet_counter;
557
    header->identification = htons( ip_globals.packet_counter );
4558 mejdrech 558
    rwlock_write_unlock( & ip_globals.lock );
4505 mejdrech 559
    header->header_checksum = 0;
560
    // unnecessary for all protocols
561
    header->header_checksum = IP_HEADER_CHECKSUM( header );
562
    return EOK;
563
}
564
 
3846 mejdrech 565
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
566
    ERROR_DECLARE;
567
 
568
    packet_t    packet;
569
 
570
    * answer_count = 0;
571
    switch( IPC_GET_METHOD( * call )){
3466 mejdrech 572
        case IPC_M_PHONE_HUNGUP:
573
            return EOK;
3666 mejdrech 574
        case NET_IL_DEVICE:
4307 mejdrech 575
            return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 576
        case IPC_M_CONNECT_TO_ME:
4505 mejdrech 577
            return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 578
        case NET_IL_SEND:
579
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
580
            return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 );
4351 mejdrech 581
        case NET_IL_DEVICE_STATE:
582
        case NET_NIL_DEVICE_STATE:
583
            return ip_device_state_msg( 0, IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
584
        case NET_IL_RECEIVED:
585
        case NET_NIL_RECEIVED:
586
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4505 mejdrech 587
            return ip_received_msg( IPC_GET_DEVICE( call ), packet );
588
        case NET_IP_ADD_ROUTE:
589
            return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
590
        case NET_IP_SET_GATEWAY:
591
            return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
592
        case NET_IL_PACKET_SPACE:
593
            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 )));
594
            * answer_count = 3;
595
            return EOK;
3466 mejdrech 596
    }
597
    return ENOTSUP;
598
}
599
 
4505 mejdrech 600
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 ){
601
    ip_netif_ref    netif;
4575 mejdrech 602
    int             index;
4505 mejdrech 603
 
604
    if( !( addr_len && prefix && content && suffix )) return EBADMEM;
4575 mejdrech 605
    * content = IP_MAX_CONTENT - IP_PREFIX;
4558 mejdrech 606
    rwlock_read_lock( & ip_globals.netifs_lock );
4575 mejdrech 607
    if( device_id < 0 ){
608
        * addr_len = IP_ADDR;
609
        * prefix = 0;
610
        * suffix = 0;
611
        for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
612
            netif = ip_netifs_get_index( & ip_globals.netifs, index );
613
            if( netif ){
614
                if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
615
                if( netif->prefix > * prefix ) * prefix = netif->prefix;
616
                if( netif->suffix > * suffix ) * suffix = netif->suffix;
617
            }
618
        }
619
        * prefix = * prefix + IP_PREFIX;
620
        * suffix = * suffix + IP_SUFFIX;
621
    }else{
622
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
623
        if( ! netif ){
624
            rwlock_read_unlock( & ip_globals.netifs_lock );
625
            return ENOENT;
626
        }
627
        * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
628
        * prefix = netif->prefix + IP_PREFIX;
629
        * suffix = netif->suffix + IP_SUFFIX;
4505 mejdrech 630
    }
4558 mejdrech 631
    rwlock_read_unlock( & ip_globals.netifs_lock );
4505 mejdrech 632
    return EOK;
633
}
634
 
635
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 ){
636
    ip_route_ref    route;
637
    ip_netif_ref    netif;
638
    int             index;
639
 
4558 mejdrech 640
    rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 641
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 642
    if( ! netif ){
643
        rwlock_write_unlock( & ip_globals.netifs_lock );
644
        return ENOENT;
645
    }
4505 mejdrech 646
    route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
4558 mejdrech 647
    if( ! route ){
648
        rwlock_write_unlock( & ip_globals.netifs_lock );
649
        return ENOMEM;
650
    }
4505 mejdrech 651
    route->address.s_addr = address.s_addr;
652
    route->netmask.s_addr = netmask.s_addr;
653
    route->gateway.s_addr = gateway.s_addr;
654
    route->netif = netif;
655
    index = ip_routes_add( & netif->routes, route );
656
    if( index < 0 ) free( route );
4558 mejdrech 657
    rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 658
    return index;
659
}
660
 
661
ip_route_ref ip_find_route( in_addr_t destination ){
662
    int             index;
663
    ip_route_ref    route;
664
    ip_netif_ref    netif;
665
 
666
    // start with the last netif - the newest one
667
    index = ip_netifs_count( & ip_globals.netifs ) - 1;
668
    while( index >= 0 ){
669
        netif = ip_netifs_get_index( & ip_globals.netifs, index );
670
        if( netif && ( netif->state == NETIF_ACTIVE )){
671
            route = ip_netif_find_route( netif, destination );
672
            if( route ) return route;
673
        }
674
        -- index;
675
    }
676
    return & ip_globals.gateway;
677
}
678
 
679
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
680
    int             index;
681
    ip_route_ref    route;
682
 
683
    if( netif ){
684
        // start with the first one - the direct route
685
        for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
686
            route = ip_routes_get_index( & netif->routes, index );
687
            if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
688
                return route;
689
            }
690
        }
691
    }
692
    return NULL;
693
}
694
 
695
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
696
    ip_netif_ref    netif;
697
 
4558 mejdrech 698
    rwlock_write_lock( & ip_globals.netifs_lock );
4505 mejdrech 699
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
4558 mejdrech 700
    if( ! netif ){
701
        rwlock_write_unlock( & ip_globals.netifs_lock );
702
        return ENOENT;
703
    }
4505 mejdrech 704
    ip_globals.gateway.address.s_addr = 0;
705
    ip_globals.gateway.netmask.s_addr = 0;
706
    ip_globals.gateway.gateway.s_addr = gateway.s_addr;
707
    ip_globals.gateway.netif = netif;
4558 mejdrech 708
    rwlock_write_unlock( & ip_globals.netifs_lock );
4505 mejdrech 709
    return EOK;
710
}
711
 
712
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ){
713
    size_t          length;
714
    packet_t        next;
715
    packet_t        new_packet;
716
 
717
    next = packet;
718
    // check all packets
719
    while( next ){
720
        length = packet_get_data_length( next );
721
        // too long?
722
        if( length > content ){
723
            if( ip_fragment_packet( next, content, prefix, suffix, addr_len ) != EOK ){
724
                new_packet = pq_detach( next );
725
                if( next == packet ){
726
                    packet = new_packet;
727
                }
728
                pq_release( ip_globals.net_phone, packet_get_id( next ));
729
                next = new_packet;
730
                continue;
731
            }
732
        }
733
        next = pq_next( next );
734
    }
735
    return packet;
736
}
737
 
738
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
739
    ERROR_DECLARE;
740
 
741
    packet_t        new_packet;
742
    ip_header_ref   header;
743
    ip_header_ref   middle_header;
744
    ip_header_ref   last_header;
745
    uint8_t *       src;
746
    uint8_t *       dest;
747
    int             address_length;
748
 
749
    address_length = packet_get_addr( packet, & src, & dest );
750
    if( address_length <= 0 ) return EINVAL;
751
    if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
752
    // get header
753
    header = ( ip_header_ref ) packet_get_data( packet );
754
    if( ! header ) return EINVAL;
755
    // fragmentation forbidden?
756
    if( header->flags & IPFLAG_DONT_FRAGMENT ){
757
        // TODO fragmentation necessary ICMP
758
        return EPERM;
759
    }
760
    // create the last fragment
4558 mejdrech 761
    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 762
    if( ! new_packet ) return ENOMEM;
763
    last_header = ip_create_last_header( new_packet, header );
764
    if( ! last_header ){
765
        pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
766
        return ENOMEM;
767
    }
768
    // biggest multiple of 8 lower than content
769
    // TODO even fragmentation?
770
    length = length & ( ~ 0x7 );// ( content / 8 ) * 8
771
    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 ))){
772
        pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
773
        return ERROR_CODE;
774
    }
775
    // mark the first as fragmented
776
    header->flags |= IPFLAG_MORE_FRAGMENTS;
777
    // create middle framgents
778
    while( IP_TOTAL_LENGTH( header ) > length ){
779
        new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
780
        if( ! new_packet ) return ENOMEM;
781
        middle_header = ip_create_middle_header( new_packet, last_header );
782
        if( ! middle_header ){
783
            pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
784
            return ENOMEM;
785
        }
786
        if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){
787
            pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
788
            return ERROR_CODE;
789
        }
790
    }
791
    // finish the first fragment
792
    header->header_checksum = IP_HEADER_CHECKSUM( header );
793
    printf( "ok\n" );
794
    return EOK;
795
}
796
 
797
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 ){
798
    ERROR_DECLARE;
799
 
800
    void *          data;
801
 
802
    data = packet_suffix( new_packet, length );
803
    if( ! data ) return ENOMEM;
804
    memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
805
    ERROR_PROPAGATE( packet_trim( packet, 0, length ));
806
    header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
807
    new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
808
    new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
809
    new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
810
    ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
811
    return pq_insert_after( packet, new_packet );
812
}
813
 
814
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
815
    ip_header_ref   middle;
816
 
817
    middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
818
    if( ! middle ) return NULL;
819
    memcpy( middle, last, IP_HEADER_LENGTH( last ));
820
    middle->flags |= IPFLAG_MORE_FRAGMENTS;
821
    return middle;
822
}
823
 
824
ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ){
825
    ip_header_ref   last;
826
    ip_option_ref   option;
827
    size_t          next;
828
    size_t          length;
829
 
830
    // allocate as much as originally
831
    last = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( first ));
832
    if( ! last ) return NULL;
833
    // copy first itself
834
    memcpy( last, first, sizeof( ip_header_t ));
835
    length = sizeof( ip_header_t );
836
    next = sizeof( ip_header_t );
837
    // process all ip options
838
    while( next < first->ihl ){
839
        option = ( ip_option_ref ) ((( void * ) first ) + next );
840
        // skip end or noop
841
        if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
842
            ++ next;
843
        }else{
844
            // copy if said so or skip
845
            if( IPOPT_COPIED( option->type )){
846
                memcpy((( void * ) last ) + length, (( void * ) first ) + next, option->length );
847
                length += option->length;
848
            }
849
            // next option
850
            next += option->length;
851
        }
852
    }
853
    // align 4 byte boundary
854
    if( length % 4 ){
855
        bzero((( void * ) last ) + length, 4 - ( length % 4 ));
856
        last->ihl = length / 4 + 1;
857
    }else{
858
        last->ihl = length / 4;
859
    }
860
    // trim the unused space
861
    if( packet_trim( packet, 0, IP_HEADER_LENGTH( first ) - IP_HEADER_LENGTH( last )) != EOK ) return NULL;
862
    return last;
863
}
864
 
865
int ip_received_msg( device_id_t device_id, packet_t packet ){
866
    packet_t        next;
867
 
868
    do{
869
        next = pq_detach( packet );
870
        if( ip_process_packet( device_id, packet ) != EOK ){
871
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
872
        }
873
        packet = next;
874
    }while( packet );
875
    return EOK;
876
}
877
 
878
int ip_process_packet( device_id_t device_id, packet_t packet ){
879
    ERROR_DECLARE;
880
 
881
    ip_header_ref   header;
882
    in_addr_t       dest;
883
    ip_route_ref    route;
884
 
885
    header = ( ip_header_ref ) packet_get_data( packet );
886
    if( ! header ) return ENOMEM;
887
    // checksum
888
    if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
889
        // TODO checksum error ICMP?
890
        return EINVAL;
891
    }
892
    // TODO ttl oxceeded ICMP?
893
    if( !( -- header->ttl )) return EINVAL;
894
    // process ipopt and get destination
895
    dest = ip_get_destination( header );
896
    ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
897
    route = ip_find_route( dest );
898
    // TODO unreachable ICMP?
899
    if( ! route ) return ENOENT;
900
    if( route->address.s_addr == dest.s_addr ){
901
        // local delivery
902
        return ip_deliver_local( device_id, packet, header );
903
    }else{
904
        return ip_send_route( packet, route->netif, route, NULL, dest );
905
    }
906
}
907
 
908
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ){
909
    ERROR_DECLARE;
910
 
911
    ip_proto_ref    proto;
912
 
913
    if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
914
        // TODO fragmented
915
        return ENOTSUP;
916
    }else{
4558 mejdrech 917
        ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
918
        rwlock_read_lock( & ip_globals.protos_lock );
4505 mejdrech 919
        proto = ip_protos_find( & ip_globals.protos, header->protocol );
4558 mejdrech 920
        if( ! proto ){
921
            rwlock_read_unlock( & ip_globals.protos_lock );
922
            return ENOENT;
923
        }
924
        if( proto->received_msg ){
925
            ERROR_CODE = proto->received_msg( device_id, packet, SERVICE_IP );
4505 mejdrech 926
        }else{
4558 mejdrech 927
            ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service );
4505 mejdrech 928
        }
4558 mejdrech 929
        rwlock_read_unlock( & ip_globals.protos_lock );
930
        return ERROR_CODE;
4505 mejdrech 931
    }
932
}
933
 
934
in_addr_t ip_get_destination( ip_header_ref header ){
935
    in_addr_t   destination;
936
 
937
    // TODO search set ipopt route?
938
    destination.s_addr = header->destination_address; //ntohl( header->destination_address );
939
    return destination;
940
}
941
 
3466 mejdrech 942
/** @}
943
 */