Subversion Repositories HelenOS

Rev

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

Rev 4728 Rev 4730
Line 74... Line 74...
74
 
74
 
75
/** Default UDP checksum computing.
75
/** Default UDP checksum computing.
76
 */
76
 */
77
#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING  true
77
#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING  true
78
 
78
 
-
 
79
/** Default UDP autobind when sending via unbound sockets.
-
 
80
 */
-
 
81
#define NET_DEFAULT_UDP_AUTOBINDING true
-
 
82
 
79
/** Maximum UDP fragment size.
83
/** Maximum UDP fragment size.
80
 */
84
 */
81
#define MAX_UDP_FRAGMENT_SIZE   65535
85
#define MAX_UDP_FRAGMENT_SIZE   65535
82
 
86
 
83
/** Free ports pool start.
87
/** Free ports pool start.
Line 88... Line 92...
88
 */
92
 */
89
#define UDP_FREE_PORTS_END      65535
93
#define UDP_FREE_PORTS_END      65535
90
 
94
 
91
/** Processes the received UDP packet queue.
95
/** Processes the received UDP packet queue.
92
 *  Is used as an entry point from the underlying IP module.
96
 *  Is used as an entry point from the underlying IP module.
93
 *  Notifies the destination socket application.
-
 
94
 *  Releases the packet on error or send an ICMP error notification..
97
 *  Locks the global lock and calls udp_process_packet() function.
95
 *  @param device_id The device identifier. Ignored parameter.
98
 *  @param device_id The device identifier. Ignored parameter.
96
 *  @param packet The received packet queue. Input/output parameter.
99
 *  @param packet The received packet queue. Input/output parameter.
97
 *  @param receiver The target service. Ignored parameter.
100
 *  @param receiver The target service. Ignored parameter.
98
 *  @param error The packet error reporting service. Prefixes the received packet. Input parameter.
101
 *  @param error The packet error reporting service. Prefixes the received packet. Input parameter.
99
 *  @returns EOK on success.
102
 *  @returns EOK on success.
-
 
103
 *  @returns Other error codes as defined for the udp_process_packet() function.
-
 
104
 */
-
 
105
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
-
 
106
 
-
 
107
/** Processes the received UDP packet queue.
-
 
108
 *  Notifies the destination socket application.
-
 
109
 *  Releases the packet on error or sends an ICMP error notification..
-
 
110
 *  @param packet The received packet queue. Input/output parameter.
-
 
111
 *  @param error The packet error reporting service. Prefixes the received packet. Input parameter.
-
 
112
 *  @returns EOK on success.
100
 *  @returns EINVAL if the packet is not valid.
113
 *  @returns EINVAL if the packet is not valid.
101
 *  @returns EINVAL if the stored packet address is not the an_addr_t.
114
 *  @returns EINVAL if the stored packet address is not the an_addr_t.
102
 *  @returns EINVAL if the packet does not contain any data.
115
 *  @returns EINVAL if the packet does not contain any data.
103
 *  @returns NO_DATA if the packet content is shorter than the user datagram header.
116
 *  @returns NO_DATA if the packet content is shorter than the user datagram header.
104
 *  @returns ENOMEM if there is not enough memory left.
117
 *  @returns ENOMEM if there is not enough memory left.
105
 *  @returns EADDRNOTAVAIL if the destination socket does not exist.
118
 *  @returns EADDRNOTAVAIL if the destination socket does not exist.
106
 *  @returns Other error codes as defined for the ip_client_process_packet() function.
119
 *  @returns Other error codes as defined for the ip_client_process_packet() function.
107
 */
120
 */
108
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
121
int udp_process_packet( packet_t packet, services_t error );
109
 
122
 
110
/** Releases the packet and returns the result.
123
/** Releases the packet and returns the result.
111
 *  @param packet The packet queue to be released. Input parameter.
124
 *  @param packet The packet queue to be released. Input parameter.
112
 *  @param result The result to be returned. Input parameter.
125
 *  @param result The result to be returned. Input parameter.
113
 *  @return The result parameter.
126
 *  @return The result parameter.
Line 174... Line 187...
174
udp_globals_t   udp_globals;
187
udp_globals_t   udp_globals;
175
 
188
 
176
int udp_initialize( async_client_conn_t client_connection ){
189
int udp_initialize( async_client_conn_t client_connection ){
177
    ERROR_DECLARE;
190
    ERROR_DECLARE;
178
 
191
 
179
    measured_string_t   names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }};
192
    measured_string_t   names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }, { "UDP_AUTOBINDING", 15 }};
180
    measured_string_ref configuration;
193
    measured_string_ref configuration;
181
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
194
    size_t              count = sizeof( names ) / sizeof( measured_string_t );
182
    char *              data;
195
    char *              data;
183
 
196
 
184
    fibril_rwlock_initialize( & udp_globals.lock );
197
    fibril_rwlock_initialize( & udp_globals.lock );
Line 196... Line 209...
196
    udp_globals.packet_dimension.prefix += sizeof( udp_header_t );
209
    udp_globals.packet_dimension.prefix += sizeof( udp_header_t );
197
    udp_globals.packet_dimension.content -= sizeof( udp_header_t );
210
    udp_globals.packet_dimension.content -= sizeof( udp_header_t );
198
    udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
211
    udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
199
    // get configuration
212
    // get configuration
200
    udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
213
    udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
-
 
214
    udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
201
    configuration = & names[ 0 ];
215
    configuration = & names[ 0 ];
202
    ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
216
    ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
203
    if( configuration ){
217
    if( configuration ){
204
        if( configuration[ 0 ].value ){
218
        if( configuration[ 0 ].value ){
205
            udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y' );
219
            udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y' );
206
        }
220
        }
-
 
221
        if( configuration[ 1 ].value ){
-
 
222
            udp_globals.autobinding = ( configuration[ 1 ].value[ 0 ] == 'y' );
-
 
223
        }
207
        net_free_settings( configuration, data );
224
        net_free_settings( configuration, data );
208
    }
225
    }
209
    fibril_rwlock_write_unlock( & udp_globals.lock );
226
    fibril_rwlock_write_unlock( & udp_globals.lock );
210
    return EOK;
227
    return EOK;
211
}
228
}
212
 
229
 
213
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
230
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
-
 
231
    int result;
-
 
232
 
-
 
233
    fibril_rwlock_read_lock( & udp_globals.lock );
-
 
234
    result = udp_process_packet( packet, error );
-
 
235
    fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
236
 
-
 
237
    return result;
-
 
238
}
-
 
239
 
-
 
240
int udp_process_packet( packet_t packet, services_t error ){
214
    ERROR_DECLARE;
241
    ERROR_DECLARE;
215
 
242
 
216
    size_t          length;
243
    size_t          length;
217
    size_t          offset;
244
    size_t          offset;
218
    int             result;
245
    int             result;
Line 274... Line 301...
274
    socket = socket_ports_find( & udp_globals.sockets, ntohs( header->destination_port ));
301
    socket = socket_ports_find( & udp_globals.sockets, ntohs( header->destination_port ));
275
    if( ! socket ){
302
    if( ! socket ){
276
        tl_send_icmp_port_unreachable( udp_globals.net_phone, udp_globals.icmp_phone, packet, error );
303
        tl_send_icmp_port_unreachable( udp_globals.net_phone, udp_globals.icmp_phone, packet, error );
277
        return EADDRNOTAVAIL;
304
        return EADDRNOTAVAIL;
278
    }
305
    }
-
 
306
 
279
    // trim after successful processing to be able to send an ICMP error message!
307
    // trim after successful processing to be able to send an ICMP error message!
280
    ERROR_PROPAGATE( packet_trim( packet, offset, 0 ));
308
    ERROR_PROPAGATE( packet_trim( packet, offset, 0 ));
-
 
309
 
281
    // count the received packet fragments
310
    // count the received packet fragments
282
    next_packet = packet;
311
    next_packet = packet;
283
    fragments = 0;
312
    fragments = 0;
284
    total_length = ntohs( header->total_length );
313
    total_length = ntohs( header->total_length );
285
    // compute header checksum if set
314
    // compute header checksum if set
Line 297... Line 326...
297
        }
326
        }
298
    }else{
327
    }else{
299
        header->checksum = 0;
328
        header->checksum = 0;
300
        checksum = 0;
329
        checksum = 0;
301
    }
330
    }
-
 
331
 
302
    do{
332
    do{
303
        ++ fragments;
333
        ++ fragments;
304
        length = packet_get_data_length( next_packet );
334
        length = packet_get_data_length( next_packet );
305
        if( length <= 0 ){
335
        if( length <= 0 ){
306
            return udp_release_and_return( packet, NO_DATA );
336
            return udp_release_and_return( packet, NO_DATA );
Line 327... Line 357...
327
        // add partial checksum if set
357
        // add partial checksum if set
328
        if( header->checksum ){
358
        if( header->checksum ){
329
            checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
359
            checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
330
        }
360
        }
331
    }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
361
    }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 ));
-
 
362
 
332
    // check checksum
363
    // check checksum
333
    if( header->checksum ){
364
    if( header->checksum ){
334
        if( flip_checksum( compact_checksum( checksum ))){
365
        if( flip_checksum( compact_checksum( checksum ))){
335
            // TODO checksum error ICMP?
366
            // TODO checksum error ICMP?
336
            // TODO remove debug dump
367
            // TODO remove debug dump
337
            printf("udp check failed %x => %x\n", header->checksum, flip_checksum( compact_checksum( checksum )));
368
            printf("udp check failed %x => %x\n", header->checksum, flip_checksum( compact_checksum( checksum )));
338
            return udp_release_and_return( packet, EINVAL );
369
            return udp_release_and_return( packet, EINVAL );
339
        }
370
        }
340
    }
371
    }
-
 
372
 
341
    // queue the received packet
373
    // queue the received packet
342
    if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
374
    if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
343
        return udp_release_and_return( packet, ERROR_CODE );
375
        return udp_release_and_return( packet, ERROR_CODE );
344
    }
376
    }
345
 
377
 
Line 354... Line 386...
354
    packet_t    packet;
386
    packet_t    packet;
355
 
387
 
356
    * answer_count = 0;
388
    * answer_count = 0;
357
    switch( IPC_GET_METHOD( * call )){
389
    switch( IPC_GET_METHOD( * call )){
358
        case NET_TL_RECEIVED:
390
        case NET_TL_RECEIVED:
359
            fibril_rwlock_read_lock( & udp_globals.lock );
-
 
360
            if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
391
            if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
361
                ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
392
                ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
362
            }
393
            }
363
            fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
364
            return ERROR_CODE;
394
            return ERROR_CODE;
365
        case IPC_M_CONNECT_TO_ME:
395
        case IPC_M_CONNECT_TO_ME:
366
            return udp_process_client_messages( callid, * call );
396
            return udp_process_client_messages( callid, * call );
367
    }
397
    }
368
    return ENOTSUP;
398
    return ENOTSUP;
Line 489... Line 519...
489
    ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port ));
519
    ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port ));
490
 
520
 
491
    socket = socket_cores_find( local_sockets, socket_id );
521
    socket = socket_cores_find( local_sockets, socket_id );
492
    if( ! socket ) return ENOTSOCK;
522
    if( ! socket ) return ENOTSOCK;
493
 
523
 
-
 
524
    if(( socket->port <= 0 ) && udp_globals.autobinding ){
494
    // bind the socket to a random free port if not bound
525
        // bind the socket to a random free port if not bound
495
    while( socket->port <= 0 ){
526
        do{
496
        // try to find a free port
527
            // try to find a free port
497
        fibril_rwlock_read_unlock( & udp_globals.lock );
528
            fibril_rwlock_read_unlock( & udp_globals.lock );
498
        fibril_rwlock_write_lock( & udp_globals.lock );
529
            fibril_rwlock_write_lock( & udp_globals.lock );
-
 
530
            // might be changed in the meantime
499
        if( socket->port <= 0 ){
531
            if( socket->port <= 0 ){
500
            ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
532
                ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
501
            // set the next port as the search starting port number
533
                // set the next port as the search starting port number
502
            udp_globals.last_used_port = socket->port;
534
                udp_globals.last_used_port = socket->port;
503
        }
535
            }
504
        fibril_rwlock_write_unlock( & udp_globals.lock );
536
            fibril_rwlock_write_unlock( & udp_globals.lock );
505
        fibril_rwlock_read_lock( & udp_globals.lock );
537
            fibril_rwlock_read_lock( & udp_globals.lock );
-
 
538
            // might be changed in the meantime
-
 
539
        }while( socket->port <= 0 );
506
    }
540
    }
507
 
541
 
508
    // TODO do not ask all the time
542
    // TODO do not ask all the time
509
    ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension.addr_len, & udp_globals.packet_dimension.prefix, & udp_globals.packet_dimension.content, & udp_globals.packet_dimension.suffix ));
543
    ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension.addr_len, & udp_globals.packet_dimension.prefix, & udp_globals.packet_dimension.content, & udp_globals.packet_dimension.suffix ));
510
 
544
 
Line 534... Line 568...
534
        if( udp_globals.checksum_computing ){
568
        if( udp_globals.checksum_computing ){
535
            checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet ));
569
            checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet ));
536
        }
570
        }
537
    }
571
    }
538
    // set the udp header
572
    // set the udp header
539
    header->source_port = htons( socket->port );
573
    header->source_port = htons(( socket->port > 0 ) ? socket->port : 0 );
540
    header->destination_port = htons( dest_port );
574
    header->destination_port = htons( dest_port );
541
    header->total_length = htons( total_length + sizeof( udp_header_t ));
575
    header->total_length = htons( total_length + sizeof( * header ));
542
    header->checksum = 0;
576
    header->checksum = 0;
543
    if( udp_globals.checksum_computing ){
577
    if( udp_globals.checksum_computing ){
544
        if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
578
        if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
545
            return udp_release_and_return( packet, ERROR_CODE );
579
            return udp_release_and_return( packet, ERROR_CODE );
546
        }
580
        }