Subversion Repositories HelenOS

Rev

Rev 4575 | Rev 4589 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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