Changeset a64c64d in mainline for uspace/srv/net/il/arp/arp.c
- Timestamp:
- 2010-03-09T22:24:31Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 74520daf
- Parents:
- 9f2ea28
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
r9f2ea28 ra64c64d 73 73 arp_globals_t arp_globals; 74 74 75 /** Clears the device specific data. 76 * @param[in] device The device specific data. 77 */ 78 void arp_clear_device(arp_device_ref device); 79 75 80 /** Creates new protocol specific data. 76 81 * Allocates and returns the needed memory block as the proto parameter. … … 82 87 */ 83 88 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address); 84 85 /** Clears the device specific data.86 * @param[in] device The device specific data.87 */88 void arp_clear_device(arp_device_ref device);89 89 90 90 /** @name Message processing functions … … 105 105 int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address); 106 106 107 /** Returns the hardware address for the given protocol address. 108 * Sends the ARP request packet if the hardware address is not found in the cache. 107 /** Updates the device content length according to the new MTU value. 109 108 * @param[in] device_id The device identifier. 110 * @param[in] protocol The protocol service. 111 * @param[in] target The target protocol address. 112 * @returns The hardware address of the target. 113 * @returns NULL if the target parameter is NULL. 114 * @returns NULL if the device is not found. 115 * @returns NULL if the device packet is too small to send a request. 116 * @returns NULL if the hardware address is not found in the cache. 117 */ 118 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target); 109 * @param[in] mtu The new mtu value. 110 * @returns ENOENT if device is not found. 111 * @returns EOK on success. 112 */ 113 int arp_mtu_changed_message(device_id_t device_id, size_t mtu); 119 114 120 115 /** Processes the received ARP packet. … … 133 128 int arp_receive_message(device_id_t device_id, packet_t packet); 134 129 135 /** Updates the device content length according to the new MTU value. 130 /** Returns the hardware address for the given protocol address. 131 * Sends the ARP request packet if the hardware address is not found in the cache. 136 132 * @param[in] device_id The device identifier. 137 * @param[in] mtu The new mtu value. 138 * @returns ENOENT if device is not found. 139 * @returns EOK on success. 140 */ 141 int arp_mtu_changed_message(device_id_t device_id, size_t mtu); 133 * @param[in] protocol The protocol service. 134 * @param[in] target The target protocol address. 135 * @returns The hardware address of the target. 136 * @returns NULL if the target parameter is NULL. 137 * @returns NULL if the device is not found. 138 * @returns NULL if the device packet is too small to send a request. 139 * @returns NULL if the hardware address is not found in the cache. 140 */ 141 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target); 142 142 143 143 /*@}*/ … … 148 148 149 149 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t) 150 151 task_id_t arp_task_get_id(void){152 return task_get_id();153 }154 155 int arp_clear_device_req(int arp_phone, device_id_t device_id){156 arp_device_ref device;157 158 fibril_rwlock_write_lock(&arp_globals.lock);159 device = arp_cache_find(&arp_globals.cache, device_id);160 if(! device){161 fibril_rwlock_write_unlock(&arp_globals.lock);162 return ENOENT;163 }164 arp_clear_device(device);165 printf("Device %d cleared\n", device_id);166 fibril_rwlock_write_unlock(&arp_globals.lock);167 return EOK;168 }169 170 int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){171 arp_device_ref device;172 arp_proto_ref proto;173 174 fibril_rwlock_write_lock(&arp_globals.lock);175 device = arp_cache_find(&arp_globals.cache, device_id);176 if(! device){177 fibril_rwlock_write_unlock(&arp_globals.lock);178 return ENOENT;179 }180 proto = arp_protos_find(&device->protos, protocol);181 if(! proto){182 fibril_rwlock_write_unlock(&arp_globals.lock);183 return ENOENT;184 }185 arp_addr_exclude(&proto->addresses, address->value, address->length);186 fibril_rwlock_write_unlock(&arp_globals.lock);187 return EOK;188 }189 150 190 151 int arp_clean_cache_req(int arp_phone){ … … 211 172 } 212 173 213 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){ 214 ERROR_DECLARE; 215 216 measured_string_ref tmp; 217 218 // copy the given address for exclusive use 219 tmp = measured_string_copy(address); 220 if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){ 221 free(tmp->value); 222 free(tmp); 223 } 224 return ERROR_CODE; 225 } 226 227 int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){ 228 measured_string_ref tmp; 229 230 fibril_rwlock_read_lock(&arp_globals.lock); 231 tmp = arp_translate_message(device_id, protocol, address); 232 if(tmp){ 233 *translation = measured_string_copy(tmp); 234 fibril_rwlock_read_unlock(&arp_globals.lock); 235 if(*translation){ 236 *data = (** translation).value; 237 return EOK; 238 }else{ 239 return ENOMEM; 240 } 241 }else{ 242 fibril_rwlock_read_unlock(&arp_globals.lock); 174 int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){ 175 arp_device_ref device; 176 arp_proto_ref proto; 177 178 fibril_rwlock_write_lock(&arp_globals.lock); 179 device = arp_cache_find(&arp_globals.cache, device_id); 180 if(! device){ 181 fibril_rwlock_write_unlock(&arp_globals.lock); 243 182 return ENOENT; 244 183 } 245 } 246 247 int arp_initialize(async_client_conn_t client_connection){ 248 ERROR_DECLARE; 249 250 fibril_rwlock_initialize(&arp_globals.lock); 184 proto = arp_protos_find(&device->protos, protocol); 185 if(! proto){ 186 fibril_rwlock_write_unlock(&arp_globals.lock); 187 return ENOENT; 188 } 189 arp_addr_exclude(&proto->addresses, address->value, address->length); 190 fibril_rwlock_write_unlock(&arp_globals.lock); 191 return EOK; 192 } 193 194 void arp_clear_device(arp_device_ref device){ 195 int count; 196 arp_proto_ref proto; 197 198 for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){ 199 proto = arp_protos_get_index(&device->protos, count); 200 if(proto){ 201 if(proto->addr){ 202 free(proto->addr); 203 } 204 if(proto->addr_data){ 205 free(proto->addr_data); 206 } 207 arp_addr_destroy(&proto->addresses); 208 } 209 } 210 arp_protos_clear(&device->protos); 211 } 212 213 int arp_clear_device_req(int arp_phone, device_id_t device_id){ 214 arp_device_ref device; 215 251 216 fibril_rwlock_write_lock(&arp_globals.lock); 252 arp_globals.client_connection = client_connection; 253 ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache)); 217 device = arp_cache_find(&arp_globals.cache, device_id); 218 if(! device){ 219 fibril_rwlock_write_unlock(&arp_globals.lock); 220 return ENOENT; 221 } 222 arp_clear_device(device); 223 printf("Device %d cleared\n", device_id); 254 224 fibril_rwlock_write_unlock(&arp_globals.lock); 255 225 return EOK; 256 226 } 257 227 258 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){ 259 ERROR_DECLARE; 260 261 *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t)); 262 if(!(*proto)){ 263 return ENOMEM; 264 } 265 (** proto).service = service; 266 (** proto).addr = address; 267 (** proto).addr_data = address->value; 268 if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){ 269 free(*proto); 270 return ERROR_CODE; 228 int arp_connect_module(services_t service){ 229 if(service != SERVICE_ARP){ 230 return EINVAL; 271 231 } 272 232 return EOK; … … 383 343 } 384 344 385 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){ 386 arp_device_ref device; 387 arp_proto_ref proto; 388 measured_string_ref addr; 389 size_t length; 390 packet_t packet; 391 arp_header_ref header; 392 393 if(! target){ 394 return NULL; 395 } 396 device = arp_cache_find(&arp_globals.cache, device_id); 397 if(! device){ 398 return NULL; 399 } 400 proto = arp_protos_find(&device->protos, protocol); 401 if((! proto) || (proto->addr->length != target->length)){ 402 return NULL; 403 } 404 addr = arp_addr_find(&proto->addresses, target->value, target->length); 405 if(addr){ 406 return addr; 407 } 408 // ARP packet content size = header + (address + translation) * 2 409 length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2; 410 if(length > device->packet_dimension.content){ 411 return NULL; 412 } 413 packet = packet_get_4(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix); 414 if(! packet){ 415 return NULL; 416 } 417 header = (arp_header_ref) packet_suffix(packet, length); 418 if(! header){ 419 pq_release(arp_globals.net_phone, packet_get_id(packet)); 420 return NULL; 421 } 422 header->hardware = htons(device->hardware); 423 header->hardware_length = (uint8_t) device->addr->length; 424 header->protocol = htons(protocol_map(device->service, protocol)); 425 header->protocol_length = (uint8_t) proto->addr->length; 426 header->operation = htons(ARPOP_REQUEST); 427 length = sizeof(arp_header_t); 428 memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length); 429 length += device->addr->length; 430 memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length); 431 length += proto->addr->length; 432 bzero(((uint8_t *) header) + length, device->addr->length); 433 length += device->addr->length; 434 memcpy(((uint8_t *) header) + length, target->value, target->length); 435 if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){ 436 pq_release(arp_globals.net_phone, packet_get_id(packet)); 437 return NULL; 438 } 439 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 440 return NULL; 441 } 442 443 int arp_receive_message(device_id_t device_id, packet_t packet){ 345 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){ 444 346 ERROR_DECLARE; 445 347 446 size_t length; 447 arp_header_ref header; 448 arp_device_ref device; 449 arp_proto_ref proto; 450 measured_string_ref hw_source; 451 uint8_t * src_hw; 452 uint8_t * src_proto; 453 uint8_t * des_hw; 454 uint8_t * des_proto; 455 456 length = packet_get_data_length(packet); 457 if(length <= sizeof(arp_header_t)){ 458 return EINVAL; 459 } 460 device = arp_cache_find(&arp_globals.cache, device_id); 461 if(! device){ 462 return ENOENT; 463 } 464 header = (arp_header_ref) packet_get_data(packet); 465 if((ntohs(header->hardware) != device->hardware) 466 || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){ 467 return EINVAL; 468 } 469 proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol))); 470 if(! proto){ 471 return ENOENT; 472 } 473 src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 474 src_proto = src_hw + header->hardware_length; 475 des_hw = src_proto + header->protocol_length; 476 des_proto = des_hw + header->hardware_length; 477 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length)); 478 // exists? 479 if(hw_source){ 480 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){ 481 return EINVAL; 482 } 483 memcpy(hw_source->value, src_hw, hw_source->length); 484 } 485 // is my protocol address? 486 if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){ 487 return EINVAL; 488 } 489 if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){ 490 // not already upadted? 491 if(! hw_source){ 492 hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length)); 493 if(! hw_source){ 494 return ENOMEM; 495 } 496 ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source)); 497 } 498 if(ntohs(header->operation) == ARPOP_REQUEST){ 499 header->operation = htons(ARPOP_REPLY); 500 memcpy(des_proto, src_proto, header->protocol_length); 501 memcpy(src_proto, proto->addr->value, header->protocol_length); 502 memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len); 503 memcpy(des_hw, hw_source->value, header->hardware_length); 504 ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length)); 505 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 506 return 1; 507 } 508 } 509 return EOK; 510 } 511 512 void arp_clear_device(arp_device_ref device){ 513 int count; 514 arp_proto_ref proto; 515 516 for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){ 517 proto = arp_protos_get_index(&device->protos, count); 518 if(proto){ 519 if(proto->addr){ 520 free(proto->addr); 521 } 522 if(proto->addr_data){ 523 free(proto->addr_data); 524 } 525 arp_addr_destroy(&proto->addresses); 526 } 527 } 528 arp_protos_clear(&device->protos); 529 } 530 531 int arp_connect_module(services_t service){ 532 if(service != SERVICE_ARP){ 533 return EINVAL; 534 } 535 return EOK; 536 } 537 538 int arp_mtu_changed_message(device_id_t device_id, size_t mtu){ 539 arp_device_ref device; 540 348 measured_string_ref tmp; 349 350 // copy the given address for exclusive use 351 tmp = measured_string_copy(address); 352 if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){ 353 free(tmp->value); 354 free(tmp); 355 } 356 return ERROR_CODE; 357 } 358 359 int arp_initialize(async_client_conn_t client_connection){ 360 ERROR_DECLARE; 361 362 fibril_rwlock_initialize(&arp_globals.lock); 541 363 fibril_rwlock_write_lock(&arp_globals.lock); 542 device = arp_cache_find(&arp_globals.cache, device_id); 543 if(! device){ 544 fibril_rwlock_write_unlock(&arp_globals.lock); 545 return ENOENT; 546 } 547 device->packet_dimension.content = mtu; 548 printf("arp - device %d changed mtu to %d\n\n", device_id, mtu); 364 arp_globals.client_connection = client_connection; 365 ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache)); 549 366 fibril_rwlock_write_unlock(&arp_globals.lock); 550 367 return EOK; … … 618 435 } 619 436 437 int arp_mtu_changed_message(device_id_t device_id, size_t mtu){ 438 arp_device_ref device; 439 440 fibril_rwlock_write_lock(&arp_globals.lock); 441 device = arp_cache_find(&arp_globals.cache, device_id); 442 if(! device){ 443 fibril_rwlock_write_unlock(&arp_globals.lock); 444 return ENOENT; 445 } 446 device->packet_dimension.content = mtu; 447 printf("arp - device %d changed mtu to %d\n\n", device_id, mtu); 448 fibril_rwlock_write_unlock(&arp_globals.lock); 449 return EOK; 450 } 451 452 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){ 453 ERROR_DECLARE; 454 455 *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t)); 456 if(!(*proto)){ 457 return ENOMEM; 458 } 459 (** proto).service = service; 460 (** proto).addr = address; 461 (** proto).addr_data = address->value; 462 if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){ 463 free(*proto); 464 return ERROR_CODE; 465 } 466 return EOK; 467 } 468 469 int arp_receive_message(device_id_t device_id, packet_t packet){ 470 ERROR_DECLARE; 471 472 size_t length; 473 arp_header_ref header; 474 arp_device_ref device; 475 arp_proto_ref proto; 476 measured_string_ref hw_source; 477 uint8_t * src_hw; 478 uint8_t * src_proto; 479 uint8_t * des_hw; 480 uint8_t * des_proto; 481 482 length = packet_get_data_length(packet); 483 if(length <= sizeof(arp_header_t)){ 484 return EINVAL; 485 } 486 device = arp_cache_find(&arp_globals.cache, device_id); 487 if(! device){ 488 return ENOENT; 489 } 490 header = (arp_header_ref) packet_get_data(packet); 491 if((ntohs(header->hardware) != device->hardware) 492 || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){ 493 return EINVAL; 494 } 495 proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol))); 496 if(! proto){ 497 return ENOENT; 498 } 499 src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 500 src_proto = src_hw + header->hardware_length; 501 des_hw = src_proto + header->protocol_length; 502 des_proto = des_hw + header->hardware_length; 503 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length)); 504 // exists? 505 if(hw_source){ 506 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){ 507 return EINVAL; 508 } 509 memcpy(hw_source->value, src_hw, hw_source->length); 510 } 511 // is my protocol address? 512 if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){ 513 return EINVAL; 514 } 515 if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){ 516 // not already upadted? 517 if(! hw_source){ 518 hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length)); 519 if(! hw_source){ 520 return ENOMEM; 521 } 522 ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source)); 523 } 524 if(ntohs(header->operation) == ARPOP_REQUEST){ 525 header->operation = htons(ARPOP_REPLY); 526 memcpy(des_proto, src_proto, header->protocol_length); 527 memcpy(src_proto, proto->addr->value, header->protocol_length); 528 memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len); 529 memcpy(des_hw, hw_source->value, header->hardware_length); 530 ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length)); 531 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 532 return 1; 533 } 534 } 535 return EOK; 536 } 537 538 task_id_t arp_task_get_id(void){ 539 return task_get_id(); 540 } 541 542 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){ 543 arp_device_ref device; 544 arp_proto_ref proto; 545 measured_string_ref addr; 546 size_t length; 547 packet_t packet; 548 arp_header_ref header; 549 550 if(! target){ 551 return NULL; 552 } 553 device = arp_cache_find(&arp_globals.cache, device_id); 554 if(! device){ 555 return NULL; 556 } 557 proto = arp_protos_find(&device->protos, protocol); 558 if((! proto) || (proto->addr->length != target->length)){ 559 return NULL; 560 } 561 addr = arp_addr_find(&proto->addresses, target->value, target->length); 562 if(addr){ 563 return addr; 564 } 565 // ARP packet content size = header + (address + translation) * 2 566 length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2; 567 if(length > device->packet_dimension.content){ 568 return NULL; 569 } 570 packet = packet_get_4(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix); 571 if(! packet){ 572 return NULL; 573 } 574 header = (arp_header_ref) packet_suffix(packet, length); 575 if(! header){ 576 pq_release(arp_globals.net_phone, packet_get_id(packet)); 577 return NULL; 578 } 579 header->hardware = htons(device->hardware); 580 header->hardware_length = (uint8_t) device->addr->length; 581 header->protocol = htons(protocol_map(device->service, protocol)); 582 header->protocol_length = (uint8_t) proto->addr->length; 583 header->operation = htons(ARPOP_REQUEST); 584 length = sizeof(arp_header_t); 585 memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length); 586 length += device->addr->length; 587 memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length); 588 length += proto->addr->length; 589 bzero(((uint8_t *) header) + length, device->addr->length); 590 length += device->addr->length; 591 memcpy(((uint8_t *) header) + length, target->value, target->length); 592 if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){ 593 pq_release(arp_globals.net_phone, packet_get_id(packet)); 594 return NULL; 595 } 596 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 597 return NULL; 598 } 599 600 int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){ 601 measured_string_ref tmp; 602 603 fibril_rwlock_read_lock(&arp_globals.lock); 604 tmp = arp_translate_message(device_id, protocol, address); 605 if(tmp){ 606 *translation = measured_string_copy(tmp); 607 fibril_rwlock_read_unlock(&arp_globals.lock); 608 if(*translation){ 609 *data = (** translation).value; 610 return EOK; 611 }else{ 612 return ENOMEM; 613 } 614 }else{ 615 fibril_rwlock_read_unlock(&arp_globals.lock); 616 return ENOENT; 617 } 618 } 619 620 620 /** @} 621 621 */
Note:
See TracChangeset
for help on using the changeset viewer.