Subversion Repositories HelenOS

Rev

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

Rev 4708 Rev 4713
Line 54... Line 54...
54
#include "../../include/ip_client.h"
54
#include "../../include/ip_client.h"
55
#include "../../include/ip_interface.h"
55
#include "../../include/ip_interface.h"
56
#include "../../include/ip_protocols.h"
56
#include "../../include/ip_protocols.h"
57
#include "../../include/icmp_client.h"
57
#include "../../include/icmp_client.h"
58
#include "../../include/icmp_interface.h"
58
#include "../../include/icmp_interface.h"
59
#include "../../include/socket.h"
59
#include "../../include/socket_codes.h"
60
#include "../../include/socket_errno.h"
60
#include "../../include/socket_errno.h"
61
 
61
 
62
#include "../../socket/socket_core.h"
62
#include "../../socket/socket_core.h"
63
#include "../../socket/socket_messages.h"
63
#include "../../socket/socket_messages.h"
64
 
64
 
Line 102... Line 102...
102
/** Releases the packet and returns the result.
102
/** Releases the packet and returns the result.
103
 *  @param packet The packet queue to be released. Input parameter.
103
 *  @param packet The packet queue to be released. Input parameter.
104
 *  @param result The result to be returned. Input parameter.
104
 *  @param result The result to be returned. Input parameter.
105
 *  @return The result parameter.
105
 *  @return The result parameter.
106
 */
106
 */
107
static int  release_and_return( packet_t packet, int result );
107
int udp_release_and_return( packet_t packet, int result );
108
 
108
 
109
/** Sends the port unreachable ICMP notification.
109
/** Sends the port unreachable ICMP notification.
110
 *  Sends the first packet and releases all the others.
110
 *  Sends the first packet and releases all the others.
111
 *  Releases the packet queu on error.
111
 *  Releases the packet queu on error.
112
 *  @param packet The packet to be send. Input parameter.
112
 *  @param packet The packet to be send. Input parameter.
Line 123... Line 123...
123
 *  @param callid The message identifier. Input parameter.
123
 *  @param callid The message identifier. Input parameter.
124
 *  @param call The message parameters. Input parameter.
124
 *  @param call The message parameters. Input parameter.
125
 *  @returns EOK on success.
125
 *  @returns EOK on success.
126
 *  @see socket.h
126
 *  @see socket.h
127
 */
127
 */
128
int process_client_messages( ipc_callid_t callid, ipc_call_t call );
128
int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
129
 
129
 
130
/** Sends data from the socket to the remote address.
130
/** Sends data from the socket to the remote address.
131
 *  Binds the socket to a free port if not already connected/bound.
131
 *  Binds the socket to a free port if not already connected/bound.
132
 *  Handles the NET_SOCKET_SENDTO message.
132
 *  Handles the NET_SOCKET_SENDTO message.
133
 *  @param local_sockets The application local sockets. Input/output parameter.
133
 *  @param local_sockets The application local sockets. Input/output parameter.
Line 246... Line 246...
246
                // process error
246
                // process error
247
                // TODO remove debug dump
247
                // TODO remove debug dump
248
                // length = icmp_client_header_length( packet );
248
                // length = icmp_client_header_length( packet );
249
                result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
249
                result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
250
                if( result < 0 ){
250
                if( result < 0 ){
251
                    return release_and_return( packet, result );
251
                    return udp_release_and_return( packet, result );
252
                }
252
                }
253
                printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
253
                printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
254
                length = ( size_t ) result;
254
                length = ( size_t ) result;
255
                if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
255
                if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
256
                    return release_and_return( packet, ERROR_CODE );
256
                    return udp_release_and_return( packet, ERROR_CODE );
257
                }
257
                }
258
                break;
258
                break;
259
            default:
259
            default:
260
                return release_and_return( packet, ENOTSUP );
260
                return udp_release_and_return( packet, ENOTSUP );
261
        }
261
        }
262
    }
262
    }
263
    // TODO process received ipopts?
263
    // TODO process received ipopts?
264
    result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
264
    result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
265
    if( result < 0 ){
265
    if( result < 0 ){
266
        return release_and_return( packet, result );
266
        return udp_release_and_return( packet, result );
267
    }
267
    }
268
    offset = ( size_t ) result;
268
    offset = ( size_t ) result;
269
 
269
 
270
    length = packet_get_data_length( packet );
270
    length = packet_get_data_length( packet );
271
    if( length <= 0 ){
271
    if( length <= 0 ){
272
        return release_and_return( packet, EINVAL );
272
        return udp_release_and_return( packet, EINVAL );
273
    }
273
    }
274
    if( length < sizeof( udp_header_t ) + offset ){
274
    if( length < sizeof( udp_header_t ) + offset ){
275
        return release_and_return( packet, NO_DATA );
275
        return udp_release_and_return( packet, NO_DATA );
276
    }
276
    }
277
    data = packet_get_data( packet );
277
    data = packet_get_data( packet );
278
    if( ! data ){
278
    if( ! data ){
279
        return release_and_return( packet, NO_DATA );
279
        return udp_release_and_return( packet, NO_DATA );
280
    }
280
    }
281
    // get udp header
281
    // get udp header
282
    header = ( udp_header_ref )( data + offset );
282
    header = ( udp_header_ref )( data + offset );
283
    // find the destination socket
283
    // find the destination socket
284
    socket = socket_ports_find( & udp_globals.sockets, ntohs( header->dest ));
284
    socket = socket_ports_find( & udp_globals.sockets, ntohs( header->dest ));
Line 294... Line 294...
294
    total_length = ntohs( header->len );
294
    total_length = ntohs( header->len );
295
    do{
295
    do{
296
        ++ fragments;
296
        ++ fragments;
297
        length = packet_get_data_length( packet );
297
        length = packet_get_data_length( packet );
298
        if( length <= 0 ){
298
        if( length <= 0 ){
299
            return release_and_return( packet, NO_DATA );
299
            return udp_release_and_return( packet, NO_DATA );
300
        }
300
        }
301
        if( total_length < length ){
301
        if( total_length < length ){
302
            // cut of the suffix if too long
302
            // cut of the suffix if too long
303
            if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
303
            if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
304
                return release_and_return( packet, ERROR_CODE );
304
                return udp_release_and_return( packet, ERROR_CODE );
305
            }
305
            }
306
            // relese the rest of the packet fragments
306
            // relese the rest of the packet fragments
307
            tmp_packet = pq_next( next_packet );
307
            tmp_packet = pq_next( next_packet );
308
            while( tmp_packet ){
308
            while( tmp_packet ){
309
                next_packet = pq_detach( tmp_packet );
309
                next_packet = pq_detach( tmp_packet );
Line 317... Line 317...
317
        }
317
        }
318
    */
318
    */
319
    }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
319
    }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
320
    // queue the received packet
320
    // queue the received packet
321
    if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
321
    if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
322
        return release_and_return( packet, ERROR_CODE );
322
        return udp_release_and_return( packet, ERROR_CODE );
323
    }
323
    }
324
 
324
 
325
    // notify the destination socket
325
    // notify the destination socket
326
    async_msg_2(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) ( ** socket ).socket_id, ( ipcarg_t ) fragments );
326
    async_msg_2(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) ( ** socket ).socket_id, ( ipcarg_t ) fragments );
327
    return EOK;
327
    return EOK;
Line 340... Line 340...
340
                ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
340
                ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
341
            }
341
            }
342
            fibril_rwlock_read_unlock( & udp_globals.lock );
342
            fibril_rwlock_read_unlock( & udp_globals.lock );
343
            return ERROR_CODE;
343
            return ERROR_CODE;
344
        case IPC_M_CONNECT_TO_ME:
344
        case IPC_M_CONNECT_TO_ME:
345
            return process_client_messages( callid, * call );
345
            return udp_process_client_messages( callid, * call );
346
    }
346
    }
347
    return ENOTSUP;
347
    return ENOTSUP;
348
}
348
}
349
 
349
 
350
int process_client_messages( ipc_callid_t callid, ipc_call_t call ){
350
int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
351
    ERROR_DECLARE;
-
 
352
 
-
 
353
    int                     res;
351
    int                     res;
354
    bool                    keep_on_going = true;
352
    bool                    keep_on_going = true;
355
    socket_cores_t          local_sockets;
353
    socket_cores_t          local_sockets;
356
    int                     app_phone = IPC_GET_PHONE( & call );
354
    int                     app_phone = IPC_GET_PHONE( & call );
357
    void *                  addr;
355
    void *                  addr;
Line 369... Line 367...
369
    socket_cores_initialize( & local_sockets );
367
    socket_cores_initialize( & local_sockets );
370
    fibril_rwlock_initialize( & lock );
368
    fibril_rwlock_initialize( & lock );
371
 
369
 
372
    while( keep_on_going ){
370
    while( keep_on_going ){
373
        // refresh data
371
        // refresh data
374
        answer_count = 0;
-
 
375
        IPC_SET_RETVAL( answer, 0 );
-
 
376
        // just to be precize
-
 
377
        IPC_SET_METHOD( answer, 0 );
372
        refresh_answer( & answer, & answer_count );
378
        IPC_SET_ARG1( answer, 0 );
-
 
379
        IPC_SET_ARG2( answer, 0 );
-
 
380
        IPC_SET_ARG3( answer, 0 );
-
 
381
        IPC_SET_ARG4( answer, 0 );
-
 
382
        IPC_SET_ARG5( answer, 0 );
-
 
383
 
373
 
384
        callid = async_get_call( & call );
374
        callid = async_get_call( & call );
385
//      printf( "message %d\n", IPC_GET_METHOD( * call ));
375
//      printf( "message %d\n", IPC_GET_METHOD( * call ));
386
 
376
 
387
        switch( IPC_GET_METHOD( call )){
377
        switch( IPC_GET_METHOD( call )){
Line 396... Line 386...
396
                * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
386
                * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
397
                * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
387
                * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
398
                answer_count = 3;
388
                answer_count = 3;
399
                break;
389
                break;
400
            case NET_SOCKET_BIND:
390
            case NET_SOCKET_BIND:
401
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
391
                res = socket_read_data( & addr, & addrlen );
402
                    res = ERROR_CODE;
392
                if( res == EOK ){
-
 
393
                    fibril_rwlock_write_lock( & lock );
-
 
394
                    fibril_rwlock_write_lock( & udp_globals.lock );
-
 
395
                    res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port );
-
 
396
                    fibril_rwlock_write_unlock( & udp_globals.lock );
-
 
397
                    fibril_rwlock_write_unlock( & lock );
403
                    break;
398
                    free( addr );
404
                }
399
                }
405
                fibril_rwlock_write_lock( & lock );
-
 
406
                fibril_rwlock_write_lock( & udp_globals.lock );
-
 
407
                res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port );
-
 
408
                fibril_rwlock_write_unlock( & udp_globals.lock );
-
 
409
                fibril_rwlock_write_unlock( & lock );
-
 
410
                free( addr );
-
 
411
                break; 
400
                break;
412
            case NET_SOCKET_SENDTO:
401
            case NET_SOCKET_SENDTO:
413
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
402
                res = socket_read_data( & addr, & addrlen );
414
                    res = ERROR_CODE;
403
                if( res == EOK ){
-
 
404
                    fibril_rwlock_read_lock( & lock );
-
 
405
                    fibril_rwlock_read_lock( & udp_globals.lock );
-
 
406
                    res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
-
 
407
                    fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
408
                    fibril_rwlock_read_unlock( & lock );
415
                    break;
409
                    free( addr );
416
                }
410
                }
417
                fibril_rwlock_read_lock( & lock );
-
 
418
                fibril_rwlock_read_lock( & udp_globals.lock );
-
 
419
                res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
-
 
420
                fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
421
                fibril_rwlock_read_unlock( & lock );
-
 
422
                free( addr );
-
 
423
                break;
411
                break;
424
            case NET_SOCKET_RECVFROM:
412
            case NET_SOCKET_RECVFROM:
425
                fibril_rwlock_read_lock( & lock );
413
                fibril_rwlock_read_lock( & lock );
426
                fibril_rwlock_read_lock( & udp_globals.lock );
414
                fibril_rwlock_read_lock( & udp_globals.lock );
427
                res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ));
415
                res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ));
Line 448... Line 436...
448
                break;
436
                break;
449
        }
437
        }
450
 
438
 
451
//      printf( "res = %d\n", res );
439
//      printf( "res = %d\n", res );
452
 
440
 
453
        switch( answer_count ){
-
 
454
            case 0:     ipc_answer_0( callid, ( ipcarg_t ) res );
-
 
455
                    continue;
-
 
456
            case 1:     ipc_answer_1( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ));
441
        answer_call( callid, res, & answer, answer_count );
457
                    continue;
-
 
458
            case 2:     ipc_answer_2( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ));
-
 
459
                    continue;
-
 
460
            case 3:     ipc_answer_3( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ));
-
 
461
                    continue;
-
 
462
            case 4:     ipc_answer_4( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ), IPC_GET_ARG4( answer ));
-
 
463
                    continue;
-
 
464
            default:    ipc_answer_5( callid, ( ipcarg_t ) res, IPC_GET_ARG1( answer ), IPC_GET_ARG2( answer ), IPC_GET_ARG3( answer ), IPC_GET_ARG4( answer ), IPC_GET_ARG5( answer ));
-
 
465
                    continue;
-
 
466
        }
-
 
467
    }
442
    }
468
 
443
 
469
    socket_cores_destroy( & local_sockets );
444
    socket_cores_destroy( & local_sockets );
470
 
445
 
471
    return EOK;
446
    return EOK;
Line 492... Line 467...
492
            address_in = ( struct sockaddr_in * ) addr;
467
            address_in = ( struct sockaddr_in * ) addr;
493
            socket = socket_cores_find( local_sockets, socket_id );
468
            socket = socket_cores_find( local_sockets, socket_id );
494
            if( ! socket ) return ENOTSOCK;
469
            if( ! socket ) return ENOTSOCK;
495
 
470
 
496
            // bind the socket to a random free port if not bound
471
            // bind the socket to a random free port if not bound
497
            if( socket->port <= 0 ){
472
            while( socket->port <= 0 ){
498
                // try to find a free port
473
                // try to find a free port
499
                fibril_rwlock_read_unlock( & udp_globals.lock );
474
                fibril_rwlock_read_unlock( & udp_globals.lock );
500
                fibril_rwlock_write_lock( & udp_globals.lock );
475
                fibril_rwlock_write_lock( & udp_globals.lock );
-
 
476
                if( socket->port <= 0 ){
501
                ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
477
                    ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
-
 
478
                    // set the next port as the search starting port number
-
 
479
                    udp_globals.last_used_port = socket->port;
-
 
480
                }
502
                fibril_rwlock_write_unlock( & udp_globals.lock );
481
                fibril_rwlock_write_unlock( & udp_globals.lock );
503
                fibril_rwlock_read_lock( & udp_globals.lock );
482
                fibril_rwlock_read_lock( & udp_globals.lock );
504
                // set the next port as the search starting port number
-
 
505
                udp_globals.last_used_port = socket->port;
-
 
506
            }
483
            }
507
            // TODO do not ask all the time
484
            // TODO do not ask all the time
508
            ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
485
            ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
509
 
486
 
510
            // read the first packet fragment
487
            // read the first packet fragment
Line 519... Line 496...
519
            }
496
            }
520
            // read the rest of the packet fragments
497
            // read the rest of the packet fragments
521
            for( index = 1; index < fragments; ++ index ){
498
            for( index = 1; index < fragments; ++ index ){
522
                result = socket_read_packet_data( & next_packet, 0, address_in );
499
                result = socket_read_packet_data( & next_packet, 0, address_in );
523
                if( result < 0 ){
500
                if( result < 0 ){
524
                    return release_and_return( packet, result );
501
                    return udp_release_and_return( packet, result );
525
                }
502
                }
526
                packet = pq_add( packet, next_packet, index, 0 );
503
                packet = pq_add( packet, next_packet, index, 0 );
527
                total_length += ( size_t ) result;
504
                total_length += ( size_t ) result;
528
            }
505
            }
529
            // set the udp header
506
            // set the udp header
Line 685... Line 662...
685
        return ERROR_CODE;
662
        return ERROR_CODE;
686
    }
663
    }
687
    return ( int ) length;
664
    return ( int ) length;
688
}
665
}
689
 
666
 
690
static int  release_and_return( packet_t packet, int result ){
667
int udp_release_and_return( packet_t packet, int result ){
691
    pq_release( udp_globals.net_phone, packet_get_id( packet ));
668
    pq_release( udp_globals.net_phone, packet_get_id( packet ));
692
    return result;
669
    return result;
693
}
670
}
694
 
671
 
695
void udp_send_icmp_port_unreachable( packet_t packet, services_t error ){
672
void udp_send_icmp_port_unreachable( packet_t packet, services_t error ){
Line 708... Line 685...
708
    && ( udp_globals.icmp_phone >= 0 )
685
    && ( udp_globals.icmp_phone >= 0 )
709
    // set both addresses to the source one (avoids the source address deletion before setting the destination one)
686
    // set both addresses to the source one (avoids the source address deletion before setting the destination one)
710
    && ( packet_set_addr( packet, src, src, ( size_t ) length ) == EOK )){
687
    && ( packet_set_addr( packet, src, src, ( size_t ) length ) == EOK )){
711
        icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
688
        icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
712
    }else{
689
    }else{
713
        release_and_return( packet, EINVAL );
690
        udp_release_and_return( packet, EINVAL );
714
    }
691
    }
715
}
692
}
716
 
693
 
717
/** @}
694
/** @}
718
 */
695
 */