Subversion Repositories HelenOS

Rev

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

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