Subversion Repositories HelenOS

Rev

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

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