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 <str.h>
00043 #include <ipc/nil.h>
00044 #include <ipc/net.h>
00045 #include <ipc/services.h>
00046
00047 #include <net/modules.h>
00048 #include <net/device.h>
00049 #include <il_remote.h>
00050 #include <adt/measured_strings.h>
00051 #include <net/packet.h>
00052 #include <packet_remote.h>
00053 #include <netif_remote.h>
00054 #include <nil_skel.h>
00055
00056 #include "nildummy.h"
00057
00059 #define NAME "nildummy"
00060
00062 #define NET_DEFAULT_MTU 1500
00063
00065 nildummy_globals_t nildummy_globals;
00066
00067 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
00068
00069 int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
00070 {
00071 fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
00072 if (nildummy_globals.proto.phone)
00073 il_device_state_msg(nildummy_globals.proto.phone, device_id,
00074 state, nildummy_globals.proto.service);
00075 fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
00076
00077 return EOK;
00078 }
00079
00080 int nil_initialize(int net_phone)
00081 {
00082 fibril_rwlock_initialize(&nildummy_globals.devices_lock);
00083 fibril_rwlock_initialize(&nildummy_globals.protos_lock);
00084 fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
00085 fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
00086
00087 nildummy_globals.net_phone = net_phone;
00088 nildummy_globals.proto.phone = 0;
00089 int rc = nildummy_devices_initialize(&nildummy_globals.devices);
00090
00091 fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
00092 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00093
00094 return rc;
00095 }
00096
00103 static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
00104 {
00105 packet_t *packet;
00106 int rc;
00107
00108 while (true) {
00109 switch (IPC_GET_IMETHOD(*icall)) {
00110 case NET_NIL_DEVICE_STATE:
00111 rc = nil_device_state_msg_local(0,
00112 IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
00113 async_answer_0(iid, (sysarg_t) rc);
00114 break;
00115
00116 case NET_NIL_RECEIVED:
00117 rc = packet_translate_remote(nildummy_globals.net_phone,
00118 &packet, IPC_GET_PACKET(*icall));
00119 if (rc == EOK)
00120 rc = nil_received_msg_local(0,
00121 IPC_GET_DEVICE(*icall), packet, 0);
00122
00123 async_answer_0(iid, (sysarg_t) rc);
00124 break;
00125
00126 default:
00127 async_answer_0(iid, (sysarg_t) ENOTSUP);
00128 }
00129
00130 iid = async_get_call(icall);
00131 }
00132 }
00133
00151 static int nildummy_device_message(device_id_t device_id, services_t service,
00152 size_t mtu)
00153 {
00154 fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
00155
00156
00157 nildummy_device_t *device =
00158 nildummy_devices_find(&nildummy_globals.devices, device_id);
00159 if (device) {
00160 if (device->service != service) {
00161 printf("Device %d already exists\n", device->device_id);
00162 fibril_rwlock_write_unlock(
00163 &nildummy_globals.devices_lock);
00164 return EEXIST;
00165 }
00166
00167
00168 if (mtu > 0)
00169 device->mtu = mtu;
00170 else
00171 device->mtu = NET_DEFAULT_MTU;
00172
00173 printf("Device %d already exists:\tMTU\t= %zu\n",
00174 device->device_id, device->mtu);
00175 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00176
00177
00178 fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
00179 if (nildummy_globals.proto.phone) {
00180 il_mtu_changed_msg(nildummy_globals.proto.phone,
00181 device->device_id, device->mtu,
00182 nildummy_globals.proto.service);
00183 }
00184 fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
00185
00186 return EOK;
00187 }
00188
00189
00190 device = (nildummy_device_t *) malloc(sizeof(nildummy_device_t));
00191 if (!device)
00192 return ENOMEM;
00193
00194 device->device_id = device_id;
00195 device->service = service;
00196 if (mtu > 0)
00197 device->mtu = mtu;
00198 else
00199 device->mtu = NET_DEFAULT_MTU;
00200
00201
00202 device->phone = netif_bind_service(device->service, device->device_id,
00203 SERVICE_ETHERNET, nildummy_receiver);
00204 if (device->phone < 0) {
00205 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00206 free(device);
00207 return device->phone;
00208 }
00209
00210
00211 int rc = netif_get_addr_req(device->phone, device->device_id,
00212 &device->addr, &device->addr_data);
00213 if (rc != EOK) {
00214 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00215 free(device);
00216 return rc;
00217 }
00218
00219
00220 int index = nildummy_devices_add(&nildummy_globals.devices,
00221 device->device_id, device);
00222 if (index < 0) {
00223 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00224 free(device->addr);
00225 free(device->addr_data);
00226 free(device);
00227 return index;
00228 }
00229
00230 printf("%s: Device registered (id: %d, service: %d, mtu: %zu)\n",
00231 NAME, device->device_id, device->service, device->mtu);
00232 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
00233 return EOK;
00234 }
00235
00246 static int nildummy_addr_message(device_id_t device_id,
00247 measured_string_t **address)
00248 {
00249 if (!address)
00250 return EBADMEM;
00251
00252 fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
00253
00254 nildummy_device_t *device =
00255 nildummy_devices_find(&nildummy_globals.devices, device_id);
00256 if (!device) {
00257 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00258 return ENOENT;
00259 }
00260
00261 *address = device->addr;
00262
00263 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00264
00265 return (*address) ? EOK : ENOENT;
00266 }
00267
00281 static int nildummy_packet_space_message(device_id_t device_id, size_t *addr_len,
00282 size_t *prefix, size_t *content, size_t *suffix)
00283 {
00284 if ((!addr_len) || (!prefix) || (!content) || (!suffix))
00285 return EBADMEM;
00286
00287 fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
00288
00289 nildummy_device_t *device =
00290 nildummy_devices_find(&nildummy_globals.devices, device_id);
00291 if (!device) {
00292 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00293 return ENOENT;
00294 }
00295
00296 *content = device->mtu;
00297
00298 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00299
00300 *addr_len = 0;
00301 *prefix = 0;
00302 *suffix = 0;
00303 return EOK;
00304 }
00305
00306 int nil_received_msg_local(int nil_phone, device_id_t device_id,
00307 packet_t *packet, services_t target)
00308 {
00309 fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
00310
00311 if (nildummy_globals.proto.phone) {
00312 do {
00313 packet_t *next = pq_detach(packet);
00314 il_received_msg(nildummy_globals.proto.phone, device_id,
00315 packet, nildummy_globals.proto.service);
00316 packet = next;
00317 } while (packet);
00318 }
00319
00320 fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
00321
00322 return EOK;
00323 }
00324
00337 static int nildummy_register_message(services_t service, int phone)
00338 {
00339 fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
00340 nildummy_globals.proto.service = service;
00341 nildummy_globals.proto.phone = phone;
00342
00343 printf("%s: Protocol registered (service: %d, phone: %d)\n",
00344 NAME, nildummy_globals.proto.service, nildummy_globals.proto.phone);
00345
00346 fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
00347 return EOK;
00348 }
00349
00361 static int nildummy_send_message(device_id_t device_id, packet_t *packet,
00362 services_t sender)
00363 {
00364 fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
00365
00366 nildummy_device_t *device =
00367 nildummy_devices_find(&nildummy_globals.devices, device_id);
00368 if (!device) {
00369 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00370 return ENOENT;
00371 }
00372
00373
00374 if (packet)
00375 netif_send_msg(device->phone, device_id, packet,
00376 SERVICE_NILDUMMY);
00377
00378 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
00379
00380 return EOK;
00381 }
00382
00383 int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
00384 ipc_call_t *answer, size_t *answer_count)
00385 {
00386 measured_string_t *address;
00387 packet_t *packet;
00388 size_t addrlen;
00389 size_t prefix;
00390 size_t suffix;
00391 size_t content;
00392 int rc;
00393
00394 *answer_count = 0;
00395 switch (IPC_GET_IMETHOD(*call)) {
00396 case IPC_M_PHONE_HUNGUP:
00397 return EOK;
00398
00399 case NET_NIL_DEVICE:
00400 return nildummy_device_message(IPC_GET_DEVICE(*call),
00401 IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
00402
00403 case NET_NIL_SEND:
00404 rc = packet_translate_remote(nildummy_globals.net_phone,
00405 &packet, IPC_GET_PACKET(*call));
00406 if (rc != EOK)
00407 return rc;
00408 return nildummy_send_message(IPC_GET_DEVICE(*call), packet,
00409 IPC_GET_SERVICE(*call));
00410
00411 case NET_NIL_PACKET_SPACE:
00412 rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call),
00413 &addrlen, &prefix, &content, &suffix);
00414 if (rc != EOK)
00415 return rc;
00416 IPC_SET_ADDR(*answer, addrlen);
00417 IPC_SET_PREFIX(*answer, prefix);
00418 IPC_SET_CONTENT(*answer, content);
00419 IPC_SET_SUFFIX(*answer, suffix);
00420 *answer_count = 4;
00421 return EOK;
00422
00423 case NET_NIL_ADDR:
00424 rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
00425 if (rc != EOK)
00426 return rc;
00427 return measured_strings_reply(address, 1);
00428
00429 case NET_NIL_BROADCAST_ADDR:
00430 rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
00431 if (rc != EOK)
00432 return rc;
00433 return measured_strings_reply(address, 1);
00434
00435 case IPC_M_CONNECT_TO_ME:
00436 return nildummy_register_message(NIL_GET_PROTO(*call),
00437 IPC_GET_PHONE(*call));
00438 }
00439
00440 return ENOTSUP;
00441 }
00442
00443 int main(int argc, char *argv[])
00444 {
00445
00446 return nil_module_start(SERVICE_NILDUMMY);
00447 }
00448