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 "net.h"
00039
00040 #include <async.h>
00041 #include <ctype.h>
00042 #include <ddi.h>
00043 #include <errno.h>
00044 #include <malloc.h>
00045 #include <stdio.h>
00046 #include <str.h>
00047 #include <str_error.h>
00048
00049 #include <ipc/services.h>
00050 #include <ipc/net.h>
00051 #include <ipc/net_net.h>
00052 #include <ipc/il.h>
00053 #include <ipc/nil.h>
00054
00055 #include <net/modules.h>
00056 #include <net/packet.h>
00057 #include <net/device.h>
00058
00059 #include <adt/char_map.h>
00060 #include <adt/generic_char_map.h>
00061 #include <adt/measured_strings.h>
00062 #include <adt/module_map.h>
00063
00064 #include <netif_remote.h>
00065 #include <nil_remote.h>
00066 #include <net_interface.h>
00067 #include <ip_interface.h>
00068
00070 #define NAME "net"
00071
00073 #define BUFFER_SIZE 256
00074
00076 net_globals_t net_globals;
00077
00078 GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t);
00079 DEVICE_MAP_IMPLEMENT(netifs, netif_t);
00080
00081 static int startup(void);
00082
00093 int add_configuration(measured_strings_t *configuration, const uint8_t *name,
00094 const uint8_t *value)
00095 {
00096 int rc;
00097
00098 measured_string_t *setting =
00099 measured_string_create_bulk(value, 0);
00100 if (!setting)
00101 return ENOMEM;
00102
00103
00104 rc = measured_strings_add(configuration, name, 0, setting);
00105 if (rc != EOK) {
00106 free(setting);
00107 return rc;
00108 }
00109
00110 return EOK;
00111 }
00112
00117 static device_id_t generate_new_device_id(void)
00118 {
00119 return device_assign_devno();
00120 }
00121
00122 static int parse_line(measured_strings_t *configuration, uint8_t *line)
00123 {
00124 int rc;
00125
00126
00127 uint8_t *name = line;
00128
00129
00130 if ((*name == '#') || (*name == '\0'))
00131 return EOK;
00132
00133
00134 while (isspace(*name))
00135 name++;
00136
00137
00138 uint8_t *value = name;
00139
00140
00141 while (isalnum(*value) || (*value == '_'))
00142 value++;
00143
00144 if (*value == '=') {
00145
00146 *value = '\0';
00147 } else {
00148
00149 *value = '\0';
00150
00151
00152 value++;
00153 while ((*value) && (*value != '='))
00154 value++;
00155
00156
00157 if (*value != '=')
00158 return EINVAL;
00159 }
00160
00161 value++;
00162
00163
00164 while (isspace(*value))
00165 value++;
00166
00167
00168 measured_string_t *setting =
00169 measured_string_create_bulk(value, 0);
00170 if (!setting)
00171 return ENOMEM;
00172
00173
00174 rc = measured_strings_add(configuration, name, 0, setting);
00175 if (rc != EOK) {
00176 free(setting);
00177 return rc;
00178 }
00179
00180 return EOK;
00181 }
00182
00183 static int read_configuration_file(const char *directory, const char *filename,
00184 measured_strings_t *configuration)
00185 {
00186 printf("%s: Reading configuration file %s/%s\n", NAME, directory, filename);
00187
00188
00189 char fname[BUFFER_SIZE];
00190 if (snprintf(fname, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)
00191 return EOVERFLOW;
00192
00193
00194 FILE *cfg = fopen(fname, "r");
00195 if (!cfg)
00196 return ENOENT;
00197
00198
00199
00200
00201
00202 unsigned int line_number = 0;
00203 size_t index = 0;
00204 uint8_t line[BUFFER_SIZE];
00205
00206 while (!ferror(cfg) && !feof(cfg)) {
00207 int read = fgetc(cfg);
00208 if ((read > 0) && (read != '\n') && (read != '\r')) {
00209 if (index >= BUFFER_SIZE) {
00210 line[BUFFER_SIZE - 1] = '\0';
00211 fprintf(stderr, "%s: Configuration line %u too "
00212 "long: %s\n", NAME, line_number, (char *) line);
00213
00214
00215 return EOVERFLOW;
00216 }
00217
00218 line[index] = (uint8_t) read;
00219 index++;
00220 } else {
00221
00222 line[index] = '\0';
00223 line_number++;
00224 if (parse_line(configuration, line) != EOK) {
00225 fprintf(stderr, "%s: Configuration error on "
00226 "line %u: %s\n", NAME, line_number, (char *) line);
00227 }
00228
00229 index = 0;
00230 }
00231 }
00232
00233 fclose(cfg);
00234 return EOK;
00235 }
00236
00246 static int read_netif_configuration(const char *name, netif_t *netif)
00247 {
00248 return read_configuration_file(CONF_DIR, name, &netif->configuration);
00249 }
00250
00257 static int read_configuration(void)
00258 {
00259 return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE,
00260 &net_globals.configuration);
00261 }
00262
00273 static int net_initialize(async_client_conn_t client_connection)
00274 {
00275 int rc;
00276
00277 netifs_initialize(&net_globals.netifs);
00278 char_map_initialize(&net_globals.netif_names);
00279 modules_initialize(&net_globals.modules);
00280 measured_strings_initialize(&net_globals.configuration);
00281
00282
00283 rc = read_configuration();
00284 if (rc != EOK)
00285 return rc;
00286
00287 rc = add_module(NULL, &net_globals.modules, (uint8_t *) LO_NAME,
00288 (uint8_t *) LO_FILENAME, SERVICE_LO, 0, connect_to_service);
00289 if (rc != EOK)
00290 return rc;
00291
00292 rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME,
00293 (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service);
00294 if (rc != EOK)
00295 return rc;
00296
00297 rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME,
00298 (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
00299 if (rc != EOK)
00300 return rc;
00301
00302 rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME,
00303 (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
00304 if (rc != EOK)
00305 return rc;
00306
00307
00308 return net_initialize_build(client_connection);
00309 }
00310
00328 static int net_module_start(async_client_conn_t client_connection)
00329 {
00330 int rc;
00331
00332 async_set_client_connection(client_connection);
00333 rc = pm_init();
00334 if (rc != EOK)
00335 return rc;
00336
00337 rc = net_initialize(client_connection);
00338 if (rc != EOK)
00339 goto out;
00340
00341 rc = async_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, NULL);
00342 if (rc != EOK)
00343 goto out;
00344
00345 rc = startup();
00346 if (rc != EOK)
00347 goto out;
00348
00349 task_retval(0);
00350 async_manager();
00351
00352 out:
00353 pm_destroy();
00354 return rc;
00355 }
00356
00369 static int net_get_conf(measured_strings_t *netif_conf,
00370 measured_string_t *configuration, size_t count, uint8_t **data)
00371 {
00372 if (data)
00373 *data = NULL;
00374
00375 size_t index;
00376 for (index = 0; index < count; index++) {
00377 measured_string_t *setting =
00378 measured_strings_find(netif_conf, configuration[index].value, 0);
00379 if (!setting)
00380 setting = measured_strings_find(&net_globals.configuration,
00381 configuration[index].value, 0);
00382
00383 if (setting) {
00384 configuration[index].length = setting->length;
00385 configuration[index].value = setting->value;
00386 } else {
00387 configuration[index].length = 0;
00388 configuration[index].value = NULL;
00389 }
00390 }
00391
00392 return EOK;
00393 }
00394
00395 int net_get_conf_req(int net_phone, measured_string_t **configuration,
00396 size_t count, uint8_t **data)
00397 {
00398 if (!configuration || (count <= 0))
00399 return EINVAL;
00400
00401 return net_get_conf(NULL, *configuration, count, data);
00402 }
00403
00404 int net_get_device_conf_req(int net_phone, device_id_t device_id,
00405 measured_string_t **configuration, size_t count, uint8_t **data)
00406 {
00407 if ((!configuration) || (count == 0))
00408 return EINVAL;
00409
00410 netif_t *netif = netifs_find(&net_globals.netifs, device_id);
00411 if (netif)
00412 return net_get_conf(&netif->configuration, *configuration, count, data);
00413 else
00414 return net_get_conf(NULL, *configuration, count, data);
00415 }
00416
00417 void net_free_settings(measured_string_t *settings, uint8_t *data)
00418 {
00419 }
00420
00437 static int start_device(netif_t *netif)
00438 {
00439 int rc;
00440
00441
00442 measured_string_t *setting =
00443 measured_strings_find(&netif->configuration, (uint8_t *) CONF_NETIF, 0);
00444
00445 netif->driver = get_running_module(&net_globals.modules, setting->value);
00446 if (!netif->driver) {
00447 fprintf(stderr, "%s: Failed to start network interface driver '%s'\n",
00448 NAME, setting->value);
00449 return EINVAL;
00450 }
00451
00452
00453 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_NIL, 0);
00454 if (setting) {
00455 netif->nil = get_running_module(&net_globals.modules, setting->value);
00456 if (!netif->nil) {
00457 fprintf(stderr, "%s: Failed to start network interface layer '%s'\n",
00458 NAME, setting->value);
00459 return EINVAL;
00460 }
00461 } else
00462 netif->nil = NULL;
00463
00464
00465 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IL, 0);
00466 netif->il = get_running_module(&net_globals.modules, setting->value);
00467 if (!netif->il) {
00468 fprintf(stderr, "%s: Failed to start internet layer '%s'\n",
00469 NAME, setting->value);
00470 return EINVAL;
00471 }
00472
00473
00474 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IRQ, 0);
00475 int irq = setting ? strtol((char *) setting->value, NULL, 10) : 0;
00476
00477 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IO, 0);
00478 uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
00479
00480 rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io);
00481 if (rc != EOK)
00482 return rc;
00483
00484
00485 services_t internet_service;
00486 if (netif->nil) {
00487 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_MTU, 0);
00488 if (!setting)
00489 setting = measured_strings_find(&net_globals.configuration,
00490 (uint8_t *) CONF_MTU, 0);
00491
00492 int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
00493
00494 rc = nil_device_req(netif->nil->phone, netif->id, mtu,
00495 netif->driver->service);
00496 if (rc != EOK)
00497 return rc;
00498
00499 internet_service = netif->nil->service;
00500 } else
00501 internet_service = netif->driver->service;
00502
00503
00504 switch (netif->il->service) {
00505 case SERVICE_IP:
00506 rc = ip_device_req(netif->il->phone, netif->id,
00507 internet_service);
00508 if (rc != EOK)
00509 return rc;
00510 break;
00511 default:
00512 return ENOENT;
00513 }
00514
00515 return netif_start_req(netif->driver->phone, netif->id);
00516 }
00517
00531 static int startup(void)
00532 {
00533 const char *conf_files[] = {
00534 "lo",
00535 "ne2k"
00536 };
00537 size_t count = sizeof(conf_files) / sizeof(char *);
00538 int rc;
00539
00540 size_t i;
00541 for (i = 0; i < count; i++) {
00542 netif_t *netif = (netif_t *) malloc(sizeof(netif_t));
00543 if (!netif)
00544 return ENOMEM;
00545
00546 netif->id = generate_new_device_id();
00547 if (!netif->id)
00548 return EXDEV;
00549
00550 rc = measured_strings_initialize(&netif->configuration);
00551 if (rc != EOK)
00552 return rc;
00553
00554
00555 rc = read_netif_configuration(conf_files[i], netif);
00556 if (rc != EOK) {
00557 measured_strings_destroy(&netif->configuration, free);
00558 free(netif);
00559 return rc;
00560 }
00561
00562
00563 measured_string_t *setting =
00564 measured_strings_find(&netif->configuration, (uint8_t *) CONF_NAME, 0);
00565 if (!setting) {
00566 fprintf(stderr, "%s: Network interface name is missing\n", NAME);
00567 measured_strings_destroy(&netif->configuration, free);
00568 free(netif);
00569 return EINVAL;
00570 }
00571 netif->name = setting->value;
00572
00573
00574 int index = netifs_add(&net_globals.netifs, netif->id, netif);
00575 if (index < 0) {
00576 measured_strings_destroy(&netif->configuration, free);
00577 free(netif);
00578 return index;
00579 }
00580
00581
00582
00583
00584
00585 rc = char_map_add(&net_globals.netif_names, netif->name, 0,
00586 index);
00587 if (rc != EOK) {
00588 measured_strings_destroy(&netif->configuration, free);
00589 netifs_exclude_index(&net_globals.netifs, index, free);
00590 return rc;
00591 }
00592
00593 rc = start_device(netif);
00594 if (rc != EOK) {
00595 printf("%s: Ignoring failed interface %s (%s)\n", NAME,
00596 netif->name, str_error(rc));
00597 measured_strings_destroy(&netif->configuration, free);
00598 netifs_exclude_index(&net_globals.netifs, index, free);
00599 continue;
00600 }
00601
00602
00603 netif->driver->usage++;
00604 if (netif->nil)
00605 netif->nil->usage++;
00606 netif->il->usage++;
00607
00608 printf("%s: Network interface started (name: %s, id: %d, driver: %s, "
00609 "nil: %s, il: %s)\n", NAME, netif->name, netif->id,
00610 netif->driver->name, netif->nil ? (char *) netif->nil->name : "[none]",
00611 netif->il->name);
00612 }
00613
00614 return EOK;
00615 }
00616
00632 int net_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
00633 size_t *answer_count)
00634 {
00635 measured_string_t *strings;
00636 uint8_t *data;
00637 int rc;
00638
00639 *answer_count = 0;
00640 switch (IPC_GET_IMETHOD(*call)) {
00641 case IPC_M_PHONE_HUNGUP:
00642 return EOK;
00643 case NET_NET_GET_DEVICE_CONF:
00644 rc = measured_strings_receive(&strings, &data,
00645 IPC_GET_COUNT(*call));
00646 if (rc != EOK)
00647 return rc;
00648 net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings,
00649 IPC_GET_COUNT(*call), NULL);
00650
00651
00652 free(data);
00653
00654 rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
00655 free(strings);
00656 return rc;
00657 case NET_NET_GET_CONF:
00658 rc = measured_strings_receive(&strings, &data,
00659 IPC_GET_COUNT(*call));
00660 if (rc != EOK)
00661 return rc;
00662 net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL);
00663
00664
00665 free(data);
00666
00667 rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
00668 free(strings);
00669 return rc;
00670 case NET_NET_STARTUP:
00671 return startup();
00672 }
00673
00674 return ENOTSUP;
00675 }
00676
00683 static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall)
00684 {
00685
00686
00687
00688
00689 async_answer_0(iid, EOK);
00690
00691 while (true) {
00692
00693 ipc_call_t answer;
00694 size_t answer_count;
00695 refresh_answer(&answer, &answer_count);
00696
00697
00698 ipc_call_t call;
00699 ipc_callid_t callid = async_get_call(&call);
00700
00701
00702 int res = net_module_message(callid, &call, &answer, &answer_count);
00703
00704
00705 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
00706 return;
00707
00708
00709 answer_call(callid, res, &answer, answer_count);
00710 }
00711 }
00712
00713 int main(int argc, char *argv[])
00714 {
00715 return net_module_start(net_client_connection);
00716 }
00717