Subversion Repositories HelenOS

Rev

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

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