Subversion Repositories HelenOS

Rev

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

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