Subversion Repositories HelenOS

Rev

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

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