Subversion Repositories HelenOS

Rev

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

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