Subversion Repositories HelenOS

Rev

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

Rev 4711 Rev 4717
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
 *  IP module implementation.
34
 *  IP module implementation.
35
 *  @see arp.h
35
 *  @see arp.h
36
 *  \todo
36
 *  \todo
37
 */
37
 */
38
 
38
 
39
#include <async.h>
39
#include <async.h>
40
#include <errno.h>
40
#include <errno.h>
41
#include <fibril_sync.h>
41
#include <fibril_sync.h>
42
#include <stdio.h>
42
#include <stdio.h>
43
#include <string.h>
43
#include <string.h>
44
 
44
 
45
#include <ipc/ipc.h>
45
#include <ipc/ipc.h>
46
#include <ipc/services.h>
46
#include <ipc/services.h>
47
 
47
 
48
#include <sys/types.h>
48
#include <sys/types.h>
49
 
49
 
50
#include "../../err.h"
50
#include "../../err.h"
51
#include "../../messages.h"
51
#include "../../messages.h"
52
#include "../../modules.h"
52
#include "../../modules.h"
53
 
53
 
54
#include "../../include/net_interface.h"
54
#include "../../include/net_interface.h"
55
#include "../../include/inet.h"
55
#include "../../include/inet.h"
56
#include "../../include/socket_codes.h"
56
#include "../../include/socket_codes.h"
57
#include "../../include/byteorder.h"
57
#include "../../include/byteorder.h"
58
#include "../../include/crc.h"
58
#include "../../include/crc.h"
59
#include "../../include/device.h"
59
#include "../../include/device.h"
60
#include "../../include/arp_interface.h"
60
#include "../../include/arp_interface.h"
61
#include "../../include/nil_interface.h"
61
#include "../../include/nil_interface.h"
62
#include "../../include/il_interface.h"
62
#include "../../include/il_interface.h"
63
#include "../../include/ip_client.h"
63
#include "../../include/ip_client.h"
64
#include "../../include/ip_interface.h"
64
#include "../../include/ip_interface.h"
65
#include "../../include/tl_interface.h"
65
#include "../../include/tl_interface.h"
66
#include "../../include/icmp_codes.h"
66
#include "../../include/icmp_codes.h"
67
#include "../../include/icmp_interface.h"
67
#include "../../include/icmp_interface.h"
68
#include "../../include/icmp_client.h"
68
#include "../../include/icmp_client.h"
69
#include "../../structures/measured_strings.h"
69
#include "../../structures/measured_strings.h"
70
#include "../../structures/module_map.h"
70
#include "../../structures/module_map.h"
71
#include "../../structures/packet/packet_client.h"
71
#include "../../structures/packet/packet_client.h"
72
 
72
 
73
#include "../../nil/nil_messages.h"
73
#include "../../nil/nil_messages.h"
74
 
74
 
75
#include "../il_messages.h"
75
#include "../il_messages.h"
76
 
76
 
77
#include "ip.h"
77
#include "ip.h"
78
#include "ip_header.h"
78
#include "ip_header.h"
79
#include "ip_messages.h"
79
#include "ip_messages.h"
80
#include "ip_module.h"
80
#include "ip_module.h"
81
 
81
 
82
/** Default IP version.
82
/** Default IP version.
83
 */
83
 */
84
#define DEFAULT_IPV     4
84
#define DEFAULT_IPV     4
85
 
85
 
86
/** Minimum IP packet content.
86
/** Minimum IP packet content.
87
 */
87
 */
88
#define IP_MIN_CONTENT  576
88
#define IP_MIN_CONTENT  576
89
 
89
 
90
/** ARP module name.
90
/** ARP module name.
91
 */
91
 */
92
#define ARP_NAME                "arp"
92
#define ARP_NAME                "arp"
93
 
93
 
94
/** ARP module filename.
94
/** ARP module filename.
95
 */
95
 */
96
#define ARP_FILENAME            "/srv/arp"
96
#define ARP_FILENAME            "/srv/arp"
97
 
97
 
98
/** IP packet address length.
98
/** IP packet address length.
99
 */
99
 */
100
#define IP_ADDR                         sizeof( in_addr_t )
100
#define IP_ADDR                         sizeof( in_addr_t )
101
 
101
 
102
/** IP packet prefix length.
102
/** IP packet prefix length.
103
 */
103
 */
104
#define IP_PREFIX                       sizeof( ip_header_t )
104
#define IP_PREFIX                       sizeof( ip_header_t )
105
 
105
 
106
/** IP packet suffix length.
106
/** IP packet suffix length.
107
 */
107
 */
108
#define IP_SUFFIX                       0
108
#define IP_SUFFIX                       0
109
 
109
 
110
/** IP packet maximum content length.
110
/** IP packet maximum content length.
111
 */
111
 */
112
#define IP_MAX_CONTENT                  65535
112
#define IP_MAX_CONTENT                  65535
113
 
113
 
114
/** Returns the actual IP header length.
114
/** Returns the actual IP header length.
115
 *  @param header The IP packet header. Input parameter.
115
 *  @param header The IP packet header. Input parameter.
116
 */
116
 */
117
#define IP_HEADER_LENGTH( header )      (( header )->ihl * 4u )
117
#define IP_HEADER_LENGTH( header )      (( header )->ihl * 4u )
118
 
118
 
119
/** Returns the actual IP packet total length.
119
/** Returns the actual IP packet total length.
120
 *  @param header The IP packet header. Input parameter.
120
 *  @param header The IP packet header. Input parameter.
121
 */
121
 */
122
#define IP_TOTAL_LENGTH( header )       ntohs(( header )->total_length )
122
#define IP_TOTAL_LENGTH( header )       ntohs(( header )->total_length )
123
 
123
 
124
/** Returns the actual IP packet data length.
124
/** Returns the actual IP packet data length.
125
 *  @param header The IP packet header. Input parameter.
125
 *  @param header The IP packet header. Input parameter.
126
 */
126
 */
127
#define IP_HEADER_DATA_LENGTH( header ) ( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header ))
127
#define IP_HEADER_DATA_LENGTH( header ) ( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header ))
128
 
128
 
129
/** Returns the IP packet header checksum.
129
/** Returns the IP packet header checksum.
130
 *  @param header The IP packet header. Input parameter.
130
 *  @param header The IP packet header. Input parameter.
131
 */
131
 */
132
#define IP_HEADER_CHECKSUM( header )    ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
132
#define IP_HEADER_CHECKSUM( header )    ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header ))))
133
 
133
 
134
/** IP global data.
134
/** IP global data.
135
 */
135
 */
136
ip_globals_t    ip_globals;
136
ip_globals_t    ip_globals;
137
 
137
 
138
DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
138
DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
139
 
139
 
140
INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
140
INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
141
 
141
 
142
GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
142
GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
143
 
143
 
144
/** Updates the device content length according to the new MTU value.
144
/** Updates the device content length according to the new MTU value.
145
 *  @param device_id The device identifier. Input parameter.
145
 *  @param device_id The device identifier. Input parameter.
146
 *  @param mtu The new mtu value. Input parameter.
146
 *  @param mtu The new mtu value. Input parameter.
147
 *  @returns EOK on success.
147
 *  @returns EOK on success.
148
 *  @returns ENOENT if device is not found.
148
 *  @returns ENOENT if device is not found.
149
 */
149
 */
150
int ip_mtu_changed_message( device_id_t device_id, size_t mtu );
150
int ip_mtu_changed_message( device_id_t device_id, size_t mtu );
151
 
151
 
152
/** Updates the device state.
152
/** Updates the device state.
153
 *  @param device_id The device identifier. Input parameter.
153
 *  @param device_id The device identifier. Input parameter.
154
 *  @param state The new state value. Input parameter.
154
 *  @param state The new state value. Input parameter.
155
 *  @returns EOK on success.
155
 *  @returns EOK on success.
156
 *  @returns ENOENT if device is not found.
156
 *  @returns ENOENT if device is not found.
157
 */
157
 */
158
int ip_device_state_message( device_id_t device_id, device_state_t state );
158
int ip_device_state_message( device_id_t device_id, device_state_t state );
159
 
159
 
160
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
160
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
161
 
161
 
162
/** Initializes a new network interface specific data.
162
/** Initializes a new network interface specific data.
163
 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
163
 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
164
 *  The device identifier and the nil service has to be set.
164
 *  The device identifier and the nil service has to be set.
165
 *  @param ip_netif Network interface specific data. Input/output parameter.
165
 *  @param ip_netif Network interface specific data. Input/output parameter.
166
 *  @returns EOK on success.
166
 *  @returns EOK on success.
167
 *  @returns ENOTSUP if DHCP is configured.
167
 *  @returns ENOTSUP if DHCP is configured.
168
 *  @returns ENOTSUP if IPv6 is configured.
168
 *  @returns ENOTSUP if IPv6 is configured.
169
 *  @returns EINVAL if any of the addresses is invalid.
169
 *  @returns EINVAL if any of the addresses is invalid.
170
 *  @returns EINVAL if the used ARP module is not known.
170
 *  @returns EINVAL if the used ARP module is not known.
171
 *  @returns ENOMEM if there is not enough memory left.
171
 *  @returns ENOMEM if there is not enough memory left.
172
 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
172
 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
173
 *  @returns Other error codes as defined for the bind_service() function.
173
 *  @returns Other error codes as defined for the bind_service() function.
174
 *  @returns Other error codes as defined for the specific arp_device_req() function.
174
 *  @returns Other error codes as defined for the specific arp_device_req() function.
175
 *  @returns Other error codes as defined for the nil_packet_size_req() function.
175
 *  @returns Other error codes as defined for the nil_packet_size_req() function.
176
 */
176
 */
177
int ip_netif_initialize( ip_netif_ref ip_netif );
177
int ip_netif_initialize( ip_netif_ref ip_netif );
178
 
178
 
179
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error );
179
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error );
180
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
180
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
181
 
181
 
182
packet_t    ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error );
182
packet_t    ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error );
183
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len );
183
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len );
184
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 );
184
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 );
185
ip_header_ref   ip_create_middle_header( packet_t packet, ip_header_ref last );
185
ip_header_ref   ip_create_middle_header( packet_t packet, ip_header_ref last );
186
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
186
void ip_create_last_header( ip_header_ref last, ip_header_ref first );
187
 
187
 
188
in_addr_t * ip_netif_address( ip_netif_ref netif );
188
in_addr_t * ip_netif_address( ip_netif_ref netif );
189
ip_route_ref    ip_find_route( in_addr_t destination );
189
ip_route_ref    ip_find_route( in_addr_t destination );
190
ip_route_ref    ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
190
ip_route_ref    ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
191
 
191
 
192
/** Processes the received IP packet.
192
/** Processes the received IP packet.
193
 *  @param device_id The source device identifier. Input parameter.
193
 *  @param device_id The source device identifier. Input parameter.
194
 *  @param packet The received packet. Input/output parameter.
194
 *  @param packet The received packet. Input/output parameter.
195
 *  @returns EOK on success and the packet is no longer needed.
195
 *  @returns EOK on success and the packet is no longer needed.
196
 *  @returns EINVAL if the packet is too small to carry the IP packet.
196
 *  @returns EINVAL if the packet is too small to carry the IP packet.
197
 *  @returns EINVAL if the received address lengths differs from the registered values.
197
 *  @returns EINVAL if the received address lengths differs from the registered values.
198
 *  @returns ENOENT if the device is not found in the cache.
198
 *  @returns ENOENT if the device is not found in the cache.
199
 *  @returns ENOENT if the protocol for the device is not found in the cache.
199
 *  @returns ENOENT if the protocol for the device is not found in the cache.
200
 *  @returns ENOMEM if there is not enough memory left.
200
 *  @returns ENOMEM if there is not enough memory left.
201
 */
201
 */
202
int ip_receive_message( device_id_t device_id, packet_t packet );
202
int ip_receive_message( device_id_t device_id, packet_t packet );
203
 
203
 
204
int ip_process_packet( device_id_t device_id, packet_t packet );
204
int ip_process_packet( device_id_t device_id, packet_t packet );
205
in_addr_t   ip_get_destination( ip_header_ref header );
205
in_addr_t   ip_get_destination( ip_header_ref header );
206
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
206
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
207
 
207
 
208
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
208
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
209
int ip_get_icmp_phone( void );
209
int ip_get_icmp_phone( void );
210
int ip_prepare_icmp( packet_t packet, ip_header_ref header );
210
int ip_prepare_icmp( packet_t packet, ip_header_ref header );
211
 
211
 
212
int ip_release_and_return( packet_t packet, int result );
212
int ip_release_and_return( packet_t packet, int result );
213
 
213
 
214
int ip_initialize( async_client_conn_t client_connection ){
214
int ip_initialize( async_client_conn_t client_connection ){
215
    ERROR_DECLARE;
215
    ERROR_DECLARE;
216
 
216
 
217
    fibril_rwlock_initialize( & ip_globals.lock );
217
    fibril_rwlock_initialize( & ip_globals.lock );
218
    fibril_rwlock_write_lock( & ip_globals.lock );
218
    fibril_rwlock_write_lock( & ip_globals.lock );
219
    fibril_rwlock_initialize( & ip_globals.protos_lock );
219
    fibril_rwlock_initialize( & ip_globals.protos_lock );
220
    fibril_rwlock_initialize( & ip_globals.netifs_lock );
220
    fibril_rwlock_initialize( & ip_globals.netifs_lock );
221
    ip_globals.packet_counter = 0;
221
    ip_globals.packet_counter = 0;
222
    ip_globals.gateway.address.s_addr = 0;
222
    ip_globals.gateway.address.s_addr = 0;
223
    ip_globals.gateway.netmask.s_addr = 0;
223
    ip_globals.gateway.netmask.s_addr = 0;
224
    ip_globals.gateway.gateway.s_addr = 0;
224
    ip_globals.gateway.gateway.s_addr = 0;
225
    ip_globals.gateway.netif = NULL;
225
    ip_globals.gateway.netif = NULL;
226
    ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
226
    ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
227
    ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
227
    ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
228
    ip_globals.client_connection = client_connection;
228
    ip_globals.client_connection = client_connection;
229
    ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
229
    ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
230
    ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
230
    ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
231
    fibril_rwlock_write_unlock( & ip_globals.lock );
231
    fibril_rwlock_write_unlock( & ip_globals.lock );
232
    return EOK;
232
    return EOK;
233
}
233
}
234
 
234
 
235
int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
235
int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
236
    ERROR_DECLARE;
236
    ERROR_DECLARE;
237
 
237
 
238
    ip_netif_ref    ip_netif;
238
    ip_netif_ref    ip_netif;
239
    ip_route_ref    route;
239
    ip_route_ref    route;
240
    int             index;
240
    int             index;
241
    char *          data;
241
    char *          data;
242
 
242
 
243
    ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
243
    ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
244
    if( ! ip_netif ) return ENOMEM;
244
    if( ! ip_netif ) return ENOMEM;
245
    if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
245
    if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
246
        free( ip_netif );
246
        free( ip_netif );
247
        return ERROR_CODE;
247
        return ERROR_CODE;
248
    }
248
    }
249
    ip_netif->device_id = device_id;
249
    ip_netif->device_id = device_id;
250
    ip_netif->service = netif;
250
    ip_netif->service = netif;
251
    ip_netif->state = NETIF_STOPPED;
251
    ip_netif->state = NETIF_STOPPED;
252
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
252
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
253
    if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
253
    if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
254
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
254
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
255
        ip_routes_destroy( & ip_netif->routes );
255
        ip_routes_destroy( & ip_netif->routes );
256
        free( ip_netif );
256
        free( ip_netif );
257
        return ERROR_CODE;
257
        return ERROR_CODE;
258
    }
258
    }
259
    if( ip_netif->arp ) ++ ip_netif->arp->usage;
259
    if( ip_netif->arp ) ++ ip_netif->arp->usage;
260
    // print the settings
260
    // print the settings
261
    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 );
261
    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 );
262
    printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
262
    printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
263
    // TODO ipv6 addresses
263
    // TODO ipv6 addresses
264
    data = ( char * ) malloc( INET_ADDRSTRLEN );
264
    data = ( char * ) malloc( INET_ADDRSTRLEN );
265
    if( data ){
265
    if( data ){
266
        for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
266
        for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
267
            route = ip_routes_get_index( & ip_netif->routes, index );
267
            route = ip_routes_get_index( & ip_netif->routes, index );
268
            if( route ){
268
            if( route ){
269
                printf( "\tRouting %d:\n", index );
269
                printf( "\tRouting %d:\n", index );
270
                inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
270
                inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
271
                printf( "\t\taddress\t= %s\n", data );
271
                printf( "\t\taddress\t= %s\n", data );
272
                inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
272
                inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
273
                printf( "\t\tnetmask\t= %s\n", data );
273
                printf( "\t\tnetmask\t= %s\n", data );
274
                inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
274
                inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
275
                printf( "\t\tgateway\t= %s\n", data );
275
                printf( "\t\tgateway\t= %s\n", data );
276
            }
276
            }
277
        }
277
        }
278
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
278
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
279
        printf( "\tbroadcast\t= %s\n", data );
279
        printf( "\tbroadcast\t= %s\n", data );
280
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
280
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
281
        printf( "\tdns1\t= %s\n", data );
281
        printf( "\tdns1\t= %s\n", data );
282
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
282
        inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
283
        printf( "\tdns2\t= %s\n", data );
283
        printf( "\tdns2\t= %s\n", data );
284
        free( data );
284
        free( data );
285
    }
285
    }
286
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
286
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
287
    return EOK;
287
    return EOK;
288
}
288
}
289
 
289
 
290
int ip_netif_initialize( ip_netif_ref ip_netif ){
290
int ip_netif_initialize( ip_netif_ref ip_netif ){
291
    ERROR_DECLARE;
291
    ERROR_DECLARE;
292
 
292
 
293
    measured_string_t   names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
293
    measured_string_t   names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
294
    measured_string_ref configuration;
294
    measured_string_ref configuration;
295
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
295
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
296
    char *              data;
296
    char *              data;
-
 
297
    measured_string_t   address;
297
    int                 index;
298
    int                 index;
298
    ip_route_ref        route;
299
    ip_route_ref        route;
299
    in_addr_t           gateway;
300
    in_addr_t           gateway;
300
 
301
 
301
    ip_netif->arp = NULL;
302
    ip_netif->arp = NULL;
302
    route = NULL;
303
    route = NULL;
303
    configuration = & names[ 0 ];
304
    configuration = & names[ 0 ];
304
    // get configuration
305
    // get configuration
305
    ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
306
    ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
306
    if( configuration ){
307
    if( configuration ){
307
        if( configuration[ 0 ].value ){
308
        if( configuration[ 0 ].value ){
308
            ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
309
            ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
309
        }else{
310
        }else{
310
            ip_netif->ipv = DEFAULT_IPV;
311
            ip_netif->ipv = DEFAULT_IPV;
311
        }
312
        }
312
        ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
313
        ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
313
        if( ip_netif->dhcp ){
314
        if( ip_netif->dhcp ){
314
            // TODO dhcp
315
            // TODO dhcp
315
            net_free_settings( configuration, data );
316
            net_free_settings( configuration, data );
316
            return ENOTSUP;
317
            return ENOTSUP;
317
        }else if( ip_netif->ipv == 4 ){
318
        }else if( ip_netif->ipv == 4 ){
318
            route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
319
            route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
319
            if( ! route ){
320
            if( ! route ){
320
                net_free_settings( configuration, data );
321
                net_free_settings( configuration, data );
321
                return ENOMEM;
322
                return ENOMEM;
322
            }
323
            }
323
            route->address.s_addr = 0;
324
            route->address.s_addr = 0;
324
            route->netmask.s_addr = 0;
325
            route->netmask.s_addr = 0;
325
            route->gateway.s_addr = 0;
326
            route->gateway.s_addr = 0;
326
            route->netif = ip_netif;
327
            route->netif = ip_netif;
327
            index = ip_routes_add( & ip_netif->routes, route );
328
            index = ip_routes_add( & ip_netif->routes, route );
328
            if( index < 0 ){
329
            if( index < 0 ){
329
                net_free_settings( configuration, data );
330
                net_free_settings( configuration, data );
330
                free( route );
331
                free( route );
331
                return index;
332
                return index;
332
            }
333
            }
333
            if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
334
            if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
334
            || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
335
            || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
335
            || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
336
            || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
336
            || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
337
            || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
337
            || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
338
            || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
338
            || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
339
            || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
339
                net_free_settings( configuration, data );
340
                net_free_settings( configuration, data );
340
                return EINVAL;
341
                return EINVAL;
341
            }
342
            }
342
        }else{
343
        }else{
343
            // TODO ipv6 in separate module
344
            // TODO ipv6 in separate module
344
            net_free_settings( configuration, data );
345
            net_free_settings( configuration, data );
345
            return ENOTSUP;
346
            return ENOTSUP;
346
        }
347
        }
347
        if( configuration[ 8 ].value ){
348
        if( configuration[ 8 ].value ){
348
            ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
349
            ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
349
            if( ! ip_netif->arp ){
350
            if( ! ip_netif->arp ){
350
                printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
351
                printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
351
                net_free_settings( configuration, data );
352
                net_free_settings( configuration, data );
352
                return EINVAL;
353
                return EINVAL;
353
            }
354
            }
354
        }else{
355
        }else{
355
            ip_netif->arp = NULL;
356
            ip_netif->arp = NULL;
356
        }
357
        }
357
        ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' );
358
        ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' );
358
        net_free_settings( configuration, data );
359
        net_free_settings( configuration, data );
359
    }
360
    }
-
 
361
    // binds the netif service which also initializes the device
360
    ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
362
    ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
361
    if( ip_netif->phone < 0 ){
363
    if( ip_netif->phone < 0 ){
362
        printf( "Failed to contact the nil service %d\n", ip_netif->service );
364
        printf( "Failed to contact the nil service %d\n", ip_netif->service );
363
        return ip_netif->phone;
365
        return ip_netif->phone;
364
    }
366
    }
365
    // MUST BE AFTER the bind_service up there!
367
    // has to be after the device netif module initialization
366
    if( ip_netif->arp ){
368
    if( ip_netif->arp ){
367
        if( route ){
369
        if( route ){
368
            configuration[ 0 ].value = ( char * ) & route->address.s_addr;
370
            address.value = ( char * ) & route->address.s_addr;
369
            configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 );
371
            address.length = CONVERT_SIZE( in_addr_t, char, 1 );
370
            ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & configuration[ 0 ] ));
372
            ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address ));
371
        }else{
373
        }else{
372
            ip_netif->arp = 0;
374
            ip_netif->arp = 0;
373
        }
375
        }
374
    }
376
    }
375
    // get packet dimensions
377
    // get packet dimensions
376
    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 ));
378
    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 ));
377
    if( ip_netif->content < IP_MIN_CONTENT ){
379
    if( ip_netif->content < IP_MIN_CONTENT ){
378
        printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
380
        printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
379
        ip_netif->content = IP_MIN_CONTENT;
381
        ip_netif->content = IP_MIN_CONTENT;
380
    }
382
    }
381
    index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
383
    index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
382
    if( index < 0 ) return index;
384
    if( index < 0 ) return index;
383
    if( gateway.s_addr ){
385
    if( gateway.s_addr ){
384
        // the default gateway
386
        // the default gateway
385
        ip_globals.gateway.address.s_addr = 0;
387
        ip_globals.gateway.address.s_addr = 0;
386
        ip_globals.gateway.netmask.s_addr = 0;
388
        ip_globals.gateway.netmask.s_addr = 0;
387
        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
389
        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
388
        ip_globals.gateway.netif = ip_netif;
390
        ip_globals.gateway.netif = ip_netif;
389
    }
391
    }
390
    return EOK;
392
    return EOK;
391
}
393
}
392
 
394
 
393
int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
395
int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
394
    ip_netif_ref    netif;
396
    ip_netif_ref    netif;
395
 
397
 
396
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
398
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
397
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
399
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
398
    if( ! netif ){
400
    if( ! netif ){
399
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
401
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
400
        return ENOENT;
402
        return ENOENT;
401
    }
403
    }
402
    netif->content = mtu;
404
    netif->content = mtu;
403
    printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
405
    printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
404
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
406
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
405
    return EOK;
407
    return EOK;
406
}
408
}
407
 
409
 
408
int ip_device_state_message( device_id_t device_id, device_state_t state ){
410
int ip_device_state_message( device_id_t device_id, device_state_t state ){
409
//  ERROR_DECLARE;
411
//  ERROR_DECLARE;
410
 
412
 
411
/*  measured_string_t   address;
413
/*  measured_string_t   address;
412
    measured_string_ref translation;
414
    measured_string_ref translation;
413
    char *              data;
415
    char *              data;
414
*/
416
*/
415
/*  packet_t        packet;
417
/*  packet_t        packet;
416
    in_addr_t       destination;
418
    in_addr_t       destination;
417
*/
419
*/
418
    ip_netif_ref    netif;
420
    ip_netif_ref    netif;
419
 
421
 
420
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
422
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
421
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
423
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
422
    if( ! netif ){
424
    if( ! netif ){
423
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
425
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
424
        return ENOENT;
426
        return ENOENT;
425
    }
427
    }
426
    netif->state = state;
428
    netif->state = state;
427
    // TODO state
429
    // TODO state
428
    printf( "ip - device %d changed state to %d\n\n", device_id, state );
430
    printf( "ip - device %d changed state to %d\n\n", device_id, state );
429
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
431
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
430
//  if( netif->arp ){
432
//  if( netif->arp ){
431
/*      address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
433
/*      address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
432
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
434
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
433
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
435
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
434
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
436
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
435
        }
437
        }
436
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
438
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
437
        free( translation );
439
        free( translation );
438
        free( data );
440
        free( data );
439
        address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
441
        address.value = ( char * ) & ip_globals.gateway.gateway.s_addr;
440
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
442
        address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 );
441
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
443
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){
442
            sleep( 2 );
444
            sleep( 2 );
443
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
445
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ));
444
        }
446
        }
445
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
447
        printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
446
        free( translation );
448
        free( translation );
447
        free( data );
449
        free( data );
448
*//*        printf( "IP - testing to send packet:\n" );
450
*//*        printf( "IP - testing to send packet:\n" );
449
        ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
451
        ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr ));
450
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
452
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
451
        if( ! packet ) return ENOMEM;
453
        if( ! packet ) return ENOMEM;
452
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
454
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
453
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
455
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
454
        if( ! packet ) return ENOMEM;
456
        if( ! packet ) return ENOMEM;
455
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
457
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
456
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
458
        packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
457
        if( ! packet ) return ENOMEM;
459
        if( ! packet ) return ENOMEM;
458
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
460
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
459
        packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
461
        packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix );
460
        if( ! packet ) return ENOMEM;
462
        if( ! packet ) return ENOMEM;
461
        // try this long version
463
        // try this long version
462
//      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 ))
464
//      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 ))
463
        if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
465
        if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 ))
464
        || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
466
        || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 ))
465
        || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
467
        || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){
466
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
468
            pq_release( ip_globals.net_phone, packet_get_id( packet ));
467
        }
469
        }
468
        ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
470
        ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP );
469
        printf( "send returned %d\n", ERROR_CODE );
471
        printf( "send returned %d\n", ERROR_CODE );
470
    }
472
    }
471
*/  return EOK;
473
*/  return EOK;
472
}
474
}
473
 
475
 
474
int ip_connect_module( services_t service ){
476
int ip_connect_module( services_t service ){
475
    return EOK;
477
    return EOK;
476
}
478
}
477
 
479
 
478
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
480
int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
479
    return ip_register( protocol, me, 0, received_msg );
481
    return ip_register( protocol, me, 0, received_msg );
480
}
482
}
481
 
483
 
482
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
484
int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
483
    ip_proto_ref    proto;
485
    ip_proto_ref    proto;
484
    int             index;
486
    int             index;
485
 
487
 
486
    if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
488
    if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
487
    proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
489
    proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
488
    if( ! proto ) return ENOMEM;
490
    if( ! proto ) return ENOMEM;
489
    proto->protocol = protocol;
491
    proto->protocol = protocol;
490
    proto->service = service;
492
    proto->service = service;
491
    proto->phone = phone;
493
    proto->phone = phone;
492
    proto->received_msg = received_msg;
494
    proto->received_msg = received_msg;
493
    fibril_rwlock_write_lock( & ip_globals.protos_lock );
495
    fibril_rwlock_write_lock( & ip_globals.protos_lock );
494
    index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
496
    index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
495
    if( index < 0 ){
497
    if( index < 0 ){
496
        fibril_rwlock_write_unlock( & ip_globals.protos_lock );
498
        fibril_rwlock_write_unlock( & ip_globals.protos_lock );
497
        free( proto );
499
        free( proto );
498
        return index;
500
        return index;
499
    }
501
    }
500
    printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
502
    printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
501
    fibril_rwlock_write_unlock( & ip_globals.protos_lock );
503
    fibril_rwlock_write_unlock( & ip_globals.protos_lock );
502
    return EOK;
504
    return EOK;
503
}
505
}
504
 
506
 
505
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
507
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
506
    ERROR_DECLARE;
508
    ERROR_DECLARE;
507
 
509
 
508
    int                 length;
510
    int                 length;
509
    ip_netif_ref        netif;
511
    ip_netif_ref        netif;
510
    ip_route_ref        route;
512
    ip_route_ref        route;
511
    in_addr_t *         dest;
513
    in_addr_t *         dest;
512
    in_addr_t *         src;
514
    in_addr_t *         src;
513
    int                 phone;
515
    int                 phone;
514
 
516
 
515
    // addresses in the host byte order
517
    // addresses in the host byte order
516
    // should be the next hop address or the target destination address
518
    // should be the next hop address or the target destination address
517
    length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest );
519
    length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest );
518
    if( length < 0 ){
520
    if( length < 0 ){
519
        return ip_release_and_return( packet, length );
521
        return ip_release_and_return( packet, length );
520
    }
522
    }
521
    // TODO IPv6
523
    // TODO IPv6
522
    if( length != IP_ADDR ){
524
    if( length != IP_ADDR ){
523
        return ip_release_and_return( packet, EINVAL );
525
        return ip_release_and_return( packet, EINVAL );
524
    }
526
    }
525
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
527
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
526
    // device specified?
528
    // device specified?
527
    if( device_id > 0 ){
529
    if( device_id > 0 ){
528
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
530
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
529
        route = ip_netif_find_route( netif, * dest );
531
        route = ip_netif_find_route( netif, * dest );
530
    }else{
532
    }else{
531
        // TODO IPv6
533
        // TODO IPv6
532
        route = ip_find_route( * dest );
534
        route = ip_find_route( * dest );
533
        netif = route ? route->netif : NULL;
535
        netif = route ? route->netif : NULL;
534
    }
536
    }
535
    if( !( netif && route )){
537
    if( !( netif && route )){
536
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
538
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
537
        phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
539
        phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
538
        if( phone >= 0 ){
540
        if( phone >= 0 ){
539
            // unreachable ICMP if no routing
541
            // unreachable ICMP if no routing
540
            icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
542
            icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
541
        }
543
        }
542
        return ENOENT;
544
        return ENOENT;
543
    }
545
    }
544
    if( error ){
546
    if( error ){
545
        // do not send for broadcast, anycast packets or network broadcast
547
        // do not send for broadcast, anycast packets or network broadcast
546
        if(( ! dest->s_addr )
548
        if(( ! dest->s_addr )
547
        || ( !( ~ dest->s_addr ))
549
        || ( !( ~ dest->s_addr ))
548
        || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
550
        || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
549
        || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
551
        || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
550
            return ip_release_and_return( packet, EINVAL );
552
            return ip_release_and_return( packet, EINVAL );
551
        }
553
        }
552
    }
554
    }
553
    // to me?
555
    // to me?
554
    if( route->address.s_addr == dest->s_addr ){
556
    if( route->address.s_addr == dest->s_addr ){
555
        // TODO loopback deliver
557
        // TODO loopback deliver
556
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
558
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
557
        return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error );
559
        return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error );
558
    }
560
    }
559
 
561
 
560
    src = ip_netif_address( netif );
562
    src = ip_netif_address( netif );
561
    if( ! src ){
563
    if( ! src ){
562
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
564
        fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
563
        return ip_release_and_return( packet, ENOENT );
565
        return ip_release_and_return( packet, ENOENT );
564
    }
566
    }
565
    if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){
567
    if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){
566
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
568
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
567
    }
569
    }
568
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
570
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
569
    return ERROR_CODE;
571
    return ERROR_CODE;
570
}
572
}
571
 
573
 
572
in_addr_t * ip_netif_address( ip_netif_ref netif ){
574
in_addr_t * ip_netif_address( ip_netif_ref netif ){
573
    ip_route_ref    route;
575
    ip_route_ref    route;
574
 
576
 
575
    route = ip_routes_get_index( & netif->routes, 0 );
577
    route = ip_routes_get_index( & netif->routes, 0 );
576
    return route ? & route->address : NULL;
578
    return route ? & route->address : NULL;
577
}
579
}
578
 
580
 
579
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ){
581
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ){
580
    ERROR_DECLARE;
582
    ERROR_DECLARE;
581
 
583
 
582
    measured_string_t   destination;
584
    measured_string_t   destination;
583
    measured_string_ref translation;
585
    measured_string_ref translation;
584
    char *              data;
586
    char *              data;
585
    int                 phone;
587
    int                 phone;
586
 
588
 
587
    // get destination hardware address
589
    // get destination hardware address
588
    if( netif->arp ){
590
    if( netif->arp ){
589
        destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
591
        destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
590
        destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
592
        destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
591
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
593
        if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
592
            sleep( 1 );
594
            sleep( 1 );
593
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
595
            ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
594
        }
596
        }
595
        if( !( translation && translation->value )){
597
        if( !( translation && translation->value )){
596
            if( translation ){
598
            if( translation ){
597
                free( translation );
599
                free( translation );
598
                free( data );
600
                free( data );
599
            }
601
            }
600
            phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
602
            phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
601
            if( phone >= 0 ){
603
            if( phone >= 0 ){
602
                // unreachable ICMP if no routing
604
                // unreachable ICMP if no routing
603
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
605
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
604
            }
606
            }
605
            return EINVAL;
607
            return EINVAL;
606
        }
608
        }
607
    }else translation = NULL;
609
    }else translation = NULL;
608
    if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
610
    if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
609
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
611
        pq_release( ip_globals.net_phone, packet_get_id( packet ));
610
    }else{
612
    }else{
611
        packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
613
        packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
612
        if( packet ){
614
        if( packet ){
613
            nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
615
            nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
614
        }
616
        }
615
    }
617
    }
616
    if( translation ){
618
    if( translation ){
617
        free( translation );
619
        free( translation );
618
        free( data );
620
        free( data );
619
    }
621
    }
620
    return ERROR_CODE;
622
    return ERROR_CODE;
621
}
623
}
622
 
624
 
623
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
625
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
624
    ERROR_DECLARE;
626
    ERROR_DECLARE;
625
 
627
 
626
    size_t              length;
628
    size_t              length;
627
    ip_header_ref       header;
629
    ip_header_ref       header;
628
    ip_header_ref       last_header;
630
    ip_header_ref       last_header;
629
    ip_header_ref       middle_header;
631
    ip_header_ref       middle_header;
630
    packet_t            next;
632
    packet_t            next;
631
 
633
 
632
    length = packet_get_data_length( packet );
634
    length = packet_get_data_length( packet );
633
    if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
635
    if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
634
    header = ( ip_header_ref ) packet_get_data( packet );
636
    header = ( ip_header_ref ) packet_get_data( packet );
635
    if( destination ){
637
    if( destination ){
636
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
638
        ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
637
    }
639
    }
638
    header->version = 4;
640
    header->version = 4;
639
    header->fragment_offset = 0;
641
    header->fragment_offset = 0;
640
    header->header_checksum = 0;
642
    header->header_checksum = 0;
641
    if( source ) header->source_address = source->s_addr;
643
    if( source ) header->source_address = source->s_addr;
642
    header->destination_address = dest.s_addr;
644
    header->destination_address = dest.s_addr;
643
    fibril_rwlock_write_lock( & ip_globals.lock );
645
    fibril_rwlock_write_lock( & ip_globals.lock );
644
    ++ ip_globals.packet_counter;
646
    ++ ip_globals.packet_counter;
645
    header->identification = htons( ip_globals.packet_counter );
647
    header->identification = htons( ip_globals.packet_counter );
646
    fibril_rwlock_write_unlock( & ip_globals.lock );
648
    fibril_rwlock_write_unlock( & ip_globals.lock );
647
    length = packet_get_data_length( packet );
649
    length = packet_get_data_length( packet );
648
    if( pq_next( packet )){
650
    if( pq_next( packet )){
649
        last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
651
        last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
650
        if( ! last_header ) return ENOMEM;
652
        if( ! last_header ) return ENOMEM;
651
        ip_create_last_header( last_header, header );
653
        ip_create_last_header( last_header, header );
652
        next = pq_next( packet );
654
        next = pq_next( packet );
653
        while( pq_next( next )){
655
        while( pq_next( next )){
654
            middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
656
            middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
655
            if( ! middle_header ) return ENOMEM;
657
            if( ! middle_header ) return ENOMEM;
656
            memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
658
            memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
657
            header->flags |= IPFLAG_MORE_FRAGMENTS;
659
            header->flags |= IPFLAG_MORE_FRAGMENTS;
658
            middle_header->total_length = htons( packet_get_data_length( next ));
660
            middle_header->total_length = htons( packet_get_data_length( next ));
659
            middle_header->fragment_offset = length / 8;
661
            middle_header->fragment_offset = length / 8;
660
            middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
662
            middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
661
            if( destination ){
663
            if( destination ){
662
                ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
664
                ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
663
            }
665
            }
664
            length += packet_get_data_length( next );
666
            length += packet_get_data_length( next );
665
            next = pq_next( next );
667
            next = pq_next( next );
666
        }
668
        }
667
        middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
669
        middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
668
        if( ! middle_header ) return ENOMEM;
670
        if( ! middle_header ) return ENOMEM;
669
        memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
671
        memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
670
        middle_header->total_length = htons( packet_get_data_length( next ));
672
        middle_header->total_length = htons( packet_get_data_length( next ));
671
        middle_header->fragment_offset = length / 8;
673
        middle_header->fragment_offset = length / 8;
672
        middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
674
        middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
673
        if( destination ){
675
        if( destination ){
674
            ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
676
            ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
675
        }
677
        }
676
        length += packet_get_data_length( next );
678
        length += packet_get_data_length( next );
677
        free( last_header );
679
        free( last_header );
678
        header->flags |= IPFLAG_MORE_FRAGMENTS;
680
        header->flags |= IPFLAG_MORE_FRAGMENTS;
679
    }
681
    }
680
    header->total_length = htons( length );
682
    header->total_length = htons( length );
681
    // unnecessary for all protocols
683
    // unnecessary for all protocols
682
    header->header_checksum = IP_HEADER_CHECKSUM( header );
684
    header->header_checksum = IP_HEADER_CHECKSUM( header );
683
    return EOK;
685
    return EOK;
684
}
686
}
685
 
687
 
686
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
688
int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
687
    ERROR_DECLARE;
689
    ERROR_DECLARE;
688
 
690
 
689
    packet_t    packet;
691
    packet_t    packet;
690
 
692
 
691
    * answer_count = 0;
693
    * answer_count = 0;
692
    switch( IPC_GET_METHOD( * call )){
694
    switch( IPC_GET_METHOD( * call )){
693
        case IPC_M_PHONE_HUNGUP:
695
        case IPC_M_PHONE_HUNGUP:
694
            return EOK;
696
            return EOK;
695
        case NET_IL_DEVICE:
697
        case NET_IL_DEVICE:
696
            return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
698
            return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
697
        case IPC_M_CONNECT_TO_ME:
699
        case IPC_M_CONNECT_TO_ME:
698
            return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
700
            return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
699
        case NET_IL_SEND:
701
        case NET_IL_SEND:
700
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
702
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
701
            return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
703
            return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
702
        case NET_IL_DEVICE_STATE:
704
        case NET_IL_DEVICE_STATE:
703
            return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
705
            return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
704
        case NET_IL_RECEIVED:
706
        case NET_IL_RECEIVED:
705
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
707
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
706
            return ip_receive_message( IPC_GET_DEVICE( call ), packet );
708
            return ip_receive_message( IPC_GET_DEVICE( call ), packet );
707
        case NET_IP_RECEIVED_ERROR:
709
        case NET_IP_RECEIVED_ERROR:
708
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
710
            ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
709
            return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
711
            return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
710
        case NET_IP_ADD_ROUTE:
712
        case NET_IP_ADD_ROUTE:
711
            return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
713
            return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
712
        case NET_IP_SET_GATEWAY:
714
        case NET_IP_SET_GATEWAY:
713
            return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
715
            return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
714
        case NET_IL_PACKET_SPACE:
716
        case NET_IL_PACKET_SPACE:
715
            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 )));
717
            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 )));
716
            * answer_count = 3;
718
            * answer_count = 3;
717
            return EOK;
719
            return EOK;
718
        case NET_IL_MTU_CHANGED:
720
        case NET_IL_MTU_CHANGED:
719
            return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
721
            return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
720
    }
722
    }
721
    return ENOTSUP;
723
    return ENOTSUP;
722
}
724
}
723
 
725
 
724
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 ){
726
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 ){
725
    ip_netif_ref    netif;
727
    ip_netif_ref    netif;
726
    int             index;
728
    int             index;
727
 
729
 
728
    if( !( addr_len && prefix && content && suffix )) return EBADMEM;
730
    if( !( addr_len && prefix && content && suffix )) return EBADMEM;
729
    * content = IP_MAX_CONTENT - IP_PREFIX;
731
    * content = IP_MAX_CONTENT - IP_PREFIX;
730
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
732
    fibril_rwlock_read_lock( & ip_globals.netifs_lock );
731
    if( device_id < 0 ){
733
    if( device_id < 0 ){
732
        * addr_len = IP_ADDR;
734
        * addr_len = IP_ADDR;
733
        * prefix = 0;
735
        * prefix = 0;
734
        * suffix = 0;
736
        * suffix = 0;
735
        for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
737
        for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
736
            netif = ip_netifs_get_index( & ip_globals.netifs, index );
738
            netif = ip_netifs_get_index( & ip_globals.netifs, index );
737
            if( netif ){
739
            if( netif ){
738
                if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
740
                if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
739
                if( netif->prefix > * prefix ) * prefix = netif->prefix;
741
                if( netif->prefix > * prefix ) * prefix = netif->prefix;
740
                if( netif->suffix > * suffix ) * suffix = netif->suffix;
742
                if( netif->suffix > * suffix ) * suffix = netif->suffix;
741
            }
743
            }
742
        }
744
        }
743
        * prefix = * prefix + IP_PREFIX;
745
        * prefix = * prefix + IP_PREFIX;
744
        * suffix = * suffix + IP_SUFFIX;
746
        * suffix = * suffix + IP_SUFFIX;
745
    }else{
747
    }else{
746
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
748
        netif = ip_netifs_find( & ip_globals.netifs, device_id );
747
        if( ! netif ){
749
        if( ! netif ){
748
            fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
750
            fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
749
            return ENOENT;
751
            return ENOENT;
750
        }
752
        }
751
        * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
753
        * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
752
        * prefix = netif->prefix + IP_PREFIX;
754
        * prefix = netif->prefix + IP_PREFIX;
753
        * suffix = netif->suffix + IP_SUFFIX;
755
        * suffix = netif->suffix + IP_SUFFIX;
754
    }
756
    }
755
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
757
    fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
756
    return EOK;
758
    return EOK;
757
}
759
}
758
 
760
 
759
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 ){
761
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 ){
760
    ip_route_ref    route;
762
    ip_route_ref    route;
761
    ip_netif_ref    netif;
763
    ip_netif_ref    netif;
762
    int             index;
764
    int             index;
763
 
765
 
764
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
766
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
765
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
767
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
766
    if( ! netif ){
768
    if( ! netif ){
767
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
769
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
768
        return ENOENT;
770
        return ENOENT;
769
    }
771
    }
770
    route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
772
    route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
771
    if( ! route ){
773
    if( ! route ){
772
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
774
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
773
        return ENOMEM;
775
        return ENOMEM;
774
    }
776
    }
775
    route->address.s_addr = address.s_addr;
777
    route->address.s_addr = address.s_addr;
776
    route->netmask.s_addr = netmask.s_addr;
778
    route->netmask.s_addr = netmask.s_addr;
777
    route->gateway.s_addr = gateway.s_addr;
779
    route->gateway.s_addr = gateway.s_addr;
778
    route->netif = netif;
780
    route->netif = netif;
779
    index = ip_routes_add( & netif->routes, route );
781
    index = ip_routes_add( & netif->routes, route );
780
    if( index < 0 ) free( route );
782
    if( index < 0 ) free( route );
781
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
783
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
782
    return index;
784
    return index;
783
}
785
}
784
 
786
 
785
ip_route_ref ip_find_route( in_addr_t destination ){
787
ip_route_ref ip_find_route( in_addr_t destination ){
786
    int             index;
788
    int             index;
787
    ip_route_ref    route;
789
    ip_route_ref    route;
788
    ip_netif_ref    netif;
790
    ip_netif_ref    netif;
789
 
791
 
790
    // start with the last netif - the newest one
792
    // start with the last netif - the newest one
791
    index = ip_netifs_count( & ip_globals.netifs ) - 1;
793
    index = ip_netifs_count( & ip_globals.netifs ) - 1;
792
    while( index >= 0 ){
794
    while( index >= 0 ){
793
        netif = ip_netifs_get_index( & ip_globals.netifs, index );
795
        netif = ip_netifs_get_index( & ip_globals.netifs, index );
794
        if( netif && ( netif->state == NETIF_ACTIVE )){
796
        if( netif && ( netif->state == NETIF_ACTIVE )){
795
            route = ip_netif_find_route( netif, destination );
797
            route = ip_netif_find_route( netif, destination );
796
            if( route ) return route;
798
            if( route ) return route;
797
        }
799
        }
798
        -- index;
800
        -- index;
799
    }
801
    }
800
    return & ip_globals.gateway;
802
    return & ip_globals.gateway;
801
}
803
}
802
 
804
 
803
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
805
ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
804
    int             index;
806
    int             index;
805
    ip_route_ref    route;
807
    ip_route_ref    route;
806
 
808
 
807
    if( netif ){
809
    if( netif ){
808
        // start with the first one - the direct route
810
        // start with the first one - the direct route
809
        for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
811
        for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
810
            route = ip_routes_get_index( & netif->routes, index );
812
            route = ip_routes_get_index( & netif->routes, index );
811
            if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
813
            if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
812
                return route;
814
                return route;
813
            }
815
            }
814
        }
816
        }
815
    }
817
    }
816
    return NULL;
818
    return NULL;
817
}
819
}
818
 
820
 
819
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
821
int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
820
    ip_netif_ref    netif;
822
    ip_netif_ref    netif;
821
 
823
 
822
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
824
    fibril_rwlock_write_lock( & ip_globals.netifs_lock );
823
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
825
    netif = ip_netifs_find( & ip_globals.netifs, device_id );
824
    if( ! netif ){
826
    if( ! netif ){
825
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
827
        fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
826
        return ENOENT;
828
        return ENOENT;
827
    }
829
    }
828
    ip_globals.gateway.address.s_addr = 0;
830
    ip_globals.gateway.address.s_addr = 0;
829
    ip_globals.gateway.netmask.s_addr = 0;
831
    ip_globals.gateway.netmask.s_addr = 0;
830
    ip_globals.gateway.gateway.s_addr = gateway.s_addr;
832
    ip_globals.gateway.gateway.s_addr = gateway.s_addr;
831
    ip_globals.gateway.netif = netif;
833
    ip_globals.gateway.netif = netif;
832
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
834
    fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
833
    return EOK;
835
    return EOK;
834
}
836
}
835
 
837
 
836
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ){
838
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ){
837
    size_t          length;
839
    size_t          length;
838
    packet_t        next;
840
    packet_t        next;
839
    packet_t        new_packet;
841
    packet_t        new_packet;
840
    int             result;
842
    int             result;
841
    int             phone;
843
    int             phone;
842
 
844
 
843
    next = packet;
845
    next = packet;
844
    // check all packets
846
    // check all packets
845
    while( next ){
847
    while( next ){
846
        length = packet_get_data_length( next );
848
        length = packet_get_data_length( next );
847
        // too long?
849
        // too long?
848
        if( length > content ){
850
        if( length > content ){
849
            result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
851
            result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
850
            if( result != EOK ){
852
            if( result != EOK ){
851
                new_packet = pq_detach( next );
853
                new_packet = pq_detach( next );
852
                if( next == packet ){
854
                if( next == packet ){
853
                    // the new first packet of the queue
855
                    // the new first packet of the queue
854
                    packet = new_packet;
856
                    packet = new_packet;
855
                }
857
                }
856
                // fragmentation needed?
858
                // fragmentation needed?
857
                if( result == EPERM ){
859
                if( result == EPERM ){
858
                    phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
860
                    phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
859
                    if( phone >= 0 ){
861
                    if( phone >= 0 ){
860
                        // fragmentation necessary ICMP
862
                        // fragmentation necessary ICMP
861
                        icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
863
                        icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
862
                    }
864
                    }
863
                }else{
865
                }else{
864
                    pq_release( ip_globals.net_phone, packet_get_id( next ));
866
                    pq_release( ip_globals.net_phone, packet_get_id( next ));
865
                }
867
                }
866
                next = new_packet;
868
                next = new_packet;
867
                continue;
869
                continue;
868
            }
870
            }
869
        }
871
        }
870
        next = pq_next( next );
872
        next = pq_next( next );
871
    }
873
    }
872
    return packet;
874
    return packet;
873
}
875
}
874
 
876
 
875
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
877
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){
876
    ERROR_DECLARE;
878
    ERROR_DECLARE;
877
 
879
 
878
    packet_t        new_packet;
880
    packet_t        new_packet;
879
    ip_header_ref   header;
881
    ip_header_ref   header;
880
    ip_header_ref   middle_header;
882
    ip_header_ref   middle_header;
881
    ip_header_ref   last_header;
883
    ip_header_ref   last_header;
882
    uint8_t *       src;
884
    uint8_t *       src;
883
    uint8_t *       dest;
885
    uint8_t *       dest;
884
    size_t          address_length;
886
    size_t          address_length;
885
    int             result;
887
    int             result;
886
 
888
 
887
    result = packet_get_addr( packet, & src, & dest );
889
    result = packet_get_addr( packet, & src, & dest );
888
    if( result <= 0 ) return EINVAL;
890
    if( result <= 0 ) return EINVAL;
889
    address_length = ( size_t ) result;
891
    address_length = ( size_t ) result;
890
    if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
892
    if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
891
    // get header
893
    // get header
892
    header = ( ip_header_ref ) packet_get_data( packet );
894
    header = ( ip_header_ref ) packet_get_data( packet );
893
    if( ! header ) return EINVAL;
895
    if( ! header ) return EINVAL;
894
    // fragmentation forbidden?
896
    // fragmentation forbidden?
895
    if( header->flags & IPFLAG_DONT_FRAGMENT ){
897
    if( header->flags & IPFLAG_DONT_FRAGMENT ){
896
        return EPERM;
898
        return EPERM;
897
    }
899
    }
898
    // create the last fragment
900
    // create the last fragment
899
    new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len ));
901
    new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len ));
900
    if( ! new_packet ) return ENOMEM;
902
    if( ! new_packet ) return ENOMEM;
901
    // allocate as much as originally
903
    // allocate as much as originally
902
    last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
904
    last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
903
    if( ! last_header ){
905
    if( ! last_header ){
904
        return ip_release_and_return( packet, ENOMEM );
906
        return ip_release_and_return( packet, ENOMEM );
905
    }
907
    }
906
    ip_create_last_header( last_header, header );
908
    ip_create_last_header( last_header, header );
907
    // trim the unused space
909
    // trim the unused space
908
    if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
910
    if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
909
        return ip_release_and_return( packet, ERROR_CODE );
911
        return ip_release_and_return( packet, ERROR_CODE );
910
    }
912
    }
911
    // biggest multiple of 8 lower than content
913
    // biggest multiple of 8 lower than content
912
    // TODO even fragmentation?
914
    // TODO even fragmentation?
913
    length = length & ( ~ 0x7 );// ( content / 8 ) * 8
915
    length = length & ( ~ 0x7 );// ( content / 8 ) * 8
914
    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 ))){
916
    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 ))){
915
        return ip_release_and_return( packet, ERROR_CODE );
917
        return ip_release_and_return( packet, ERROR_CODE );
916
    }
918
    }
917
    // mark the first as fragmented
919
    // mark the first as fragmented
918
    header->flags |= IPFLAG_MORE_FRAGMENTS;
920
    header->flags |= IPFLAG_MORE_FRAGMENTS;
919
    // create middle framgents
921
    // create middle framgents
920
    while( IP_TOTAL_LENGTH( header ) > length ){
922
    while( IP_TOTAL_LENGTH( header ) > length ){
921
        new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
923
        new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len ));
922
        if( ! new_packet ) return ENOMEM;
924
        if( ! new_packet ) return ENOMEM;
923
        middle_header = ip_create_middle_header( new_packet, last_header );
925
        middle_header = ip_create_middle_header( new_packet, last_header );
924
        if( ! middle_header ){
926
        if( ! middle_header ){
925
            return ip_release_and_return( packet, ENOMEM );
927
            return ip_release_and_return( packet, ENOMEM );
926
        }
928
        }
927
        if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){
929
        if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){
928
            return ip_release_and_return( packet, ERROR_CODE );
930
            return ip_release_and_return( packet, ERROR_CODE );
929
        }
931
        }
930
    }
932
    }
931
    // finish the first fragment
933
    // finish the first fragment
932
    header->header_checksum = IP_HEADER_CHECKSUM( header );
934
    header->header_checksum = IP_HEADER_CHECKSUM( header );
933
    return EOK;
935
    return EOK;
934
}
936
}
935
 
937
 
936
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 ){
938
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 ){
937
    ERROR_DECLARE;
939
    ERROR_DECLARE;
938
 
940
 
939
    void *          data;
941
    void *          data;
940
 
942
 
941
    data = packet_suffix( new_packet, length );
943
    data = packet_suffix( new_packet, length );
942
    if( ! data ) return ENOMEM;
944
    if( ! data ) return ENOMEM;
943
    memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
945
    memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
944
    ERROR_PROPAGATE( packet_trim( packet, 0, length ));
946
    ERROR_PROPAGATE( packet_trim( packet, 0, length ));
945
    header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
947
    header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
946
    new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
948
    new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
947
    new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
949
    new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8;
948
    new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
950
    new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
949
    ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
951
    ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length ));
950
    return pq_insert_after( packet, new_packet );
952
    return pq_insert_after( packet, new_packet );
951
}
953
}
952
 
954
 
953
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
955
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
954
    ip_header_ref   middle;
956
    ip_header_ref   middle;
955
 
957
 
956
    middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
958
    middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
957
    if( ! middle ) return NULL;
959
    if( ! middle ) return NULL;
958
    memcpy( middle, last, IP_HEADER_LENGTH( last ));
960
    memcpy( middle, last, IP_HEADER_LENGTH( last ));
959
    middle->flags |= IPFLAG_MORE_FRAGMENTS;
961
    middle->flags |= IPFLAG_MORE_FRAGMENTS;
960
    return middle;
962
    return middle;
961
}
963
}
962
 
964
 
963
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
965
void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
964
    ip_option_ref   option;
966
    ip_option_ref   option;
965
    size_t          next;
967
    size_t          next;
966
    size_t          length;
968
    size_t          length;
967
 
969
 
968
    // copy first itself
970
    // copy first itself
969
    memcpy( last, first, sizeof( ip_header_t ));
971
    memcpy( last, first, sizeof( ip_header_t ));
970
    length = sizeof( ip_header_t );
972
    length = sizeof( ip_header_t );
971
    next = sizeof( ip_header_t );
973
    next = sizeof( ip_header_t );
972
    // process all ip options
974
    // process all ip options
973
    while( next < first->ihl ){
975
    while( next < first->ihl ){
974
        option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
976
        option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
975
        // skip end or noop
977
        // skip end or noop
976
        if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
978
        if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
977
            ++ next;
979
            ++ next;
978
        }else{
980
        }else{
979
            // copy if said so or skip
981
            // copy if said so or skip
980
            if( IPOPT_COPIED( option->type )){
982
            if( IPOPT_COPIED( option->type )){
981
                memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
983
                memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
982
                length += option->length;
984
                length += option->length;
983
            }
985
            }
984
            // next option
986
            // next option
985
            next += option->length;
987
            next += option->length;
986
        }
988
        }
987
    }
989
    }
988
    // align 4 byte boundary
990
    // align 4 byte boundary
989
    if( length % 4 ){
991
    if( length % 4 ){
990
        bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
992
        bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
991
        last->ihl = length / 4 + 1;
993
        last->ihl = length / 4 + 1;
992
    }else{
994
    }else{
993
        last->ihl = length / 4;
995
        last->ihl = length / 4;
994
    }
996
    }
995
    last->header_checksum = 0;
997
    last->header_checksum = 0;
996
}
998
}
997
 
999
 
998
int ip_receive_message( device_id_t device_id, packet_t packet ){
1000
int ip_receive_message( device_id_t device_id, packet_t packet ){
999
    packet_t        next;
1001
    packet_t        next;
1000
 
1002
 
1001
    do{
1003
    do{
1002
        next = pq_detach( packet );
1004
        next = pq_detach( packet );
1003
        ip_process_packet( device_id, packet );
1005
        ip_process_packet( device_id, packet );
1004
        packet = next;
1006
        packet = next;
1005
    }while( packet );
1007
    }while( packet );
1006
    return EOK;
1008
    return EOK;
1007
}
1009
}
1008
 
1010
 
1009
int ip_process_packet( device_id_t device_id, packet_t packet ){
1011
int ip_process_packet( device_id_t device_id, packet_t packet ){
1010
    ERROR_DECLARE;
1012
    ERROR_DECLARE;
1011
 
1013
 
1012
    ip_header_ref   header;
1014
    ip_header_ref   header;
1013
    in_addr_t       dest;
1015
    in_addr_t       dest;
1014
    ip_route_ref    route;
1016
    ip_route_ref    route;
1015
    int             phone;
1017
    int             phone;
1016
 
1018
 
1017
    header = ( ip_header_ref ) packet_get_data( packet );
1019
    header = ( ip_header_ref ) packet_get_data( packet );
1018
    if( ! header ){
1020
    if( ! header ){
1019
        return ip_release_and_return( packet, ENOMEM );
1021
        return ip_release_and_return( packet, ENOMEM );
1020
    }
1022
    }
1021
    // checksum
1023
    // checksum
1022
    if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
1024
    if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
1023
        // TODO checksum error ICMP?
1025
        // TODO checksum error ICMP?
1024
        return ip_release_and_return( packet, EINVAL );
1026
        return ip_release_and_return( packet, EINVAL );
1025
    }
1027
    }
1026
    if( header->ttl <= 1 ){
1028
    if( header->ttl <= 1 ){
1027
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1029
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1028
        if( phone >= 0 ){
1030
        if( phone >= 0 ){
1029
            // ttl oxceeded ICMP
1031
            // ttl oxceeded ICMP
1030
            icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
1032
            icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
1031
        }
1033
        }
1032
        return EINVAL;
1034
        return EINVAL;
1033
    }
1035
    }
1034
    // process ipopt and get destination
1036
    // process ipopt and get destination
1035
    dest = ip_get_destination( header );
1037
    dest = ip_get_destination( header );
1036
    ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
1038
    ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR ));
1037
    route = ip_find_route( dest );
1039
    route = ip_find_route( dest );
1038
    if( ! route ){
1040
    if( ! route ){
1039
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1041
        phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1040
        if( phone >= 0 ){
1042
        if( phone >= 0 ){
1041
            // unreachable ICMP
1043
            // unreachable ICMP
1042
            icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1044
            icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1043
        }
1045
        }
1044
        return ENOENT;
1046
        return ENOENT;
1045
    }
1047
    }
1046
    if( route->address.s_addr == dest.s_addr ){
1048
    if( route->address.s_addr == dest.s_addr ){
1047
        // local delivery
1049
        // local delivery
1048
        return ip_deliver_local( device_id, packet, header, 0 );
1050
        return ip_deliver_local( device_id, packet, header, 0 );
1049
    }else{
1051
    }else{
1050
        // only if routing enabled
1052
        // only if routing enabled
1051
        if( route->netif->routing ){
1053
        if( route->netif->routing ){
1052
            -- header->ttl;
1054
            -- header->ttl;
1053
            return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
1055
            return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
1054
        }else{
1056
        }else{
1055
            phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1057
            phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
1056
            if( phone >= 0 ){
1058
            if( phone >= 0 ){
1057
                // unreachable ICMP if no routing
1059
                // unreachable ICMP if no routing
1058
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1060
                icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
1059
            }
1061
            }
1060
            return ENOENT;
1062
            return ENOENT;
1061
        }
1063
        }
1062
    }
1064
    }
1063
}
1065
}
1064
 
1066
 
1065
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
1067
int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
1066
    uint8_t *           data;
1068
    uint8_t *           data;
1067
    int                 offset;
1069
    int                 offset;
1068
    icmp_type_t         type;
1070
    icmp_type_t         type;
1069
    icmp_code_t         code;
1071
    icmp_code_t         code;
1070
    ip_netif_ref        netif;
1072
    ip_netif_ref        netif;
1071
    measured_string_t   address;
1073
    measured_string_t   address;
1072
    ip_route_ref        route;
1074
    ip_route_ref        route;
1073
    ip_header_ref       header;
1075
    ip_header_ref       header;
1074
 
1076
 
1075
    switch( error ){
1077
    switch( error ){
1076
        case SERVICE_ICMP:
1078
        case SERVICE_ICMP:
1077
            offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
1079
            offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
1078
            if( offset < 0 ){
1080
            if( offset < 0 ){
1079
                return ip_release_and_return( packet, ENOMEM );
1081
                return ip_release_and_return( packet, ENOMEM );
1080
            }
1082
            }
1081
            data = packet_get_data( packet );
1083
            data = packet_get_data( packet );
1082
            header = ( ip_header_ref ) data + offset;
1084
            header = ( ip_header_ref ) data + offset;
1083
            // destination host unreachable?
1085
            // destination host unreachable?
1084
            if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
1086
            if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
1085
                fibril_rwlock_read_lock( & ip_globals.netifs_lock );
1087
                fibril_rwlock_read_lock( & ip_globals.netifs_lock );
1086
                netif = ip_netifs_find( & ip_globals.netifs, device_id );
1088
                netif = ip_netifs_find( & ip_globals.netifs, device_id );
1087
                if( netif && netif->arp ){
1089
                if( netif && netif->arp ){
1088
                    route = ip_routes_get_index( & netif->routes, 0 );
1090
                    route = ip_routes_get_index( & netif->routes, 0 );
1089
                    // from the same network?
1091
                    // from the same network?
1090
                    if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
1092
                    if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
1091
                        // clear the ARP mapping if any
1093
                        // clear the ARP mapping if any
1092
                        address.value = ( char * ) & header->destination_address;
1094
                        address.value = ( char * ) & header->destination_address;
1093
                        address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
1095
                        address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
1094
                        arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
1096
                        arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
1095
                    }
1097
                    }
1096
                }
1098
                }
1097
                fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
1099
                fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
1098
            }
1100
            }
1099
            break;
1101
            break;
1100
        default:
1102
        default:
1101
            return ip_release_and_return( packet, ENOTSUP );
1103
            return ip_release_and_return( packet, ENOTSUP );
1102
    }
1104
    }
1103
    return ip_deliver_local( device_id, packet, header, error );
1105
    return ip_deliver_local( device_id, packet, header, error );
1104
}
1106
}
1105
 
1107
 
1106
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
1108
int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
1107
    ERROR_DECLARE;
1109
    ERROR_DECLARE;
1108
 
1110
 
1109
    ip_proto_ref    proto;
1111
    ip_proto_ref    proto;
1110
    int             phone;
1112
    int             phone;
1111
 
1113
 
1112
    if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
1114
    if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){
1113
        // TODO fragmented
1115
        // TODO fragmented
1114
        return ENOTSUP;
1116
        return ENOTSUP;
1115
    }else{
1117
    }else{
1116
        ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
1118
        ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR ));
1117
        fibril_rwlock_read_lock( & ip_globals.protos_lock );
1119
        fibril_rwlock_read_lock( & ip_globals.protos_lock );
1118
        proto = ip_protos_find( & ip_globals.protos, header->protocol );
1120
        proto = ip_protos_find( & ip_globals.protos, header->protocol );
1119
        if( ! proto ){
1121
        if( ! proto ){
1120
            fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1122
            fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1121
            phone = ip_prepare_icmp_and_get_phone( error, packet, header );
1123
            phone = ip_prepare_icmp_and_get_phone( error, packet, header );
1122
            if( phone >= 0 ){
1124
            if( phone >= 0 ){
1123
                // unreachable ICMP
1125
                // unreachable ICMP
1124
                icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
1126
                icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
1125
            }
1127
            }
1126
            return ENOENT;
1128
            return ENOENT;
1127
        }
1129
        }
1128
        if( proto->received_msg ){
1130
        if( proto->received_msg ){
1129
            ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error );
1131
            ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error );
1130
        }else{
1132
        }else{
1131
            ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
1133
            ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
1132
        }
1134
        }
1133
        fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1135
        fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1134
        return ERROR_CODE;
1136
        return ERROR_CODE;
1135
    }
1137
    }
1136
}
1138
}
1137
 
1139
 
1138
in_addr_t ip_get_destination( ip_header_ref header ){
1140
in_addr_t ip_get_destination( ip_header_ref header ){
1139
    in_addr_t   destination;
1141
    in_addr_t   destination;
1140
 
1142
 
1141
    // TODO search set ipopt route?
1143
    // TODO search set ipopt route?
1142
    destination.s_addr = header->destination_address;
1144
    destination.s_addr = header->destination_address;
1143
    return destination;
1145
    return destination;
1144
}
1146
}
1145
 
1147
 
1146
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
1148
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
1147
    packet_t    next;
1149
    packet_t    next;
1148
 
1150
 
1149
    // detach the first packet and release the others
1151
    // detach the first packet and release the others
1150
    next = pq_detach( packet );
1152
    next = pq_detach( packet );
1151
    if( next ){
1153
    if( next ){
1152
        pq_release( ip_globals.net_phone, packet_get_id( next ));
1154
        pq_release( ip_globals.net_phone, packet_get_id( next ));
1153
    }
1155
    }
1154
    if( ! header ){
1156
    if( ! header ){
1155
        if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
1157
        if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
1156
        // get header
1158
        // get header
1157
        header = ( ip_header_ref ) packet_get_data( packet );
1159
        header = ( ip_header_ref ) packet_get_data( packet );
1158
        if( ! header ) return EINVAL;
1160
        if( ! header ) return EINVAL;
1159
    }
1161
    }
1160
    // only for the first fragment
1162
    // only for the first fragment
1161
    if( header->fragment_offset ) return EINVAL;
1163
    if( header->fragment_offset ) return EINVAL;
1162
    // set the destination address
1164
    // set the destination address
1163
    return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address ));
1165
    return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address ));
1164
}
1166
}
1165
 
1167
 
1166
int ip_get_icmp_phone( void ){
1168
int ip_get_icmp_phone( void ){
1167
    ip_proto_ref    proto;
1169
    ip_proto_ref    proto;
1168
    int             phone;
1170
    int             phone;
1169
 
1171
 
1170
    fibril_rwlock_read_lock( & ip_globals.protos_lock );
1172
    fibril_rwlock_read_lock( & ip_globals.protos_lock );
1171
    proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
1173
    proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
1172
    phone = proto ? proto->phone : ENOENT;
1174
    phone = proto ? proto->phone : ENOENT;
1173
    fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1175
    fibril_rwlock_read_unlock( & ip_globals.protos_lock );
1174
    return phone;
1176
    return phone;
1175
}
1177
}
1176
 
1178
 
1177
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
1179
int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
1178
    int phone;
1180
    int phone;
1179
 
1181
 
1180
    phone = ip_get_icmp_phone();
1182
    phone = ip_get_icmp_phone();
1181
    if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
1183
    if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
1182
        return ip_release_and_return( packet, EINVAL );
1184
        return ip_release_and_return( packet, EINVAL );
1183
    }
1185
    }
1184
    return phone;
1186
    return phone;
1185
}
1187
}
1186
 
1188
 
1187
int ip_release_and_return( packet_t packet, int result ){
1189
int ip_release_and_return( packet_t packet, int result ){
1188
    pq_release( ip_globals.net_phone, packet_get_id( packet ));
1190
    pq_release( ip_globals.net_phone, packet_get_id( packet ));
1189
    return result;
1191
    return result;
1190
}
1192
}
1191
 
1193
 
1192
/** @}
1194
/** @}
1193
 */
1195
 */
1194
 
1196