Subversion Repositories HelenOS

Rev

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