00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <async.h>
00039 #include <malloc.h>
00040 #include <mem.h>
00041 #include <fibril_synch.h>
00042 #include <assert.h>
00043 #include <stdio.h>
00044 #include <str.h>
00045 #include <task.h>
00046 #include <adt/measured_strings.h>
00047 #include <ipc/services.h>
00048 #include <ipc/net.h>
00049 #include <ipc/arp.h>
00050 #include <ipc/il.h>
00051 #include <ipc/nil.h>
00052 #include <byteorder.h>
00053 #include <errno.h>
00054 #include <net/modules.h>
00055 #include <net/device.h>
00056 #include <net/packet.h>
00057 #include <nil_remote.h>
00058 #include <protocol_map.h>
00059 #include <packet_client.h>
00060 #include <packet_remote.h>
00061 #include <il_remote.h>
00062 #include <il_skel.h>
00063 #include "arp.h"
00064
00066 #define NAME "arp"
00067
00069 #define ARP_TRANS_WAIT 1000000
00070
00073
00075 #define ARPOP_REQUEST 1
00076
00078 #define ARPOP_REPLY 2
00079
00085 typedef struct arp_header arp_header_t;
00086
00088 struct arp_header {
00093 uint16_t hardware;
00094
00096 uint16_t protocol;
00098 uint8_t hardware_length;
00100 uint8_t protocol_length;
00101
00106 uint16_t operation;
00107 } __attribute__ ((packed));
00108
00110 arp_globals_t arp_globals;
00111
00112 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
00113 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
00114 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
00115
00116 static void arp_clear_trans(arp_trans_t *trans)
00117 {
00118 if (trans->hw_addr) {
00119 free(trans->hw_addr);
00120 trans->hw_addr = NULL;
00121 }
00122
00123 fibril_condvar_broadcast(&trans->cv);
00124 }
00125
00126 static void arp_clear_addr(arp_addr_t *addresses)
00127 {
00128 int count;
00129
00130 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
00131 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
00132 count);
00133 if (trans)
00134 arp_clear_trans(trans);
00135 }
00136 }
00137
00142 static void arp_clear_device(arp_device_t *device)
00143 {
00144 int count;
00145
00146 for (count = arp_protos_count(&device->protos) - 1; count >= 0;
00147 count--) {
00148 arp_proto_t *proto = arp_protos_get_index(&device->protos,
00149 count);
00150
00151 if (proto) {
00152 if (proto->addr)
00153 free(proto->addr);
00154
00155 if (proto->addr_data)
00156 free(proto->addr_data);
00157
00158 arp_clear_addr(&proto->addresses);
00159 arp_addr_destroy(&proto->addresses, free);
00160 }
00161 }
00162
00163 arp_protos_clear(&device->protos, free);
00164 }
00165
00166 static int arp_clean_cache_req(int arp_phone)
00167 {
00168 int count;
00169
00170 fibril_mutex_lock(&arp_globals.lock);
00171 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
00172 count--) {
00173 arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
00174 count);
00175
00176 if (device) {
00177 arp_clear_device(device);
00178 if (device->addr_data)
00179 free(device->addr_data);
00180
00181 if (device->broadcast_data)
00182 free(device->broadcast_data);
00183 }
00184 }
00185
00186 arp_cache_clear(&arp_globals.cache, free);
00187 fibril_mutex_unlock(&arp_globals.lock);
00188
00189 return EOK;
00190 }
00191
00192 static int arp_clear_address_req(int arp_phone, device_id_t device_id,
00193 services_t protocol, measured_string_t *address)
00194 {
00195 fibril_mutex_lock(&arp_globals.lock);
00196
00197 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00198 if (!device) {
00199 fibril_mutex_unlock(&arp_globals.lock);
00200 return ENOENT;
00201 }
00202
00203 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
00204 if (!proto) {
00205 fibril_mutex_unlock(&arp_globals.lock);
00206 return ENOENT;
00207 }
00208
00209 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
00210 address->length);
00211 if (trans)
00212 arp_clear_trans(trans);
00213
00214 arp_addr_exclude(&proto->addresses, address->value, address->length, free);
00215
00216 fibril_mutex_unlock(&arp_globals.lock);
00217 return EOK;
00218 }
00219
00220 static int arp_clear_device_req(int arp_phone, device_id_t device_id)
00221 {
00222 fibril_mutex_lock(&arp_globals.lock);
00223
00224 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00225 if (!device) {
00226 fibril_mutex_unlock(&arp_globals.lock);
00227 return ENOENT;
00228 }
00229
00230 arp_clear_device(device);
00231
00232 fibril_mutex_unlock(&arp_globals.lock);
00233 return EOK;
00234 }
00235
00248 static int arp_proto_create(arp_proto_t **proto, services_t service,
00249 measured_string_t *address)
00250 {
00251 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
00252 if (!*proto)
00253 return ENOMEM;
00254
00255 (*proto)->service = service;
00256 (*proto)->addr = address;
00257 (*proto)->addr_data = address->value;
00258
00259 int rc = arp_addr_initialize(&(*proto)->addresses);
00260 if (rc != EOK) {
00261 free(*proto);
00262 return rc;
00263 }
00264
00265 return EOK;
00266 }
00267
00291 static int arp_receive_message(device_id_t device_id, packet_t *packet)
00292 {
00293 int rc;
00294
00295 size_t length = packet_get_data_length(packet);
00296 if (length <= sizeof(arp_header_t))
00297 return EINVAL;
00298
00299 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00300 if (!device)
00301 return ENOENT;
00302
00303 arp_header_t *header = (arp_header_t *) packet_get_data(packet);
00304 if ((ntohs(header->hardware) != device->hardware) ||
00305 (length < sizeof(arp_header_t) + header->hardware_length * 2U +
00306 header->protocol_length * 2U)) {
00307 return EINVAL;
00308 }
00309
00310 arp_proto_t *proto = arp_protos_find(&device->protos,
00311 protocol_unmap(device->service, ntohs(header->protocol)));
00312 if (!proto)
00313 return ENOENT;
00314
00315 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
00316 uint8_t *src_proto = src_hw + header->hardware_length;
00317 uint8_t *des_hw = src_proto + header->protocol_length;
00318 uint8_t *des_proto = des_hw + header->hardware_length;
00319
00320 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
00321 header->protocol_length);
00322
00323 if ((trans) && (trans->hw_addr)) {
00324
00325 if (trans->hw_addr->length != header->hardware_length)
00326 return EINVAL;
00327
00328 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
00329 }
00330
00331
00332 if (proto->addr->length != header->protocol_length)
00333 return EINVAL;
00334
00335 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
00336 if (!trans) {
00337
00338 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
00339 if (!trans)
00340 return ENOMEM;
00341
00342 trans->hw_addr = NULL;
00343 fibril_condvar_initialize(&trans->cv);
00344 rc = arp_addr_add(&proto->addresses, src_proto,
00345 header->protocol_length, trans);
00346 if (rc != EOK) {
00347 free(trans);
00348 return rc;
00349 }
00350 }
00351
00352 if (!trans->hw_addr) {
00353 trans->hw_addr = measured_string_create_bulk(src_hw,
00354 header->hardware_length);
00355 if (!trans->hw_addr)
00356 return ENOMEM;
00357
00358
00359 fibril_condvar_broadcast(&trans->cv);
00360 }
00361
00362 if (ntohs(header->operation) == ARPOP_REQUEST) {
00363 header->operation = htons(ARPOP_REPLY);
00364 memcpy(des_proto, src_proto, header->protocol_length);
00365 memcpy(src_proto, proto->addr->value,
00366 header->protocol_length);
00367 memcpy(src_hw, device->addr->value,
00368 device->packet_dimension.addr_len);
00369 memcpy(des_hw, trans->hw_addr->value,
00370 header->hardware_length);
00371
00372 rc = packet_set_addr(packet, src_hw, des_hw,
00373 header->hardware_length);
00374 if (rc != EOK)
00375 return rc;
00376
00377 nil_send_msg(device->phone, device_id, packet,
00378 SERVICE_ARP);
00379 return 1;
00380 }
00381 }
00382
00383 return EOK;
00384 }
00385
00395 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
00396 {
00397 fibril_mutex_lock(&arp_globals.lock);
00398
00399 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00400 if (!device) {
00401 fibril_mutex_unlock(&arp_globals.lock);
00402 return ENOENT;
00403 }
00404
00405 device->packet_dimension.content = mtu;
00406
00407 fibril_mutex_unlock(&arp_globals.lock);
00408
00409 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
00410
00411 return EOK;
00412 }
00413
00420 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
00421 {
00422 packet_t *packet;
00423 int rc;
00424
00425 while (true) {
00426 switch (IPC_GET_IMETHOD(*icall)) {
00427 case NET_IL_DEVICE_STATE:
00428
00429 async_answer_0(iid, (sysarg_t) EOK);
00430 break;
00431
00432 case NET_IL_RECEIVED:
00433 rc = packet_translate_remote(arp_globals.net_phone, &packet,
00434 IPC_GET_PACKET(*icall));
00435 if (rc == EOK) {
00436 fibril_mutex_lock(&arp_globals.lock);
00437 do {
00438 packet_t *next = pq_detach(packet);
00439 rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
00440 if (rc != 1) {
00441 pq_release_remote(arp_globals.net_phone,
00442 packet_get_id(packet));
00443 }
00444
00445 packet = next;
00446 } while (packet);
00447 fibril_mutex_unlock(&arp_globals.lock);
00448 }
00449 async_answer_0(iid, (sysarg_t) rc);
00450 break;
00451
00452 case NET_IL_MTU_CHANGED:
00453 rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
00454 IPC_GET_MTU(*icall));
00455 async_answer_0(iid, (sysarg_t) rc);
00456 break;
00457
00458 default:
00459 async_answer_0(iid, (sysarg_t) ENOTSUP);
00460 }
00461
00462 iid = async_get_call(icall);
00463 }
00464 }
00465
00484 static int arp_device_message(device_id_t device_id, services_t service,
00485 services_t protocol, measured_string_t *address)
00486 {
00487 int index;
00488 int rc;
00489
00490 fibril_mutex_lock(&arp_globals.lock);
00491
00492
00493 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00494 if (device) {
00495 if (device->service != service) {
00496 printf("%s: Device %d already exists\n", NAME,
00497 device->device_id);
00498 fibril_mutex_unlock(&arp_globals.lock);
00499 return EEXIST;
00500 }
00501
00502 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
00503 if (proto) {
00504 free(proto->addr);
00505 free(proto->addr_data);
00506 proto->addr = address;
00507 proto->addr_data = address->value;
00508 } else {
00509 rc = arp_proto_create(&proto, protocol, address);
00510 if (rc != EOK) {
00511 fibril_mutex_unlock(&arp_globals.lock);
00512 return rc;
00513 }
00514
00515 index = arp_protos_add(&device->protos, proto->service,
00516 proto);
00517 if (index < 0) {
00518 fibril_mutex_unlock(&arp_globals.lock);
00519 free(proto);
00520 return index;
00521 }
00522
00523 printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
00524 device_id, protocol);
00525 }
00526 } else {
00527 hw_type_t hardware = hardware_map(service);
00528 if (!hardware)
00529 return ENOENT;
00530
00531
00532 device = (arp_device_t *) malloc(sizeof(arp_device_t));
00533 if (!device) {
00534 fibril_mutex_unlock(&arp_globals.lock);
00535 return ENOMEM;
00536 }
00537
00538 device->hardware = hardware;
00539 device->device_id = device_id;
00540 rc = arp_protos_initialize(&device->protos);
00541 if (rc != EOK) {
00542 fibril_mutex_unlock(&arp_globals.lock);
00543 free(device);
00544 return rc;
00545 }
00546
00547 arp_proto_t *proto;
00548 rc = arp_proto_create(&proto, protocol, address);
00549 if (rc != EOK) {
00550 fibril_mutex_unlock(&arp_globals.lock);
00551 free(device);
00552 return rc;
00553 }
00554
00555 index = arp_protos_add(&device->protos, proto->service, proto);
00556 if (index < 0) {
00557 fibril_mutex_unlock(&arp_globals.lock);
00558 arp_protos_destroy(&device->protos, free);
00559 free(device);
00560 return index;
00561 }
00562
00563 device->service = service;
00564
00565
00566 device->phone = nil_bind_service(device->service,
00567 (sysarg_t) device->device_id, SERVICE_ARP,
00568 arp_receiver);
00569 if (device->phone < 0) {
00570 fibril_mutex_unlock(&arp_globals.lock);
00571 arp_protos_destroy(&device->protos, free);
00572 free(device);
00573 return EREFUSED;
00574 }
00575
00576
00577 rc = nil_packet_size_req(device->phone, device_id,
00578 &device->packet_dimension);
00579 if (rc != EOK) {
00580 fibril_mutex_unlock(&arp_globals.lock);
00581 arp_protos_destroy(&device->protos, free);
00582 free(device);
00583 return rc;
00584 }
00585
00586
00587 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
00588 &device->addr_data);
00589 if (rc != EOK) {
00590 fibril_mutex_unlock(&arp_globals.lock);
00591 arp_protos_destroy(&device->protos, free);
00592 free(device);
00593 return rc;
00594 }
00595
00596
00597 rc = nil_get_broadcast_addr_req(device->phone, device_id,
00598 &device->broadcast_addr, &device->broadcast_data);
00599 if (rc != EOK) {
00600 fibril_mutex_unlock(&arp_globals.lock);
00601 free(device->addr);
00602 free(device->addr_data);
00603 arp_protos_destroy(&device->protos, free);
00604 free(device);
00605 return rc;
00606 }
00607
00608 rc = arp_cache_add(&arp_globals.cache, device->device_id,
00609 device);
00610 if (rc != EOK) {
00611 fibril_mutex_unlock(&arp_globals.lock);
00612 free(device->addr);
00613 free(device->addr_data);
00614 free(device->broadcast_addr);
00615 free(device->broadcast_data);
00616 arp_protos_destroy(&device->protos, free);
00617 free(device);
00618 return rc;
00619 }
00620 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
00621 " proto: %d)\n", NAME, device->device_id, device->hardware,
00622 device->service, protocol);
00623 }
00624
00625 fibril_mutex_unlock(&arp_globals.lock);
00626 return EOK;
00627 }
00628
00629 int il_initialize(int net_phone)
00630 {
00631 fibril_mutex_initialize(&arp_globals.lock);
00632
00633 fibril_mutex_lock(&arp_globals.lock);
00634 arp_globals.net_phone = net_phone;
00635 int rc = arp_cache_initialize(&arp_globals.cache);
00636 fibril_mutex_unlock(&arp_globals.lock);
00637
00638 return rc;
00639 }
00640
00641 static int arp_send_request(device_id_t device_id, services_t protocol,
00642 measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
00643 {
00644
00645 size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
00646 if (length > device->packet_dimension.content)
00647 return ELIMIT;
00648
00649 packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
00650 device->packet_dimension.addr_len, device->packet_dimension.prefix,
00651 length, device->packet_dimension.suffix);
00652 if (!packet)
00653 return ENOMEM;
00654
00655 arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
00656 if (!header) {
00657 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
00658 return ENOMEM;
00659 }
00660
00661 header->hardware = htons(device->hardware);
00662 header->hardware_length = (uint8_t) device->addr->length;
00663 header->protocol = htons(protocol_map(device->service, protocol));
00664 header->protocol_length = (uint8_t) proto->addr->length;
00665 header->operation = htons(ARPOP_REQUEST);
00666
00667 length = sizeof(arp_header_t);
00668
00669 memcpy(((uint8_t *) header) + length, device->addr->value,
00670 device->addr->length);
00671 length += device->addr->length;
00672 memcpy(((uint8_t *) header) + length, proto->addr->value,
00673 proto->addr->length);
00674 length += proto->addr->length;
00675 bzero(((uint8_t *) header) + length, device->addr->length);
00676 length += device->addr->length;
00677 memcpy(((uint8_t *) header) + length, target->value, target->length);
00678
00679 int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
00680 (uint8_t *) device->broadcast_addr->value, device->addr->length);
00681 if (rc != EOK) {
00682 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
00683 return rc;
00684 }
00685
00686 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
00687 return EOK;
00688 }
00689
00705 static int arp_translate_message(device_id_t device_id, services_t protocol,
00706 measured_string_t *target, measured_string_t **translation)
00707 {
00708 bool retry = false;
00709 int rc;
00710
00711 assert(fibril_mutex_is_locked(&arp_globals.lock));
00712
00713 restart:
00714 if ((!target) || (!translation))
00715 return EBADMEM;
00716
00717 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
00718 if (!device)
00719 return ENOENT;
00720
00721 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
00722 if ((!proto) || (proto->addr->length != target->length))
00723 return ENOENT;
00724
00725 arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
00726 target->length);
00727 if (trans) {
00728 if (trans->hw_addr) {
00729
00730 *translation = trans->hw_addr;
00731 return EOK;
00732 }
00733
00734 if (retry) {
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 arp_clear_trans(trans);
00747 arp_addr_exclude(&proto->addresses, target->value,
00748 target->length, free);
00749 return EAGAIN;
00750 }
00751
00752
00753
00754
00755
00756 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
00757 ARP_TRANS_WAIT);
00758 if (rc == ETIMEOUT)
00759 return ENOENT;
00760
00761
00762
00763
00764
00765 retry = true;
00766 goto restart;
00767 }
00768
00769 if (retry)
00770 return EAGAIN;
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 rc = arp_send_request(device_id, protocol, target, device, proto);
00783 if (rc != EOK)
00784 return rc;
00785
00786 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
00787 if (!trans)
00788 return ENOMEM;
00789
00790 trans->hw_addr = NULL;
00791 fibril_condvar_initialize(&trans->cv);
00792
00793 rc = arp_addr_add(&proto->addresses, target->value, target->length,
00794 trans);
00795 if (rc != EOK) {
00796 free(trans);
00797 return rc;
00798 }
00799
00800 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
00801 ARP_TRANS_WAIT);
00802 if (rc == ETIMEOUT) {
00803
00804
00805
00806
00807 arp_clear_trans(trans);
00808 arp_addr_exclude(&proto->addresses, target->value,
00809 target->length, free);
00810 return ENOENT;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820 retry = true;
00821 goto restart;
00822 }
00823
00838 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
00839 size_t *count)
00840 {
00841 measured_string_t *address;
00842 measured_string_t *translation;
00843 uint8_t *data;
00844 int rc;
00845
00846 *count = 0;
00847 switch (IPC_GET_IMETHOD(*call)) {
00848 case IPC_M_PHONE_HUNGUP:
00849 return EOK;
00850
00851 case NET_ARP_DEVICE:
00852 rc = measured_strings_receive(&address, &data, 1);
00853 if (rc != EOK)
00854 return rc;
00855
00856 rc = arp_device_message(IPC_GET_DEVICE(*call),
00857 IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
00858 if (rc != EOK) {
00859 free(address);
00860 free(data);
00861 }
00862
00863 return rc;
00864
00865 case NET_ARP_TRANSLATE:
00866 rc = measured_strings_receive(&address, &data, 1);
00867 if (rc != EOK)
00868 return rc;
00869
00870 fibril_mutex_lock(&arp_globals.lock);
00871 rc = arp_translate_message(IPC_GET_DEVICE(*call),
00872 IPC_GET_SERVICE(*call), address, &translation);
00873 free(address);
00874 free(data);
00875
00876 if (rc != EOK) {
00877 fibril_mutex_unlock(&arp_globals.lock);
00878 return rc;
00879 }
00880
00881 if (!translation) {
00882 fibril_mutex_unlock(&arp_globals.lock);
00883 return ENOENT;
00884 }
00885
00886 rc = measured_strings_reply(translation, 1);
00887 fibril_mutex_unlock(&arp_globals.lock);
00888 return rc;
00889
00890 case NET_ARP_CLEAR_DEVICE:
00891 return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
00892
00893 case NET_ARP_CLEAR_ADDRESS:
00894 rc = measured_strings_receive(&address, &data, 1);
00895 if (rc != EOK)
00896 return rc;
00897
00898 arp_clear_address_req(0, IPC_GET_DEVICE(*call),
00899 IPC_GET_SERVICE(*call), address);
00900 free(address);
00901 free(data);
00902 return EOK;
00903
00904 case NET_ARP_CLEAN_CACHE:
00905 return arp_clean_cache_req(0);
00906 }
00907
00908 return ENOTSUP;
00909 }
00910
00911 int main(int argc, char *argv[])
00912 {
00913
00914 return il_module_start(SERVICE_ARP);
00915 }
00916