Subversion Repositories HelenOS

Rev

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

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