Changeset 797b704 in mainline for uspace/srv/net/il/arp/arp.c
- Timestamp:
- 2011-01-12T14:40:09Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update
- Children:
- 014dd57b
- Parents:
- 73ac2e9
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
r73ac2e9 r797b704 35 35 * @see arp.h 36 36 */ 37 38 #include "arp.h"39 #include "arp_header.h"40 #include "arp_oc.h"41 #include "arp_module.h"42 37 43 38 #include <async.h> … … 64 59 #include <packet_client.h> 65 60 #include <packet_remote.h> 66 #include <il_ interface.h>67 #include <il_ local.h>68 61 #include <il_remote.h> 62 #include <il_skel.h> 63 #include "arp.h" 69 64 70 65 /** ARP module name. */ … … 73 68 /** Number of microseconds to wait for an ARP reply. */ 74 69 #define ARP_TRANS_WAIT 1000000 70 71 /** @name ARP operation codes definitions */ 72 /*@{*/ 73 74 /** REQUEST operation code. */ 75 #define ARPOP_REQUEST 1 76 77 /** REPLY operation code. */ 78 #define ARPOP_REPLY 2 79 80 /*@}*/ 81 82 /** Type definition of an ARP protocol header. 83 * @see arp_header 84 */ 85 typedef struct arp_header arp_header_t; 86 87 /** ARP protocol header. */ 88 struct arp_header { 89 /** 90 * Hardware type identifier. 91 * @see hardware.h 92 */ 93 uint16_t hardware; 94 95 /** Protocol identifier. */ 96 uint16_t protocol; 97 /** Hardware address length in bytes. */ 98 uint8_t hardware_length; 99 /** Protocol address length in bytes. */ 100 uint8_t protocol_length; 101 102 /** 103 * ARP packet type. 104 * @see arp_oc.h 105 */ 106 uint16_t operation; 107 } __attribute__ ((packed)); 75 108 76 109 /** ARP global data. */ … … 231 264 232 265 return EOK; 266 } 267 268 /** Process the received ARP packet. 269 * 270 * Update the source hardware address if the source entry exists or the packet 271 * is targeted to my protocol address. 272 * 273 * Respond to the ARP request if the packet is the ARP request and is 274 * targeted to my address. 275 * 276 * @param[in] device_id Source device identifier. 277 * @param[in,out] packet Received packet. 278 * 279 * @return EOK on success and the packet is no longer needed. 280 * @return One on success and the packet has been reused. 281 * @return EINVAL if the packet is too small to carry an ARP 282 * packet. 283 * @return EINVAL if the received address lengths differs from 284 * the registered values. 285 * @return ENOENT if the device is not found in the cache. 286 * @return ENOENT if the protocol for the device is not found in 287 * the cache. 288 * @return ENOMEM if there is not enough memory left. 289 * 290 */ 291 static int arp_receive_message(device_id_t device_id, packet_t *packet) 292 { 293 int rc; 294 295 size_t length = packet_get_data_length(packet); 296 if (length <= sizeof(arp_header_t)) 297 return EINVAL; 298 299 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 300 if (!device) 301 return ENOENT; 302 303 arp_header_t *header = (arp_header_t *) packet_get_data(packet); 304 if ((ntohs(header->hardware) != device->hardware) || 305 (length < sizeof(arp_header_t) + header->hardware_length * 2U + 306 header->protocol_length * 2U)) { 307 return EINVAL; 308 } 309 310 arp_proto_t *proto = arp_protos_find(&device->protos, 311 protocol_unmap(device->service, ntohs(header->protocol))); 312 if (!proto) 313 return ENOENT; 314 315 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 316 uint8_t *src_proto = src_hw + header->hardware_length; 317 uint8_t *des_hw = src_proto + header->protocol_length; 318 uint8_t *des_proto = des_hw + header->hardware_length; 319 320 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto, 321 header->protocol_length); 322 323 if ((trans) && (trans->hw_addr)) { 324 /* Translation exists */ 325 if (trans->hw_addr->length != header->hardware_length) 326 return EINVAL; 327 328 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 329 } 330 331 /* Is my protocol address? */ 332 if (proto->addr->length != header->protocol_length) 333 return EINVAL; 334 335 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 336 if (!trans) { 337 /* Update the translation */ 338 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 339 if (!trans) 340 return ENOMEM; 341 342 trans->hw_addr = NULL; 343 fibril_condvar_initialize(&trans->cv); 344 rc = arp_addr_add(&proto->addresses, src_proto, 345 header->protocol_length, trans); 346 if (rc != EOK) { 347 /* The generic char map has already freed trans! */ 348 return rc; 349 } 350 } 351 352 if (!trans->hw_addr) { 353 trans->hw_addr = measured_string_create_bulk(src_hw, 354 header->hardware_length); 355 if (!trans->hw_addr) 356 return ENOMEM; 357 358 /* Notify the fibrils that wait for the translation. */ 359 fibril_condvar_broadcast(&trans->cv); 360 } 361 362 if (ntohs(header->operation) == ARPOP_REQUEST) { 363 header->operation = htons(ARPOP_REPLY); 364 memcpy(des_proto, src_proto, header->protocol_length); 365 memcpy(src_proto, proto->addr->value, 366 header->protocol_length); 367 memcpy(src_hw, device->addr->value, 368 device->packet_dimension.addr_len); 369 memcpy(des_hw, trans->hw_addr->value, 370 header->hardware_length); 371 372 rc = packet_set_addr(packet, src_hw, des_hw, 373 header->hardware_length); 374 if (rc != EOK) 375 return rc; 376 377 nil_send_msg(device->phone, device_id, packet, 378 SERVICE_ARP); 379 return 1; 380 } 381 } 382 383 return EOK; 384 } 385 386 /** Update the device content length according to the new MTU value. 387 * 388 * @param[in] device_id Device identifier. 389 * @param[in] mtu New MTU value. 390 * 391 * @return ENOENT if device is not found. 392 * @return EOK on success. 393 * 394 */ 395 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 396 { 397 fibril_mutex_lock(&arp_globals.lock); 398 399 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 400 if (!device) { 401 fibril_mutex_unlock(&arp_globals.lock); 402 return ENOENT; 403 } 404 405 device->packet_dimension.content = mtu; 406 407 fibril_mutex_unlock(&arp_globals.lock); 408 409 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 410 411 return EOK; 412 } 413 414 /** Process IPC messages from the registered device driver modules 415 * 416 * @param[in] iid Message identifier. 417 * @param[in,out] icall Message parameters. 418 * 419 */ 420 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall) 421 { 422 packet_t *packet; 423 int rc; 424 425 while (true) { 426 switch (IPC_GET_IMETHOD(*icall)) { 427 case NET_IL_DEVICE_STATE: 428 /* Do nothing - keep the cache */ 429 ipc_answer_0(iid, (sysarg_t) EOK); 430 break; 431 432 case NET_IL_RECEIVED: 433 rc = packet_translate_remote(arp_globals.net_phone, &packet, 434 IPC_GET_PACKET(*icall)); 435 if (rc == EOK) { 436 fibril_mutex_lock(&arp_globals.lock); 437 do { 438 packet_t *next = pq_detach(packet); 439 rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet); 440 if (rc != 1) { 441 pq_release_remote(arp_globals.net_phone, 442 packet_get_id(packet)); 443 } 444 445 packet = next; 446 } while (packet); 447 fibril_mutex_unlock(&arp_globals.lock); 448 } 449 ipc_answer_0(iid, (sysarg_t) rc); 450 break; 451 452 case NET_IL_MTU_CHANGED: 453 rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall), 454 IPC_GET_MTU(*icall)); 455 ipc_answer_0(iid, (sysarg_t) rc); 456 break; 457 458 default: 459 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 460 } 461 462 iid = async_get_call(icall); 463 } 233 464 } 234 465 … … 335 566 device->phone = nil_bind_service(device->service, 336 567 (sysarg_t) device->device_id, SERVICE_ARP, 337 arp_ globals.client_connection);568 arp_receiver); 338 569 if (device->phone < 0) { 339 570 fibril_mutex_unlock(&arp_globals.lock); … … 396 627 } 397 628 398 /** Initialize the ARP module. 399 * 400 * @param[in] client_connection The client connection processing function. 401 * The module skeleton propagates its own one. 402 * 403 * @return EOK on success. 404 * @return ENOMEM if there is not enough memory left. 405 * 406 */ 407 int arp_initialize(async_client_conn_t client_connection) 629 int il_initialize(int net_phone) 408 630 { 409 631 fibril_mutex_initialize(&arp_globals.lock); 410 632 411 633 fibril_mutex_lock(&arp_globals.lock); 412 arp_globals. client_connection = client_connection;634 arp_globals.net_phone = net_phone; 413 635 int rc = arp_cache_initialize(&arp_globals.cache); 414 636 fibril_mutex_unlock(&arp_globals.lock); 415 637 416 638 return rc; 417 }418 419 /** Update the device content length according to the new MTU value.420 *421 * @param[in] device_id Device identifier.422 * @param[in] mtu New MTU value.423 *424 * @return ENOENT if device is not found.425 * @return EOK on success.426 *427 */428 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)429 {430 fibril_mutex_lock(&arp_globals.lock);431 432 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);433 if (!device) {434 fibril_mutex_unlock(&arp_globals.lock);435 return ENOENT;436 }437 438 device->packet_dimension.content = mtu;439 440 fibril_mutex_unlock(&arp_globals.lock);441 442 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);443 444 return EOK;445 }446 447 /** Process the received ARP packet.448 *449 * Update the source hardware address if the source entry exists or the packet450 * is targeted to my protocol address.451 *452 * Respond to the ARP request if the packet is the ARP request and is453 * targeted to my address.454 *455 * @param[in] device_id Source device identifier.456 * @param[in,out] packet Received packet.457 *458 * @return EOK on success and the packet is no longer needed.459 * @return One on success and the packet has been reused.460 * @return EINVAL if the packet is too small to carry an ARP461 * packet.462 * @return EINVAL if the received address lengths differs from463 * the registered values.464 * @return ENOENT if the device is not found in the cache.465 * @return ENOENT if the protocol for the device is not found in466 * the cache.467 * @return ENOMEM if there is not enough memory left.468 *469 */470 static int arp_receive_message(device_id_t device_id, packet_t *packet)471 {472 int rc;473 474 size_t length = packet_get_data_length(packet);475 if (length <= sizeof(arp_header_t))476 return EINVAL;477 478 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);479 if (!device)480 return ENOENT;481 482 arp_header_t *header = (arp_header_t *) packet_get_data(packet);483 if ((ntohs(header->hardware) != device->hardware) ||484 (length < sizeof(arp_header_t) + header->hardware_length * 2U +485 header->protocol_length * 2U)) {486 return EINVAL;487 }488 489 arp_proto_t *proto = arp_protos_find(&device->protos,490 protocol_unmap(device->service, ntohs(header->protocol)));491 if (!proto)492 return ENOENT;493 494 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);495 uint8_t *src_proto = src_hw + header->hardware_length;496 uint8_t *des_hw = src_proto + header->protocol_length;497 uint8_t *des_proto = des_hw + header->hardware_length;498 499 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,500 header->protocol_length);501 502 if ((trans) && (trans->hw_addr)) {503 /* Translation exists */504 if (trans->hw_addr->length != header->hardware_length)505 return EINVAL;506 507 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);508 }509 510 /* Is my protocol address? */511 if (proto->addr->length != header->protocol_length)512 return EINVAL;513 514 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {515 if (!trans) {516 /* Update the translation */517 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));518 if (!trans)519 return ENOMEM;520 521 trans->hw_addr = NULL;522 fibril_condvar_initialize(&trans->cv);523 rc = arp_addr_add(&proto->addresses, src_proto,524 header->protocol_length, trans);525 if (rc != EOK) {526 /* The generic char map has already freed trans! */527 return rc;528 }529 }530 531 if (!trans->hw_addr) {532 trans->hw_addr = measured_string_create_bulk(src_hw,533 header->hardware_length);534 if (!trans->hw_addr)535 return ENOMEM;536 537 /* Notify the fibrils that wait for the translation. */538 fibril_condvar_broadcast(&trans->cv);539 }540 541 if (ntohs(header->operation) == ARPOP_REQUEST) {542 header->operation = htons(ARPOP_REPLY);543 memcpy(des_proto, src_proto, header->protocol_length);544 memcpy(src_proto, proto->addr->value,545 header->protocol_length);546 memcpy(src_hw, device->addr->value,547 device->packet_dimension.addr_len);548 memcpy(des_hw, trans->hw_addr->value,549 header->hardware_length);550 551 rc = packet_set_addr(packet, src_hw, des_hw,552 header->hardware_length);553 if (rc != EOK)554 return rc;555 556 nil_send_msg(device->phone, device_id, packet,557 SERVICE_ARP);558 return 1;559 }560 }561 562 return EOK;563 639 } 564 640 … … 714 790 * 715 791 */ 716 int arp_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,792 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 717 793 size_t *count) 718 794 { … … 720 796 measured_string_t *translation; 721 797 uint8_t *data; 722 packet_t *packet;723 packet_t *next;724 798 int rc; 725 799 … … 784 858 case NET_ARP_CLEAN_CACHE: 785 859 return arp_clean_cache_req(0); 786 787 case NET_IL_DEVICE_STATE:788 /* Do nothing - keep the cache */789 return EOK;790 791 case NET_IL_RECEIVED:792 793 rc = packet_translate_remote(arp_globals.net_phone, &packet,794 IPC_GET_PACKET(*call));795 if (rc != EOK)796 return rc;797 798 fibril_mutex_lock(&arp_globals.lock);799 do {800 next = pq_detach(packet);801 rc = arp_receive_message(IPC_GET_DEVICE(*call), packet);802 if (rc != 1) {803 pq_release_remote(arp_globals.net_phone,804 packet_get_id(packet));805 }806 packet = next;807 } while (packet);808 fibril_mutex_unlock(&arp_globals.lock);809 810 return EOK;811 812 case NET_IL_MTU_CHANGED:813 return arp_mtu_changed_message(IPC_GET_DEVICE(*call),814 IPC_GET_MTU(*call));815 860 } 816 861 … … 818 863 } 819 864 820 /** Default thread for new connections.821 *822 * @param[in] iid Initial message identifier.823 * @param[in] icall Initial message call structure.824 */825 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)826 {827 /*828 * Accept the connection829 * - Answer the first IPC_M_CONNECT_ME_TO call.830 */831 ipc_answer_0(iid, EOK);832 833 while (true) {834 ipc_call_t answer;835 size_t count;836 837 /* Clear the answer structure */838 refresh_answer(&answer, &count);839 840 /* Fetch the next message */841 ipc_call_t call;842 ipc_callid_t callid = async_get_call(&call);843 844 /* Process the message */845 int res = il_module_message(callid, &call, &answer,846 &count);847 848 /*849 * End if told to either by the message or the processing850 * result.851 */852 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||853 (res == EHANGUP))854 return;855 856 /* Answer the message */857 answer_call(callid, res, &answer, count);858 }859 }860 861 865 int main(int argc, char *argv[]) 862 866 { 863 867 /* Start the module */ 864 return il_module_start( il_client_connection);868 return il_module_start(SERVICE_ARP); 865 869 } 866 870
Note:
See TracChangeset
for help on using the changeset viewer.