Subversion Repositories HelenOS

Rev

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

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