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 | } |