Subversion Repositories HelenOS

Rev

Rev 4719 | Rev 4721 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4719 Rev 4720
Line 61... Line 61...
61
#include "../../include/il_interface.h"
61
#include "../../include/il_interface.h"
62
#include "../../include/inet.h"
62
#include "../../include/inet.h"
63
#include "../../include/ip_client.h"
63
#include "../../include/ip_client.h"
64
#include "../../include/ip_interface.h"
64
#include "../../include/ip_interface.h"
65
#include "../../include/ip_protocols.h"
65
#include "../../include/ip_protocols.h"
-
 
66
#include "../../include/net_interface.h"
66
#include "../../include/socket_codes.h"
67
#include "../../include/socket_codes.h"
67
#include "../../include/socket_errno.h"
68
#include "../../include/socket_errno.h"
68
 
69
 
69
#include "../../tl/tl_messages.h"
70
#include "../../tl/tl_messages.h"
70
 
71
 
71
#include "icmp.h"
72
#include "icmp.h"
72
#include "icmp_header.h"
73
#include "icmp_header.h"
73
#include "icmp_messages.h"
74
#include "icmp_messages.h"
74
#include "icmp_module.h"
75
#include "icmp_module.h"
75
 
76
 
-
 
77
/** Original datagram length in bytes transfered to the error notification message.
-
 
78
 */
76
#define ICMP_KEEP_LENGTH    8
79
#define ICMP_KEEP_LENGTH    8
77
 
80
 
-
 
81
/** Computes the ICMP datagram checksum.
-
 
82
 *  @param header The ICMP datagram header. Input/output parameter.
-
 
83
 *  @param length The total datagram length. Input parameter.
-
 
84
 *  @returns The computed checksum.
-
 
85
 */
78
#define ICMP_CHECKSUM( header, length )     htons( ip_checksum(( uint8_t * ) ( header ), ( length )))
86
#define ICMP_CHECKSUM( header, length )     htons( ip_checksum(( uint8_t * ) ( header ), ( length )))
79
 
87
 
-
 
88
/** An echo request datagrams pattern.
-
 
89
 */
80
#define ICMP_ECHO_TEXT                  "Hello from HelenOS."
90
#define ICMP_ECHO_TEXT                  "Hello from HelenOS."
81
 
91
 
-
 
92
/** Computes an ICMP reply data key.
-
 
93
 *  @param id The message identifier. Input parameter.
-
 
94
 *  @param sequence The message sequence number. Input parameter.
-
 
95
 *  @returns The computed ICMP reply data key.
-
 
96
 */
82
#define ICMP_GET_LOCK_KEY( id, sequence )   ((( id ) << 16 ) | ( sequence & 0xFFFF ))
97
#define ICMP_GET_REPLY_KEY( id, sequence )  ((( id ) << 16 ) | ( sequence & 0xFFFF ))
-
 
98
 
-
 
99
/** Type definition of the ICMP reply timeout.
-
 
100
 *  @see icmp_reply_timeout
-
 
101
 */
-
 
102
typedef struct icmp_reply_timeout   icmp_reply_timeout_t;
-
 
103
 
-
 
104
/** Type definition of the ICMP reply timeout pointer.
-
 
105
 *  @see icmp_reply_timeout
-
 
106
 */
-
 
107
typedef icmp_reply_timeout_t *  icmp_reply_timeout_ref;
83
 
108
 
84
/** Processes the received ICMP packet.
109
/** Processes the received ICMP packet.
85
 *  Is used as an entry point from the underlying IP module.
110
 *  Is used as an entry point from the underlying IP module.
86
 *  Releases the packet on error.
111
 *  Releases the packet on error.
87
 *  @param device_id The device identifier. Ignored parameter.
112
 *  @param device_id The device identifier. Ignored parameter.
Line 107... Line 132...
107
 *  @returns Other error codes as defined for the ip_client_process_packet() function.
132
 *  @returns Other error codes as defined for the ip_client_process_packet() function.
108
 */
133
 */
109
int icmp_process_packet( packet_t packet, services_t error );
134
int icmp_process_packet( packet_t packet, services_t error );
110
 
135
 
111
/** Processes the client messages.
136
/** Processes the client messages.
112
 *  Remenbers the assigned identifier and sequence numbers.
137
 *  Remembers the assigned identifier and sequence numbers.
113
 *  Runs until the client module disconnects.
138
 *  Runs until the client module disconnects.
114
 *  @param callid The message identifier. Input parameter.
139
 *  @param callid The message identifier. Input parameter.
115
 *  @param call The message parameters. Input parameter.
140
 *  @param call The message parameters. Input parameter.
116
 *  @returns EOK on success.
141
 *  @returns EOK.
117
 *  @see icmp_interface.h
142
 *  @see icmp_interface.h
-
 
143
 *  @see icmp_api.h
118
 */
144
 */
119
int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
145
int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
120
 
146
 
-
 
147
/** Processes the generic client messages.
-
 
148
 *  @param call The message parameters. Input parameter.
-
 
149
 *  @returns EOK on success.
-
 
150
 *  @returns ENOTSUP if the message is not known.
-
 
151
 *  @returns Other error codes as defined for the packet_translate() function.
-
 
152
 *  @returns Other error codes as defined for the icmp_destination_unreachable_msg() function.
-
 
153
 *  @returns Other error codes as defined for the icmp_source_quench_msg() function.
-
 
154
 *  @returns Other error codes as defined for the icmp_time_exceeded_msg() function.
-
 
155
 *  @returns Other error codes as defined for the icmp_parameter_problem_msg() function.
-
 
156
 *  @see icmp_interface.h
-
 
157
 */
-
 
158
int icmp_process_message( ipc_call_t * call );
-
 
159
 
121
/** Releases the packet and returns the result.
160
/** Releases the packet and returns the result.
122
 *  @param packet The packet queue to be released. Input parameter.
161
 *  @param packet The packet queue to be released. Input parameter.
123
 *  @param result The result to be returned. Input parameter.
162
 *  @param result The result to be returned. Input parameter.
124
 *  @return The result parameter.
163
 *  @returns The result parameter.
125
 */
164
 */
126
int icmp_release_and_return( packet_t packet, int result );
165
int icmp_release_and_return( packet_t packet, int result );
127
 
166
 
-
 
167
/** Requests an echo message.
-
 
168
 *  Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout.
-
 
169
 *  Blocks the caller until the reply or the timeout occurres.
-
 
170
 *  @param id The message identifier. Input parameter.
-
 
171
 *  @param sequence The message sequence parameter. Input parameter.
-
 
172
 *  @param size The message data length in bytes. Input parameter.
-
 
173
 *  @param timeout The timeout in miliseconds. Input parameter.
-
 
174
 *  @param ttl The time to live. Input parameter.
-
 
175
 *  @param tos The type of service. Input parameter.
-
 
176
 *  @param dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. Input parameter.
-
 
177
 *  @param addr The target host address. Input parameter.
-
 
178
 *  @param addrlen The torget host address length. Input parameter.
-
 
179
 *  @returns ICMP_ECHO on success.
-
 
180
 *  @returns ETIMEOUT if the reply has not arrived before the timeout.
-
 
181
 *  @returns ICMP type of the received error notification.
-
 
182
 *  @returns EINVAL if the addrlen parameter is less or equal to zero (<=0).
-
 
183
 *  @returns ENOMEM if there is not enough memory left.
-
 
184
 *  @returns EPARTY if there was an internal error.
-
 
185
 */
128
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen );
186
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen );
-
 
187
 
-
 
188
/** Prepares the ICMP error packet.
-
 
189
 *  Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
-
 
190
 *  Prefixes and returns the ICMP header.
-
 
191
 *  @param packet The original packet. Input/output parameter.
-
 
192
 *  @returns The prefixed ICMP header.
-
 
193
 *  @returns NULL on errors.
-
 
194
 */
129
icmp_header_ref icmp_prepare_packet( packet_t packet );
195
icmp_header_ref icmp_prepare_packet( packet_t packet );
-
 
196
 
-
 
197
/** Sends the ICMP message.
-
 
198
 *  Sets the message type and code and computes the checksum.
-
 
199
 *  Error messages are sent only if allowed in the configuration.
-
 
200
 *  Releases the packet on errors.
-
 
201
 *  @returns EOK on success.
-
 
202
 *  @returns EPERM if the error message is not allowed.
-
 
203
 */
130
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error );
204
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error );
-
 
205
 
-
 
206
/** Tries to set the pending reply result as the received message type.
-
 
207
 *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
-
 
208
 *  The global lock is not released in this case to be reused by the parent fibril.
-
 
209
 *  Releases the packet.
-
 
210
 *  @param packet The received reply message. Input parameter.
-
 
211
 *  @param header The ICMP message header. Input parameter.
-
 
212
 *  @param type The received reply message type. Input parameter.
-
 
213
 *  @param code The received reply message code. Input parameter.
-
 
214
 *  @returns EOK.
-
 
215
 */
131
int process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code );
216
int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code );
-
 
217
 
-
 
218
/** Tries to set the pending reply result as timeouted.
-
 
219
 *  Sleeps the timeout period of time and then tries to obtain and set the pending reply result as timeouted and signals the reply result.
-
 
220
 *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
-
 
221
 *  The global lock is not released in this case to be reused by the parent fibril.
-
 
222
 *  Should run in a searate fibril.
-
 
223
 *  @param data The icmp_reply_timeout structure. Input parameter.
-
 
224
 *  @returns EOK on success.
-
 
225
 *  @returns EINVAL if the data parameter is NULL.
-
 
226
 */
-
 
227
int icmp_timeout_for_reply( void * data );
-
 
228
 
-
 
229
/** ICMP reply timeout data.
-
 
230
 *  Used as a timeouting fibril argument.
-
 
231
 *  @see icmp_timeout_for_reply()
-
 
232
 */
-
 
233
struct icmp_reply_timeout{
-
 
234
    /** Reply data key.
-
 
235
     */
-
 
236
    int         reply_key;
-
 
237
    /** Timeout in microseconds.
-
 
238
     */
-
 
239
    suseconds_t timeout;
-
 
240
};
132
 
241
 
133
/** ICMP global data.
242
/** ICMP global data.
134
 */
243
 */
135
icmp_globals_t  icmp_globals;
244
icmp_globals_t  icmp_globals;
136
 
245
 
137
INT_MAP_IMPLEMENT( time_locks, atomic_t );
246
INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t );
138
 
247
 
139
GENERIC_FIELD_IMPLEMENT( echo_data, icmp_echo_t );
248
GENERIC_FIELD_IMPLEMENT( icmp_echo_data, icmp_echo_t );
140
 
249
 
141
int icmp_echo_msg( int icmp_phone, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
250
int icmp_echo_msg( int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
142
    icmp_echo_ref   echo_data;
251
    icmp_echo_ref   echo_data;
143
    int             res;
252
    int             res;
144
 
253
 
145
    fibril_rwlock_write_lock( & icmp_globals.lock );
254
    fibril_rwlock_write_lock( & icmp_globals.lock );
146
    // use the phone as the echo data index
255
    // use the phone as the echo data index
147
    echo_data = echo_data_get_index( & icmp_globals.echo_data, icmp_phone );
256
    echo_data = icmp_echo_data_get_index( & icmp_globals.echo_data, icmp_phone );
148
    if( ! echo_data ){
257
    if( ! echo_data ){
149
        res = ENOENT;
258
        res = ENOENT;
150
    }else{
259
    }else{
151
        res = icmp_echo( echo_data->id, echo_data->sequence, size, timeout, ttl, tos, dont_fragment, addr, addrlen );
260
        res = icmp_echo( echo_data->id, echo_data->sequence, size, timeout, ttl, tos, dont_fragment, addr, addrlen );
152
        ++ echo_data->sequence;
261
        ++ echo_data->sequence;
153
    }
262
    }
154
    fibril_rwlock_write_unlock( & icmp_globals.lock );
263
    fibril_rwlock_write_unlock( & icmp_globals.lock );
155
    return res;
264
    return res;
156
}
265
}
157
 
266
 
-
 
267
int icmp_timeout_for_reply( void * data ){
-
 
268
    icmp_reply_ref          reply;
-
 
269
    icmp_reply_timeout_ref  timeout = data;
-
 
270
 
-
 
271
    if( ! timeout ){
-
 
272
        return EINVAL;
-
 
273
    }
-
 
274
    // sleep the given timeout
-
 
275
    async_usleep( timeout->timeout );
-
 
276
    // lock the globals
-
 
277
    fibril_rwlock_write_lock( & icmp_globals.lock );
-
 
278
    // find the pending reply
-
 
279
    reply = icmp_replies_find( & icmp_globals.replies, timeout->reply_key );
-
 
280
    if( reply ){
-
 
281
        // set the timeout result
-
 
282
        reply->result = ETIMEOUT;
-
 
283
        // notify the main fibril
-
 
284
        fibril_condvar_signal( & reply->condvar );
-
 
285
    }else{
-
 
286
        // unlock only if no reply
-
 
287
        fibril_rwlock_write_unlock( & icmp_globals.lock );
-
 
288
    }
-
 
289
    // release the timeout structure
-
 
290
    free( timeout );
-
 
291
    return EOK;
-
 
292
}
-
 
293
 
158
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
294
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
159
    ERROR_DECLARE;
295
    ERROR_DECLARE;
160
 
296
 
161
    icmp_header_ref header;
297
    icmp_header_ref header;
162
    packet_t        packet;
298
    packet_t        packet;
163
    size_t          offset;
299
    size_t          length;
164
    uint8_t *       data;
300
    uint8_t *       data;
165
    atomic_t *      lock;
301
    icmp_reply_ref          reply;
-
 
302
    icmp_reply_timeout_ref  reply_timeout;
166
    int             result;
303
    int             result;
167
    int             index;
304
    int             index;
168
    int             lock_key;
305
    fid_t           fibril;
169
    struct sockaddr_in *    address_in;
-
 
170
    struct timeval  time_before;
-
 
171
    struct timeval  time_after;
-
 
172
 
306
 
-
 
307
    if( addrlen <= 0 ){
-
 
308
        return EINVAL;
-
 
309
    }
-
 
310
    length = ( size_t ) addrlen;
173
    // TODO do not ask all the time
311
    // TODO do not ask all the time
174
    ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
312
    ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
175
    packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.addr_len, sizeof( icmp_header_t ) + icmp_globals.prefix, icmp_globals.suffix );
313
    packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.addr_len, sizeof( icmp_header_t ) + icmp_globals.prefix, icmp_globals.suffix );
176
    if( ! packet ) return ENOMEM;
314
    if( ! packet ) return ENOMEM;
-
 
315
 
-
 
316
    // prepare the requesting packet
177
    // set the destination address
317
    // set the destination address
178
    if( addrlen < sizeof( struct sockaddr )){
-
 
179
        return icmp_release_and_return( packet, EINVAL );
-
 
180
    }
-
 
181
    switch( addr->sa_family ){
-
 
182
        case AF_INET:
-
 
183
            if( addrlen != sizeof( struct sockaddr_in )){
-
 
184
                return icmp_release_and_return( packet, EINVAL );
-
 
185
            }
-
 
186
            address_in = ( struct sockaddr_in * ) addr;
-
 
187
            if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){
318
    if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length ))){
188
                return icmp_release_and_return( packet, ERROR_CODE );
319
        return icmp_release_and_return( packet, ERROR_CODE );
189
            }
-
 
190
            break;
-
 
191
        default:
-
 
192
            return icmp_release_and_return( packet, EAFNOSUPPORT );
-
 
193
    }
320
    }
194
    // allocate space in the packet
321
    // allocate space in the packet
195
    data = ( uint8_t * ) packet_suffix( packet, size );
322
    data = ( uint8_t * ) packet_suffix( packet, size );
196
    if( ! data ){
323
    if( ! data ){
197
        return icmp_release_and_return( packet, ENOMEM );
324
        return icmp_release_and_return( packet, ENOMEM );
198
    }
325
    }
-
 
326
    // fill the data
199
    offset = 0;
327
    length = 0;
200
    while( size > offset + sizeof( ICMP_ECHO_TEXT )){
328
    while( size > length + sizeof( ICMP_ECHO_TEXT )){
201
        memcpy( data + offset, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT ));
329
        memcpy( data + length, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT ));
202
        offset += sizeof( ICMP_ECHO_TEXT );
330
        length += sizeof( ICMP_ECHO_TEXT );
203
    }
331
    }
204
    memcpy( data + offset, ICMP_ECHO_TEXT, size - offset );
332
    memcpy( data + length, ICMP_ECHO_TEXT, size - length );
-
 
333
    // prefix the header
205
    header = icmp_prepare_packet( packet );
334
    header = PACKET_PREFIX( packet, icmp_header_t );
206
    if( ! header ){
335
    if( ! header ){
207
        return icmp_release_and_return( packet, ENOMEM );
336
        return icmp_release_and_return( packet, ENOMEM );
208
    }
337
    }
-
 
338
    bzero( header, sizeof( * header ));
209
    header->un.echo.id = id;
339
    header->un.echo.id = id;
210
    header->un.echo.sequence = sequence;
340
    header->un.echo.sequence = sequence;
211
    lock_key = ICMP_GET_LOCK_KEY( header->un.echo.id, header->un.echo.sequence );
-
 
-
 
341
 
212
    // create a locked fuxed
342
    // prepare the reply and the reply timeout structures
213
    lock = malloc( sizeof( * lock ));
343
    reply_timeout = malloc( sizeof( * reply_timeout ));
214
    if( ! lock ){
344
    if( ! reply_timeout ){
215
        return icmp_release_and_return( packet, ENOMEM );
345
        return icmp_release_and_return( packet, ENOMEM );
216
    }
346
    }
-
 
347
    reply = malloc( sizeof( * reply ));
-
 
348
    if( ! reply ){
217
    atomic_set( lock, 0 );
349
        free( reply_timeout );
-
 
350
        return icmp_release_and_return( packet, ENOMEM );
-
 
351
    }
-
 
352
    reply_timeout->reply_key = ICMP_GET_REPLY_KEY( header->un.echo.id, header->un.echo.sequence );
-
 
353
    // timeout in microseconds
-
 
354
    reply_timeout->timeout = timeout * 1000;
-
 
355
    fibril_mutex_initialize( & reply->mutex );
-
 
356
    fibril_mutex_lock( & reply->mutex );
-
 
357
    fibril_condvar_initialize( & reply->condvar );
218
    index = time_locks_add( & icmp_globals.time_locks, lock_key, lock );
358
    index = icmp_replies_add( & icmp_globals.replies, reply_timeout->reply_key, reply );
219
    if( index < 0 ){
359
    if( index < 0 ){
220
        free( lock );
360
        free( reply );
-
 
361
        free( reply_timeout );
221
        return icmp_release_and_return( packet, index );
362
        return icmp_release_and_return( packet, index );
222
    }
363
    }
223
    if( ERROR_OCCURRED( icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 ))){
-
 
224
        free( lock );
-
 
225
        return icmp_release_and_return( packet, ERROR_CODE );
-
 
226
    }
-
 
227
    // unlock the global to allow unlocking and other fibrils to work
-
 
228
    // try to lock again - may be unlocked by the reply
-
 
229
    ERROR_PROPAGATE( gettimeofday( & time_before, NULL ));
-
 
230
    do{
-
 
231
        result = atomic_get( lock );
-
 
232
        if( result ){
-
 
233
            break;
-
 
234
        }else{
-
 
235
            fibril_rwlock_write_unlock( & icmp_globals.lock );
-
 
236
            // TODO does not yield?
364
    // start the timeouting thread
237
            //printf( "y %d\n", fibril_yield());
-
 
238
            fibril_yield();
-
 
239
            fibril_rwlock_write_lock( & icmp_globals.lock );
-
 
240
            ERROR_PROPAGATE( gettimeofday( & time_after, NULL ));
-
 
241
        }
-
 
242
    }while( tv_sub( & time_after, & time_before ) <= timeout );
365
    fibril = fibril_create( icmp_timeout_for_reply, reply_timeout );
243
    if( ! result ){
366
    if( ! fibril ){
244
        result = ELIMIT;
367
        return EPARTY;
245
    }
368
    }
-
 
369
    fibril_add_ready( fibril );
-
 
370
 
-
 
371
    // unlock the globals and wait for a reply
-
 
372
    fibril_rwlock_write_unlock( & icmp_globals.lock );
-
 
373
 
-
 
374
    // send the request
-
 
375
    icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 );
-
 
376
 
-
 
377
    // wait for a reply
-
 
378
    fibril_condvar_wait( & reply->condvar, & reply->mutex );
-
 
379
    // read the result
-
 
380
    result = reply->result;
-
 
381
 
246
    // destroy the lock
382
    // destroy the reply structure
-
 
383
    fibril_mutex_unlock( & reply->mutex );
247
    time_locks_exclude_index( & icmp_globals.time_locks, index );
384
    icmp_replies_exclude_index( & icmp_globals.replies, index );
248
    return result;
385
    return result;
249
}
386
}
250
 
387
 
251
int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
388
int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
252
    icmp_header_ref header;
389
    icmp_header_ref header;
253
 
390
 
254
    header = icmp_prepare_packet( packet );
391
    header = icmp_prepare_packet( packet );
255
    if( ! header ) return ENOMEM;
392
    if( ! header ){
-
 
393
        return icmp_release_and_return( packet, ENOMEM );
-
 
394
    }
256
    if( mtu ){
395
    if( mtu ){
257
        header->un.frag.mtu = mtu;
396
        header->un.frag.mtu = mtu;
258
    }
397
    }
259
    return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP );
398
    return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP );
260
}
399
}
261
 
400
 
262
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
401
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
263
    icmp_header_ref header;
402
    icmp_header_ref header;
264
 
403
 
265
    header = icmp_prepare_packet( packet );
404
    header = icmp_prepare_packet( packet );
266
    if( ! header ) return ENOMEM;
405
    if( ! header ){
-
 
406
        return icmp_release_and_return( packet, ENOMEM );
-
 
407
    }
267
    return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP );
408
    return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP );
268
}
409
}
269
 
410
 
270
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
411
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
271
    icmp_header_ref header;
412
    icmp_header_ref header;
272
 
413
 
273
    header = icmp_prepare_packet( packet );
414
    header = icmp_prepare_packet( packet );
274
    if( ! header ) return ENOMEM;
415
    if( ! header ){
-
 
416
        return icmp_release_and_return( packet, ENOMEM );
-
 
417
    }
275
    return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP );
418
    return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP );
276
}
419
}
277
 
420
 
278
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
421
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
279
    icmp_header_ref header;
422
    icmp_header_ref header;
280
 
423
 
281
    header = icmp_prepare_packet( packet );
424
    header = icmp_prepare_packet( packet );
282
    if( ! header ) return ENOMEM;
425
    if( ! header ){
-
 
426
        return icmp_release_and_return( packet, ENOMEM );
-
 
427
    }
283
    header->un.param.pointer = pointer;
428
    header->un.param.pointer = pointer;
284
    return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP );
429
    return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP );
285
}
430
}
286
 
431
 
287
icmp_header_ref icmp_prepare_packet( packet_t packet ){
432
icmp_header_ref icmp_prepare_packet( packet_t packet ){
Line 292... Line 437...
292
    total_length = packet_get_data_length( packet );
437
    total_length = packet_get_data_length( packet );
293
    if( total_length <= 0 ) return NULL;
438
    if( total_length <= 0 ) return NULL;
294
    header_length = ip_client_header_length( packet );
439
    header_length = ip_client_header_length( packet );
295
    if( header_length <= 0 ) return NULL;
440
    if( header_length <= 0 ) return NULL;
296
    // truncate if longer than 64 bits (without the IP header)
441
    // truncate if longer than 64 bits (without the IP header)
297
    if( total_length - header_length > ICMP_KEEP_LENGTH ){
442
    if(( total_length - header_length > ICMP_KEEP_LENGTH )
298
        if( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK ) return NULL;
443
    && ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){
299
    }
-
 
300
    header = PACKET_PREFIX( packet, icmp_header_t );
-
 
301
    if( ! header ){
-
 
302
        pq_release( icmp_globals.net_phone, packet_get_id( packet ));
-
 
303
        return NULL;
444
        return NULL;
304
    }
445
    }
-
 
446
    header = PACKET_PREFIX( packet, icmp_header_t );
-
 
447
    if( ! header ) return NULL;
305
    bzero( header, sizeof( * header ));
448
    bzero( header, sizeof( * header ));
306
    return header;
449
    return header;
307
}
450
}
308
 
451
 
309
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){
452
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){
310
    ERROR_DECLARE;
453
    ERROR_DECLARE;
311
 
454
 
-
 
455
    // do not send an error if disabled
-
 
456
    if( error && ( ! icmp_globals.error_reporting )){
-
 
457
        return icmp_release_and_return( packet, EPERM );
-
 
458
    }
312
    header->type = type;
459
    header->type = type;
313
    header->code = code;
460
    header->code = code;
314
    header->checksum = 0;
461
    header->checksum = 0;
315
    header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
462
    header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
316
    if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, 0, 0, 0, 0 ))){
463
    if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, 0, 0, 0, 0 ))){
317
        pq_release( icmp_globals.net_phone, packet_get_id( packet ));
464
        return icmp_release_and_return( packet, ERROR_CODE );
318
        return ERROR_CODE;
-
 
319
    }
465
    }
320
    return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
466
    return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
321
}
467
}
322
 
468
 
323
int icmp_connect_module( services_t service ){
469
int icmp_connect_module( services_t service ){
Line 330... Line 476...
330
    fibril_rwlock_write_lock( & icmp_globals.lock );
476
    fibril_rwlock_write_lock( & icmp_globals.lock );
331
    ++ icmp_globals.last_used_id;
477
    ++ icmp_globals.last_used_id;
332
    echo_data->id = icmp_globals.last_used_id;
478
    echo_data->id = icmp_globals.last_used_id;
333
    echo_data->sequence = 0;
479
    echo_data->sequence = 0;
334
    // remember the assigned echo data
480
    // remember the assigned echo data
335
    index = echo_data_add( & icmp_globals.echo_data, echo_data );
481
    index = icmp_echo_data_add( & icmp_globals.echo_data, echo_data );
336
    if( index < 0 ){
482
    if( index < 0 ){
337
        free( echo_data );
483
        free( echo_data );
338
    }
484
    }
339
    fibril_rwlock_write_unlock( & icmp_globals.lock );
485
    fibril_rwlock_write_unlock( & icmp_globals.lock );
340
    // return the echo data index as the ICMP phone
486
    // return the echo data index as the ICMP phone
Line 342... Line 488...
342
}
488
}
343
 
489
 
344
int icmp_initialize( async_client_conn_t client_connection ){
490
int icmp_initialize( async_client_conn_t client_connection ){
345
    ERROR_DECLARE;
491
    ERROR_DECLARE;
346
 
492
 
-
 
493
    measured_string_t   names[] = {{ "ICMP_ERROR_REPORTING", 20 }, { "ICMP_ECHO_REPLYING", 18 }};
-
 
494
    measured_string_ref configuration;
-
 
495
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
-
 
496
    char *              data;
-
 
497
 
347
    fibril_rwlock_initialize( & icmp_globals.lock );
498
    fibril_rwlock_initialize( & icmp_globals.lock );
348
    fibril_rwlock_write_lock( & icmp_globals.lock );
499
    fibril_rwlock_write_lock( & icmp_globals.lock );
349
    time_locks_initialize( & icmp_globals.time_locks );
500
    icmp_replies_initialize( & icmp_globals.replies );
350
    echo_data_initialize( & icmp_globals.echo_data );
501
    icmp_echo_data_initialize( & icmp_globals.echo_data );
351
    icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
502
    icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
352
    if( icmp_globals.ip_phone < 0 ){
503
    if( icmp_globals.ip_phone < 0 ){
353
        return icmp_globals.ip_phone;
504
        return icmp_globals.ip_phone;
354
    }
505
    }
355
    ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
506
    ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
356
    icmp_globals.prefix += sizeof( icmp_header_t );
507
    icmp_globals.prefix += sizeof( icmp_header_t );
357
    icmp_globals.content -= sizeof( icmp_header_t );
508
    icmp_globals.content -= sizeof( icmp_header_t );
-
 
509
    configuration = & names[ 0 ];
-
 
510
    // get configuration
-
 
511
    ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
-
 
512
    if( configuration ){
-
 
513
        icmp_globals.error_reporting = configuration[ 0 ].value && ( configuration[ 0 ].value[ 0 ] == 'y' );
-
 
514
        icmp_globals.echo_replying = configuration[ 1 ].value && ( configuration[ 1 ].value[ 0 ] == 'y' );
-
 
515
        net_free_settings( configuration, data );
-
 
516
    }
358
    fibril_rwlock_write_unlock( & icmp_globals.lock );
517
    fibril_rwlock_write_unlock( & icmp_globals.lock );
359
    return EOK;
518
    return EOK;
360
}
519
}
361
 
520
 
362
int icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
521
int icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
363
    ERROR_DECLARE;
522
    ERROR_DECLARE;
364
 
523
 
365
    if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
524
    if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
366
        pq_release( icmp_globals.net_phone, packet_get_id( packet ));
525
        return icmp_release_and_return( packet, ERROR_CODE );
367
        return ERROR_CODE;
-
 
368
    }
526
    }
369
 
527
 
370
    return EOK;
528
    return EOK;
371
}
529
}
372
 
530
 
Line 399... Line 557...
399
        }
557
        }
400
    }
558
    }
401
    // get rid of the ip header
559
    // get rid of the ip header
402
    result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
560
    result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
403
    if( result < 0 ) return result;
561
    if( result < 0 ) return result;
404
    packet_trim( packet, ( size_t ) result, 0 );
562
    ERROR_PROPAGATE( packet_trim( packet, ( size_t ) result, 0 ));
405
 
563
 
406
    length = packet_get_data_length( packet );
564
    length = packet_get_data_length( packet );
407
    if( length <= 0 ) return EINVAL;
565
    if( length <= 0 ) return EINVAL;
408
    if( length < sizeof( icmp_header_t )) return EINVAL;
566
    if( length < sizeof( icmp_header_t )) return EINVAL;
409
    data = packet_get_data( packet );
567
    data = packet_get_data( packet );
410
    if( ! data ) return EINVAL;
568
    if( ! data ) return EINVAL;
411
    // get icmp header
569
    // get icmp header
412
    header = ( icmp_header_ref ) data;
570
    header = ( icmp_header_ref ) data;
413
    // checksum
571
    // checksum
414
    if(( header->checksum ) && ( ICMP_CHECKSUM( header, length ))){
572
/*  if(( header->checksum ) && ( ICMP_CHECKSUM( header, length ))){
-
 
573
        // set the original message type on error notification
-
 
574
        // type swap observed in Qemu
-
 
575
        if( error ){
-
 
576
            switch( header->type ){
-
 
577
                case ICMP_ECHOREPLY:
-
 
578
                    header->type = ICMP_ECHO;
-
 
579
                    break;
-
 
580
            }
-
 
581
        }
-
 
582
        if( ICMP_CHECKSUM( header, length )){
-
 
583
            return EINVAL;
-
 
584
        }
-
 
585
    }
-
 
586
*/  if( header->checksum ){
-
 
587
        while( ICMP_CHECKSUM( header, length )){
-
 
588
            // set the original message type on error notification
-
 
589
            // type swap observed in Qemu
-
 
590
            if( error ){
-
 
591
                switch( header->type ){
-
 
592
                    case ICMP_ECHOREPLY:
-
 
593
                        header->type = ICMP_ECHO;
-
 
594
                        continue;
-
 
595
                }
-
 
596
            }
415
        return EINVAL;
597
            return EINVAL;
-
 
598
        }
416
    }
599
    }
417
    switch( header->type ){
600
    switch( header->type ){
418
        case ICMP_ECHOREPLY:
601
        case ICMP_ECHOREPLY:
419
            return process_echo_reply( packet, header, ICMP_ECHO, 0 );
-
 
420
        case ICMP_ECHO:
-
 
421
            if( error ){
602
            if( error ){
422
                return process_echo_reply( packet, header, type, code );
603
                return icmp_process_echo_reply( packet, header, type, code );
423
            }else{
604
            }else{
-
 
605
                return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
-
 
606
            }
-
 
607
        case ICMP_ECHO:
-
 
608
            if( error ){
-
 
609
                return icmp_process_echo_reply( packet, header, type, code );
-
 
610
            // do not send a reply if disabled
-
 
611
            }else if( icmp_globals.echo_replying ){
424
                addrlen = packet_get_addr( packet, & src, NULL );
612
                addrlen = packet_get_addr( packet, & src, NULL );
425
                if(( addrlen > 0 )
613
                if(( addrlen > 0 )
426
                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
614
                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
427
                && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
615
                && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
428
                    // send the reply
616
                    // send the reply
429
                    return icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 );
617
                    icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 );
-
 
618
                    return EOK;
430
                }else{
619
                }else{
431
                    return icmp_release_and_return( packet, EINVAL );
620
                    return EINVAL;
432
                }
621
                }
-
 
622
            }else{
-
 
623
                return EPERM;
433
            }
624
            }
434
        case ICMP_DEST_UNREACH:
625
        case ICMP_DEST_UNREACH:
435
        case ICMP_SOURCE_QUENCH:
626
        case ICMP_SOURCE_QUENCH:
436
        case ICMP_REDIRECT:
627
        case ICMP_REDIRECT:
437
        case ICMP_ALTERNATE_ADDR:
628
        case ICMP_ALTERNATE_ADDR:
Line 441... Line 632...
441
        case ICMP_PARAMETERPROB:
632
        case ICMP_PARAMETERPROB:
442
        case ICMP_CONVERSION_ERROR:
633
        case ICMP_CONVERSION_ERROR:
443
        case ICMP_REDIRECT_MOBILE:
634
        case ICMP_REDIRECT_MOBILE:
444
        case ICMP_SKIP:
635
        case ICMP_SKIP:
445
        case ICMP_PHOTURIS:
636
        case ICMP_PHOTURIS:
446
            fibril_rwlock_read_lock( & icmp_globals.lock );
-
 
447
            ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
637
            ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
448
            fibril_rwlock_read_unlock( & icmp_globals.lock );
-
 
449
            return EOK;
638
            return EOK;
450
        default:
639
        default:
451
            return icmp_release_and_return( packet, ENOTSUP );
640
            return ENOTSUP;
452
    }
641
    }
453
}
642
}
454
 
643
 
455
int process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
644
int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
456
    int             lock_key;
645
    int             reply_key;
457
    atomic_t *      lock;
646
    icmp_reply_ref  reply;
458
 
647
 
-
 
648
    // compute the reply key
459
    lock_key = ICMP_GET_LOCK_KEY( header->un.echo.id, header->un.echo.sequence );
649
    reply_key = ICMP_GET_REPLY_KEY( header->un.echo.id, header->un.echo.sequence );
-
 
650
    pq_release( icmp_globals.net_phone, packet_get_id( packet ));
-
 
651
    // lock the globals
460
    fibril_rwlock_write_lock( & icmp_globals.lock );
652
    fibril_rwlock_write_lock( & icmp_globals.lock );
-
 
653
    // find the pending reply
461
    lock = time_locks_find( & icmp_globals.time_locks, lock_key );
654
    reply = icmp_replies_find( & icmp_globals.replies, reply_key );
462
    if( lock ){
655
    if( reply ){
-
 
656
        // set the result
-
 
657
        reply->result = type;
463
        // unlock the lock for the waiting fibril
658
        // notify the main fibril
-
 
659
        fibril_condvar_signal( & reply->condvar );
-
 
660
    }else{
464
        atomic_set( lock, type );
661
        // unlock only if no reply
-
 
662
        fibril_rwlock_write_unlock( & icmp_globals.lock );
465
    }
663
    }
466
    pq_release( icmp_globals.net_phone, packet_get_id( packet ));
-
 
467
    fibril_rwlock_write_unlock( & icmp_globals.lock );
-
 
468
    return EOK;
664
    return EOK;
469
}
665
}
470
 
666
 
471
int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
667
int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
472
    ERROR_DECLARE;
668
    ERROR_DECLARE;
Line 480... Line 676...
480
                ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call ));
676
                ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call ));
481
            }
677
            }
482
            return ERROR_CODE;
678
            return ERROR_CODE;
483
        case NET_ICMP_INIT:
679
        case NET_ICMP_INIT:
484
            return icmp_process_client_messages( callid, * call );
680
            return icmp_process_client_messages( callid, * call );
-
 
681
        default:
-
 
682
            return icmp_process_message( call );
485
    }
683
    }
486
    return ENOTSUP;
684
    return ENOTSUP;
487
}
685
}
488
 
686
 
489
int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
687
int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
Line 491... Line 689...
491
 
689
 
492
    bool                    keep_on_going = true;
690
    bool                    keep_on_going = true;
493
    fibril_rwlock_t         lock;
691
    fibril_rwlock_t         lock;
494
    ipc_call_t              answer;
692
    ipc_call_t              answer;
495
    int                     answer_count;
693
    int                     answer_count;
496
    packet_t                packet;
-
 
497
    size_t                  addrlen;
694
    size_t                  length;
498
    struct sockaddr *       addr;
695
    struct sockaddr *       addr;
499
    icmp_param_t            id;
696
    icmp_param_t            id;
500
    icmp_param_t            sequence = 0;
697
    icmp_param_t            sequence = 0;
501
    ipc_callid_t            data_callid;
698
    ipc_callid_t            data_callid;
502
 
699
 
Line 524... Line 721...
524
                keep_on_going = false;
721
                keep_on_going = false;
525
                ERROR_CODE = EOK;
722
                ERROR_CODE = EOK;
526
                break;
723
                break;
527
            case NET_ICMP_ECHO:
724
            case NET_ICMP_ECHO:
528
                fibril_rwlock_write_lock( & lock );
725
                fibril_rwlock_write_lock( & lock );
529
                if( ! ipc_data_write_receive( & data_callid, & addrlen )){
726
                if( ! ipc_data_write_receive( & data_callid, & length )){
530
                    ERROR_CODE = EINVAL;
727
                    ERROR_CODE = EINVAL;
531
                }else{
728
                }else{
532
                    addr = malloc( addrlen );
729
                    addr = malloc( length );
533
                    if( ! addr ){
730
                    if( ! addr ){
534
                        ERROR_CODE = ENOMEM;
731
                        ERROR_CODE = ENOMEM;
535
                    }else{
732
                    }else{
536
                        if( ! ERROR_OCCURRED( ipc_data_write_finalize( data_callid, addr, addrlen ))){
733
                        if( ! ERROR_OCCURRED( ipc_data_write_finalize( data_callid, addr, length ))){
537
                            fibril_rwlock_write_lock( & icmp_globals.lock );
734
                            fibril_rwlock_write_lock( & icmp_globals.lock );
538
                            ERROR_CODE = icmp_echo( id, sequence, ICMP_GET_SIZE( call ), ICMP_GET_TIMEOUT( call ), ICMP_GET_TTL( call ), ICMP_GET_TOS( call ), ICMP_GET_DONT_FRAGMENT( call ), addr, addrlen );
735
                            ERROR_CODE = icmp_echo( id, sequence, ICMP_GET_SIZE( call ), ICMP_GET_TIMEOUT( call ), ICMP_GET_TTL( call ), ICMP_GET_TOS( call ), ICMP_GET_DONT_FRAGMENT( call ), addr, ( socklen_t ) length );
539
                            fibril_rwlock_write_unlock( & icmp_globals.lock );
736
                            fibril_rwlock_write_unlock( & icmp_globals.lock );
540
                            free( addr );
737
                            free( addr );
541
                            ++ sequence;
738
                            ++ sequence;
542
                        }
739
                        }
543
                    }
740
                    }
544
                }
741
                }
545
                fibril_rwlock_write_unlock( & lock );
742
                fibril_rwlock_write_unlock( & lock );
546
                break;
743
                break;
547
            case NET_ICMP_DEST_UNREACH:
-
 
548
                if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){
-
 
549
                    ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet );
-
 
550
                }
-
 
551
                break;
-
 
552
            case NET_ICMP_SOURCE_QUENCH:
-
 
553
                if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){
-
 
554
                    ERROR_CODE = icmp_source_quench_msg( 0, packet );
-
 
555
                }
-
 
556
            case NET_ICMP_TIME_EXCEEDED:
-
 
557
                if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){
-
 
558
                    ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet );
-
 
559
                }
-
 
560
                break;
-
 
561
            case NET_ICMP_PARAMETERPROB:
-
 
562
                if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){
-
 
563
                    ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet );
-
 
564
                }
-
 
565
            default:
744
            default:
566
                ERROR_CODE = ENOTSUP;
745
                ERROR_CODE = icmp_process_message( & call );
567
        }
746
        }
568
 
747
 
569
        answer_call( callid, ERROR_CODE, & answer, answer_count );
748
        answer_call( callid, ERROR_CODE, & answer, answer_count );
570
    }
749
    }
571
 
750
 
572
    return EOK;
751
    return EOK;
573
}
752
}
574
 
753
 
-
 
754
int icmp_process_message( ipc_call_t * call ){
-
 
755
    ERROR_DECLARE;
-
 
756
 
-
 
757
    packet_t    packet;
-
 
758
 
-
 
759
    switch( IPC_GET_METHOD( * call )){
-
 
760
        case NET_ICMP_DEST_UNREACH:
-
 
761
            if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
-
 
762
                ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet );
-
 
763
            }
-
 
764
            return ERROR_CODE;
-
 
765
        case NET_ICMP_SOURCE_QUENCH:
-
 
766
            if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
-
 
767
                ERROR_CODE = icmp_source_quench_msg( 0, packet );
-
 
768
            }
-
 
769
            return ERROR_CODE;
-
 
770
        case NET_ICMP_TIME_EXCEEDED:
-
 
771
            if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
-
 
772
                ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet );
-
 
773
            }
-
 
774
            return ERROR_CODE;
-
 
775
        case NET_ICMP_PARAMETERPROB:
-
 
776
            if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
-
 
777
                ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet );
-
 
778
            }
-
 
779
            return ERROR_CODE;
-
 
780
        default:
-
 
781
            return ENOTSUP;
-
 
782
    }
-
 
783
}
-
 
784
 
575
int icmp_release_and_return( packet_t packet, int result ){
785
int icmp_release_and_return( packet_t packet, int result ){
576
    pq_release( icmp_globals.net_phone, packet_get_id( packet ));
786
    pq_release( icmp_globals.net_phone, packet_get_id( packet ));
577
    return result;
787
    return result;
578
}
788
}
579
 
789