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