Subversion Repositories HelenOS

Rev

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

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