Subversion Repositories HelenOS

Rev

Rev 4720 | Rev 4730 | 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.  *  Networking subsystem central module implementation.
  35.  */
  36.  
  37. #include <async.h>
  38. #include <ctype.h>
  39. #include <ddi.h>
  40. #include <errno.h>
  41. #include <malloc.h>
  42. #include <stdio.h>
  43. #include <string.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.  
  52. #include "../structures/char_map.h"
  53. #include "../structures/generic_char_map.h"
  54. #include "../structures/measured_strings.h"
  55. #include "../structures/module_map.h"
  56. #include "../structures/packet/packet.h"
  57.  
  58. #include "../il/il_messages.h"
  59. #include "../include/device.h"
  60. #include "../include/netif_interface.h"
  61. #include "../include/nil_interface.h"
  62. #include "../include/net_interface.h"
  63. #include "../include/ip_interface.h"
  64.  
  65. #include "net.h"
  66.  
  67. /** Networking module name.
  68.  */
  69. #define NAME    "Networking"
  70.  
  71. /** Prints the module name.
  72.  *  @see NAME
  73.  */
  74. void    module_print_name( void );
  75.  
  76. /** Starts the networking module.
  77.  *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
  78.  *  @param client_connection The client connection processing function. The module skeleton propagates its own one. Input parameter.
  79.  *  @returns EOK on successful module termination.
  80.  *  @returns Other error codes as defined for the net_initialize() function.
  81.  *  @returns Other error codes as defined for the REGISTER_ME() macro function.
  82.  */
  83. int module_start( async_client_conn_t client_connection );
  84.  
  85. //int       parse_line( measured_strings_ref configuration, char * line );
  86.  
  87. /** Reads the networking subsystem global configuration.
  88.  *  @returns EOK on success.
  89.  *  @returns Other error codes as defined for the add_configuration() function.
  90.  */
  91. int     read_configuration( void );
  92.  
  93. /** Starts the network interface according to its configuration.
  94.  *  Registers the network interface with the subsystem modules.
  95.  *  Starts the needed subsystem modules.
  96.  *  @param netif The network interface specific data.
  97.  *  @returns EOK on success.
  98.  *  @returns EINVAL if there are some settings missing.
  99.  *  @returns ENOENT if the internet protocol module is not known.
  100.  *  @returns Other error codes as defined for the netif_probe_req() function.
  101.  *  @returns Other error codes as defined for the nil_device_req() function.
  102.  *  @returns Other error codes as defined for the needed internet layer registering function.
  103.  */
  104. int     start_device( netif_ref netif );
  105.  
  106. /** Reads the configuration and starts all network interfaces.
  107.  *  @returns EOK on success.
  108.  *  @returns EXDEV if there is no available system-unique device identifier.
  109.  *  @returns EINVAL if any of the network interface names are not configured.
  110.  *  @returns ENOMEM if there is not enough memory left.
  111.  *  @returns Other error codes as defined for the read_configuration() function.
  112.  *  @returns Other error codes as defined for the read_netif_configuration() function.
  113.  *  @returns Other error codes as defined for the start_device() function.
  114.  */
  115. int     startup( void );
  116.  
  117. /** Generates new system-unique device identifier.
  118.  *  @returns The system-unique devic identifier.
  119.  */
  120. device_id_t generate_new_device_id( void );
  121.  
  122. /** Returns the configured values.
  123.  *  The network interface configuration is searched first.
  124.  *  @param netif_conf The network interface configuration setting. Input parameter.
  125.  *  @param configuration The found configured values. Output parameter.
  126.  *  @param count The desired settings count. Input parameter.
  127.  *  @param data The found configuration settings data. Output parameter.
  128.  *  @returns EOK.
  129.  */
  130. int net_get_conf( measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data );
  131.  
  132. /** Initializes the networking module.
  133.  *  @param client_connection The client connection processing function. The module skeleton propagates its own one. Input parameter.
  134.  *  @returns EOK on success.
  135.  *  @returns ENOMEM if there is not enough memory left.
  136.  */
  137. int net_initialize( async_client_conn_t client_connection );
  138.  
  139. /** Reads the network interface specific configuration.
  140.  *  @param name The network interface name. Input parameter.
  141.  *  @param netif The network interface structure. Input/output parameter.
  142.  *  @returns EOK on success.
  143.  *  @returns Other error codes as defined for the add_configuration() function.
  144.  */
  145. int read_netif_configuration( char * name, netif_ref netif );
  146.  
  147. /** Networking module global data.
  148.  */
  149. net_globals_t   net_globals;
  150.  
  151. DEVICE_MAP_IMPLEMENT( netifs, netif_t )
  152.  
  153. GENERIC_CHAR_MAP_IMPLEMENT( measured_strings, measured_string_t )
  154.  
  155. void module_print_name( void ){
  156.     printf( "%s", NAME );
  157. }
  158.  
  159. int module_start( async_client_conn_t client_connection ){
  160.     ERROR_DECLARE;
  161.  
  162.     ipcarg_t    phonehash;
  163.  
  164.     async_set_client_connection( client_connection );
  165.     ERROR_PROPAGATE( pm_init());
  166.     if( ERROR_OCCURRED( net_initialize( client_connection ))
  167.     || ERROR_OCCURRED( REGISTER_ME( SERVICE_NETWORKING, & phonehash ))){
  168.         pm_destroy();
  169.         return ERROR_CODE;
  170.     }
  171.  
  172.     async_manager();
  173.  
  174.     pm_destroy();
  175.     return EOK;
  176. }
  177.  
  178. int net_initialize( async_client_conn_t client_connection ){
  179.     ERROR_DECLARE;
  180.  
  181.     netifs_initialize( & net_globals.netifs );
  182.     char_map_initialize( & net_globals.netif_names );
  183.     modules_initialize( & net_globals.modules );
  184.     measured_strings_initialize( & net_globals.configuration );
  185.  
  186.     // TODO dynamic configuration
  187.     ERROR_PROPAGATE( read_configuration());
  188.  
  189.     ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service ));
  190.     ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service ));
  191.     ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service ));
  192.     ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service ));
  193.  
  194.     // build specific initialization
  195.     return net_initialize_build( client_connection );
  196. }
  197.  
  198. int net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data ){
  199.     netif_ref   netif;
  200.  
  201.     if( !( configuration && ( count > 0 ))) return EINVAL;
  202.     netif = netifs_find( & net_globals.netifs, device_id );
  203.     if( netif ){
  204.         return net_get_conf( & netif->configuration, * configuration, count, data );
  205.     }else{
  206.         return net_get_conf( NULL, * configuration, count, data );
  207.     }
  208. }
  209.  
  210. int net_get_conf_req( int net_phone, measured_string_ref * configuration, size_t count, char ** data ){
  211.     if( !( configuration && ( count > 0 ))) return EINVAL;
  212.     return net_get_conf( NULL, * configuration, count, data );
  213. }
  214.  
  215. int net_get_conf( measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data ){
  216.     measured_string_ref setting;
  217.     size_t              index;
  218.  
  219.     if( data ) * data = NULL;
  220.     for( index = 0; index < count; ++ index ){
  221.         setting = measured_strings_find( netif_conf, configuration[ index ].value, 0 );
  222.         if( ! setting ){
  223.             setting = measured_strings_find( & net_globals.configuration, configuration[ index ].value, 0 );
  224.         }
  225.         if( setting ){
  226.             configuration[ index ].length = setting->length;
  227.             configuration[ index ].value = setting->value;
  228.         }else{
  229.             configuration[ index ].length = 0;
  230.             configuration[ index ].value = NULL;
  231.         }
  232.     }
  233.     return EOK;
  234. }
  235.  
  236. void net_free_settings( measured_string_ref settings, char * data ){
  237. }
  238.  
  239. int net_connect_module( services_t service ){
  240.     return EOK;
  241. }
  242.  
  243. int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  244.     ERROR_DECLARE;
  245.  
  246.     measured_string_ref strings;
  247.     char *              data;
  248.  
  249.     * answer_count = 0;
  250.     switch( IPC_GET_METHOD( * call )){
  251.         case IPC_M_PHONE_HUNGUP:
  252.             return EOK;
  253.         case NET_NET_DEVICE:
  254.             // TODO configure, register
  255.             printf( "Networking: new netif %d\n", IPC_GET_DEVICE( call ));
  256.             return EOK;
  257.         case NET_NET_GET_DEVICE_CONF:
  258.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  259.             net_get_device_conf_req( 0, IPC_GET_DEVICE( call ), & strings, IPC_GET_COUNT( call ), NULL );
  260.             // strings should not contain received data anymore
  261.             free( data );
  262.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  263.             free( strings );
  264.             return ERROR_CODE;
  265.         case NET_NET_GET_CONF:
  266.             ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
  267.             net_get_conf_req( 0, & strings, IPC_GET_COUNT( call ), NULL );
  268.             // strings should not contain received data anymore
  269.             free( data );
  270.             ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
  271.             free( strings );
  272.             return ERROR_CODE;
  273.         case NET_NET_STARTUP:
  274.             return startup();
  275.     }
  276.     return ENOTSUP;
  277. }
  278.  
  279. /*
  280. int parse_line( measured_strings_ref configuration, char * line ){
  281.     ERROR_DECLARE;
  282.  
  283.     measured_string_ref setting;
  284.     char *          name;
  285.     char *          value;
  286.  
  287.     // from the beginning
  288.     name = line;
  289.     // skip spaces
  290.     while( isspace( * name )) ++ name;
  291.     // remember the name start
  292.     value = name;
  293.     // skip the name
  294.     while( isalnum( * value ) || ( * value == '_' )){
  295.         // make uppercase
  296. //      * value = toupper( * value );
  297.         ++ value;
  298.     }
  299.     if( * value == '=' ){
  300.         // terminate the name
  301.         * value = '\0';
  302.     }else{
  303.         // terminate the name
  304.         * value = '\0';
  305.         // skip until '='
  306.         ++ value;
  307.         while(( * value ) && ( * value != '=' )) ++ value;
  308.         // not found?
  309.         if( * value != '=' ) return EINVAL;
  310.     }
  311.     ++ value;
  312.     // skip spaces
  313.     while( isspace( * value )) ++ value;
  314.     // create a bulk measured string till the end
  315.     setting = measured_string_create_bulk( value, -1 );
  316.     if( ! setting ) return ENOMEM;
  317.     // add the configuration setting
  318.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  319.         free( setting );
  320.         return ERROR_CODE;
  321.     }
  322.     return EOK;
  323. }
  324. */
  325.  
  326. int add_configuration( measured_strings_ref configuration, const char * name, const char * value ){
  327.     ERROR_DECLARE;
  328.  
  329.     measured_string_ref setting;
  330.  
  331.     setting = measured_string_create_bulk( value, 0 );
  332.     if( ! setting ) return ENOMEM;
  333.     // add the configuration setting
  334.     if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
  335.         free( setting );
  336.         return ERROR_CODE;
  337.     }
  338.     return EOK;
  339. }
  340.  
  341. device_id_t generate_new_device_id( void ){
  342.     return device_assign_devno();
  343. }
  344.  
  345. int read_configuration( void ){
  346.     ERROR_DECLARE;
  347.  
  348.     // read general configuration
  349.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "IPV", "4" ));
  350.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "MTU", "1500" ));
  351.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ERROR_REPORTING", "yes" ));  //anything else not starting with 'y'
  352.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ECHO_REPLYING", "yes" ));  //anything else not starting with 'y'
  353.     ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "UDP_CHECKSUM_COMPUTING", "yes" ));  //anything else not starting with 'y'
  354.     return EOK;
  355. }
  356.  
  357. int read_netif_configuration( char * name, netif_ref netif ){
  358.     ERROR_DECLARE;
  359.  
  360.     if( str_lcmp( name, "lo", 2 ) == 0 ){
  361.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME ));
  362.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME ));
  363.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME ));
  364.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" ));
  365.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" ));
  366.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" ));
  367.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" ));
  368.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "15535" ));
  369.     }else if( str_lcmp( name, "ne2k", 4 ) == 0 ){
  370.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" ));
  371.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME ));
  372.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_MODE", "DIX" )); //8023_2_LSAP( not supported ), 8023_2_SNAP
  373. //      ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_DUMMY", "yes" )); //anything else not starting with 'y'
  374.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME ));
  375.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IRQ", "9" ));
  376.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IO", "300" ));
  377.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "576" ));
  378.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" ));
  379.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.15" ));
  380.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" ));
  381.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.255.255.240" ));
  382.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" ));
  383.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" ));
  384.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" ));
  385.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" ));
  386.         ERROR_PROPAGATE( add_configuration( & netif->configuration, "ARP", "arp" ));
  387.     }
  388.     return read_netif_configuration_build( name, netif );
  389. }
  390.  
  391. int start_device( netif_ref netif ){
  392.     ERROR_DECLARE;
  393.  
  394.     measured_string_ref setting;
  395.     services_t          internet_service;
  396.     int                 irq;
  397.     int                 io;
  398.     int                 mtu;
  399.  
  400.     // mandatory netif
  401.     setting = measured_strings_find( & netif->configuration, CONF_NETIF, 0 );
  402.     netif->driver = get_running_module( & net_globals.modules, setting->value );
  403.     if( ! netif->driver ){
  404.         printf( "Failed to start the network interface driver %s\n", setting->value );
  405.         return EINVAL;
  406.     }
  407.     // optional network interface layer
  408.     setting = measured_strings_find( & netif->configuration, CONF_NIL, 0 );
  409.     if( setting ){
  410.         netif->nil = get_running_module( & net_globals.modules, setting->value );
  411.         if( ! netif->nil ){
  412.             printf( "Failed to start the network interface layer %s\n", setting->value );
  413.             return EINVAL;
  414.         }
  415.     }else{
  416.         netif->nil = NULL;
  417.     }
  418.     // mandatory internet layer
  419.     setting = measured_strings_find( & netif->configuration, CONF_IL, 0 );
  420.     netif->il = get_running_module( & net_globals.modules, setting->value );
  421.     if( ! netif->il ){
  422.         printf( "Failed to start the internet layer %s\n", setting->value );
  423.         return EINVAL;
  424.     }
  425.     // end of the static loopback initialization
  426.     // startup the loopback interface
  427.     setting = measured_strings_find( & netif->configuration, CONF_IRQ, 0 );
  428.     irq = setting ? strtol( setting->value, NULL, 10 ) : 0;
  429.     setting = measured_strings_find( & netif->configuration, CONF_IO, 0 );
  430.     io = setting ? strtol( setting->value, NULL, 16 ) : 0;
  431.     ERROR_PROPAGATE( netif_probe_req( netif->driver->phone, netif->id, irq, io ));
  432.     if( netif->nil ){
  433.         setting = measured_strings_find( & netif->configuration, CONF_MTU, 0 );
  434.         if( ! setting ){
  435.             setting = measured_strings_find( & net_globals.configuration, CONF_MTU, 0 );
  436.         }
  437.         mtu = setting ? strtol( setting->value, NULL, 10 ) : 0;
  438.         ERROR_PROPAGATE( nil_device_req( netif->nil->phone, netif->id, mtu, netif->driver->service ));
  439.         internet_service = netif->nil->service;
  440.     }else{
  441.         internet_service = netif->driver->service;
  442.     }
  443.     switch( netif->il->service ){
  444.         case SERVICE_IP:
  445.             ERROR_PROPAGATE( ip_device_req( netif->il->phone, netif->id, internet_service ));
  446.             break;
  447.         default:
  448.             return ENOENT;
  449.     }
  450.     ERROR_PROPAGATE( netif_start_req( netif->driver->phone, netif->id ));
  451.     return EOK;
  452. }
  453.  
  454. int startup( void ){
  455.     ERROR_DECLARE;
  456.  
  457.     char *      conf_files[] = { "lo", "ne2k" };
  458.     int         count = sizeof( conf_files ) / sizeof( char * );
  459.     int         index;
  460.     netif_ref   netif;
  461.     int         i;
  462.     measured_string_ref setting;
  463.  
  464.     for( i = 0; i < count; ++ i ){
  465.         netif = ( netif_ref ) malloc( sizeof( netif_t ));
  466.         if( ! netif ) return ENOMEM;
  467.  
  468.         netif->id = generate_new_device_id();
  469.         if( ! netif->id ) return EXDEV;
  470.         ERROR_PROPAGATE( measured_strings_initialize( & netif->configuration ));
  471.         // read configuration files
  472.         if( ERROR_OCCURRED( read_netif_configuration( conf_files[ i ], netif ))){
  473.             measured_strings_destroy( & netif->configuration );
  474.             free( netif );
  475.             return ERROR_CODE;
  476.         }
  477.         // mandatory name
  478.         setting = measured_strings_find( & netif->configuration, CONF_NAME, 0 );
  479.         if( ! setting ){
  480.             printf( "The name is missing\n" );
  481.             measured_strings_destroy( & netif->configuration );
  482.             free( netif );
  483.             return EINVAL;
  484.         }
  485.         netif->name = setting->value;
  486.         // add to the netifs map
  487.         index = netifs_add( & net_globals.netifs, netif->id, netif );
  488.         if( index < 0 ){
  489.             measured_strings_destroy( & netif->configuration );
  490.             free( netif );
  491.             return index;
  492.         }
  493.         // add to the netif names map
  494.         if( ERROR_OCCURRED( char_map_add( & net_globals.netif_names, netif->name, 0, index ))
  495.         // start network interfaces and needed modules
  496.         || ERROR_OCCURRED( start_device( netif ))){
  497.             measured_strings_destroy( & netif->configuration );
  498.             netifs_exclude_index( & net_globals.netifs, index );
  499.             return ERROR_CODE;
  500.         }
  501.         // increment modules' usage
  502.         ++ netif->driver->usage;
  503.         if( netif->nil ) ++ netif->nil->usage;
  504.         ++ netif->il->usage;
  505.         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 );
  506.     }
  507.     return EOK;
  508. }
  509.  
  510. /** @}
  511.  */
  512.