Changeset 71b00dcc in mainline for uspace/srv/net/tl/icmp/icmp.c
- Timestamp:
- 2010-03-07T22:51:38Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 60ab6c3
- Parents:
- b5cbff4 (diff), 31c80a5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/icmp/icmp.c
rb5cbff4 r71b00dcc 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. … … 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. … … 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 ) return ENOMEM; 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 } 292 294 293 295 // prepare the requesting packet 294 296 // set the destination address 295 if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length))){296 return icmp_release_and_return( packet, ERROR_CODE);297 if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){ 298 return icmp_release_and_return(packet, ERROR_CODE); 297 299 } 298 300 // allocate space in the packet 299 data = ( uint8_t * ) packet_suffix( packet, size);300 if( ! data){301 return icmp_release_and_return( packet, ENOMEM);301 data = (uint8_t *) packet_suffix(packet, size); 302 if(! data){ 303 return icmp_release_and_return(packet, ENOMEM); 302 304 } 303 305 // fill the data 304 306 length = 0; 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);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); 310 312 // prefix the 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));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)); 316 318 header->un.echo.identifier = id; 317 319 header->un.echo.sequence_number = sequence; 318 320 319 321 // prepare the reply structure 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);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); 332 334 } 333 335 334 336 // unlock the globals so that we can wait for the reply 335 fibril_rwlock_write_unlock( & icmp_globals.lock);337 fibril_rwlock_write_unlock(&icmp_globals.lock); 336 338 337 339 // send the request 338 icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);340 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment); 339 341 340 342 // wait for the reply 341 343 // timeout in microseconds 342 if( ERROR_OCCURRED( fibril_condvar_wait_timeout( & reply->condvar, & reply->mutex, timeout * 1000))){344 if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){ 343 345 result = ERROR_CODE; 344 346 }else{ … … 348 350 349 351 // drop the reply mutex before locking the globals again 350 fibril_mutex_unlock( & reply->mutex);351 fibril_rwlock_write_lock( & icmp_globals.lock);352 fibril_mutex_unlock(&reply->mutex); 353 fibril_rwlock_write_lock(&icmp_globals.lock); 352 354 353 355 // destroy the reply structure 354 icmp_replies_exclude_index( & icmp_globals.replies, index);356 icmp_replies_exclude_index(&icmp_globals.replies, index); 355 357 return result; 356 358 } 357 359 358 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){359 icmp_header_ref 360 361 header = icmp_prepare_packet( packet);362 if( ! header){363 return icmp_release_and_return( packet, ENOMEM);364 } 365 if( mtu){360 int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){ 361 icmp_header_ref header; 362 363 header = icmp_prepare_packet(packet); 364 if(! header){ 365 return icmp_release_and_return(packet, ENOMEM); 366 } 367 if(mtu){ 366 368 header->un.frag.mtu = mtu; 367 369 } 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 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 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 393 394 header = icmp_prepare_packet( packet);395 if( ! header){396 return icmp_release_and_return( packet, ENOMEM);370 return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0); 371 } 372 373 int icmp_source_quench_msg(int icmp_phone, packet_t packet){ 374 icmp_header_ref header; 375 376 header = icmp_prepare_packet(packet); 377 if(! header){ 378 return icmp_release_and_return(packet, ENOMEM); 379 } 380 return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0); 381 } 382 383 int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){ 384 icmp_header_ref header; 385 386 header = icmp_prepare_packet(packet); 387 if(! header){ 388 return icmp_release_and_return(packet, ENOMEM); 389 } 390 return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0); 391 } 392 393 int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){ 394 icmp_header_ref header; 395 396 header = icmp_prepare_packet(packet); 397 if(! header){ 398 return icmp_release_and_return(packet, ENOMEM); 397 399 } 398 400 header->un.param.pointer = pointer; 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; 401 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0); 402 } 403 404 icmp_header_ref icmp_prepare_packet(packet_t packet){ 405 icmp_header_ref header; 406 size_t header_length; 407 size_t total_length; 408 409 total_length = packet_get_data_length(packet); 410 if(total_length <= 0){ 411 return NULL; 412 } 413 header_length = ip_client_header_length(packet); 414 if(header_length <= 0){ 415 return NULL; 416 } 411 417 // 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)){418 if((total_length > header_length + ICMP_KEEP_LENGTH) 419 && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){ 414 420 return NULL; 415 421 } 416 header = PACKET_PREFIX( packet, icmp_header_t ); 417 if( ! header ) return NULL; 418 bzero( header, sizeof( * header )); 422 header = PACKET_PREFIX(packet, icmp_header_t); 423 if(! header){ 424 return NULL; 425 } 426 bzero(header, sizeof(*header)); 419 427 return header; 420 428 } 421 429 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){430 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){ 423 431 ERROR_DECLARE; 424 432 425 433 // do not send an error if disabled 426 if( error && ( ! icmp_globals.error_reporting)){427 return icmp_release_and_return( packet, EPERM);434 if(error && (! icmp_globals.error_reporting)){ 435 return icmp_release_and_return(packet, EPERM); 428 436 } 429 437 header->type = type; 430 438 header->code = code; 431 439 header->checksum = 0; 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; 440 header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet)); 441 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){ 442 return icmp_release_and_return(packet, ERROR_CODE); 443 } 444 return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error); 445 } 446 447 int icmp_connect_module(services_t service, suseconds_t timeout){ 448 icmp_echo_ref echo_data; 449 icmp_param_t id; 450 int index; 451 452 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 453 if(! echo_data){ 454 return ENOMEM; 455 } 446 456 // assign a new identifier 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);457 fibril_rwlock_write_lock(&icmp_globals.lock); 458 index = icmp_bind_free_id(echo_data); 459 if(index < 0){ 460 free(echo_data); 461 fibril_rwlock_write_unlock(&icmp_globals.lock); 452 462 return index; 453 463 }else{ 454 464 id = echo_data->identifier; 455 fibril_rwlock_write_unlock( & icmp_globals.lock);465 fibril_rwlock_write_unlock(&icmp_globals.lock); 456 466 // return the echo data identifier as the ICMP phone 457 467 return id; … … 459 469 } 460 470 461 int icmp_initialize( async_client_conn_t client_connection){471 int icmp_initialize(async_client_conn_t client_connection){ 462 472 ERROR_DECLARE; 463 473 464 measured_string_t names[] = {{ str_dup("ICMP_ERROR_REPORTING"), 20 }, { str_dup("ICMP_ECHO_REPLYING"), 18}};465 measured_string_ref 466 size_t count = sizeof( names ) / sizeof( measured_string_t);467 char * 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){474 measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}}; 475 measured_string_ref configuration; 476 size_t count = sizeof(names) / sizeof(measured_string_t); 477 char * data; 478 479 fibril_rwlock_initialize(&icmp_globals.lock); 480 fibril_rwlock_write_lock(&icmp_globals.lock); 481 icmp_replies_initialize(&icmp_globals.replies); 482 icmp_echo_data_initialize(&icmp_globals.echo_data); 483 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg); 484 if(icmp_globals.ip_phone < 0){ 475 485 return icmp_globals.ip_phone; 476 486 } 477 ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension));487 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension)); 478 488 icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE; 479 489 icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE; … … 481 491 icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING; 482 492 icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING; 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');493 configuration = &names[0]; 494 ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data)); 495 if(configuration){ 496 if(configuration[0].value){ 497 icmp_globals.error_reporting = (configuration[0].value[0] == 'y'); 488 498 } 489 if( configuration[ 1 ].value){490 icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y');499 if(configuration[1].value){ 500 icmp_globals.echo_replying = (configuration[1].value[0] == 'y'); 491 501 } 492 net_free_settings( configuration, data);493 } 494 fibril_rwlock_write_unlock( & icmp_globals.lock);502 net_free_settings(configuration, data); 503 } 504 fibril_rwlock_write_unlock(&icmp_globals.lock); 495 505 return EOK; 496 506 } 497 507 498 int icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error){508 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 499 509 ERROR_DECLARE; 500 510 501 if( ERROR_OCCURRED( icmp_process_packet( packet, error))){502 return icmp_release_and_return( packet, ERROR_CODE);511 if(ERROR_OCCURRED(icmp_process_packet(packet, error))){ 512 return icmp_release_and_return(packet, ERROR_CODE); 503 513 } 504 514 … … 506 516 } 507 517 508 int icmp_process_packet( packet_t packet, services_t error){518 int icmp_process_packet(packet_t packet, services_t error){ 509 519 ERROR_DECLARE; 510 520 511 size_t 512 uint8_t * 513 int 514 int 515 void * 516 icmp_header_ref 517 icmp_type_t 518 icmp_code_t 519 520 if( error){521 switch( error){521 size_t length; 522 uint8_t * src; 523 int addrlen; 524 int result; 525 void * data; 526 icmp_header_ref header; 527 icmp_type_t type; 528 icmp_code_t code; 529 530 if(error){ 531 switch(error){ 522 532 case SERVICE_ICMP: 523 533 // process error 524 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); 525 if( result < 0 ) return result; 526 length = ( size_t ) result; 534 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 535 if(result < 0){ 536 return result; 537 } 538 length = (size_t) result; 527 539 // remove the error header 528 ERROR_PROPAGATE( packet_trim( packet, length, 0));540 ERROR_PROPAGATE(packet_trim(packet, length, 0)); 529 541 break; 530 542 default: … … 533 545 } 534 546 // get rid of the ip header 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; 547 length = ip_client_header_length(packet); 548 ERROR_PROPAGATE(packet_trim(packet, length, 0)); 549 550 length = packet_get_data_length(packet); 551 if(length <= 0){ 552 return EINVAL; 553 } 554 if(length < ICMP_HEADER_SIZE){ 555 return EINVAL; 556 } 557 data = packet_get_data(packet); 558 if(! data){ 559 return EINVAL; 560 } 543 561 // get icmp header 544 header = ( icmp_header_ref) data;562 header = (icmp_header_ref) data; 545 563 // checksum 546 if( header->checksum){547 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO){564 if(header->checksum){ 565 while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){ 548 566 // set the original message type on error notification 549 567 // type swap observed in Qemu 550 if( error){551 switch( header->type){568 if(error){ 569 switch(header->type){ 552 570 case ICMP_ECHOREPLY: 553 571 header->type = ICMP_ECHO; … … 558 576 } 559 577 } 560 switch( header->type){578 switch(header->type){ 561 579 case ICMP_ECHOREPLY: 562 if( error){563 return icmp_process_echo_reply( packet, header, type, code);580 if(error){ 581 return icmp_process_echo_reply(packet, header, type, code); 564 582 }else{ 565 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0);583 return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0); 566 584 } 567 585 case ICMP_ECHO: 568 if( error){569 return icmp_process_echo_reply( packet, header, type, code);586 if(error){ 587 return icmp_process_echo_reply(packet, header, type, code); 570 588 // do not send a reply if disabled 571 }else if( icmp_globals.echo_replying){572 addrlen = packet_get_addr( packet, & src, NULL);573 if(( addrlen > 0)589 }else if(icmp_globals.echo_replying){ 590 addrlen = packet_get_addr(packet, &src, NULL); 591 if((addrlen > 0) 574 592 // set both addresses to the source one (avoids the source address deletion before setting the destination one) 575 && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK)){593 && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){ 576 594 // send the reply 577 icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);595 icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0); 578 596 return EOK; 579 597 }else{ … … 595 613 case ICMP_SKIP: 596 614 case ICMP_PHOTURIS: 597 ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);615 ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP); 598 616 return EOK; 599 617 default: … … 602 620 } 603 621 604 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){605 int 606 icmp_reply_ref 622 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){ 623 int reply_key; 624 icmp_reply_ref reply; 607 625 608 626 // compute the reply key 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));627 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number); 628 pq_release(icmp_globals.net_phone, packet_get_id(packet)); 611 629 // lock the globals 612 fibril_rwlock_write_lock( & icmp_globals.lock);630 fibril_rwlock_write_lock(&icmp_globals.lock); 613 631 // find the pending reply 614 reply = icmp_replies_find( & icmp_globals.replies, reply_key);615 if( reply){632 reply = icmp_replies_find(&icmp_globals.replies, reply_key); 633 if(reply){ 616 634 // set the result 617 635 reply->result = type; 618 636 // notify the waiting fibril 619 fibril_condvar_signal( & reply->condvar);620 } 621 fibril_rwlock_write_unlock( & icmp_globals.lock);637 fibril_condvar_signal(&reply->condvar); 638 } 639 fibril_rwlock_write_unlock(&icmp_globals.lock); 622 640 return EOK; 623 641 } 624 642 625 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){643 int icmp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 626 644 ERROR_DECLARE; 627 645 628 packet_t 629 630 * 631 switch( IPC_GET_METHOD( * call)){646 packet_t packet; 647 648 *answer_count = 0; 649 switch(IPC_GET_METHOD(*call)){ 632 650 case NET_TL_RECEIVED: 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));651 if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 652 ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call)); 635 653 } 636 654 return ERROR_CODE; 637 655 case NET_ICMP_INIT: 638 return icmp_process_client_messages( callid, * call);656 return icmp_process_client_messages(callid, * call); 639 657 default: 640 return icmp_process_message( call);658 return icmp_process_message(call); 641 659 } 642 660 return ENOTSUP; 643 661 } 644 662 645 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call){663 int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){ 646 664 ERROR_DECLARE; 647 665 648 bool 666 bool keep_on_going = true; 649 667 // fibril_rwlock_t lock; 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; 668 ipc_call_t answer; 669 int answer_count; 670 size_t length; 671 struct sockaddr * addr; 672 ipc_callid_t data_callid; 673 icmp_echo_ref echo_data; 674 int res; 656 675 657 676 /* … … 659 678 * - Answer the first NET_ICMP_INIT call. 660 679 */ 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; 680 res = EOK; 681 answer_count = 0; 682 683 // fibril_rwlock_initialize(&lock); 684 685 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 686 if(! echo_data){ 687 return ENOMEM; 688 } 689 667 690 // assign a new identifier 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 )){ 691 fibril_rwlock_write_lock(&icmp_globals.lock); 692 res = icmp_bind_free_id(echo_data); 693 fibril_rwlock_write_unlock(&icmp_globals.lock); 694 if(res < 0){ 695 free(echo_data); 696 return res; 697 } 698 699 while(keep_on_going){ 700 701 // answer the call 702 answer_call(callid, res, &answer, answer_count); 703 704 // refresh data 705 refresh_answer(&answer, &answer_count); 706 707 // get the next call 708 callid = async_get_call(&call); 709 710 // process the call 711 switch(IPC_GET_METHOD(call)){ 682 712 case IPC_M_PHONE_HUNGUP: 683 713 keep_on_going = false; 684 ERROR_CODE = EOK;714 res = EHANGUP; 685 715 break; 686 716 case NET_ICMP_ECHO: 687 // fibril_rwlock_write_lock( & lock);688 if( ! async_data_write_receive( & data_callid, & length)){689 ERROR_CODE= EINVAL;717 // fibril_rwlock_write_lock(&lock); 718 if(! async_data_write_receive(&data_callid, &length)){ 719 res = EINVAL; 690 720 }else{ 691 addr = malloc( length);692 if( ! addr){693 ERROR_CODE= ENOMEM;721 addr = malloc(length); 722 if(! addr){ 723 res = ENOMEM; 694 724 }else{ 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){725 if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){ 726 fibril_rwlock_write_lock(&icmp_globals.lock); 727 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); 728 fibril_rwlock_write_unlock(&icmp_globals.lock); 729 free(addr); 730 if(echo_data->sequence_number < MAX_UINT16){ 701 731 ++ echo_data->sequence_number; 702 732 }else{ 703 733 echo_data->sequence_number = 0; 704 734 } 735 }else{ 736 res = ERROR_CODE; 705 737 } 706 738 } 707 739 } 708 // fibril_rwlock_write_unlock( & lock);740 // fibril_rwlock_write_unlock(&lock); 709 741 break; 710 742 default: 711 ERROR_CODE = icmp_process_message( & call);743 res = icmp_process_message(&call); 712 744 } 713 714 answer_call( callid, ERROR_CODE, & answer, answer_count );715 745 } 716 746 717 747 // release the identifier 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){748 fibril_rwlock_write_lock(&icmp_globals.lock); 749 icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier); 750 fibril_rwlock_write_unlock(&icmp_globals.lock); 751 return res; 752 } 753 754 int icmp_process_message(ipc_call_t * call){ 725 755 ERROR_DECLARE; 726 756 727 packet_t 728 729 switch( IPC_GET_METHOD( * call)){757 packet_t packet; 758 759 switch(IPC_GET_METHOD(*call)){ 730 760 case NET_ICMP_DEST_UNREACH: 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);761 if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 762 ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet); 733 763 } 734 764 return ERROR_CODE; 735 765 case NET_ICMP_SOURCE_QUENCH: 736 if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call)))){737 ERROR_CODE = icmp_source_quench_msg( 0, packet);766 if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 767 ERROR_CODE = icmp_source_quench_msg(0, packet); 738 768 } 739 769 return ERROR_CODE; 740 770 case NET_ICMP_TIME_EXCEEDED: 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);771 if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 772 ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet); 743 773 } 744 774 return ERROR_CODE; 745 775 case NET_ICMP_PARAMETERPROB: 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);776 if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 777 ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet); 748 778 } 749 779 return ERROR_CODE; … … 753 783 } 754 784 755 int icmp_release_and_return( packet_t packet, int result){756 pq_release( icmp_globals.net_phone, packet_get_id( packet));785 int icmp_release_and_return(packet_t packet, int result){ 786 pq_release(icmp_globals.net_phone, packet_get_id(packet)); 757 787 return result; 758 788 } 759 789 760 int icmp_bind_free_id( icmp_echo_ref echo_data ){ 761 icmp_param_t index; 762 763 if( ! echo_data ) return EBADMEM; 790 int icmp_bind_free_id(icmp_echo_ref echo_data){ 791 icmp_param_t index; 792 793 if(! echo_data){ 794 return EBADMEM; 795 } 764 796 // from the last used one 765 797 index = icmp_globals.last_used_id; … … 767 799 ++ index; 768 800 // til the range end 769 if( index >= ICMP_FREE_IDS_END){801 if(index >= ICMP_FREE_IDS_END){ 770 802 // start from the range beginning 771 803 index = ICMP_FREE_IDS_START - 1; … … 773 805 ++ index; 774 806 // til the last used one 775 if( index >= icmp_globals.last_used_id){807 if(index >= icmp_globals.last_used_id){ 776 808 // none found 777 809 return ENOTCONN; 778 810 } 779 }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL);811 }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 780 812 // found, break immediately 781 813 break; 782 814 } 783 }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL);815 }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 784 816 echo_data->identifier = index; 785 817 echo_data->sequence_number = 0; 786 return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data);818 return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data); 787 819 } 788 820
Note:
See TracChangeset
for help on using the changeset viewer.