Subversion Repositories HelenOS

Rev

Rev 4505 | Rev 4558 | 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
 
4506 mejdrech 224
    ip_netif->arp = 0;
225
    route = NULL;
4307 mejdrech 226
    configuration = & names[ 0 ];
3846 mejdrech 227
    // get configuration
4307 mejdrech 228
    ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
229
    if( configuration ){
230
        if( configuration[ 0 ].value ){
231
            ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
3846 mejdrech 232
        }else{
233
            ip_netif->ipv = DEFAULT_IPV;
234
        }
4332 mejdrech 235
        ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
3846 mejdrech 236
        if( ip_netif->dhcp ){
237
            // TODO dhcp
4307 mejdrech 238
            net_free_settings( configuration, data );
3846 mejdrech 239
            return ENOTSUP;
240
        }else if( ip_netif->ipv == 4 ){
4505 mejdrech 241
            route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
242
            if( ! route ){
243
                net_free_settings( configuration, data );
244
                return ENOMEM;
245
            }
246
            route->address.s_addr = 0;
247
            route->netmask.s_addr = 0;
248
            route->gateway.s_addr = 0;
249
            route->netif = ip_netif;
250
            index = ip_routes_add( & ip_netif->routes, route );
251
            if( index < 0 ){
252
                net_free_settings( configuration, data );
253
                free( route );
254
                return index;
255
            }
256
            if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
257
            || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
258
            || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
259
            || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
4307 mejdrech 260
            || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
261
            || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
262
                net_free_settings( configuration, data );
3846 mejdrech 263
                return EINVAL;
264
            }
265
        }else{
4505 mejdrech 266
            // TODO ipv6 in separate module
4307 mejdrech 267
            net_free_settings( configuration, data );
3846 mejdrech 268
            return ENOTSUP;
269
        }
4307 mejdrech 270
        if( configuration[ 8 ].value ){
271
            ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
4192 mejdrech 272
            if( ! ip_netif->arp ){
4307 mejdrech 273
                printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
274
                net_free_settings( configuration, data );
4192 mejdrech 275
                return EINVAL;
276
            }
277
        }else{
278
            ip_netif->arp = NULL;
279
        }
4307 mejdrech 280
        net_free_settings( configuration, data );
3846 mejdrech 281
    }
4505 mejdrech 282
    ip_netif->phone = bind_service( ip_netif->service, ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
4192 mejdrech 283
    if( ip_netif->phone < 0 ){
4505 mejdrech 284
        printf( "Failed to contact the nil service %d\n", ip_netif->service );
4192 mejdrech 285
        return ip_netif->phone;
286
    }
4505 mejdrech 287
    // MUST BE AFTER the bind_service up there!
4192 mejdrech 288
    if( ip_netif->arp ){
4506 mejdrech 289
        if( route ){
290
            configuration[ 0 ].value = ( char * ) & route->address.s_addr;
291
            configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 );
292
            ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & configuration[ 0 ] ));
293
        }else{
294
            ip_netif->arp = 0;
295
        }
4192 mejdrech 296
    }
4505 mejdrech 297
    // get packet dimensions
298
    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 ));
299
    if( ip_netif->content < IP_MIN_CONTENT ){
300
        printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
301
        ip_netif->content = IP_MIN_CONTENT;
302
    }
4192 mejdrech 303
    index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
4505 mejdrech 304
    if( index < 0 ) return index;
305
    if( gateway.s_addr ){
306
        // the default gateway
307
        ip_globals.gateway.address.s_addr = 0;
308
        ip_globals.gateway.netmask.s_addr = 0;
309
        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
310
        ip_globals.gateway.netif = ip_netif;
4192 mejdrech 311
    }
3846 mejdrech 312
    return EOK;
313
}
314
 
4307 mejdrech 315
int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ){
4506 mejdrech 316
//  ERROR_DECLARE;
4243 mejdrech 317
 
4505 mejdrech 318
/*  measured_string_t   address;
319
    measured_string_ref translation;
320
    char *              data;
321
*/
4506 mejdrech 322
/*  packet_t        packet;
4505 mejdrech 323
    in_addr_t       destination;
4506 mejdrech 324
*/
4243 mejdrech 325
    ip_netif_ref    netif;
326
 
327
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
328
    if( ! netif ) return ENOENT;
4505 mejdrech 329
    netif->state = state;
3846 mejdrech 330
    // TODO state
4307 mejdrech 331
    printf( "ip - device %d changed state to %d\n\n", device_id, state );
4506 mejdrech 332
//  if( netif->arp ){
4505 mejdrech 333
/*      address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
334
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
4327 mejdrech 335
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4505 mejdrech 336
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
337
        }
338
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
339
        free( translation );
340
        free( data );
341
        address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
342
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
343
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
4327 mejdrech 344
            sleep( 2 );
345
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
346
        }
4307 mejdrech 347
        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 348
        free( translation );
349
        free( data );
4506 mejdrech 350
*//*        printf( "IP - testing to send packet:\n" );
4505 mejdrech 351
        ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
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, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
356
        if( ! packet ) return ENOMEM;
357
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
358
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
359
        if( ! packet ) return ENOMEM;
360
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
361
        packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
362
        if( ! packet ) return ENOMEM;
363
        // try this long version
364
//      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 ))
365
        if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
366
        || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
367
        || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
368
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
369
        }
370
        ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
371
        printf( "send returned %d\n", ERROR_CODE );
4243 mejdrech 372
    }
4506 mejdrech 373
*/  return EOK;
4307 mejdrech 374
}
375
 
376
int ip_connect_module( services_t service ){
377
    return EOK;
378
}
379
 
4505 mejdrech 380
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg ){
381
    return ip_register( protocol, me, 0, tl_received_msg );
382
}
383
 
384
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ){
3846 mejdrech 385
    ip_proto_ref    proto;
4192 mejdrech 386
    int             index;
3846 mejdrech 387
 
4505 mejdrech 388
    if( !( protocol && service && (( phone > 0 ) || ( tl_received_msg )))) return EINVAL;
3846 mejdrech 389
    proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
390
    if( ! proto ) return ENOMEM;
391
    proto->protocol = protocol;
4505 mejdrech 392
    proto->service = service;
3846 mejdrech 393
    proto->phone = phone;
4505 mejdrech 394
    proto->tl_received_msg = tl_received_msg;
4192 mejdrech 395
    index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
396
    if( index < 0 ){
3846 mejdrech 397
        free( proto );
4192 mejdrech 398
        return index;
3846 mejdrech 399
    }
4307 mejdrech 400
    printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
3846 mejdrech 401
    return EOK;
402
}
403
 
4505 mejdrech 404
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender ){
405
    ERROR_DECLARE;
406
 
407
    int                 length;
408
    ip_netif_ref        netif;
409
    ip_route_ref        route;
410
    in_addr_t           dest;
411
    in_addr_t *         src;
412
 
413
    // addresses in the host byte order
414
    // should be the next hop address or the target destination address
415
    length = packet_get_addr( packet, NULL, ( void * )( & dest.s_addr ));
416
    if( length < 0 ){
417
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
418
        return length;
419
    }
420
    // TODO IPv6
421
    if( length != IP_ADDR ){
422
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
423
        return EINVAL;
424
    }
425
//  rwlock_read_lock( & ip_globals.devices_lock );
426
    // device specified?
427
//  dest.s_addr = ntohl( dest.s_addr );
428
    if( device_id ){
429
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
430
        route = ip_netif_find_route( netif, dest );
431
    }else{
432
        // TODO IPv6
433
        route = ip_find_route( dest );
434
        netif = route ? route->netif : NULL;
435
    }
436
    if( !( netif && route )){
437
//      rwlock_read_unlock( & ip_globals.devices_lock );
438
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
439
        return ENOENT;
440
    }
441
    // to me?
442
    if( route->address.s_addr == dest.s_addr ){
443
        // TODO loopback deliver
444
    }
445
 
446
    src = ip_netif_addr( netif );
447
    if( ! src ){
448
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
449
        return ENOENT;
450
    }
451
    if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, dest ))){
452
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
453
    }
454
    return ERROR_CODE;
455
}
456
 
457
in_addr_t * ip_netif_addr( ip_netif_ref netif ){
458
    ip_route_ref    route;
459
 
460
    route = ip_routes_get_index( & netif->routes, 0 );
461
    return route ? & route->address : NULL;
462
}
463
 
464
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){
465
    ERROR_DECLARE;
466
 
467
    packet_t            next;
468
    packet_t            tmp;
469
    measured_string_t   destination;
470
    measured_string_ref translation;
471
    char *              data;
472
 
473
    if( route->gateway.s_addr ){
474
        dest.s_addr = route->gateway.s_addr;
475
    }
476
    // get destination hardware address
477
    if( netif->arp ){
478
        destination.value = ( char * ) & dest.s_addr;
479
        destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
480
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
481
            usleep( 200000 );
482
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
483
        }
484
        // TODO unreachable
485
        if( ! translation ) return EINVAL;
486
        if( ! translation->value ){
487
            // TODO unreachable
488
            free( translation );
489
            free( data );
490
            return EINVAL;
491
        }
492
    }else translation = NULL;
493
    // process packet queue
494
    next = packet;
495
    do{
496
        if( ERROR_OCCURRED( ip_prepare_packet( src, next, translation ))){
497
            // release invalid packet
498
            tmp = pq_detach( next );
499
            if( next == packet ) packet = tmp;
500
            pq_release( ip_globals.net_phone, packet_get_id( next ));
501
            next = tmp;
502
        }else{
503
            next = pq_next( next );
504
        }
505
    }while( next );
506
    if( translation ){
507
        free( translation );
508
        free( data );
509
    }
510
    // send packet queue
511
    if( packet ){
512
        packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len );
513
        if( packet ){
514
            nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
515
        }
516
    }
517
//  rwlock_read_unlock( & ip_globals.netifs_lock );
3846 mejdrech 518
    return EOK;
519
}
520
 
4505 mejdrech 521
int ip_prepare_packet( in_addr_t * source, packet_t packet, measured_string_ref destination ){
522
    ERROR_DECLARE;
523
 
524
    int                 length;
525
    ip_header_ref       header;
526
 
527
    length = packet_get_data_length( packet );
528
    if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
529
    header = ( ip_header_ref ) packet_get_data( packet );
530
    if( destination ){
531
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
532
    }
533
    header->version = 4;
534
    header->total_length = htons( length );
535
    header->fragment_offset = 0;
536
    if( source ) header->source_address = source->s_addr;//htonl( source.s_addr );
537
    ++ ip_globals.packet_counter;
538
    header->identification = htons( ip_globals.packet_counter );
539
    header->header_checksum = 0;
540
    // unnecessary for all protocols
541
    header->header_checksum = IP_HEADER_CHECKSUM( header );
542
    return EOK;
543
}
544
 
3846 mejdrech 545
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
546
    ERROR_DECLARE;
547
 
548
    packet_t    packet;
549
 
550
    * answer_count = 0;
551
    switch( IPC_GET_METHOD( * call )){
3466 mejdrech 552
        case IPC_M_PHONE_HUNGUP:
553
            return EOK;
3666 mejdrech 554
        case NET_IL_DEVICE:
4307 mejdrech 555
            return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
3846 mejdrech 556
        case IPC_M_CONNECT_TO_ME:
4505 mejdrech 557
            return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
4307 mejdrech 558
        case NET_IL_SEND:
559
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
560
            return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 );
4351 mejdrech 561
        case NET_IL_DEVICE_STATE:
562
        case NET_NIL_DEVICE_STATE:
563
            return ip_device_state_msg( 0, IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
564
        case NET_IL_RECEIVED:
565
        case NET_NIL_RECEIVED:
566
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
4505 mejdrech 567
            return ip_received_msg( IPC_GET_DEVICE( call ), packet );
568
        case NET_IP_ADD_ROUTE:
569
            return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
570
        case NET_IP_SET_GATEWAY:
571
            return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
572
        case NET_IL_PACKET_SPACE:
573
            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 )));
574
            * answer_count = 3;
575
            return EOK;
3466 mejdrech 576
    }
577
    return ENOTSUP;
578
}
579
 
4505 mejdrech 580
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 ){
581
    ip_netif_ref    netif;
582
 
583
    if( !( addr_len && prefix && content && suffix )) return EBADMEM;
584
//  rwlock_read_lock( & ip_globals.netifs_lock );
585
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
586
    if( ! netif ){
587
//      rwlock_read_unlock( & ip_globals.netifs_lock );
588
        return ENOENT;
589
    }
590
    * content = IP_MAX_CONTENT - IP_PREFIX;
591
    * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
592
    * prefix = netif->prefix + IP_PREFIX;
593
    * suffix = netif->suffix + IP_SUFFIX;
594
//  rwlock_read_unlock( & ip_globals.netifs_lock );
595
    return EOK;
596
}
597
 
598
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 ){
599
    ip_route_ref    route;
600
    ip_netif_ref    netif;
601
    int             index;
602
 
603
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
604
    if( ! netif ) return ENOENT;
605
    route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
606
    if( ! route ) return ENOMEM;
607
    route->address.s_addr = address.s_addr;
608
    route->netmask.s_addr = netmask.s_addr;
609
    route->gateway.s_addr = gateway.s_addr;
610
    route->netif = netif;
611
    index = ip_routes_add( & netif->routes, route );
612
    if( index < 0 ) free( route );
613
    return index;
614
}
615
 
616
ip_route_ref ip_find_route( in_addr_t destination ){
617
    int             index;
618
    ip_route_ref    route;
619
    ip_netif_ref    netif;
620
 
621
    // start with the last netif - the newest one
622
    index = ip_netifs_count( & ip_globals.netifs ) - 1;
623
    while( index >= 0 ){
624
        netif = ip_netifs_get_index( & ip_globals.netifs, index );
625
        if( netif && ( netif->state == NETIF_ACTIVE )){
626
            route = ip_netif_find_route( netif, destination );
627
            if( route ) return route;
628
        }
629
        -- index;
630
    }
631
    return & ip_globals.gateway;
632
}
633
 
634
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
635
    int             index;
636
    ip_route_ref    route;
637
 
638
    if( netif ){
639
        // start with the first one - the direct route
640
        for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
641
            route = ip_routes_get_index( & netif->routes, index );
642
            if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
643
                return route;
644
            }
645
        }
646
    }
647
    return NULL;
648
}
649
 
650
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
651
    ip_netif_ref    netif;
652
 
653
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
654
    if( ! netif ) return ENOENT;
655
    ip_globals.gateway.address.s_addr = 0;
656
    ip_globals.gateway.netmask.s_addr = 0;
657
    ip_globals.gateway.gateway.s_addr = gateway.s_addr;
658
    ip_globals.gateway.netif = netif;
659
    return EOK;
660
}
661
 
662
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ){
663
    size_t          length;
664
    packet_t        next;
665
    packet_t        new_packet;
666
 
667
    next = packet;
668
    // check all packets
669
    while( next ){
670
        length = packet_get_data_length( next );
671
        // too long?
672
        if( length > content ){
673
            if( ip_fragment_packet( next, content, prefix, suffix, addr_len ) != EOK ){
674
                new_packet = pq_detach( next );
675
                if( next == packet ){
676
                    packet = new_packet;
677
                }
678
                pq_release( ip_globals.net_phone, packet_get_id( next ));
679
                next = new_packet;
680
                continue;
681
            }
682
        }
683
        next = pq_next( next );
684
    }
685
    return packet;
686
}
687
 
688
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
689
    ERROR_DECLARE;
690
 
691
    packet_t        new_packet;
692
    ip_header_ref   header;
693
    ip_header_ref   middle_header;
694
    ip_header_ref   last_header;
695
    uint8_t *       src;
696
    uint8_t *       dest;
697
    int             address_length;
698
 
699
    address_length = packet_get_addr( packet, & src, & dest );
700
    if( address_length <= 0 ) return EINVAL;
701
    if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
702
    // get header
703
    header = ( ip_header_ref ) packet_get_data( packet );
704
    if( ! header ) return EINVAL;
705
    // fragmentation forbidden?
706
    if( header->flags & IPFLAG_DONT_FRAGMENT ){
707
        // TODO fragmentation necessary ICMP
708
        return EPERM;
709
    }
710
    // create the last fragment
711
    new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length > addr_len ) ? address_length : addr_len ));
712
    if( ! new_packet ) return ENOMEM;
713
    last_header = ip_create_last_header( new_packet, header );
714
    if( ! last_header ){
715
        pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
716
        return ENOMEM;
717
    }
718
    // biggest multiple of 8 lower than content
719
    // TODO even fragmentation?
720
    length = length & ( ~ 0x7 );// ( content / 8 ) * 8
721
    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 ))){
722
        pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
723
        return ERROR_CODE;
724
    }
725
    // mark the first as fragmented
726
    header->flags |= IPFLAG_MORE_FRAGMENTS;
727
    // create middle framgents
728
    while( IP_TOTAL_LENGTH( header ) > length ){
729
        new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
730
        if( ! new_packet ) return ENOMEM;
731
        middle_header = ip_create_middle_header( new_packet, last_header );
732
        if( ! middle_header ){
733
            pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
734
            return ENOMEM;
735
        }
736
        if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){
737
            pq_release( ip_globals.net_phone, packet_get_id( new_packet ));
738
            return ERROR_CODE;
739
        }
740
    }
741
    // finish the first fragment
742
    header->header_checksum = IP_HEADER_CHECKSUM( header );
743
    printf( "ok\n" );
744
    return EOK;
745
}
746
 
747
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 ){
748
    ERROR_DECLARE;
749
 
750
    void *          data;
751
 
752
    data = packet_suffix( new_packet, length );
753
    if( ! data ) return ENOMEM;
754
    memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
755
    ERROR_PROPAGATE( packet_trim( packet, 0, length ));
756
    header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
757
    new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
758
    new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
759
    new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
760
    ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
761
    return pq_insert_after( packet, new_packet );
762
}
763
 
764
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
765
    ip_header_ref   middle;
766
 
767
    middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
768
    if( ! middle ) return NULL;
769
    memcpy( middle, last, IP_HEADER_LENGTH( last ));
770
    middle->flags |= IPFLAG_MORE_FRAGMENTS;
771
    return middle;
772
}
773
 
774
ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ){
775
    ip_header_ref   last;
776
    ip_option_ref   option;
777
    size_t          next;
778
    size_t          length;
779
 
780
    // allocate as much as originally
781
    last = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( first ));
782
    if( ! last ) return NULL;
783
    // copy first itself
784
    memcpy( last, first, sizeof( ip_header_t ));
785
    length = sizeof( ip_header_t );
786
    next = sizeof( ip_header_t );
787
    // process all ip options
788
    while( next < first->ihl ){
789
        option = ( ip_option_ref ) ((( void * ) first ) + next );
790
        // skip end or noop
791
        if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
792
            ++ next;
793
        }else{
794
            // copy if said so or skip
795
            if( IPOPT_COPIED( option->type )){
796
                memcpy((( void * ) last ) + length, (( void * ) first ) + next, option->length );
797
                length += option->length;
798
            }
799
            // next option
800
            next += option->length;
801
        }
802
    }
803
    // align 4 byte boundary
804
    if( length % 4 ){
805
        bzero((( void * ) last ) + length, 4 - ( length % 4 ));
806
        last->ihl = length / 4 + 1;
807
    }else{
808
        last->ihl = length / 4;
809
    }
810
    // trim the unused space
811
    if( packet_trim( packet, 0, IP_HEADER_LENGTH( first ) - IP_HEADER_LENGTH( last )) != EOK ) return NULL;
812
    return last;
813
}
814
 
815
int ip_received_msg( device_id_t device_id, packet_t packet ){
816
    packet_t        next;
817
 
818
    do{
819
        next = pq_detach( packet );
820
        if( ip_process_packet( device_id, packet ) != EOK ){
821
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
822
        }
823
        packet = next;
824
    }while( packet );
825
    return EOK;
826
}
827
 
828
int ip_process_packet( device_id_t device_id, packet_t packet ){
829
    ERROR_DECLARE;
830
 
831
    ip_header_ref   header;
832
    in_addr_t       dest;
833
    ip_route_ref    route;
834
 
835
    header = ( ip_header_ref ) packet_get_data( packet );
836
    if( ! header ) return ENOMEM;
837
    // checksum
838
    if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
839
        // TODO checksum error ICMP?
840
        return EINVAL;
841
    }
842
    // TODO ttl oxceeded ICMP?
843
    if( !( -- header->ttl )) return EINVAL;
844
    // process ipopt and get destination
845
    dest = ip_get_destination( header );
846
    ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
847
    route = ip_find_route( dest );
848
    // TODO unreachable ICMP?
849
    if( ! route ) return ENOENT;
850
    if( route->address.s_addr == dest.s_addr ){
851
        // local delivery
852
        return ip_deliver_local( device_id, packet, header );
853
    }else{
854
        return ip_send_route( packet, route->netif, route, NULL, dest );
855
    }
856
}
857
 
858
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ){
859
    ERROR_DECLARE;
860
 
861
    ip_proto_ref    proto;
862
 
863
    if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
864
        // TODO fragmented
865
        return ENOTSUP;
866
    }else{
867
        proto = ip_protos_find( & ip_globals.protos, header->protocol );
868
        if( ! proto ) return ENOENT;
869
        ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
870
        if( proto->tl_received_msg ){
871
            return proto->tl_received_msg( device_id, packet, SERVICE_IP );
872
        }else{
873
            return tl_received_msg( proto->phone, device_id, packet, proto->service );
874
        }
875
    }
876
}
877
 
878
in_addr_t ip_get_destination( ip_header_ref header ){
879
    in_addr_t   destination;
880
 
881
    // TODO search set ipopt route?
882
    destination.s_addr = header->destination_address; //ntohl( header->destination_address );
883
    return destination;
884
}
885
 
3466 mejdrech 886
/** @}
887
 */