Subversion Repositories HelenOS

Rev

Rev 4271 | Rev 4351 | Go to most recent revision | Blame | Compare with Previous | 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.  
  57. #include "../il/il_messages.h"
  58. #include "../include/device.h"
  59. #include "../include/netif_interface.h"
  60. #include "../include/nil_interface.h"
  61. #include "../include/net_interface.h"
  62. #include "../include/ip_interface.h"
  63.  
  64. #include "net.h"
  65.  
  66. #define NAME    "Networking"
  67.  
  68. void    module_print_name( void );
  69. measured_string_ref configuration_find( measured_strings_ref configuration, const char * name );
  70. int module_start( async_client_conn_t client_connection );
  71. //int       parse_line( measured_strings_ref configuration, char * line );
  72. int     read_configuration( void );
  73. int     start_device( netif_ref netif );
  74. int     startup( void );
  75. device_id_t generate_new_device_id( void );
  76. int net_get_conf( measured_strings_ref device_conf, measured_string_ref configuration, int count, char ** data );
  77.  
  78. net_globals_t   net_globals;
  79.  
  80. DEVICE_MAP_IMPLEMENT( netifs, netif_t )
  81.  
  82. GENERIC_CHAR_MAP_IMPLEMENT( measured_strings, measured_string_t )
  83.  
  84. void module_print_name( void ){
  85.     printf( "%s", NAME );
  86. }
  87.  
  88. int module_start( async_client_conn_t client_connection ){
  89.     ERROR_DECLARE;
  90.  
  91.     ipcarg_t    phonehash;
  92.  
  93.     async_set_client_connection( client_connection );
  94.     ERROR_PROPAGATE( pm_init());
  95.     if( ERROR_OCCURRED( net_initialize())
  96.     || ERROR_OCCURRED( REGISTER_ME( SERVICE_NETWORKING, & phonehash ))){
  97.         pm_destroy();
  98.         return ERROR_CODE;
  99.     }
  100.  
  101.     async_manager();
  102.  
  103.     pm_destroy();
  104.     return EOK;
  105. }
  106.  
  107. int net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, int count, char ** data ){
  108.     netif_ref   netif;
  109.  
  110.     if( !( configuration && ( count > 0 ))) return EINVAL;
  111.     netif = netifs_find( & net_globals.netifs, device_id );
  112.     if( netif ){
  113.         return net_get_conf( & netif->configuration, * configuration, count, data );
  114.     }else{
  115.         return net_get_conf( NULL, * configuration, count, data );
  116.     }
  117. }
  118.  
  119. int net_get_conf_req( int net_phone, measured_string_ref * configuration, int count, char ** data ){
  120.     if( !( configuration && ( count > 0 ))) return EINVAL;
  121.     return net_get_conf( NULL, * configuration, count, data );
  122. }
  123.  
  124. int net_get_conf( measured_strings_ref device_conf, measured_string_ref configuration, int count, char ** data ){
  125.     measured_string_ref setting;
  126.     int                 index;
  127.  
  128.     if( data ) * data = NULL;
  129.     for( index = 0; index < count; ++ index ){
  130.         setting = measured_strings_find( device_conf, configuration[ index ].value, 0 );
  131.         if( ! setting ){
  132.             setting = measured_strings_find( & net_globals.configuration, configuration[ index ].value, 0 );
  133.         }
  134.         if( setting ){
  135.             configuration[ index ].length = setting->length;
  136.             configuration[ index ].value = setting->value;
  137.         }else{
  138.             configuration[ index ].length = 0;
  139.             configuration[ index ].value = NULL;
  140.         }
  141.     }
  142.     return EOK;
  143. }
  144.  
  145. void net_free_settings( measured_string_ref settings, char * data ){
  146. }
  147.  
  148. int net_connect_module( services_t service ){
  149.     return EOK;
  150. }
  151.  
  152. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  153.     ERROR_DECLARE;
  154.  
  155.     measured_string_ref strings;
  156.     char *              data;
  157.  
  158.     * answer_count = 0;
  159.     switch( IPC_GET_METHOD( * call )){
  160.         case IPC_M_PHONE_HUNGUP:
  161.             return EOK;
  162.         case NET_NET_DEVICE:
  163.             // TODO configure, register
  164.             printf( "Networking: new netif %d\n", IPC_GET_DEVICE( call ));
  165.             return EOK;
  166.         case NET_NET_GET_DEVICE_CONF:
  167.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  168.             net_get_device_conf_req( 0, IPC_GET_DEVICE( call ), & strings, IPC_GET_COUNT( call ), NULL );
  169.             // strings should not contain received data anymore
  170.             free( data );
  171.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  172.             free( strings );
  173.             return ERROR_CODE;
  174.         case NET_NET_GET_CONF:
  175.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  176.             net_get_conf_req( 0, & strings, IPC_GET_COUNT( call ), NULL );
  177.             // strings should not contain received data anymore
  178.             free( data );
  179.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  180.             free( strings );
  181.             return ERROR_CODE;
  182.         case NET_NET_STARTUP:
  183.             return startup();
  184.     }
  185.     return ENOTSUP;
  186. }
  187.  
  188. /*
  189. int parse_line( measured_strings_ref configuration, char * line ){
  190.     ERROR_DECLARE;
  191.  
  192.     measured_string_ref setting;
  193.     char *          name;
  194.     char *          value;
  195.  
  196.     // from the beginning
  197.     name = line;
  198.     // skip spaces
  199.     while( isspace( * name )) ++ name;
  200.     // remember the name start
  201.     value = name;
  202.     // skip the name
  203.     while( isalnum( * value ) || ( * value == '_' )){
  204.         // make uppercase
  205. //      * value = toupper( * value );
  206.         ++ value;
  207.     }
  208.     if( * value == '=' ){
  209.         // terminate the name
  210.         * value = '\0';
  211.     }else{
  212.         // terminate the name
  213.         * value = '\0';
  214.         // skip until '='
  215.         ++ value;
  216.         while(( * value ) && ( * value != '=' )) ++ value;
  217.         // not found?
  218.         if( * value != '=' ) return EINVAL;
  219.     }
  220.     ++ value;
  221.     // skip spaces
  222.     while( isspace( * value )) ++ value;
  223.     // create a bulk measured string till the end
  224.     setting = measured_string_create_bulk( value, -1 );
  225.     if( ! setting ) return ENOMEM;
  226.     // add the configuration setting
  227.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  228.         free( setting );
  229.         return ERROR_CODE;
  230.     }
  231.     return EOK;
  232. }
  233. */
  234.  
  235. int add_configuration( measured_strings_ref configuration, const char * name, const char * value ){
  236.     ERROR_DECLARE;
  237.  
  238.     measured_string_ref setting;
  239.  
  240.     setting = measured_string_create_bulk( value, 0 );
  241.     if( ! setting ) return ENOMEM;
  242.     // add the configuration setting
  243.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  244.         free( setting );
  245.         return ERROR_CODE;
  246.     }
  247.     return EOK;
  248. }
  249.  
  250. device_id_t generate_new_device_id( void ){
  251.     return device_assign_devno();
  252. }
  253.  
  254. int read_configuration( void ){
  255.     ERROR_DECLARE;
  256.  
  257.     // read general configuration
  258.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "IPV", "4" ));
  259.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "MTU", "1500" ));
  260.     return EOK;
  261. }
  262.  
  263. int start_device( netif_ref netif ){
  264.     ERROR_DECLARE;
  265.  
  266.     measured_string_ref setting;
  267.     services_t          internet_service;
  268.     int                 irq;
  269.     int                 io;
  270.     int                 mtu;
  271.  
  272.     // mandatory netif
  273.     setting = measured_strings_find( & netif->configuration, CONF_NETIF, 0 );
  274.     netif->driver = get_running_module( & net_globals.modules, setting->value );
  275.     if( ! netif->driver ){
  276.         printf( "Failed to start the network interface driver %s\n", setting->value );
  277.         return EINVAL;
  278.     }
  279.     // optional network interface layer
  280.     setting = measured_strings_find( & netif->configuration, CONF_NIL, 0 );
  281.     if( setting ){
  282.         netif->nil = get_running_module( & net_globals.modules, setting->value );
  283.         if( ! netif->nil ){
  284.             printf( "Failed to start the network interface layer %s\n", setting->value );
  285.             return EINVAL;
  286.         }
  287.     }else{
  288.         netif->nil = NULL;
  289.     }
  290.     // mandatory internet layer
  291.     setting = measured_strings_find( & netif->configuration, CONF_IL, 0 );
  292.     netif->il = get_running_module( & net_globals.modules, setting->value );
  293.     if( ! netif->il ){
  294.         printf( "Failed to start the internet layer %s\n", setting->value );
  295.         return EINVAL;
  296.     }
  297.     // end of the static loopback initialization
  298.     // startup the loopback interface
  299.     setting = measured_strings_find( & netif->configuration, CONF_IRQ, 0 );
  300.     irq = setting ? strtol( setting->value, NULL, 10 ) : 0;
  301.     setting = measured_strings_find( & netif->configuration, CONF_IO, 0 );
  302.     io = setting ? strtol( setting->value, NULL, 16 ) : 0;
  303.     ERROR_PROPAGATE( netif_probe_req( netif->driver->phone, netif->id, irq, io ));
  304.     if( netif->nil ){
  305.         setting = measured_strings_find( & netif->configuration, CONF_MTU, 0 );
  306.         if( ! setting ){
  307.             setting = measured_strings_find( & net_globals.configuration, CONF_MTU, 0 );
  308.         }
  309.         mtu = setting ? strtol( setting->value, NULL, 10 ) : 0;
  310.         ERROR_PROPAGATE( nil_device_req( netif->nil->phone, netif->id, mtu, netif->driver->service ));
  311.         internet_service = netif->nil->service;
  312.     }else{
  313.         internet_service = netif->driver->service;
  314.     }
  315.     switch( netif->il->service ){
  316.         case SERVICE_IP:
  317.             ERROR_PROPAGATE( ip_device_req( netif->il->phone, netif->id, internet_service ));
  318.             break;
  319.         default:
  320.             return ENOENT;
  321.     }
  322.     ERROR_PROPAGATE( netif_start_req( netif->driver->phone, netif->id ));
  323.     return EOK;
  324. }
  325.  
  326. int startup( void ){
  327.     ERROR_DECLARE;
  328.  
  329.     char *      conf_files[] = { "lo", "ne2k" };
  330.     int         count = sizeof( conf_files ) / sizeof( char * );
  331.     int         index;
  332.     netif_ref   netif;
  333.     int         i;
  334.     measured_string_ref setting;
  335.  
  336.     // TODO dynamic configuration
  337.     ERROR_PROPAGATE( read_configuration());
  338.  
  339.     for( i = 0; i < count; ++ i ){
  340.         netif = ( netif_ref ) malloc( sizeof( netif_t ));
  341.         if( ! netif ) return ENOMEM;
  342.  
  343.         netif->id = generate_new_device_id();
  344.         if( ! netif->id ) return EXDEV;
  345.         ERROR_PROPAGATE( measured_strings_initialize( & netif->configuration ));
  346.         // read configuration files
  347.         if( ERROR_OCCURRED( read_netif_configuration( conf_files[ i ], netif ))){
  348.             measured_strings_destroy( & netif->configuration );
  349.             free( netif );
  350.             return ERROR_CODE;
  351.         }
  352.         // mandatory name
  353.         setting = measured_strings_find( & netif->configuration, CONF_NAME, 0 );
  354.         if( ! setting ){
  355.             printf( "The name is missing\n" );
  356.             measured_strings_destroy( & netif->configuration );
  357.             free( netif );
  358.             return EINVAL;
  359.         }
  360.         netif->name = setting->value;
  361.         // add to the netifs map
  362.         index = netifs_add( & net_globals.netifs, netif->id, netif );
  363.         if( index < 0 ){
  364.             measured_strings_destroy( & netif->configuration );
  365.             free( netif );
  366.             return index;
  367.         }
  368.         // add to the netif names map
  369.         if( ERROR_OCCURRED( char_map_add( & net_globals.netif_names, netif->name, 0, index ))
  370.         // start network interfaces and needed modules
  371.         || ERROR_OCCURRED( start_device( netif ))){
  372.             measured_strings_destroy( & netif->configuration );
  373.             netifs_exclude_index( & net_globals.netifs, index );
  374.             return ERROR_CODE;
  375.         }
  376.         // increment modules' usage
  377.         ++ netif->driver->usage;
  378.         if( netif->nil ) ++ netif->nil->usage;
  379.         ++ netif->il->usage;
  380.         printf( "New network interface started:\n\tname\t= %s\n\tid\t= %d\n\tdriver\t= %s\n\tnil\t= %s\n\til\t= %s\n", netif->name, netif->id, netif->driver->name, netif->nil ? netif->nil->name : NULL, netif->il->name );
  381.     }
  382.     return EOK;
  383. }
  384.  
  385. /** @}
  386.  */
  387.