Subversion Repositories HelenOS

Rev

Rev 4243 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup net
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  */
  35.  
  36. #include <async.h>
  37. #include <ctype.h>
  38. #include <ddi.h>
  39. #include <errno.h>
  40. #include <malloc.h>
  41. #include <stdio.h>
  42.  
  43. #include <ipc/ipc.h>
  44. #include <ipc/services.h>
  45.  
  46. #include "../err.h"
  47. #include "../messages.h"
  48. #include "../modules.h"
  49. //#include "../self_test.h"
  50.  
  51. #include "../structures/char_map.h"
  52. #include "../structures/generic_char_map.h"
  53. #include "../structures/measured_strings.h"
  54. #include "../structures/module_map.h"
  55. #include "../structures/packet/packet.h"
  56. #include "../structures/packet/packet_server.h"
  57.  
  58. #include "../il/ip/ip_messages.h"
  59. #include "../include/device.h"
  60. #include "../include/netif_messages.h"
  61. #include "../include/nil_messages.h"
  62. /*
  63. #if IP_BUNDLE
  64.  
  65.     #include "../ip/ip_module.h"
  66.  
  67. #endif
  68.  
  69. #if TCP_BUNDLE
  70.  
  71.     #include "../tcp/tcp_module.h"
  72.  
  73. #endif
  74. */
  75. #define NAME    "Networking"
  76.  
  77. #define LO_NAME             "lo"
  78. #define LO_FILENAME         "/srv/lo"
  79. #define DP8390_NAME         "dp8390"
  80. #define DP8390_FILENAME     "/srv/dp8390"
  81. #define ETHERNET_NAME       "ethernet"
  82. #define ETHERNET_FILENAME   "/srv/eth"
  83. #define IP_NAME             "ip"
  84. #define IP_FILENAME         "/srv/ip"
  85.  
  86. #define CONF_NAME           "NAME"
  87. #define CONF_NETIF          "NETIF"
  88. #define CONF_NIL            "NIL"
  89. #define CONF_IL             "IL"
  90. #define CONF_IRQ            "IRQ"
  91. #define CONF_IO             "IO"
  92. #define CONF_MTU            "MTU"
  93.  
  94. #define IPC_GET_DEVICE( call )  ( device_id_t ) IPC_GET_ARG1( * call )
  95. #define IPC_GET_COUNT( call )   ( int ) IPC_GET_ARG2( * call )
  96.  
  97. typedef struct netif        netif_t;
  98. typedef netif_t *       netif_ref;
  99.  
  100. typedef struct networking_globals   networking_globals_t;
  101.  
  102. DEVICE_MAP_DECLARE( netifs, netif_t )
  103.  
  104. GENERIC_CHAR_MAP_DECLARE( measured_strings, measured_string_t )
  105.  
  106. /** A present network interface device.
  107.  */
  108. struct netif{
  109.     /** A system-unique network interface identifier.
  110.      */
  111.     device_id_t     id;
  112.     /** A serving network interface driver module index.
  113.      */
  114.     module_ref      driver;
  115.     /** A serving link layer module index.
  116.      */
  117.     module_ref      nil;
  118.     /** A serving internet layer module index.
  119.      */
  120.     module_ref      il;
  121.     /** A system-unique network interface name.
  122.      */
  123.     char *          name;
  124.     /** Configuration.
  125.      */
  126.     measured_strings_t  configuration;
  127. };
  128.  
  129. /** A networking module global variables.
  130.  */
  131. struct networking_globals{
  132.     /** Present network interfaces.
  133.      */
  134.     netifs_t        netifs;
  135.     /** Network interface structure indices by names.
  136.      */
  137.     char_map_t      netif_names;
  138.     /** Available modules.
  139.      */
  140.     modules_t       modules;
  141.     /** Global configuration.
  142.      */
  143.     measured_strings_t  configuration;
  144. };
  145.  
  146. void    networking_print_name( void );
  147. measured_string_ref configuration_find( measured_strings_ref configuration, const char * name );
  148. int networking_start_module( async_client_conn_t client_connection );
  149. int     networking_initialize( void );
  150. int networking_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
  151. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
  152. //int       parse_line( measured_strings_ref configuration, char * line );
  153. int     add_configuration( measured_strings_ref configuration, const char * name, const char * value );
  154. int     read_configuration( void );
  155. int     read_netif_configuration( char * name, netif_ref netif );
  156. int     start_device( netif_ref netif );
  157. int     startup( void );
  158. device_id_t generate_new_device_id( void );
  159.  
  160. static networking_globals_t networking_globals;
  161.  
  162. DEVICE_MAP_IMPLEMENT( netifs, netif_t )
  163.  
  164. GENERIC_CHAR_MAP_IMPLEMENT( measured_strings, measured_string_t )
  165.  
  166. void networking_print_name( void ){
  167.     printf( "%s", NAME );
  168. }
  169.  
  170. int networking_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  171. /*#ifdef NETWORKING_module
  172.         //TODO map to *_message
  173.         if( IS_NET_IL_MESSAGE( call ) || IS_NET_IP_MESSAGE( call )){
  174.             return ip_message( callid, call, answer, answer_count );
  175. *//*        }else if( IS_NET_ARP_MESSAGE( call )){
  176.             return arp_message( callid, call, answer, answer_count );
  177. *//*        }else if( IS_NET_RARP_MESSAGE( call )){
  178.             return rarp_message( callid, call, answer, answer_count );
  179. *//*        }else if( IS_NET_ICMP_MESSAGE( call )){
  180.             return icmp_message( callid, call, answer, answer_count );
  181. *//*        }else if( IS_NET_UDP_MESSAGE( call )){
  182.             return udp_message( callid, call, answer, answer_count );
  183. *//*        }else if( IS_NET_TCP_MESSAGE( call )){
  184.             return tcp_message( callid, call, answer, answer_count );
  185. *//*        }else if( IS_NET_SOCKET_MESSAGE( call )){
  186.             return socket_message( callid, call, answer, answer_count );
  187. *//*        }else if( IS_NET_NIL_MESSAGE( call ) || IS_NET_ETHERNET_MESSAGE( call )){
  188.             return ethernet_message( callid, call, answer, answer_count );
  189. *//*        }else{
  190. #endif
  191. */          if( IS_NET_PACKET_MESSAGE( call )){
  192.                 return packet_server_message( callid, call, answer, answer_count );
  193.             }else{
  194.                 return net_message( callid, call, answer, answer_count );
  195.             }
  196. /*#ifdef NETWORKING_module
  197.         }
  198. #endif
  199. */
  200. }
  201.  
  202. int networking_start_module( async_client_conn_t client_connection ){
  203.     ERROR_DECLARE;
  204.  
  205.     ipcarg_t    phonehash;
  206.  
  207.     async_set_client_connection( client_connection );
  208.     ERROR_PROPAGATE( pm_init());
  209.     if( ERROR_OCCURRED( networking_initialize())
  210.     || ERROR_OCCURRED( REGISTER_ME( SERVICE_NETWORKING, & phonehash ))){
  211.         pm_destroy();
  212.         return ERROR_CODE;
  213.     }
  214.  
  215.     async_manager();
  216.  
  217.     pm_destroy();
  218.     return EOK;
  219. }
  220.  
  221. int networking_initialize( void ){
  222.     ERROR_DECLARE;
  223.  
  224.     task_id_t   task_id;
  225.  
  226.     netifs_initialize( & networking_globals.netifs );
  227.     char_map_initialize( & networking_globals.netif_names );
  228.     modules_initialize( & networking_globals.modules );
  229.     measured_strings_initialize( & networking_globals.configuration );
  230.  
  231.     // run self tests
  232. //  ERROR_PROPAGATE( self_test());
  233.  
  234.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0 ));
  235.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0 ));
  236.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0 ));
  237.  
  238. //#ifdef NETWORKING_modular
  239.     task_id = spawn( "/srv/ip" );
  240.     if( ! task_id ) return EINVAL;
  241.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_id ));
  242. //  if( ! spawn( "/srv/udp" )) return EINVAL;
  243. //  if( ! spawn( "/srv/tcp" )) return EINVAL;
  244. //  if( ! spawn( "/srv/socket" )) return EINVAL;
  245. //  not always necesssary
  246. //  if( ! spawn( "/srv/arp" )) return EINVAL;
  247. //  if( ! spawn( "/srv/rarp" )) return EINVAL;
  248. //  if( ! spawn( "/srv/icmp" )) return EINVAL;
  249. /*
  250. #else
  251. #ifdef NETWORKING_module
  252.     ipcarg_t    phonehash;
  253.  
  254.     ERROR_PROPAGATE( REGISTER_ME( SERVICE_IP, & phonehash ));
  255.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_get_id()));
  256.     ERROR_PROPAGATE( ip_initialize());
  257. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ARP, & phonehash ));
  258. //  ERROR_PROPAGATE( arp_initialize());
  259. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_RARP, & phonehash ));
  260. //  ERROR_PROPAGATE( rarp_initialize());
  261. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ICMP, & phonehash ));
  262. //  ERROR_PROPAGATE( icmp_initialize());
  263. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_UDP, & phonehash ));
  264. //  ERROR_PROPAGATE( udp_initialize());
  265.     ERROR_PROPAGATE( REGISTER_ME( SERVICE_TCP, & phonehash ));
  266.     ERROR_PROPAGATE( tcp_initialize());
  267. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_SOCKET, & phonehash ));
  268. //  ERROR_PROPAGATE( socket_initialize());
  269. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ETHERNET, & phonehash ));
  270. //  ERROR_PROPAGATE( ethernet_initialize());
  271. #endif
  272. #endif
  273. */
  274.     return EOK;
  275. }
  276.  
  277. //TODO as ip.c
  278. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  279.     ERROR_DECLARE;
  280.  
  281.     measured_string_ref strings;
  282.     char *          data;
  283.     int         index;
  284.     measured_string_ref setting;
  285.     measured_strings_ref    configuration;
  286.     netif_ref       netif;
  287.  
  288.     * answer_count = 0;
  289.     switch( IPC_GET_METHOD( * call )){
  290.         case IPC_M_PHONE_HUNGUP:
  291.             return EOK;
  292.         case NET_NET_DEVICE:
  293.             // TODO configure, register
  294.             printf( "\nNetworking: new netif %d", IPC_GET_DEVICE( call ));
  295.             return EOK;
  296.         case NET_NET_GET_DEVICE_CONF:
  297.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  298.             netif = netifs_find( & networking_globals.netifs, IPC_GET_DEVICE( call ));
  299.             if( netif ){
  300.                 configuration = & netif->configuration;
  301.             }else{
  302.                 configuration = NULL;
  303.             }
  304.             for( index = 0; index < IPC_GET_COUNT( call ); ++ index ){
  305.                 setting = measured_strings_find( configuration, strings[ index ].value, 0 );
  306.                 if( ! setting ){
  307.                     setting = measured_strings_find( & networking_globals.configuration, strings[ index ].value, 0 );
  308.                 }
  309.                 if( setting ){
  310.                     strings[ index ].length = setting->length;
  311.                     strings[ index ].value = setting->value;
  312.                 }else{
  313.                     strings[ index ].length = 0;
  314.                     strings[ index ].value = NULL;
  315.                 }
  316.             }
  317.             // strings should not contain received data anymore
  318.             free( data );
  319.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  320.             free( strings );
  321.             return ERROR_CODE;
  322.         case NET_NET_GET_CONF:
  323.             // arg1 = count
  324.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  325.             for( index = 0; index < IPC_GET_COUNT( call ); ++ index ){
  326.                 setting = measured_strings_find( & networking_globals.configuration, strings[ index ].value, 0 );
  327.                 if( setting ){
  328.                     strings[ index ].length = setting->length;
  329.                     strings[ index ].value = setting->value;
  330.                 }else{
  331.                     strings[ index ].length = 0;
  332.                     strings[ index ].value = NULL;
  333.                 }
  334.             }
  335.             // strings should not contain received data anymore
  336.             free( data );
  337.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  338.             free( strings );
  339.             return ERROR_CODE;
  340.         case NET_NET_STARTUP:
  341.             return startup();
  342.     }
  343.     return ENOTSUP;
  344. }
  345.  
  346. /*
  347. int parse_line( measured_strings_ref configuration, char * line ){
  348.     ERROR_DECLARE;
  349.  
  350.     measured_string_ref setting;
  351.     char *          name;
  352.     char *          value;
  353.  
  354.     // from the beginning
  355.     name = line;
  356.     // skip spaces
  357.     while( isspace( * name )) ++ name;
  358.     // remember the name start
  359.     value = name;
  360.     // skip the name
  361.     while( isalnum( * value ) || ( * value == '_' )){
  362.         // make uppercase
  363. //      * value = toupper( * value );
  364.         ++ value;
  365.     }
  366.     if( * value == '=' ){
  367.         // terminate the name
  368.         * value = '\0';
  369.     }else{
  370.         // terminate the name
  371.         * value = '\0';
  372.         // skip until '='
  373.         ++ value;
  374.         while(( * value ) && ( * value != '=' )) ++ value;
  375.         // not found?
  376.         if( * value != '=' ) return EINVAL;
  377.     }
  378.     ++ value;
  379.     // skip spaces
  380.     while( isspace( * value )) ++ value;
  381.     // create a bulk measured string till the end
  382.     setting = measured_string_create_bulk( value, -1 );
  383.     if( ! setting ) return ENOMEM;
  384.     // add the configuration setting
  385.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  386.         free( setting );
  387.         return ERROR_CODE;
  388.     }
  389.     return EOK;
  390. }
  391. */
  392.  
  393. int add_configuration( measured_strings_ref configuration, const char * name, const char * value ){
  394.     ERROR_DECLARE;
  395.  
  396.     measured_string_ref setting;
  397.  
  398.     setting = measured_string_create_bulk( value, 0 );
  399.     if( ! setting ) return ENOMEM;
  400.     // add the configuration setting
  401.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  402.         free( setting );
  403.         return ERROR_CODE;
  404.     }
  405.     return EOK;
  406. }
  407.  
  408. device_id_t generate_new_device_id( void ){
  409.     return device_assign_devno();
  410. }
  411.  
  412. int read_configuration( void ){
  413.     ERROR_DECLARE;
  414.  
  415.     // read general configuration
  416.     ERROR_PROPAGATE( add_configuration( & networking_globals.configuration, "IPV", "4" ));
  417.     ERROR_PROPAGATE( add_configuration( & networking_globals.configuration, "MTU", "1500" ));
  418.     return EOK;
  419. }
  420.  
  421. int read_netif_configuration( char * name, netif_ref netif ){
  422.     ERROR_DECLARE;
  423.  
  424.     if( strncmp( name, "lo", 2 ) == 0 ){
  425.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME ));
  426.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME ));
  427.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME ));
  428.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" ));
  429.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" ));
  430.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" ));
  431.     }else if( strncmp( name, "ne2k", 4 ) == 0 ){
  432.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" ));
  433.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME ));
  434. #ifdef NETWORKING_module
  435.         // ethernet bundled in dp8390
  436.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", DP8390_NAME ));
  437. #else
  438.         // standalone ethernet
  439.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", ETHERNET_NAME ));
  440. #endif
  441.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME ));
  442.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IRQ", "9" ));
  443.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IO", "300" ));
  444.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "1492" ));
  445.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" ));
  446.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.5" ));
  447.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.255.255.0" ));
  448.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" ));
  449.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" ));
  450.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" ));
  451.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" ));
  452.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "ARP", "arp" ));
  453.     }
  454.     return EOK;
  455. }
  456.  
  457. int start_device( netif_ref netif ){
  458.     ERROR_DECLARE;
  459.  
  460.     measured_string_ref setting;
  461.     services_t          internet_service;
  462.     int                 irq;
  463.     int                 io;
  464.     int                 mtu;
  465.  
  466.     // mandatory netif
  467.     setting = measured_strings_find( & netif->configuration, CONF_NETIF, 0 );
  468.     netif->driver = get_running_module( & networking_globals.modules, setting->value );
  469.     if( ! netif->driver ){
  470.         printf( "\nFailed to start the network interface driver %s", setting->value );
  471.         return EINVAL;
  472.     }
  473.     // optional network interface layer
  474.     setting = measured_strings_find( & netif->configuration, CONF_NIL, 0 );
  475.     if( setting ){
  476.         netif->nil = get_running_module( & networking_globals.modules, setting->value );
  477.         if( ! netif->nil ){
  478.             printf( "\nFailed to start the network interface layer %s", setting->value );
  479.             return EINVAL;
  480.         }
  481.     }else{
  482.         netif->nil = NULL;
  483.     }
  484.     // mandatory internet layer
  485.     setting = measured_strings_find( & netif->configuration, CONF_IL, 0 );
  486.     netif->il = get_running_module( & networking_globals.modules, setting->value );
  487.     if( ! netif->il ){
  488.         printf( "\nFailed to start the internet layer %s", setting->value );
  489.         return EINVAL;
  490.     }
  491.     // end of the static loopback initialization
  492.     // startup the loopback interface
  493.     setting = measured_strings_find( & netif->configuration, CONF_IRQ, 0 );
  494.     irq = setting ? strtol( setting->value, NULL, 10 ) : 0;
  495.     setting = measured_strings_find( & netif->configuration, CONF_IO, 0 );
  496.     io = setting ? strtol( setting->value, NULL, 16 ) : 0;
  497.     ERROR_PROPAGATE( netif_probe_req( netif->driver->phone, netif->id, irq, io ));
  498.     if( netif->nil ){
  499.         setting = measured_strings_find( & netif->configuration, CONF_MTU, 0 );
  500.         if( ! setting ){
  501.             setting = measured_strings_find( & networking_globals.configuration, CONF_MTU, 0 );
  502.         }
  503.         mtu = setting ? strtol( setting->value, NULL, 10 ) : 0;
  504.         ERROR_PROPAGATE( nil_device_req( netif->nil->phone, netif->id, mtu, netif->driver->service ));
  505.         internet_service = netif->nil->service;
  506.     }else{
  507.         internet_service = netif->driver->service;
  508.     }
  509.     // TODO IL_BUNDLE
  510.     ERROR_PROPAGATE( async_req_3_0( netif->il->phone, NET_IL_DEVICE, netif->id, 0, internet_service ));
  511.     ERROR_PROPAGATE( netif_start_req( netif->driver->phone, netif->id ));
  512.     return EOK;
  513. }
  514.  
  515. int startup( void ){
  516.     ERROR_DECLARE;
  517.  
  518.     char *      conf_files[] = { "lo", "ne2k" };
  519.     int         count = sizeof( conf_files ) / sizeof( char * );
  520.     int         index;
  521.     netif_ref   netif;
  522.     int         i;
  523.     measured_string_ref setting;
  524.  
  525.     // TODO dynamic configuration
  526.     ERROR_PROPAGATE( read_configuration());
  527.  
  528.     for( i = 0; i < count; ++ i ){
  529.         netif = ( netif_ref ) malloc( sizeof( netif_t ));
  530.         if( ! netif ) return ENOMEM;
  531.  
  532.         netif->id = generate_new_device_id();
  533.         if( ! netif->id ) return EXDEV;
  534.         ERROR_PROPAGATE( measured_strings_initialize( & netif->configuration ));
  535.         // read configuration files
  536.         if( ERROR_OCCURRED( read_netif_configuration( conf_files[ i ], netif ))){
  537.             measured_strings_destroy( & netif->configuration );
  538.             free( netif );
  539.             return ERROR_CODE;
  540.         }
  541.         // mandatory name
  542.         setting = measured_strings_find( & netif->configuration, CONF_NAME, 0 );
  543.         if( ! setting ){
  544.             printf( "\nThe name is missing" );
  545.             measured_strings_destroy( & netif->configuration );
  546.             free( netif );
  547.             return EINVAL;
  548.         }
  549.         netif->name = setting->value;
  550.         // add to the netifs map
  551.         index = netifs_add( & networking_globals.netifs, netif->id, netif );
  552.         if( index < 0 ){
  553.             measured_strings_destroy( & netif->configuration );
  554.             free( netif );
  555.             return index;
  556.         }
  557.         // add to the netif names map
  558.         if( ERROR_OCCURRED( char_map_add( & networking_globals.netif_names, netif->name, 0, index ))
  559.         // start network interfaces and needed modules
  560.         || ERROR_OCCURRED( start_device( netif ))){
  561.             measured_strings_destroy( & netif->configuration );
  562.             netifs_exclude_index( & networking_globals.netifs, index );
  563.             return ERROR_CODE;
  564.         }
  565.         // increment modules' usage
  566.         ++ netif->driver->usage;
  567.         if( netif->nil ) ++ netif->nil->usage;
  568.         ++ netif->il->usage;
  569.         printf( "\nNew network interface started:\n\tname\t= %s\n\tid\t= %d\n\tdriver\t= %s\n\tnil\t= %s\n\til\t= %s", netif->name, netif->id, netif->driver->name, netif->nil ? netif->nil->name : NULL, netif->il->name );
  570.     }
  571.     return EOK;
  572. }
  573.  
  574. /** @}
  575.  */
  576.