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 <stdio.h>
00042 #include <byteorder.h>
00043 #include <str.h>
00044 #include <errno.h>
00045 #include <ipc/nil.h>
00046 #include <ipc/net.h>
00047 #include <ipc/services.h>
00048 #include <net/modules.h>
00049 #include <net_checksum.h>
00050 #include <ethernet_lsap.h>
00051 #include <ethernet_protocols.h>
00052 #include <protocol_map.h>
00053 #include <net/device.h>
00054 #include <netif_remote.h>
00055 #include <net_interface.h>
00056 #include <il_remote.h>
00057 #include <adt/measured_strings.h>
00058 #include <packet_client.h>
00059 #include <packet_remote.h>
00060 #include <nil_skel.h>
00061
00062 #include "eth.h"
00063
00065 #define NAME "eth"
00066
00068 #define ETH_PREFIX \
00069 (sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \
00070 sizeof(eth_header_snap_t))
00071
00073 #define ETH_SUFFIX (sizeof(eth_fcs_t))
00074
00076 #define ETH_MAX_CONTENT 1500u
00077
00079 #define ETH_MIN_CONTENT 46u
00080
00082 #define ETH_MAX_TAGGED_CONTENT(flags) \
00083 (ETH_MAX_CONTENT - \
00084 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
00085 sizeof(eth_header_lsap_t) : 0) - \
00086 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
00087
00089 #define ETH_MIN_TAGGED_CONTENT(flags) \
00090 (ETH_MIN_CONTENT - \
00091 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
00092 sizeof(eth_header_lsap_t) : 0) - \
00093 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
00094
00096 #define ETH_DUMMY_SHIFT 0
00097
00099 #define ETH_MODE_SHIFT 1
00100
00104 #define ETH_DUMMY (1 << ETH_DUMMY_SHIFT)
00105
00109 #define IS_DUMMY(flags) ((flags) & ETH_DUMMY)
00110
00116 #define ETH_MODE_MASK (3 << ETH_MODE_SHIFT)
00117
00119 #define ETH_DIX (1 << ETH_MODE_SHIFT)
00120
00127 #define IS_DIX(flags) (((flags) & ETH_MODE_MASK) == ETH_DIX)
00128
00130 #define ETH_8023_2_LSAP (2 << ETH_MODE_SHIFT)
00131
00138 #define IS_8023_2_LSAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
00139
00141 #define ETH_8023_2_SNAP (3 << ETH_MODE_SHIFT)
00142
00149 #define IS_8023_2_SNAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
00150
00154 typedef enum eth_addr_type eth_addr_type_t;
00155
00157 enum eth_addr_type {
00159 ETH_LOCAL_ADDR,
00161 ETH_BROADCAST_ADDR
00162 };
00163
00165 eth_globals_t eth_globals;
00166
00167 DEVICE_MAP_IMPLEMENT(eth_devices, eth_device_t);
00168 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
00169
00170 int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
00171 {
00172 int index;
00173 eth_proto_t *proto;
00174
00175 fibril_rwlock_read_lock(ð_globals.protos_lock);
00176 for (index = eth_protos_count(ð_globals.protos) - 1; index >= 0;
00177 index--) {
00178 proto = eth_protos_get_index(ð_globals.protos, index);
00179 if (proto && proto->phone) {
00180 il_device_state_msg(proto->phone, device_id, state,
00181 proto->service);
00182 }
00183 }
00184 fibril_rwlock_read_unlock(ð_globals.protos_lock);
00185
00186 return EOK;
00187 }
00188
00189 int nil_initialize(int net_phone)
00190 {
00191 int rc;
00192
00193 fibril_rwlock_initialize(ð_globals.devices_lock);
00194 fibril_rwlock_initialize(ð_globals.protos_lock);
00195
00196 fibril_rwlock_write_lock(ð_globals.devices_lock);
00197 fibril_rwlock_write_lock(ð_globals.protos_lock);
00198 eth_globals.net_phone = net_phone;
00199
00200 eth_globals.broadcast_addr =
00201 measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
00202 if (!eth_globals.broadcast_addr) {
00203 rc = ENOMEM;
00204 goto out;
00205 }
00206
00207 rc = eth_devices_initialize(ð_globals.devices);
00208 if (rc != EOK) {
00209 free(eth_globals.broadcast_addr);
00210 goto out;
00211 }
00212
00213 rc = eth_protos_initialize(ð_globals.protos);
00214 if (rc != EOK) {
00215 free(eth_globals.broadcast_addr);
00216 eth_devices_destroy(ð_globals.devices, free);
00217 }
00218 out:
00219 fibril_rwlock_write_unlock(ð_globals.protos_lock);
00220 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00221
00222 return rc;
00223 }
00224
00231 static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall)
00232 {
00233 packet_t *packet;
00234 int rc;
00235
00236 while (true) {
00237 switch (IPC_GET_IMETHOD(*icall)) {
00238 case NET_NIL_DEVICE_STATE:
00239 nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
00240 IPC_GET_STATE(*icall));
00241 async_answer_0(iid, EOK);
00242 break;
00243 case NET_NIL_RECEIVED:
00244 rc = packet_translate_remote(eth_globals.net_phone,
00245 &packet, IPC_GET_PACKET(*icall));
00246 if (rc == EOK)
00247 rc = nil_received_msg_local(0,
00248 IPC_GET_DEVICE(*icall), packet, 0);
00249
00250 async_answer_0(iid, (sysarg_t) rc);
00251 break;
00252 default:
00253 async_answer_0(iid, (sysarg_t) ENOTSUP);
00254 }
00255
00256 iid = async_get_call(icall);
00257 }
00258 }
00259
00277 static int eth_device_message(device_id_t device_id, services_t service,
00278 size_t mtu)
00279 {
00280 eth_device_t *device;
00281 int index;
00282 measured_string_t names[2] = {
00283 {
00284 (uint8_t *) "ETH_MODE",
00285 8
00286 },
00287 {
00288 (uint8_t *) "ETH_DUMMY",
00289 9
00290 }
00291 };
00292 measured_string_t *configuration;
00293 size_t count = sizeof(names) / sizeof(measured_string_t);
00294 uint8_t *data;
00295 eth_proto_t *proto;
00296 int rc;
00297
00298 fibril_rwlock_write_lock(ð_globals.devices_lock);
00299
00300 device = eth_devices_find(ð_globals.devices, device_id);
00301 if (device) {
00302 if (device->service != service) {
00303 printf("Device %d already exists\n", device->device_id);
00304 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00305 return EEXIST;
00306 }
00307
00308
00309 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
00310 device->mtu = mtu;
00311 else
00312 device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
00313
00314 printf("Device %d already exists:\tMTU\t= %zu\n",
00315 device->device_id, device->mtu);
00316 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00317
00318
00319 fibril_rwlock_read_lock(ð_globals.protos_lock);
00320 for (index = 0; index < eth_protos_count(ð_globals.protos);
00321 index++) {
00322 proto = eth_protos_get_index(ð_globals.protos,
00323 index);
00324 if (proto->phone) {
00325 il_mtu_changed_msg(proto->phone,
00326 device->device_id, device->mtu,
00327 proto->service);
00328 }
00329 }
00330
00331 fibril_rwlock_read_unlock(ð_globals.protos_lock);
00332 return EOK;
00333 }
00334
00335
00336 device = (eth_device_t *) malloc(sizeof(eth_device_t));
00337 if (!device)
00338 return ENOMEM;
00339
00340 device->device_id = device_id;
00341 device->service = service;
00342 device->flags = 0;
00343 if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
00344 device->mtu = mtu;
00345 else
00346 device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
00347
00348 configuration = &names[0];
00349 rc = net_get_device_conf_req(eth_globals.net_phone, device->device_id,
00350 &configuration, count, &data);
00351 if (rc != EOK) {
00352 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00353 free(device);
00354 return rc;
00355 }
00356
00357 if (configuration) {
00358 if (!str_lcmp((char *) configuration[0].value, "DIX",
00359 configuration[0].length)) {
00360 device->flags |= ETH_DIX;
00361 } else if(!str_lcmp((char *) configuration[0].value, "8023_2_LSAP",
00362 configuration[0].length)) {
00363 device->flags |= ETH_8023_2_LSAP;
00364 } else {
00365 device->flags |= ETH_8023_2_SNAP;
00366 }
00367
00368 if (configuration[1].value &&
00369 (configuration[1].value[0] == 'y')) {
00370 device->flags |= ETH_DUMMY;
00371 }
00372 net_free_settings(configuration, data);
00373 } else {
00374 device->flags |= ETH_8023_2_SNAP;
00375 }
00376
00377
00378 device->phone = netif_bind_service(device->service, device->device_id,
00379 SERVICE_ETHERNET, eth_receiver);
00380 if (device->phone < 0) {
00381 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00382 free(device);
00383 return device->phone;
00384 }
00385
00386
00387 rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
00388 &device->addr_data);
00389 if (rc != EOK) {
00390 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00391 free(device);
00392 return rc;
00393 }
00394
00395
00396 index = eth_devices_add(ð_globals.devices, device->device_id,
00397 device);
00398 if (index < 0) {
00399 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00400 free(device->addr);
00401 free(device->addr_data);
00402 free(device);
00403 return index;
00404 }
00405
00406 printf("%s: Device registered (id: %d, service: %d: mtu: %zu, "
00407 "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n",
00408 NAME, device->device_id, device->service, device->mtu,
00409 device->addr_data[0], device->addr_data[1],
00410 device->addr_data[2], device->addr_data[3],
00411 device->addr_data[4], device->addr_data[5], device->flags);
00412
00413 fibril_rwlock_write_unlock(ð_globals.devices_lock);
00414 return EOK;
00415 }
00416
00428 static eth_proto_t *eth_process_packet(int flags, packet_t *packet)
00429 {
00430 eth_header_snap_t *header;
00431 size_t length;
00432 eth_type_t type;
00433 size_t prefix;
00434 size_t suffix;
00435 eth_fcs_t *fcs;
00436 uint8_t *data;
00437 int rc;
00438
00439 length = packet_get_data_length(packet);
00440
00441 if (IS_DUMMY(flags))
00442 packet_trim(packet, sizeof(eth_preamble_t), 0);
00443 if (length < sizeof(eth_header_t) + ETH_MIN_CONTENT +
00444 (IS_DUMMY(flags) ? ETH_SUFFIX : 0))
00445 return NULL;
00446
00447 data = packet_get_data(packet);
00448 header = (eth_header_snap_t *) data;
00449 type = ntohs(header->header.ethertype);
00450
00451 if (type >= ETH_MIN_PROTO) {
00452
00453 prefix = sizeof(eth_header_t);
00454 suffix = 0;
00455 fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
00456 length -= sizeof(eth_fcs_t);
00457 } else if(type <= ETH_MAX_CONTENT) {
00458
00459 if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
00460 (header->lsap.ssap == ETH_LSAP_GLSAP)) {
00461
00462 return NULL;
00463 } else if((header->lsap.dsap == ETH_LSAP_SNAP) &&
00464 (header->lsap.ssap == ETH_LSAP_SNAP)) {
00465
00466
00467
00468
00469 type = ntohs(header->snap.ethertype);
00470 prefix = sizeof(eth_header_t) +
00471 sizeof(eth_header_lsap_t) +
00472 sizeof(eth_header_snap_t);
00473 } else {
00474
00475 type = lsap_map(header->lsap.dsap);
00476 prefix = sizeof(eth_header_t) +
00477 sizeof(eth_header_lsap_t);
00478 }
00479
00480 suffix = (type < ETH_MIN_CONTENT) ? ETH_MIN_CONTENT - type : 0U;
00481 fcs = (eth_fcs_t *) data + prefix + type + suffix;
00482 suffix += length - prefix - type;
00483 length = prefix + type + suffix;
00484 } else {
00485
00486 return NULL;
00487 }
00488
00489 if (IS_DUMMY(flags)) {
00490 if (~compute_crc32(~0U, data, length * 8) != ntohl(*fcs))
00491 return NULL;
00492 suffix += sizeof(eth_fcs_t);
00493 }
00494
00495 rc = packet_set_addr(packet, header->header.source_address,
00496 header->header.destination_address, ETH_ADDR);
00497 if (rc != EOK)
00498 return NULL;
00499
00500 rc = packet_trim(packet, prefix, suffix);
00501 if (rc != EOK)
00502 return NULL;
00503
00504 return eth_protos_find(ð_globals.protos, type);
00505 }
00506
00507 int nil_received_msg_local(int nil_phone, device_id_t device_id,
00508 packet_t *packet, services_t target)
00509 {
00510 eth_proto_t *proto;
00511 packet_t *next;
00512 eth_device_t *device;
00513 int flags;
00514
00515 fibril_rwlock_read_lock(ð_globals.devices_lock);
00516 device = eth_devices_find(ð_globals.devices, device_id);
00517 if (!device) {
00518 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00519 return ENOENT;
00520 }
00521
00522 flags = device->flags;
00523 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00524
00525 fibril_rwlock_read_lock(ð_globals.protos_lock);
00526 do {
00527 next = pq_detach(packet);
00528 proto = eth_process_packet(flags, packet);
00529 if (proto) {
00530 il_received_msg(proto->phone, device_id, packet,
00531 proto->service);
00532 } else {
00533
00534 pq_release_remote(eth_globals.net_phone,
00535 packet_get_id(packet));
00536 }
00537 packet = next;
00538 } while(packet);
00539
00540 fibril_rwlock_read_unlock(ð_globals.protos_lock);
00541 return EOK;
00542 }
00543
00555 static int eth_packet_space_message(device_id_t device_id, size_t *addr_len,
00556 size_t *prefix, size_t *content, size_t *suffix)
00557 {
00558 eth_device_t *device;
00559
00560 if (!addr_len || !prefix || !content || !suffix)
00561 return EBADMEM;
00562
00563 fibril_rwlock_read_lock(ð_globals.devices_lock);
00564 device = eth_devices_find(ð_globals.devices, device_id);
00565 if (!device) {
00566 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00567 return ENOENT;
00568 }
00569
00570 *content = device->mtu;
00571 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00572
00573 *addr_len = ETH_ADDR;
00574 *prefix = ETH_PREFIX;
00575 *suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
00576
00577 return EOK;
00578 }
00579
00589 static int eth_addr_message(device_id_t device_id, eth_addr_type_t type,
00590 measured_string_t **address)
00591 {
00592 eth_device_t *device;
00593
00594 if (!address)
00595 return EBADMEM;
00596
00597 if (type == ETH_BROADCAST_ADDR) {
00598 *address = eth_globals.broadcast_addr;
00599 } else {
00600 fibril_rwlock_read_lock(ð_globals.devices_lock);
00601 device = eth_devices_find(ð_globals.devices, device_id);
00602 if (!device) {
00603 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00604 return ENOENT;
00605 }
00606 *address = device->addr;
00607 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00608 }
00609
00610 return (*address) ? EOK : ENOENT;
00611 }
00612
00623 static int eth_register_message(services_t service, int phone)
00624 {
00625 eth_proto_t *proto;
00626 int protocol;
00627 int index;
00628
00629 protocol = protocol_map(SERVICE_ETHERNET, service);
00630 if (!protocol)
00631 return ENOENT;
00632
00633 fibril_rwlock_write_lock(ð_globals.protos_lock);
00634 proto = eth_protos_find(ð_globals.protos, protocol);
00635 if (proto) {
00636 proto->phone = phone;
00637 fibril_rwlock_write_unlock(ð_globals.protos_lock);
00638 return EOK;
00639 } else {
00640 proto = (eth_proto_t *) malloc(sizeof(eth_proto_t));
00641 if (!proto) {
00642 fibril_rwlock_write_unlock(ð_globals.protos_lock);
00643 return ENOMEM;
00644 }
00645
00646 proto->service = service;
00647 proto->protocol = protocol;
00648 proto->phone = phone;
00649
00650 index = eth_protos_add(ð_globals.protos, protocol, proto);
00651 if (index < 0) {
00652 fibril_rwlock_write_unlock(ð_globals.protos_lock);
00653 free(proto);
00654 return index;
00655 }
00656 }
00657
00658 printf("%s: Protocol registered (protocol: %d, service: %d, phone: "
00659 "%d)\n", NAME, proto->protocol, proto->service, proto->phone);
00660
00661 fibril_rwlock_write_unlock(ð_globals.protos_lock);
00662 return EOK;
00663 }
00664
00678 static int
00679 eth_prepare_packet(int flags, packet_t *packet, uint8_t *src_addr, int ethertype,
00680 size_t mtu)
00681 {
00682 eth_header_snap_t *header;
00683 eth_header_lsap_t *header_lsap;
00684 eth_header_t *header_dix;
00685 eth_fcs_t *fcs;
00686 uint8_t *src;
00687 uint8_t *dest;
00688 size_t length;
00689 int i;
00690 void *padding;
00691 eth_preamble_t *preamble;
00692
00693 i = packet_get_addr(packet, &src, &dest);
00694 if (i < 0)
00695 return i;
00696 if (i != ETH_ADDR)
00697 return EINVAL;
00698
00699 length = packet_get_data_length(packet);
00700 if (length > mtu)
00701 return EINVAL;
00702
00703 if (length < ETH_MIN_TAGGED_CONTENT(flags)) {
00704 padding = packet_suffix(packet,
00705 ETH_MIN_TAGGED_CONTENT(flags) - length);
00706 if (!padding)
00707 return ENOMEM;
00708
00709 bzero(padding, ETH_MIN_TAGGED_CONTENT(flags) - length);
00710 }
00711
00712 if (IS_DIX(flags)) {
00713 header_dix = PACKET_PREFIX(packet, eth_header_t);
00714 if (!header_dix)
00715 return ENOMEM;
00716
00717 header_dix->ethertype = (uint16_t) ethertype;
00718 memcpy(header_dix->source_address, src_addr, ETH_ADDR);
00719 memcpy(header_dix->destination_address, dest, ETH_ADDR);
00720 src = &header_dix->destination_address[0];
00721 } else if(IS_8023_2_LSAP(flags)) {
00722 header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
00723 if (!header_lsap)
00724 return ENOMEM;
00725
00726 header_lsap->header.ethertype = htons(length +
00727 sizeof(eth_header_lsap_t));
00728 header_lsap->lsap.dsap = lsap_unmap(ntohs(ethertype));
00729 header_lsap->lsap.ssap = header_lsap->lsap.dsap;
00730 header_lsap->lsap.ctrl = IEEE_8023_2_UI;
00731 memcpy(header_lsap->header.source_address, src_addr, ETH_ADDR);
00732 memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
00733 src = &header_lsap->header.destination_address[0];
00734 } else if(IS_8023_2_SNAP(flags)) {
00735 header = PACKET_PREFIX(packet, eth_header_snap_t);
00736 if (!header)
00737 return ENOMEM;
00738
00739 header->header.ethertype = htons(length +
00740 sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t));
00741 header->lsap.dsap = (uint16_t) ETH_LSAP_SNAP;
00742 header->lsap.ssap = header->lsap.dsap;
00743 header->lsap.ctrl = IEEE_8023_2_UI;
00744
00745 for (i = 0; i < 3; ++ i)
00746 header->snap.protocol[i] = 0;
00747
00748 header->snap.ethertype = (uint16_t) ethertype;
00749 memcpy(header->header.source_address, src_addr, ETH_ADDR);
00750 memcpy(header->header.destination_address, dest, ETH_ADDR);
00751 src = &header->header.destination_address[0];
00752 }
00753
00754 if (IS_DUMMY(flags)) {
00755 preamble = PACKET_PREFIX(packet, eth_preamble_t);
00756 if (!preamble)
00757 return ENOMEM;
00758
00759 for (i = 0; i < 7; ++ i)
00760 preamble->preamble[i] = ETH_PREAMBLE;
00761
00762 preamble->sfd = ETH_SFD;
00763
00764 fcs = PACKET_SUFFIX(packet, eth_fcs_t);
00765 if (!fcs)
00766 return ENOMEM;
00767
00768 *fcs = htonl(~compute_crc32(~0U, src, length * 8));
00769 }
00770
00771 return EOK;
00772 }
00773
00786 static int eth_send_message(device_id_t device_id, packet_t *packet,
00787 services_t sender)
00788 {
00789 eth_device_t *device;
00790 packet_t *next;
00791 packet_t *tmp;
00792 int ethertype;
00793 int rc;
00794
00795 ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
00796 if (!ethertype) {
00797 pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
00798 return EINVAL;
00799 }
00800
00801 fibril_rwlock_read_lock(ð_globals.devices_lock);
00802 device = eth_devices_find(ð_globals.devices, device_id);
00803 if (!device) {
00804 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00805 return ENOENT;
00806 }
00807
00808
00809 next = packet;
00810 do {
00811 rc = eth_prepare_packet(device->flags, next,
00812 (uint8_t *) device->addr->value, ethertype, device->mtu);
00813 if (rc != EOK) {
00814
00815 tmp = pq_detach(next);
00816 if (next == packet)
00817 packet = tmp;
00818 pq_release_remote(eth_globals.net_phone,
00819 packet_get_id(next));
00820 next = tmp;
00821 } else {
00822 next = pq_next(next);
00823 }
00824 } while(next);
00825
00826
00827 if (packet) {
00828 netif_send_msg(device->phone, device_id, packet,
00829 SERVICE_ETHERNET);
00830 }
00831
00832 fibril_rwlock_read_unlock(ð_globals.devices_lock);
00833 return EOK;
00834 }
00835
00836 int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
00837 ipc_call_t *answer, size_t *answer_count)
00838 {
00839 measured_string_t *address;
00840 packet_t *packet;
00841 size_t addrlen;
00842 size_t prefix;
00843 size_t suffix;
00844 size_t content;
00845 int rc;
00846
00847 *answer_count = 0;
00848 switch (IPC_GET_IMETHOD(*call)) {
00849 case IPC_M_PHONE_HUNGUP:
00850 return EOK;
00851
00852 case NET_NIL_DEVICE:
00853 return eth_device_message(IPC_GET_DEVICE(*call),
00854 IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
00855 case NET_NIL_SEND:
00856 rc = packet_translate_remote(eth_globals.net_phone, &packet,
00857 IPC_GET_PACKET(*call));
00858 if (rc != EOK)
00859 return rc;
00860 return eth_send_message(IPC_GET_DEVICE(*call), packet,
00861 IPC_GET_SERVICE(*call));
00862 case NET_NIL_PACKET_SPACE:
00863 rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen,
00864 &prefix, &content, &suffix);
00865 if (rc != EOK)
00866 return rc;
00867 IPC_SET_ADDR(*answer, addrlen);
00868 IPC_SET_PREFIX(*answer, prefix);
00869 IPC_SET_CONTENT(*answer, content);
00870 IPC_SET_SUFFIX(*answer, suffix);
00871 *answer_count = 4;
00872 return EOK;
00873 case NET_NIL_ADDR:
00874 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
00875 &address);
00876 if (rc != EOK)
00877 return rc;
00878 return measured_strings_reply(address, 1);
00879 case NET_NIL_BROADCAST_ADDR:
00880 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
00881 &address);
00882 if (rc != EOK)
00883 return EOK;
00884 return measured_strings_reply(address, 1);
00885 case IPC_M_CONNECT_TO_ME:
00886 return eth_register_message(NIL_GET_PROTO(*call),
00887 IPC_GET_PHONE(*call));
00888 }
00889
00890 return ENOTSUP;
00891 }
00892
00893 int main(int argc, char *argv[])
00894 {
00895
00896 return nil_module_start(SERVICE_ETHERNET);
00897 }
00898