Subversion Repositories HelenOS

Rev

Rev 4155 | 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. #include <task.h>
  43. #include <unistd.h>
  44.  
  45. #include <ipc/ipc.h>
  46. #include <ipc/services.h>
  47.  
  48. #include "../err.h"
  49. #include "../messages.h"
  50. #include "../modules.h"
  51. //#include "../self_test.h"
  52.  
  53. #include "../structures/char_map.h"
  54. #include "../structures/generic_char_map.h"
  55. #include "../structures/measured_strings.h"
  56. #include "../structures/packet/packet.h"
  57. #include "../structures/packet/packet_server.h"
  58.  
  59. #include "../il/ip/ip_messages.h"
  60. #include "../netif/device.h"
  61.  
  62. #if IP_BUNDLE
  63.  
  64.     #include "../ip/ip_module.h"
  65.  
  66. #endif
  67.  
  68. #if TCP_BUNDLE
  69.  
  70.     #include "../tcp/tcp_module.h"
  71.  
  72. #endif
  73.  
  74. #define NAME    "Networking"
  75.  
  76. #define LO_NAME             "lo"
  77. #define LO_FILENAME         "/srv/lo"
  78. #define DP8390_NAME         "dp8390"
  79. #define DP8390_FILENAME     "/srv/dp8390"
  80. #define ETHERNET_NAME       "ethernet"
  81. #define ETHERNET_FILENAME   "/srv/eth"
  82. #define IP_NAME             "ip"
  83. #define IP_FILENAME         "/srv/ip"
  84.  
  85. #define CONF_NAME           "NAME"
  86. #define CONF_NETIF          "NETIF"
  87. #define CONF_NIL            "NIL"
  88. #define CONF_IL             "IL"
  89. #define CONF_IRQ            "IRQ"
  90. #define CONF_IO             "IO"
  91. #define CONF_MTU            "MTU"
  92.  
  93. #define IPC_GET_DEVICE( call )  ( device_id_t ) IPC_GET_ARG1( * call )
  94. #define IPC_GET_COUNT( call )   ( int ) IPC_GET_ARG2( * call )
  95.  
  96. typedef struct module_struct    module_t;
  97. typedef module_t *      module_ref;
  98.  
  99. typedef struct netif        netif_t;
  100. typedef netif_t *       netif_ref;
  101.  
  102. typedef struct networking_globals   networking_globals_t;
  103.  
  104. DEVICE_MAP_DECLARE( netifs, netif_t )
  105.  
  106. GENERIC_CHAR_MAP_DECLARE( measured_strings, measured_string_t )
  107.  
  108. GENERIC_CHAR_MAP_DECLARE( modules, module_t )
  109.  
  110. struct module_struct{
  111.     task_id_t   task_id;
  112.     services_t  service;
  113.     int         phone;
  114.     int         usage;
  115.     char *      name;
  116.     char *      filename;
  117. };
  118.  
  119. /** A present network interface device.
  120.  */
  121. struct netif{
  122.     /** A system-unique network interface identifier.
  123.      */
  124.     device_id_t     id;
  125.     /** A serving network interface driver module index.
  126.      */
  127.     module_ref      driver;
  128.     /** A serving link layer module index.
  129.      */
  130.     module_ref      nil;
  131.     /** A serving internet layer module index.
  132.      */
  133.     module_ref      il;
  134.     /** A system-unique network interface name.
  135.      */
  136.     char *          name;
  137.     /** Configuration.
  138.      */
  139.     measured_strings_t  configuration;
  140. };
  141.  
  142. /** A networking module global variables.
  143.  */
  144. struct networking_globals{
  145.     /** Present network interfaces.
  146.      */
  147.     netifs_t        netifs;
  148.     /** Network interface structure indices by names.
  149.      */
  150.     char_map_t      netif_names;
  151.     /** Available modules.
  152.      */
  153.     modules_t       modules;
  154.     /** Global configuration.
  155.      */
  156.     measured_strings_t  configuration;
  157. };
  158.  
  159. void    networking_print_name( void );
  160. int     add_module( module_ref * module, modules_ref modules, char * name, char * filename, services_t service, task_id_t task_id );
  161. measured_string_ref configuration_find( measured_strings_ref configuration, const char * name );
  162. int networking_start_module( async_client_conn_t client_connection );
  163. int     networking_initialize( void );
  164. int networking_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
  165. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
  166. //int       parse_line( measured_strings_ref configuration, char * line );
  167. int     add_configuration( measured_strings_ref configuration, const char * name, const char * value );
  168. int     read_configuration( void );
  169. task_id_t   spawn( char * fname );
  170. int     startup( void );
  171. device_id_t generate_new_device_id( void );
  172.  
  173. static networking_globals_t networking_globals;
  174.  
  175. DEVICE_MAP_IMPLEMENT( netifs, netif_t )
  176.  
  177. GENERIC_CHAR_MAP_IMPLEMENT( measured_strings, measured_string_t )
  178.  
  179. GENERIC_CHAR_MAP_IMPLEMENT( modules, module_t )
  180.  
  181. void networking_print_name( void ){
  182.     printf( NAME );
  183. }
  184.  
  185. int add_module( module_ref * module, modules_ref modules, char * name, char * filename, services_t service, task_id_t task_id ){
  186.     ERROR_DECLARE;
  187.  
  188.     module_ref  tmp_module;
  189.  
  190.     tmp_module = ( module_ref ) malloc( sizeof( module_t ));
  191.     if( ! tmp_module ) return ENOMEM;
  192.     tmp_module->task_id = task_id;
  193.     tmp_module->phone = 0;
  194.     tmp_module->usage = 0;
  195.     tmp_module->name = name;
  196.     tmp_module->filename = filename;
  197.     tmp_module->service = service;
  198.     if( ERROR_OCCURRED( modules_add( modules, tmp_module->name, 0, tmp_module ))){
  199.         free( tmp_module );
  200.         return ERROR_CODE;
  201.     }
  202.     if( module ) * module = tmp_module;
  203.     return EOK;
  204. }
  205.  
  206. int networking_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  207. #ifdef NETWORKING_module
  208.         //TODO map to *_message
  209.         if( IS_NET_IL_MESSAGE( call ) || IS_NET_IP_MESSAGE( call )){
  210.             return ip_message( callid, call, answer, answer_count );
  211. /*      }else if( IS_NET_ARP_MESSAGE( call )){
  212.             return arp_message( callid, call, answer, answer_count );
  213. *//*        }else if( IS_NET_RARP_MESSAGE( call )){
  214.             return rarp_message( callid, call, answer, answer_count );
  215. *//*        }else if( IS_NET_ICMP_MESSAGE( call )){
  216.             return icmp_message( callid, call, answer, answer_count );
  217. *//*        }else if( IS_NET_UDP_MESSAGE( call )){
  218.             return udp_message( callid, call, answer, answer_count );
  219. */      }else if( IS_NET_TCP_MESSAGE( call )){
  220.             return tcp_message( callid, call, answer, answer_count );
  221. /*      }else if( IS_NET_SOCKET_MESSAGE( call )){
  222.             return socket_message( callid, call, answer, answer_count );
  223. *//*        }else if( IS_NET_NIL_MESSAGE( call ) || IS_NET_ETHERNET_MESSAGE( call )){
  224.             return ethernet_message( callid, call, answer, answer_count );
  225. */      }else{
  226. #endif
  227.             if( IS_NET_PACKET_MESSAGE( call )){
  228.                 return packet_server_message( callid, call, answer, answer_count );
  229.             }else{
  230.                 return net_message( callid, call, answer, answer_count );
  231.             }
  232. #ifdef NETWORKING_module
  233.         }
  234. #endif
  235. }
  236.  
  237. int networking_start_module( async_client_conn_t client_connection ){
  238.     ERROR_DECLARE;
  239.  
  240.     ipcarg_t    phonehash;
  241.  
  242.     async_set_client_connection( client_connection );
  243.     ERROR_PROPAGATE( pm_init());
  244.     if( ERROR_OCCURRED( networking_initialize())
  245.     || ERROR_OCCURRED( REGISTER_ME( SERVICE_NETWORKING, & phonehash ))){
  246.         pm_destroy();
  247.         return ERROR_CODE;
  248.     }
  249.  
  250.     async_manager();
  251.  
  252.     pm_destroy();
  253.     return EOK;
  254. }
  255.  
  256. int networking_initialize( void ){
  257.     ERROR_DECLARE;
  258.  
  259.     task_id_t   task_id;
  260.  
  261.     netifs_initialize( & networking_globals.netifs );
  262.     char_map_initialize( & networking_globals.netif_names );
  263.     modules_initialize( & networking_globals.modules );
  264.     measured_strings_initialize( & networking_globals.configuration );
  265.  
  266.     // run self tests
  267. //  ERROR_PROPAGATE( self_test());
  268.  
  269.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0 ));
  270.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0 ));
  271.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0 ));
  272.  
  273. #ifdef NETWORKING_modular
  274.     task_id = spawn( "/srv/ip" );
  275.     if( ! task_id ) return EINVAL;
  276.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_id ));
  277. //  if( ! spawn( "/srv/udp" )) return EINVAL;
  278. //  if( ! spawn( "/srv/tcp" )) return EINVAL;
  279. //  if( ! spawn( "/srv/socket" )) return EINVAL;
  280. //  not always necesssary
  281. //  if( ! spawn( "/srv/arp" )) return EINVAL;
  282. //  if( ! spawn( "/srv/rarp" )) return EINVAL;
  283. //  if( ! spawn( "/srv/icmp" )) return EINVAL;
  284.  
  285. #else
  286. #ifdef NETWORKING_module
  287.     ipcarg_t    phonehash;
  288.  
  289.     ERROR_PROPAGATE( REGISTER_ME( SERVICE_IP, & phonehash ));
  290.     ERROR_PROPAGATE( add_module( NULL, & networking_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_get_id()));
  291.     ERROR_PROPAGATE( ip_initialize());
  292. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ARP, & phonehash ));
  293. //  ERROR_PROPAGATE( arp_initialize());
  294. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_RARP, & phonehash ));
  295. //  ERROR_PROPAGATE( rarp_initialize());
  296. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ICMP, & phonehash ));
  297. //  ERROR_PROPAGATE( icmp_initialize());
  298. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_UDP, & phonehash ));
  299. //  ERROR_PROPAGATE( udp_initialize());
  300.     ERROR_PROPAGATE( REGISTER_ME( SERVICE_TCP, & phonehash ));
  301.     ERROR_PROPAGATE( tcp_initialize());
  302. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_SOCKET, & phonehash ));
  303. //  ERROR_PROPAGATE( socket_initialize());
  304. //  ERROR_PROPAGATE( REGISTER_ME( SERVICE_ETHERNET, & phonehash ));
  305. //  ERROR_PROPAGATE( ethernet_initialize());
  306. #endif
  307. #endif
  308.  
  309.     return EOK;
  310. }
  311.  
  312. //TODO as ip.c
  313. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  314.     ERROR_DECLARE;
  315.  
  316.     measured_string_ref strings;
  317.     char *          data;
  318.     int         index;
  319.     measured_string_ref setting;
  320.     measured_strings_ref    configuration;
  321.     netif_ref       netif;
  322.  
  323.     * answer_count = 0;
  324.     switch( IPC_GET_METHOD( * call )){
  325.         case IPC_M_PHONE_HUNGUP:
  326.             return EOK;
  327.         case NET_NET_DEVICE:
  328.             // TODO configure, register
  329.             printf( "\nNetworking: new netif %d", IPC_GET_DEVICE( call ));
  330.             return EOK;
  331.         case NET_NET_GET_DEVICE_CONF:
  332.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  333.             netif = netifs_find( & networking_globals.netifs, IPC_GET_DEVICE( call ));
  334.             if( netif ){
  335.                 configuration = & netif->configuration;
  336.             }else{
  337.                 configuration = NULL;
  338.             }
  339.             for( index = 0; index < IPC_GET_COUNT( call ); ++ index ){
  340.                 setting = measured_strings_find( configuration, strings[ index ].value, 0 );
  341.                 if( ! setting ){
  342.                     setting = measured_strings_find( & networking_globals.configuration, strings[ index ].value, 0 );
  343.                 }
  344.                 if( setting ){
  345.                     strings[ index ].length = setting->length;
  346.                     strings[ index ].value = setting->value;
  347.                 }else{
  348.                     strings[ index ].length = 0;
  349.                     strings[ index ].value = NULL;
  350.                 }
  351.             }
  352.             // strings should not contain received data anymore
  353.             free( data );
  354.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  355.             free( strings );
  356.             return ERROR_CODE;
  357.         case NET_NET_GET_CONF:
  358.             // arg1 = count
  359.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  360.             for( index = 0; index < IPC_GET_COUNT( call ); ++ index ){
  361.                 setting = measured_strings_find( & networking_globals.configuration, strings[ index ].value, 0 );
  362.                 if( setting ){
  363.                     strings[ index ].length = setting->length;
  364.                     strings[ index ].value = setting->value;
  365.                 }else{
  366.                     strings[ index ].length = 0;
  367.                     strings[ index ].value = NULL;
  368.                 }
  369.             }
  370.             // strings should not contain received data anymore
  371.             free( data );
  372.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  373.             free( strings );
  374.             return ERROR_CODE;
  375.         case NET_NET_STARTUP:
  376.             return startup();
  377.     }
  378.     return ENOTSUP;
  379. }
  380.  
  381. /*
  382. int parse_line( measured_strings_ref configuration, char * line ){
  383.     ERROR_DECLARE;
  384.  
  385.     measured_string_ref setting;
  386.     char *          name;
  387.     char *          value;
  388.  
  389.     // from the beginning
  390.     name = line;
  391.     // skip spaces
  392.     while( isspace( * name )) ++ name;
  393.     // remember the name start
  394.     value = name;
  395.     // skip the name
  396.     while( isalnum( * value ) || ( * value == '_' )){
  397.         // make uppercase
  398. //      * value = toupper( * value );
  399.         ++ value;
  400.     }
  401.     if( * value == '=' ){
  402.         // terminate the name
  403.         * value = '\0';
  404.     }else{
  405.         // terminate the name
  406.         * value = '\0';
  407.         // skip until '='
  408.         ++ value;
  409.         while(( * value ) && ( * value != '=' )) ++ value;
  410.         // not found?
  411.         if( * value != '=' ) return EINVAL;
  412.     }
  413.     ++ value;
  414.     // skip spaces
  415.     while( isspace( * value )) ++ value;
  416.     // create a bulk measured string till the end
  417.     setting = measured_string_create_bulk( value, -1 );
  418.     if( ! setting ) return ENOMEM;
  419.     // add the configuration setting
  420.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  421.         free( setting );
  422.         return ERROR_CODE;
  423.     }
  424.     return EOK;
  425. }
  426. */
  427.  
  428. int add_configuration( measured_strings_ref configuration, const char * name, const char * value ){
  429.     ERROR_DECLARE;
  430.  
  431.     measured_string_ref setting;
  432.  
  433.     setting = measured_string_create_bulk( value, 0 );
  434.     if( ! setting ) return ENOMEM;
  435.     // add the configuration setting
  436.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  437.         free( setting );
  438.         return ERROR_CODE;
  439.     }
  440.     return EOK;
  441. }
  442.  
  443. device_id_t generate_new_device_id( void ){
  444.     return device_assign_devno();
  445. }
  446.  
  447. int read_configuration( void ){
  448.     ERROR_DECLARE;
  449.  
  450.     netif_ref           netif;
  451.     measured_string_ref setting;
  452.     services_t          internet_service;
  453.     int                 index;
  454.     int                 irq;
  455.     int                 io;
  456.     int                 mtu;
  457.  
  458.     // read general configuration
  459.     ERROR_PROPAGATE( add_configuration( & networking_globals.configuration, "IPV", "4" ));
  460.     ERROR_PROPAGATE( add_configuration( & networking_globals.configuration, "MTU", "1500" ));
  461.  
  462.     // read network interfaces configuration
  463.  
  464.     netif = ( netif_ref ) malloc( sizeof( netif_t ));
  465.     if( ! netif ) return ENOMEM;
  466.     netif->id = generate_new_device_id();
  467.     ERROR_PROPAGATE( measured_strings_initialize( & netif->configuration ));
  468.     if( ERROR_OCCURRED( add_configuration( & netif->configuration, "NAME", "eth0" ))
  469.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "NETIF", DP8390_NAME ))
  470.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "NIL", ETHERNET_NAME ))
  471.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IL", IP_NAME ))
  472.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IRQ", "9" ))
  473.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IO", "300" ))
  474.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IP_CONFIG", "STATIC" ))
  475.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.5" ))
  476.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "NETMASK", "255.255.255.0" ))
  477.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" ))
  478.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" ))
  479.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" ))
  480.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" ))
  481.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "ARP", "ARP" ))){
  482.         measured_strings_destroy( & netif->configuration );
  483.         free( netif );
  484.         return ERROR_CODE;
  485.     }
  486. /*  if( ERROR_OCCURRED( add_configuration( & netif->configuration, "NAME", LO_NAME ))
  487.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "NETIF", LO_NAME ))
  488.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IL", IP_NAME ))
  489.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IP_CONFIG", "STATIC" ))
  490.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" ))
  491.     || ERROR_OCCURRED( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" ))){
  492.         measured_strings_destroy( & netif->configuration );
  493.         free( netif );
  494.         return ERROR_CODE;
  495.     }
  496. */  // mandatory name
  497.     setting = measured_strings_find( & netif->configuration, CONF_NAME, 0 );
  498.     if( ! setting ){
  499.         printf( "\nThe name is missing" );
  500.         measured_strings_destroy( & netif->configuration );
  501.         free( netif );
  502.         return EINVAL;
  503.     }
  504.     netif->name = setting->value;
  505.     // mandatory netif
  506.     setting = measured_strings_find( & netif->configuration, CONF_NETIF, 0 );
  507.     if( ! setting ){
  508.         printf( "\nThe network interface driver is missing" );
  509.         measured_strings_destroy( & netif->configuration );
  510.         free( netif );
  511.         return EINVAL;
  512.     }
  513.     netif->driver = modules_find( & networking_globals.modules, setting->value, 0 );
  514.     if( ! netif->driver ){
  515.         printf( "\nThe network interface driver is unknown" );
  516.         // TODO register the unknown one
  517.         measured_strings_destroy( & netif->configuration );
  518.         free( netif );
  519.         return EINVAL;
  520.     }
  521.     if( ! netif->driver->task_id ){
  522.         netif->driver->task_id = spawn( netif->driver->filename );
  523.         if( ! netif->driver->task_id ){
  524.             printf( "\nFailed to start the network interface driver" );
  525.             measured_strings_destroy( & netif->configuration );
  526.             free( netif );
  527.             return EINVAL;
  528.         }
  529.     }
  530.     // optional network interface layer
  531.     setting = measured_strings_find( & netif->configuration, CONF_NIL, 0 );
  532.     if( setting ){
  533.         netif->nil = modules_find( & networking_globals.modules, setting->value, 0 );
  534.         if( ! netif->nil ){
  535.             printf( "\nThe network interface layer is unknown" );
  536.             // TODO register the unknown one
  537.             -- netif->driver->usage;
  538.             measured_strings_destroy( & netif->configuration );
  539.             free( netif );
  540.             return EINVAL;
  541.         }
  542.         if( ! netif->nil->task_id ){
  543.             netif->nil->task_id = spawn( netif->nil->filename );
  544.             if( ! netif->nil->task_id ){
  545.                 printf( "\nFailed to start the network interface layer" );
  546.                 -- netif->driver->usage;
  547.                 measured_strings_destroy( & netif->configuration );
  548.                 free( netif );
  549.                 return EINVAL;
  550.             }
  551.         }
  552.     }else{
  553.         netif->nil = NULL;
  554.     }
  555.     // mandatory internet layer
  556.     setting = measured_strings_find( & netif->configuration, CONF_IL, 0 );
  557.     if( ! setting ){
  558.         printf( "\nThe internet layer is missing" );
  559.         -- netif->driver->usage;
  560.         -- netif->nil->usage;
  561.         measured_strings_destroy( & netif->configuration );
  562.         free( netif );
  563.         return EINVAL;
  564.     }
  565.     netif->il = modules_find( & networking_globals.modules, setting->value, 0 );
  566.     if( ! netif->il ){
  567.         printf( "\nThe internet layer is unknown" );
  568.         // TODO register the unknown one
  569.         -- netif->driver->usage;
  570.         -- netif->nil->usage;
  571.         measured_strings_destroy( & netif->configuration );
  572.         free( netif );
  573.         return EINVAL;
  574.     }
  575.     if( ! netif->il->task_id ){
  576.         netif->il->task_id = spawn( netif->il->filename );
  577.         if( ! netif->il->task_id ){
  578.             printf( "\nFailed to start the internet layer" );
  579.             -- netif->driver->usage;
  580.             -- netif->nil->usage;
  581.             measured_strings_destroy( & netif->configuration );
  582.             free( netif );
  583.             return EINVAL;
  584.         }
  585.     }
  586.     index = netifs_add( & networking_globals.netifs, netif->id, netif );
  587.     if( index < 0 ){
  588.         free( netif );
  589.         return index;
  590.     }
  591.     if( ERROR_OCCURRED( char_map_add( & networking_globals.netif_names, netif->name, 0, index ))){
  592.         netifs_exclude_index( & networking_globals.netifs, index );
  593.         return ERROR_CODE;
  594.     }
  595.     // end of the static loopback initialization
  596.     // startup the loopback interface
  597.     if( ! netif->driver->phone ){
  598.         netif->driver->phone = connect_to_service( netif->driver->service );
  599.     }
  600.     setting = measured_strings_find( & netif->configuration, CONF_IRQ, 0 );
  601.     irq = setting ? strtol( setting->value, NULL, 10 ) : 0;
  602.     setting = measured_strings_find( & netif->configuration, CONF_IO, 0 );
  603.     io = setting ? strtol( setting->value, NULL, 16 ) : 0;
  604.     ERROR_PROPAGATE( async_req_3_0( netif->driver->phone, NET_NETIF_PROBE, netif->id, irq, io ));
  605.     ++ netif->driver->usage;
  606.     if( netif->nil ){
  607.         if( ! netif->nil->phone ){
  608.             netif->nil->phone = connect_to_service( netif->nil->service );
  609.         }
  610.         setting = measured_strings_find( & netif->configuration, CONF_MTU, 0 );
  611.         if( ! setting ){
  612.             setting = measured_strings_find( & networking_globals.configuration, CONF_MTU, 0 );
  613.         }
  614.         mtu = setting ? strtol( setting->value, NULL, 10 ) : 0;
  615.         ERROR_PROPAGATE( async_req_3_0( netif->nil->phone, NET_NIL_DEVICE, netif->id, netif->driver->service, mtu ));
  616.         ++ netif->nil->usage;
  617.         internet_service = netif->nil->service;
  618.     }else{
  619.         internet_service = netif->driver->service;
  620.     }
  621.     if( ! netif->il->phone ){
  622.         netif->il->phone = connect_to_service( netif->il->service );
  623.     }
  624.     // TODO IL_BUNDLE
  625.     ERROR_PROPAGATE( async_req_2_0( netif->il->phone, NET_IL_DEVICE, netif->id, internet_service ));
  626.     ++ netif->il->usage;
  627.     // TODO startup?
  628.     ERROR_PROPAGATE( async_req_1_0( netif->driver->phone, NET_NETIF_START, netif->id ));
  629.     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 );
  630.     return EOK;
  631. }
  632.  
  633. task_id_t spawn( char * fname ){
  634.     char * argv[ 2 ];
  635. //  char * argv[ 4 ];
  636.     task_id_t   res;
  637.  
  638. //  printf( "Spawning %s\n", fname );
  639.     argv[ 0 ] = fname;
  640.     argv[ 1 ] = NULL;
  641.     res = task_spawn( fname, argv );
  642. /*  argv[ 0 ] = "/app/trace";
  643.     argv[ 1 ] = "+ti";
  644.     argv[ 2 ] = fname;
  645.     argv[ 3 ] = NULL;
  646.     res = task_spawn( "/app/trace", argv );
  647. */
  648.     if( res != 0 ){
  649.         /* Success */
  650.         usleep( 50000 );
  651.     }
  652.     return res;
  653. }
  654.  
  655. int startup( void ){
  656.     ERROR_DECLARE;
  657.  
  658.     // read configuration files
  659.     if( ERROR_OCCURRED( read_configuration())) return ERROR_CODE;
  660.  
  661.     // start network interfaces and needed modules
  662. //  start_device( "/sbin/lo", "/sbin/dummy_link_layer" );
  663.     return EOK;
  664. }
  665.  
  666. /** @}
  667.  */
  668.