Changes in uspace/srv/net/tl/icmp/icmp.c [aadf01e:b5cbff4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/icmp/icmp.c
raadf01e rb5cbff4 102 102 * @returns The computed checksum. 103 103 */ 104 #define ICMP_CHECKSUM( header, length) htons(ip_checksum((uint8_t *) (header), (length)))104 #define ICMP_CHECKSUM( header, length ) htons( ip_checksum(( uint8_t * ) ( header ), ( length ))) 105 105 106 106 /** An echo request datagrams pattern. … … 113 113 * @returns The computed ICMP reply data key. 114 114 */ 115 #define ICMP_GET_REPLY_KEY( id, sequence) (((id) << 16) | (sequence &0xFFFF))115 #define ICMP_GET_REPLY_KEY( id, sequence ) ((( id ) << 16 ) | ( sequence & 0xFFFF )) 116 116 117 117 /** Processes the received ICMP packet. … … 125 125 * @returns Other error codes as defined for the icmp_process_packet() function. 126 126 */ 127 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);127 int icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ); 128 128 129 129 /** Processes the received ICMP packet. … … 140 140 * @returns Other error codes as defined for the ip_client_process_packet() function. 141 141 */ 142 int icmp_process_packet(packet_t packet, services_t error);142 int icmp_process_packet( packet_t packet, services_t error ); 143 143 144 144 /** Processes the client messages. … … 151 151 * @see icmp_api.h 152 152 */ 153 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call);153 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ); 154 154 155 155 /** Processes the generic client messages. … … 164 164 * @see icmp_interface.h 165 165 */ 166 int icmp_process_message(ipc_call_t * call);166 int icmp_process_message( ipc_call_t * call ); 167 167 168 168 /** Releases the packet and returns the result. … … 171 171 * @returns The result parameter. 172 172 */ 173 int icmp_release_and_return(packet_t packet, int result);173 int icmp_release_and_return( packet_t packet, int result ); 174 174 175 175 /** Requests an echo message. 176 176 * Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout. 177 * Blocks the caller until the reply or the timeout occur res.177 * Blocks the caller until the reply or the timeout occurs. 178 178 * @param[in] id The message identifier. 179 179 * @param[in] sequence The message sequence parameter. … … 192 192 * @returns EPARTY if there was an internal error. 193 193 */ 194 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);194 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 ); 195 195 196 196 /** Prepares the ICMP error packet. … … 201 201 * @returns NULL on errors. 202 202 */ 203 icmp_header_ref icmp_prepare_packet(packet_t packet);203 icmp_header_ref icmp_prepare_packet( packet_t packet ); 204 204 205 205 /** Sends the ICMP message. … … 218 218 * @returns EPERM if the error message is not allowed. 219 219 */ 220 int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment);220 int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ); 221 221 222 222 /** Tries to set the pending reply result as the received message type. 223 * If the reply data are still present, the reply timeouted and the parent fibril is awaken.224 * The global lock is not released in this case to be reused by the parent fibril.223 * If the reply data is not present, the reply timed out and the other fibril 224 * is already awake. 225 225 * Releases the packet. 226 226 * @param[in] packet The received reply message. … … 230 230 * @returns EOK. 231 231 */ 232 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code);232 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ); 233 233 234 234 /** Assigns a new identifier for the connection. … … 239 239 * @returns ENOTCONN if no free identifier have been found. 240 240 */ 241 int icmp_bind_free_id(icmp_echo_ref echo_data);241 int icmp_bind_free_id( icmp_echo_ref echo_data ); 242 242 243 243 /** ICMP global data. … … 245 245 icmp_globals_t icmp_globals; 246 246 247 INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t);248 249 INT_MAP_IMPLEMENT( icmp_echo_data, icmp_echo_t);250 251 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){252 icmp_echo_ref 253 int 254 255 fibril_rwlock_write_lock( &icmp_globals.lock);247 INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t ); 248 249 INT_MAP_IMPLEMENT( icmp_echo_data, icmp_echo_t ); 250 251 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 ){ 252 icmp_echo_ref echo_data; 253 int res; 254 255 fibril_rwlock_write_lock( & icmp_globals.lock ); 256 256 // use the phone as the echo data index 257 echo_data = icmp_echo_data_find( &icmp_globals.echo_data, icmp_phone);258 if( ! echo_data){257 echo_data = icmp_echo_data_find( & icmp_globals.echo_data, icmp_phone ); 258 if( ! echo_data ){ 259 259 res = ENOENT; 260 260 }else{ 261 res = icmp_echo( echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen);262 if( echo_data->sequence_number < MAX_UINT16){261 res = icmp_echo( echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen ); 262 if( echo_data->sequence_number < MAX_UINT16 ){ 263 263 ++ echo_data->sequence_number; 264 264 }else{ … … 266 266 } 267 267 } 268 fibril_rwlock_write_unlock( &icmp_globals.lock);268 fibril_rwlock_write_unlock( & icmp_globals.lock ); 269 269 return res; 270 270 } 271 271 272 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){272 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 ){ 273 273 ERROR_DECLARE; 274 274 275 icmp_header_ref 276 packet_t 277 size_t 278 uint8_t * 279 icmp_reply_ref 280 int 281 int 282 int 283 284 if( addrlen <= 0){275 icmp_header_ref header; 276 packet_t packet; 277 size_t length; 278 uint8_t * data; 279 icmp_reply_ref reply; 280 int reply_key; 281 int result; 282 int index; 283 284 if( addrlen <= 0 ){ 285 285 return EINVAL; 286 286 } 287 length = ( size_t) addrlen;287 length = ( size_t ) addrlen; 288 288 // TODO do not ask all the time 289 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension)); 290 packet = packet_get_4(icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix); 291 if(! packet){ 292 return ENOMEM; 293 } 289 ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension )); 290 packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix ); 291 if( ! packet ) return ENOMEM; 294 292 295 293 // prepare the requesting packet 296 294 // set the destination address 297 if( ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){298 return icmp_release_and_return( packet, ERROR_CODE);295 if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length ))){ 296 return icmp_release_and_return( packet, ERROR_CODE ); 299 297 } 300 298 // allocate space in the packet 301 data = ( uint8_t *) packet_suffix(packet, size);302 if( ! data){303 return icmp_release_and_return( packet, ENOMEM);299 data = ( uint8_t * ) packet_suffix( packet, size ); 300 if( ! data ){ 301 return icmp_release_and_return( packet, ENOMEM ); 304 302 } 305 303 // fill the data 306 304 length = 0; 307 while( size > length + sizeof(ICMP_ECHO_TEXT)){308 memcpy( data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));309 length += sizeof( ICMP_ECHO_TEXT);310 } 311 memcpy( data + length, ICMP_ECHO_TEXT, size - length);305 while( size > length + sizeof( ICMP_ECHO_TEXT )){ 306 memcpy( data + length, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT )); 307 length += sizeof( ICMP_ECHO_TEXT ); 308 } 309 memcpy( data + length, ICMP_ECHO_TEXT, size - length ); 312 310 // prefix the header 313 header = PACKET_PREFIX( packet, icmp_header_t);314 if( ! header){315 return icmp_release_and_return( packet, ENOMEM);316 } 317 bzero( header, sizeof(*header));311 header = PACKET_PREFIX( packet, icmp_header_t ); 312 if( ! header ){ 313 return icmp_release_and_return( packet, ENOMEM ); 314 } 315 bzero( header, sizeof( * header )); 318 316 header->un.echo.identifier = id; 319 317 header->un.echo.sequence_number = sequence; 320 318 321 319 // prepare the reply structure 322 reply = malloc( sizeof(*reply));323 if( ! reply){324 return icmp_release_and_return( packet, ENOMEM);325 } 326 fibril_mutex_initialize( &reply->mutex);327 fibril_mutex_lock( &reply->mutex);328 fibril_condvar_initialize( &reply->condvar);329 reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number);330 index = icmp_replies_add( &icmp_globals.replies, reply_key, reply);331 if( index < 0){332 free( reply);333 return icmp_release_and_return( packet, index);334 } 335 336 // unlock the globals and wait for areply337 fibril_rwlock_write_unlock( &icmp_globals.lock);320 reply = malloc( sizeof( * reply )); 321 if( ! reply ){ 322 return icmp_release_and_return( packet, ENOMEM ); 323 } 324 fibril_mutex_initialize( & reply->mutex ); 325 fibril_mutex_lock( & reply->mutex ); 326 fibril_condvar_initialize( & reply->condvar ); 327 reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number ); 328 index = icmp_replies_add( & icmp_globals.replies, reply_key, reply ); 329 if( index < 0 ){ 330 free( reply ); 331 return icmp_release_and_return( packet, index ); 332 } 333 334 // unlock the globals so that we can wait for the reply 335 fibril_rwlock_write_unlock( & icmp_globals.lock ); 338 336 339 337 // send the request 340 icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);341 342 // wait for areply338 icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment ); 339 340 // wait for the reply 343 341 // timeout in microseconds 344 if( ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){342 if( ERROR_OCCURRED( fibril_condvar_wait_timeout( & reply->condvar, & reply->mutex, timeout * 1000 ))){ 345 343 result = ERROR_CODE; 346 347 // lock the globals again and clean up348 fibril_rwlock_write_lock(&icmp_globals.lock);349 344 }else{ 350 345 // read the result 351 346 result = reply->result; 352 353 // release the reply structure 354 fibril_mutex_unlock(&reply->mutex); 355 } 347 } 348 349 // drop the reply mutex before locking the globals again 350 fibril_mutex_unlock( & reply->mutex ); 351 fibril_rwlock_write_lock( & icmp_globals.lock ); 356 352 357 353 // destroy the reply structure 358 icmp_replies_exclude_index( &icmp_globals.replies, index);354 icmp_replies_exclude_index( & icmp_globals.replies, index ); 359 355 return result; 360 356 } 361 357 362 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){363 icmp_header_ref 364 365 header = icmp_prepare_packet( packet);366 if( ! header){367 return icmp_release_and_return( packet, ENOMEM);368 } 369 if( mtu){358 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){ 359 icmp_header_ref header; 360 361 header = icmp_prepare_packet( packet ); 362 if( ! header ){ 363 return icmp_release_and_return( packet, ENOMEM ); 364 } 365 if( mtu ){ 370 366 header->un.frag.mtu = mtu; 371 367 } 372 return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);373 } 374 375 int icmp_source_quench_msg( int icmp_phone, packet_t packet){376 icmp_header_ref 377 378 header = icmp_prepare_packet( packet);379 if( ! header){380 return icmp_release_and_return( packet, ENOMEM);381 } 382 return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0);383 } 384 385 int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet){386 icmp_header_ref 387 388 header = icmp_prepare_packet( packet);389 if( ! header){390 return icmp_release_and_return( packet, ENOMEM);391 } 392 return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0);393 } 394 395 int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){396 icmp_header_ref 397 398 header = icmp_prepare_packet( packet);399 if( ! header){400 return icmp_release_and_return( packet, ENOMEM);368 return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); 369 } 370 371 int icmp_source_quench_msg( int icmp_phone, packet_t packet ){ 372 icmp_header_ref header; 373 374 header = icmp_prepare_packet( packet ); 375 if( ! header ){ 376 return icmp_release_and_return( packet, ENOMEM ); 377 } 378 return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 ); 379 } 380 381 int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){ 382 icmp_header_ref header; 383 384 header = icmp_prepare_packet( packet ); 385 if( ! header ){ 386 return icmp_release_and_return( packet, ENOMEM ); 387 } 388 return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); 389 } 390 391 int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){ 392 icmp_header_ref header; 393 394 header = icmp_prepare_packet( packet ); 395 if( ! header ){ 396 return icmp_release_and_return( packet, ENOMEM ); 401 397 } 402 398 header->un.param.pointer = pointer; 403 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0); 404 } 405 406 icmp_header_ref icmp_prepare_packet(packet_t packet){ 407 icmp_header_ref header; 408 size_t header_length; 409 size_t total_length; 410 411 total_length = packet_get_data_length(packet); 412 if(total_length <= 0){ 399 return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); 400 } 401 402 icmp_header_ref icmp_prepare_packet( packet_t packet ){ 403 icmp_header_ref header; 404 size_t header_length; 405 size_t total_length; 406 407 total_length = packet_get_data_length( packet ); 408 if( total_length <= 0 ) return NULL; 409 header_length = ip_client_header_length( packet ); 410 if( header_length <= 0 ) return NULL; 411 // truncate if longer than 64 bits (without the IP header) 412 if(( total_length > header_length + ICMP_KEEP_LENGTH ) 413 && ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){ 413 414 return NULL; 414 415 } 415 header_length = ip_client_header_length(packet); 416 if(header_length <= 0){ 417 return NULL; 418 } 419 // truncate if longer than 64 bits (without the IP header) 420 if((total_length > header_length + ICMP_KEEP_LENGTH) 421 && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){ 422 return NULL; 423 } 424 header = PACKET_PREFIX(packet, icmp_header_t); 425 if(! header){ 426 return NULL; 427 } 428 bzero(header, sizeof(*header)); 416 header = PACKET_PREFIX( packet, icmp_header_t ); 417 if( ! header ) return NULL; 418 bzero( header, sizeof( * header )); 429 419 return header; 430 420 } 431 421 432 int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment){422 int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ){ 433 423 ERROR_DECLARE; 434 424 435 425 // do not send an error if disabled 436 if( error && (! icmp_globals.error_reporting)){437 return icmp_release_and_return( packet, EPERM);426 if( error && ( ! icmp_globals.error_reporting )){ 427 return icmp_release_and_return( packet, EPERM ); 438 428 } 439 429 header->type = type; 440 430 header->code = code; 441 431 header->checksum = 0; 442 header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet)); 443 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){ 444 return icmp_release_and_return(packet, ERROR_CODE); 445 } 446 return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error); 447 } 448 449 int icmp_connect_module(services_t service, suseconds_t timeout){ 450 icmp_echo_ref echo_data; 451 icmp_param_t id; 452 int index; 453 454 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 455 if(! echo_data){ 456 return ENOMEM; 457 } 432 header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet )); 433 if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){ 434 return icmp_release_and_return( packet, ERROR_CODE ); 435 } 436 return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error ); 437 } 438 439 int icmp_connect_module( services_t service, suseconds_t timeout ){ 440 icmp_echo_ref echo_data; 441 icmp_param_t id; 442 int index; 443 444 echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data )); 445 if( ! echo_data ) return ENOMEM; 458 446 // assign a new identifier 459 fibril_rwlock_write_lock( &icmp_globals.lock);460 index = icmp_bind_free_id( echo_data);461 if( index < 0){462 free( echo_data);463 fibril_rwlock_write_unlock( &icmp_globals.lock);447 fibril_rwlock_write_lock( & icmp_globals.lock ); 448 index = icmp_bind_free_id( echo_data ); 449 if( index < 0 ){ 450 free( echo_data ); 451 fibril_rwlock_write_unlock( & icmp_globals.lock ); 464 452 return index; 465 453 }else{ 466 454 id = echo_data->identifier; 467 fibril_rwlock_write_unlock( &icmp_globals.lock);455 fibril_rwlock_write_unlock( & icmp_globals.lock ); 468 456 // return the echo data identifier as the ICMP phone 469 457 return id; … … 471 459 } 472 460 473 int icmp_initialize( async_client_conn_t client_connection){461 int icmp_initialize( async_client_conn_t client_connection ){ 474 462 ERROR_DECLARE; 475 463 476 measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};477 measured_string_ref 478 size_t count = sizeof(names) / sizeof(measured_string_t);479 char * 480 481 fibril_rwlock_initialize( &icmp_globals.lock);482 fibril_rwlock_write_lock( &icmp_globals.lock);483 icmp_replies_initialize( &icmp_globals.replies);484 icmp_echo_data_initialize( &icmp_globals.echo_data);485 icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg);486 if( icmp_globals.ip_phone < 0){464 measured_string_t names[] = {{ str_dup("ICMP_ERROR_REPORTING"), 20 }, { str_dup("ICMP_ECHO_REPLYING"), 18 }}; 465 measured_string_ref configuration; 466 size_t count = sizeof( names ) / sizeof( measured_string_t ); 467 char * data; 468 469 fibril_rwlock_initialize( & icmp_globals.lock ); 470 fibril_rwlock_write_lock( & icmp_globals.lock ); 471 icmp_replies_initialize( & icmp_globals.replies ); 472 icmp_echo_data_initialize( & icmp_globals.echo_data ); 473 icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg ); 474 if( icmp_globals.ip_phone < 0 ){ 487 475 return icmp_globals.ip_phone; 488 476 } 489 ERROR_PROPAGATE( ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));477 ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension )); 490 478 icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE; 491 479 icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE; … … 493 481 icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING; 494 482 icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING; 495 configuration = & names[0];496 ERROR_PROPAGATE( net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));497 if( configuration){498 if( configuration[0].value){499 icmp_globals.error_reporting = ( configuration[0].value[0] == 'y');483 configuration = & names[ 0 ]; 484 ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data )); 485 if( configuration ){ 486 if( configuration[ 0 ].value ){ 487 icmp_globals.error_reporting = ( configuration[ 0 ].value[ 0 ] == 'y' ); 500 488 } 501 if( configuration[1].value){502 icmp_globals.echo_replying = ( configuration[1].value[0] == 'y');489 if( configuration[ 1 ].value ){ 490 icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' ); 503 491 } 504 net_free_settings( configuration, data);505 } 506 fibril_rwlock_write_unlock( &icmp_globals.lock);492 net_free_settings( configuration, data ); 493 } 494 fibril_rwlock_write_unlock( & icmp_globals.lock ); 507 495 return EOK; 508 496 } 509 497 510 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){498 int icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){ 511 499 ERROR_DECLARE; 512 500 513 if( ERROR_OCCURRED(icmp_process_packet(packet, error))){514 return icmp_release_and_return( packet, ERROR_CODE);501 if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){ 502 return icmp_release_and_return( packet, ERROR_CODE ); 515 503 } 516 504 … … 518 506 } 519 507 520 int icmp_process_packet( packet_t packet, services_t error){508 int icmp_process_packet( packet_t packet, services_t error ){ 521 509 ERROR_DECLARE; 522 510 523 size_t 524 uint8_t * 525 int 526 int 527 void * 528 icmp_header_ref 529 icmp_type_t 530 icmp_code_t 531 532 if( error){533 switch( error){511 size_t length; 512 uint8_t * src; 513 int addrlen; 514 int result; 515 void * data; 516 icmp_header_ref header; 517 icmp_type_t type; 518 icmp_code_t code; 519 520 if( error ){ 521 switch( error ){ 534 522 case SERVICE_ICMP: 535 523 // process error 536 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 537 if(result < 0){ 538 return result; 539 } 540 length = (size_t) result; 524 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); 525 if( result < 0 ) return result; 526 length = ( size_t ) result; 541 527 // remove the error header 542 ERROR_PROPAGATE( packet_trim(packet, length, 0));528 ERROR_PROPAGATE( packet_trim( packet, length, 0 )); 543 529 break; 544 530 default: … … 547 533 } 548 534 // get rid of the ip header 549 length = ip_client_header_length(packet); 550 ERROR_PROPAGATE(packet_trim(packet, length, 0)); 551 552 length = packet_get_data_length(packet); 553 if(length <= 0){ 554 return EINVAL; 555 } 556 if(length < ICMP_HEADER_SIZE){ 557 return EINVAL; 558 } 559 data = packet_get_data(packet); 560 if(! data){ 561 return EINVAL; 562 } 535 length = ip_client_header_length( packet ); 536 ERROR_PROPAGATE( packet_trim( packet, length, 0 )); 537 538 length = packet_get_data_length( packet ); 539 if( length <= 0 ) return EINVAL; 540 if( length < ICMP_HEADER_SIZE) return EINVAL; 541 data = packet_get_data( packet ); 542 if( ! data ) return EINVAL; 563 543 // get icmp header 564 header = ( icmp_header_ref) data;544 header = ( icmp_header_ref ) data; 565 545 // checksum 566 if( header->checksum){567 while( ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){546 if( header->checksum ){ 547 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO ){ 568 548 // set the original message type on error notification 569 549 // type swap observed in Qemu 570 if( error){571 switch( header->type){550 if( error ){ 551 switch( header->type ){ 572 552 case ICMP_ECHOREPLY: 573 553 header->type = ICMP_ECHO; … … 578 558 } 579 559 } 580 switch( header->type){560 switch( header->type ){ 581 561 case ICMP_ECHOREPLY: 582 if( error){583 return icmp_process_echo_reply( packet, header, type, code);562 if( error ){ 563 return icmp_process_echo_reply( packet, header, type, code ); 584 564 }else{ 585 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0);565 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 ); 586 566 } 587 567 case ICMP_ECHO: 588 if( error){589 return icmp_process_echo_reply( packet, header, type, code);568 if( error ){ 569 return icmp_process_echo_reply( packet, header, type, code ); 590 570 // do not send a reply if disabled 591 }else if( icmp_globals.echo_replying){592 addrlen = packet_get_addr( packet, &src, NULL);593 if(( addrlen > 0)571 }else if( icmp_globals.echo_replying ){ 572 addrlen = packet_get_addr( packet, & src, NULL ); 573 if(( addrlen > 0 ) 594 574 // set both addresses to the source one (avoids the source address deletion before setting the destination one) 595 && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){575 && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){ 596 576 // send the reply 597 icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);577 icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 ); 598 578 return EOK; 599 579 }else{ … … 615 595 case ICMP_SKIP: 616 596 case ICMP_PHOTURIS: 617 ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);597 ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP ); 618 598 return EOK; 619 599 default: … … 622 602 } 623 603 624 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){625 int 626 icmp_reply_ref 604 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){ 605 int reply_key; 606 icmp_reply_ref reply; 627 607 628 608 // compute the reply key 629 reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number);630 pq_release( icmp_globals.net_phone, packet_get_id(packet));609 reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number ); 610 pq_release( icmp_globals.net_phone, packet_get_id( packet )); 631 611 // lock the globals 632 fibril_rwlock_write_lock( &icmp_globals.lock);612 fibril_rwlock_write_lock( & icmp_globals.lock ); 633 613 // find the pending reply 634 reply = icmp_replies_find( &icmp_globals.replies, reply_key);635 if( reply){614 reply = icmp_replies_find( & icmp_globals.replies, reply_key ); 615 if( reply ){ 636 616 // set the result 637 617 reply->result = type; 638 // notify the main fibril 639 fibril_condvar_signal(&reply->condvar); 640 }else{ 641 // unlock only if no reply 642 fibril_rwlock_write_unlock(&icmp_globals.lock); 643 } 618 // notify the waiting fibril 619 fibril_condvar_signal( & reply->condvar ); 620 } 621 fibril_rwlock_write_unlock( & icmp_globals.lock ); 644 622 return EOK; 645 623 } 646 624 647 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){625 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ 648 626 ERROR_DECLARE; 649 627 650 packet_t 651 652 * answer_count = 0;653 switch( IPC_GET_METHOD(*call)){628 packet_t packet; 629 630 * answer_count = 0; 631 switch( IPC_GET_METHOD( * call )){ 654 632 case NET_TL_RECEIVED: 655 if( ! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){656 ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));633 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ 634 ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call )); 657 635 } 658 636 return ERROR_CODE; 659 637 case NET_ICMP_INIT: 660 return icmp_process_client_messages( callid, * call);638 return icmp_process_client_messages( callid, * call ); 661 639 default: 662 return icmp_process_message( call);640 return icmp_process_message( call ); 663 641 } 664 642 return ENOTSUP; 665 643 } 666 644 667 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call){645 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){ 668 646 ERROR_DECLARE; 669 647 670 bool 648 bool keep_on_going = true; 671 649 // fibril_rwlock_t lock; 672 ipc_call_t answer; 673 int answer_count; 674 size_t length; 675 struct sockaddr * addr; 676 ipc_callid_t data_callid; 677 icmp_echo_ref echo_data; 678 int res; 650 ipc_call_t answer; 651 int answer_count; 652 size_t length; 653 struct sockaddr * addr; 654 ipc_callid_t data_callid; 655 icmp_echo_ref echo_data; 679 656 680 657 /* … … 682 659 * - Answer the first NET_ICMP_INIT call. 683 660 */ 684 res = EOK; 685 answer_count = 0; 686 687 // fibril_rwlock_initialize(&lock); 688 689 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 690 if(! echo_data){ 691 return ENOMEM; 692 } 693 661 ipc_answer_0( callid, EOK ); 662 663 // fibril_rwlock_initialize( & lock ); 664 665 echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data )); 666 if( ! echo_data ) return ENOMEM; 694 667 // assign a new identifier 695 fibril_rwlock_write_lock(&icmp_globals.lock); 696 res = icmp_bind_free_id(echo_data); 697 fibril_rwlock_write_unlock(&icmp_globals.lock); 698 if(res < 0){ 699 free(echo_data); 700 return res; 701 } 702 703 while(keep_on_going){ 704 705 // answer the call 706 answer_call(callid, res, &answer, answer_count); 707 708 // refresh data 709 refresh_answer(&answer, &answer_count); 710 711 // get the next call 712 callid = async_get_call(&call); 713 714 // process the call 715 switch(IPC_GET_METHOD(call)){ 668 fibril_rwlock_write_lock( & icmp_globals.lock ); 669 ERROR_CODE = icmp_bind_free_id( echo_data ); 670 fibril_rwlock_write_unlock( & icmp_globals.lock ); 671 if( ERROR_CODE < 0 ){ 672 free( echo_data ); 673 return ERROR_CODE; 674 } 675 676 while( keep_on_going ){ 677 refresh_answer( & answer, & answer_count ); 678 679 callid = async_get_call( & call ); 680 681 switch( IPC_GET_METHOD( call )){ 716 682 case IPC_M_PHONE_HUNGUP: 717 683 keep_on_going = false; 718 res = EHANGUP;684 ERROR_CODE = EOK; 719 685 break; 720 686 case NET_ICMP_ECHO: 721 // fibril_rwlock_write_lock( &lock);722 if( ! async_data_write_receive(&data_callid, &length)){723 res= EINVAL;687 // fibril_rwlock_write_lock( & lock ); 688 if( ! async_data_write_receive( & data_callid, & length )){ 689 ERROR_CODE = EINVAL; 724 690 }else{ 725 addr = malloc( length);726 if( ! addr){727 res= ENOMEM;691 addr = malloc( length ); 692 if( ! addr ){ 693 ERROR_CODE = ENOMEM; 728 694 }else{ 729 if( ! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){730 fibril_rwlock_write_lock( &icmp_globals.lock);731 res = icmp_echo(echo_data->identifier, echo_data->sequence_number, 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);732 fibril_rwlock_write_unlock( &icmp_globals.lock);733 free( addr);734 if( echo_data->sequence_number < MAX_UINT16){695 if( ! ERROR_OCCURRED( async_data_write_finalize( data_callid, addr, length ))){ 696 fibril_rwlock_write_lock( & icmp_globals.lock ); 697 ERROR_CODE = icmp_echo( echo_data->identifier, echo_data->sequence_number, 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 ); 698 fibril_rwlock_write_unlock( & icmp_globals.lock ); 699 free( addr ); 700 if( echo_data->sequence_number < MAX_UINT16 ){ 735 701 ++ echo_data->sequence_number; 736 702 }else{ 737 703 echo_data->sequence_number = 0; 738 704 } 739 }else{740 res = ERROR_CODE;741 705 } 742 706 } 743 707 } 744 // fibril_rwlock_write_unlock( &lock);708 // fibril_rwlock_write_unlock( & lock ); 745 709 break; 746 710 default: 747 res = icmp_process_message(&call);711 ERROR_CODE = icmp_process_message( & call ); 748 712 } 713 714 answer_call( callid, ERROR_CODE, & answer, answer_count ); 749 715 } 750 716 751 717 // release the identifier 752 fibril_rwlock_write_lock( &icmp_globals.lock);753 icmp_echo_data_exclude( &icmp_globals.echo_data, echo_data->identifier);754 fibril_rwlock_write_unlock( &icmp_globals.lock);755 return res;756 } 757 758 int icmp_process_message( ipc_call_t * call){718 fibril_rwlock_write_lock( & icmp_globals.lock ); 719 icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->identifier ); 720 fibril_rwlock_write_unlock( & icmp_globals.lock ); 721 return EOK; 722 } 723 724 int icmp_process_message( ipc_call_t * call ){ 759 725 ERROR_DECLARE; 760 726 761 packet_t 762 763 switch( IPC_GET_METHOD(*call)){727 packet_t packet; 728 729 switch( IPC_GET_METHOD( * call )){ 764 730 case NET_ICMP_DEST_UNREACH: 765 if( ! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){766 ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);731 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ 732 ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet ); 767 733 } 768 734 return ERROR_CODE; 769 735 case NET_ICMP_SOURCE_QUENCH: 770 if( ! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){771 ERROR_CODE = icmp_source_quench_msg( 0, packet);736 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ 737 ERROR_CODE = icmp_source_quench_msg( 0, packet ); 772 738 } 773 739 return ERROR_CODE; 774 740 case NET_ICMP_TIME_EXCEEDED: 775 if( ! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){776 ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE(call), packet);741 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ 742 ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet ); 777 743 } 778 744 return ERROR_CODE; 779 745 case NET_ICMP_PARAMETERPROB: 780 if( ! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){781 ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);746 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ 747 ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet ); 782 748 } 783 749 return ERROR_CODE; … … 787 753 } 788 754 789 int icmp_release_and_return(packet_t packet, int result){790 pq_release( icmp_globals.net_phone, packet_get_id(packet));755 int icmp_release_and_return( packet_t packet, int result ){ 756 pq_release( icmp_globals.net_phone, packet_get_id( packet )); 791 757 return result; 792 758 } 793 759 794 int icmp_bind_free_id(icmp_echo_ref echo_data){ 795 icmp_param_t index; 796 797 if(! echo_data){ 798 return EBADMEM; 799 } 760 int icmp_bind_free_id( icmp_echo_ref echo_data ){ 761 icmp_param_t index; 762 763 if( ! echo_data ) return EBADMEM; 800 764 // from the last used one 801 765 index = icmp_globals.last_used_id; … … 803 767 ++ index; 804 768 // til the range end 805 if( index >= ICMP_FREE_IDS_END){769 if( index >= ICMP_FREE_IDS_END ){ 806 770 // start from the range beginning 807 771 index = ICMP_FREE_IDS_START - 1; … … 809 773 ++ index; 810 774 // til the last used one 811 if( index >= icmp_globals.last_used_id){775 if( index >= icmp_globals.last_used_id ){ 812 776 // none found 813 777 return ENOTCONN; 814 778 } 815 }while( icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);779 }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL ); 816 780 // found, break immediately 817 781 break; 818 782 } 819 }while( icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);783 }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL ); 820 784 echo_data->identifier = index; 821 785 echo_data->sequence_number = 0; 822 return icmp_echo_data_add( &icmp_globals.echo_data, index, echo_data);786 return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data ); 823 787 } 824 788
Note:
See TracChangeset
for help on using the changeset viewer.