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