2006-01-02 21:04:38 +03:00
/*
* net / tipc / config . c : TIPC configuration management code
2007-02-09 17:25:21 +03:00
*
2006-01-11 21:14:19 +03:00
* Copyright ( c ) 2002 - 2006 , Ericsson AB
2011-02-25 22:22:11 +03:00
* Copyright ( c ) 2004 - 2007 , 2010 - 2011 , Wind River Systems
2006-01-02 21:04:38 +03:00
* All rights reserved .
*
2006-01-11 15:30:43 +03:00
* Redistribution and use in source and binary forms , with or without
2006-01-02 21:04:38 +03:00
* modification , are permitted provided that the following conditions are met :
*
2006-01-11 15:30:43 +03:00
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission .
2006-01-02 21:04:38 +03:00
*
2006-01-11 15:30:43 +03:00
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) version 2 as published by the Free
* Software Foundation .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
2006-01-02 21:04:38 +03:00
* POSSIBILITY OF SUCH DAMAGE .
*/
# include "core.h"
# include "port.h"
# include "name_table.h"
# include "config.h"
2010-12-31 21:59:20 +03:00
static u32 config_port_ref ;
2006-01-02 21:04:38 +03:00
2006-06-27 13:53:55 +04:00
static DEFINE_SPINLOCK ( config_lock ) ;
2006-01-02 21:04:38 +03:00
static const void * req_tlv_area ; /* request message TLV area */
static int req_tlv_space ; /* request message TLV area size */
static int rep_headroom ; /* reply message headroom to use */
2006-01-18 02:38:21 +03:00
struct sk_buff * tipc_cfg_reply_alloc ( int payload_size )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
buf = alloc_skb ( rep_headroom + payload_size , GFP_ATOMIC ) ;
if ( buf )
skb_reserve ( buf , rep_headroom ) ;
return buf ;
}
2007-02-09 17:25:21 +03:00
int tipc_cfg_append_tlv ( struct sk_buff * buf , int tlv_type ,
2006-01-18 02:38:21 +03:00
void * tlv_data , int tlv_data_size )
2006-01-02 21:04:38 +03:00
{
2007-04-20 07:29:13 +04:00
struct tlv_desc * tlv = ( struct tlv_desc * ) skb_tail_pointer ( buf ) ;
2006-01-02 21:04:38 +03:00
int new_tlv_space = TLV_SPACE ( tlv_data_size ) ;
2010-12-31 21:59:25 +03:00
if ( skb_tailroom ( buf ) < new_tlv_space )
2006-01-02 21:04:38 +03:00
return 0 ;
skb_put ( buf , new_tlv_space ) ;
tlv - > tlv_type = htons ( tlv_type ) ;
tlv - > tlv_len = htons ( TLV_LENGTH ( tlv_data_size ) ) ;
if ( tlv_data_size & & tlv_data )
memcpy ( TLV_DATA ( tlv ) , tlv_data , tlv_data_size ) ;
return 1 ;
}
2010-10-13 17:20:35 +04:00
static struct sk_buff * tipc_cfg_reply_unsigned_type ( u16 tlv_type , u32 value )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
2006-11-08 11:19:09 +03:00
__be32 value_net ;
2006-01-02 21:04:38 +03:00
2006-01-18 02:38:21 +03:00
buf = tipc_cfg_reply_alloc ( TLV_SPACE ( sizeof ( value ) ) ) ;
2006-01-02 21:04:38 +03:00
if ( buf ) {
value_net = htonl ( value ) ;
2007-02-09 17:25:21 +03:00
tipc_cfg_append_tlv ( buf , tlv_type , & value_net ,
2006-01-18 02:38:21 +03:00
sizeof ( value_net ) ) ;
2006-01-02 21:04:38 +03:00
}
return buf ;
}
2010-10-13 17:20:35 +04:00
static struct sk_buff * tipc_cfg_reply_unsigned ( u32 value )
{
return tipc_cfg_reply_unsigned_type ( TIPC_TLV_UNSIGNED , value ) ;
}
2006-01-18 02:38:21 +03:00
struct sk_buff * tipc_cfg_reply_string_type ( u16 tlv_type , char * string )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
int string_len = strlen ( string ) + 1 ;
2006-01-18 02:38:21 +03:00
buf = tipc_cfg_reply_alloc ( TLV_SPACE ( string_len ) ) ;
2006-01-02 21:04:38 +03:00
if ( buf )
2006-01-18 02:38:21 +03:00
tipc_cfg_append_tlv ( buf , tlv_type , string , string_len ) ;
2006-01-02 21:04:38 +03:00
return buf ;
}
2010-05-11 18:30:08 +04:00
# define MAX_STATS_INFO 2000
static struct sk_buff * tipc_show_stats ( void )
{
struct sk_buff * buf ;
struct tlv_desc * rep_tlv ;
struct print_buf pb ;
int str_len ;
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
value = ntohl ( * ( u32 * ) TLV_DATA ( req_tlv_area ) ) ;
if ( value ! = 0 )
return tipc_cfg_reply_error_string ( " unsupported argument " ) ;
buf = tipc_cfg_reply_alloc ( TLV_SPACE ( MAX_STATS_INFO ) ) ;
if ( buf = = NULL )
return NULL ;
rep_tlv = ( struct tlv_desc * ) buf - > data ;
tipc_printbuf_init ( & pb , ( char * ) TLV_DATA ( rep_tlv ) , MAX_STATS_INFO ) ;
tipc_printf ( & pb , " TIPC version " TIPC_MOD_VER " \n " ) ;
/* Use additional tipc_printf()'s to return more info ... */
str_len = tipc_printbuf_validate ( & pb ) ;
skb_put ( buf , TLV_SPACE ( str_len ) ) ;
TLV_SET ( rep_tlv , TIPC_TLV_ULTRA_STRING , NULL , str_len ) ;
return buf ;
}
2006-01-02 21:04:38 +03:00
static struct sk_buff * cfg_enable_bearer ( void )
{
struct tipc_bearer_config * args ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_BEARER_CONFIG ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
args = ( struct tipc_bearer_config * ) TLV_DATA ( req_tlv_area ) ;
if ( tipc_enable_bearer ( args - > name ,
2011-02-28 22:56:15 +03:00
ntohl ( args - > disc_domain ) ,
2006-01-02 21:04:38 +03:00
ntohl ( args - > priority ) ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( " unable to enable bearer " ) ;
2006-01-02 21:04:38 +03:00
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_disable_bearer ( void )
{
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_BEARER_NAME ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
if ( tipc_disable_bearer ( ( char * ) TLV_DATA ( req_tlv_area ) ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( " unable to disable bearer " ) ;
2006-01-02 21:04:38 +03:00
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_own_addr ( void )
{
u32 addr ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_NET_ADDR ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
2006-11-08 11:19:09 +03:00
addr = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-01-02 21:04:38 +03:00
if ( addr = = tipc_own_addr )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
if ( ! tipc_addr_node_valid ( addr ) )
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (node address) " ) ;
2006-06-26 10:51:08 +04:00
if ( tipc_mode = = TIPC_NET_MODE )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (cannot change node address once assigned) " ) ;
2006-06-26 10:51:08 +04:00
2007-02-09 17:25:21 +03:00
/*
2011-10-18 22:47:02 +04:00
* Must temporarily release configuration spinlock while switching into
* networking mode as it calls tipc_eth_media_start ( ) , which may sleep .
* Releasing the lock is harmless as other locally - issued configuration
* commands won ' t occur until this one completes , and remotely - issued
* configuration commands can ' t be received until a local configuration
* command to enable the first bearer is received and processed .
2006-06-26 10:51:08 +04:00
*/
2006-01-02 21:04:38 +03:00
spin_unlock_bh ( & config_lock ) ;
2008-05-22 01:55:04 +04:00
tipc_core_start_net ( addr ) ;
2006-01-02 21:04:38 +03:00
spin_lock_bh ( & config_lock ) ;
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_remote_mng ( void )
{
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
2006-11-08 11:19:09 +03:00
value = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-01-02 21:04:38 +03:00
tipc_remote_management = ( value ! = 0 ) ;
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_publications ( void )
{
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
2006-11-08 11:19:09 +03:00
value = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 1 , 65535 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (max publications must be 1-65535) " ) ;
2006-01-02 21:04:38 +03:00
tipc_max_publications = value ;
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_subscriptions ( void )
{
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-01-02 21:04:38 +03:00
2006-11-08 11:19:09 +03:00
value = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 1 , 65535 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (max subscriptions must be 1-65535 " ) ;
2006-01-02 21:04:38 +03:00
tipc_max_subscriptions = value ;
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_ports ( void )
{
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-11-08 11:19:09 +03:00
value = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-06-26 10:51:08 +04:00
if ( value = = tipc_max_ports )
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 127 , 65535 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (max ports must be 127-65535) " ) ;
2006-06-26 10:51:08 +04:00
if ( tipc_mode ! = TIPC_NOT_RUNNING )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
2006-06-26 10:51:08 +04:00
" (cannot change max ports while TIPC is active) " ) ;
2006-01-02 21:04:38 +03:00
tipc_max_ports = value ;
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_netid ( void )
{
u32 value ;
if ( ! TLV_CHECK ( req_tlv_area , req_tlv_space , TIPC_TLV_UNSIGNED ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_TLV_ERROR ) ;
2006-11-08 11:19:09 +03:00
value = ntohl ( * ( __be32 * ) TLV_DATA ( req_tlv_area ) ) ;
2006-06-26 10:51:08 +04:00
if ( value = = tipc_net_id )
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 1 , 9999 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (network id must be 1-9999) " ) ;
2006-06-26 10:51:08 +04:00
if ( tipc_mode = = TIPC_NET_MODE )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
2006-06-26 10:51:08 +04:00
" (cannot change network id once TIPC has joined a network) " ) ;
tipc_net_id = value ;
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
2006-01-18 02:38:21 +03:00
struct sk_buff * tipc_cfg_do_cmd ( u32 orig_node , u16 cmd , const void * request_area ,
int request_space , int reply_headroom )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * rep_tlv_buf ;
spin_lock_bh ( & config_lock ) ;
/* Save request and reply details in a well-known location */
req_tlv_area = request_area ;
req_tlv_space = request_space ;
rep_headroom = reply_headroom ;
/* Check command authorization */
if ( likely ( orig_node = = tipc_own_addr ) ) {
/* command is permitted */
} else if ( cmd > = 0x8000 ) {
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (cannot be done remotely) " ) ;
2006-01-02 21:04:38 +03:00
goto exit ;
} else if ( ! tipc_remote_management ) {
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NO_REMOTE ) ;
2006-01-02 21:04:38 +03:00
goto exit ;
2010-12-31 21:59:32 +03:00
} else if ( cmd > = 0x4000 ) {
2006-01-02 21:04:38 +03:00
u32 domain = 0 ;
2006-01-18 02:38:21 +03:00
if ( ( tipc_nametbl_translate ( TIPC_ZM_SRV , 0 , & domain ) = = 0 ) | |
2006-01-02 21:04:38 +03:00
( domain ! = orig_node ) ) {
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NOT_ZONE_MSTR ) ;
2006-01-02 21:04:38 +03:00
goto exit ;
}
}
/* Call appropriate processing routine */
switch ( cmd ) {
case TIPC_CMD_NOOP :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_NODES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_node_get_nodes ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_LINKS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_node_get_links ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_SHOW_LINK_STATS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_link_cmd_show_stats ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_RESET_LINK_STATS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_link_cmd_reset_stats ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_SHOW_NAME_TABLE :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_nametbl_get ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_BEARER_NAMES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_bearer_get_names ( ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MEDIA_NAMES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_media_get_names ( ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_SHOW_PORTS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_port_get_ports ( ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_SET_LOG_SIZE :
2008-05-05 12:20:04 +04:00
rep_tlv_buf = tipc_log_resize_cmd ( req_tlv_area , req_tlv_space ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_DUMP_LOG :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_log_dump ( ) ;
2006-01-02 21:04:38 +03:00
break ;
2010-05-11 18:30:08 +04:00
case TIPC_CMD_SHOW_STATS :
rep_tlv_buf = tipc_show_stats ( ) ;
break ;
2006-01-02 21:04:38 +03:00
case TIPC_CMD_SET_LINK_TOL :
case TIPC_CMD_SET_LINK_PRI :
case TIPC_CMD_SET_LINK_WINDOW :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_link_cmd_config ( req_tlv_area , req_tlv_space , cmd ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_ENABLE_BEARER :
rep_tlv_buf = cfg_enable_bearer ( ) ;
break ;
case TIPC_CMD_DISABLE_BEARER :
rep_tlv_buf = cfg_disable_bearer ( ) ;
break ;
case TIPC_CMD_SET_NODE_ADDR :
rep_tlv_buf = cfg_set_own_addr ( ) ;
break ;
case TIPC_CMD_SET_REMOTE_MNG :
rep_tlv_buf = cfg_set_remote_mng ( ) ;
break ;
case TIPC_CMD_SET_MAX_PORTS :
rep_tlv_buf = cfg_set_max_ports ( ) ;
break ;
case TIPC_CMD_SET_MAX_PUBL :
rep_tlv_buf = cfg_set_max_publications ( ) ;
break ;
case TIPC_CMD_SET_MAX_SUBSCR :
rep_tlv_buf = cfg_set_max_subscriptions ( ) ;
break ;
case TIPC_CMD_SET_NETID :
rep_tlv_buf = cfg_set_netid ( ) ;
break ;
case TIPC_CMD_GET_REMOTE_MNG :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_remote_management ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_PORTS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_ports ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_PUBL :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_publications ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_SUBSCR :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_subscriptions ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_NETID :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_net_id ) ;
2006-01-02 21:04:38 +03:00
break ;
2008-05-22 01:52:30 +04:00
case TIPC_CMD_NOT_NET_ADMIN :
rep_tlv_buf =
tipc_cfg_reply_error_string ( TIPC_CFG_NOT_NET_ADMIN ) ;
break ;
2010-12-31 21:59:16 +03:00
case TIPC_CMD_SET_MAX_ZONES :
case TIPC_CMD_GET_MAX_ZONES :
2010-12-31 21:59:17 +03:00
case TIPC_CMD_SET_MAX_SLAVES :
case TIPC_CMD_GET_MAX_SLAVES :
2010-12-31 21:59:19 +03:00
case TIPC_CMD_SET_MAX_CLUSTERS :
case TIPC_CMD_GET_MAX_CLUSTERS :
2011-02-25 22:22:11 +03:00
case TIPC_CMD_SET_MAX_NODES :
case TIPC_CMD_GET_MAX_NODES :
2010-12-31 21:59:16 +03:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (obsolete command) " ) ;
break ;
2006-01-02 21:04:38 +03:00
default :
2006-10-17 09:00:56 +04:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (unknown command) " ) ;
2006-01-02 21:04:38 +03:00
break ;
}
/* Return reply buffer */
exit :
spin_unlock_bh ( & config_lock ) ;
return rep_tlv_buf ;
}
static void cfg_named_msg_event ( void * userdata ,
u32 port_ref ,
struct sk_buff * * buf ,
const unchar * msg ,
u32 size ,
2007-02-09 17:25:21 +03:00
u32 importance ,
2006-01-02 21:04:38 +03:00
struct tipc_portid const * orig ,
struct tipc_name_seq const * dest )
{
struct tipc_cfg_msg_hdr * req_hdr ;
struct tipc_cfg_msg_hdr * rep_hdr ;
struct sk_buff * rep_buf ;
/* Validate configuration message header (ignore invalid message) */
req_hdr = ( struct tipc_cfg_msg_hdr * ) msg ;
if ( ( size < sizeof ( * req_hdr ) ) | |
( size ! = TCM_ALIGN ( ntohl ( req_hdr - > tcm_len ) ) ) | |
( ntohs ( req_hdr - > tcm_flags ) ! = TCM_F_REQUEST ) ) {
2006-06-26 10:52:17 +04:00
warn ( " Invalid configuration message discarded \n " ) ;
2006-01-02 21:04:38 +03:00
return ;
}
/* Generate reply for request (if can't, return request) */
2006-01-18 02:38:21 +03:00
rep_buf = tipc_cfg_do_cmd ( orig - > node ,
2007-02-09 17:25:21 +03:00
ntohs ( req_hdr - > tcm_type ) ,
2006-01-18 02:38:21 +03:00
msg + sizeof ( * req_hdr ) ,
size - sizeof ( * req_hdr ) ,
BUF_HEADROOM + MAX_H_SIZE + sizeof ( * rep_hdr ) ) ;
2006-01-02 21:04:38 +03:00
if ( rep_buf ) {
skb_push ( rep_buf , sizeof ( * rep_hdr ) ) ;
rep_hdr = ( struct tipc_cfg_msg_hdr * ) rep_buf - > data ;
memcpy ( rep_hdr , req_hdr , sizeof ( * rep_hdr ) ) ;
rep_hdr - > tcm_len = htonl ( rep_buf - > len ) ;
rep_hdr - > tcm_flags & = htons ( ~ TCM_F_REQUEST ) ;
} else {
rep_buf = * buf ;
* buf = NULL ;
}
/* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */
tipc_send_buf2port ( port_ref , orig , rep_buf , rep_buf - > len ) ;
}
2006-01-18 02:38:21 +03:00
int tipc_cfg_init ( void )
2006-01-02 21:04:38 +03:00
{
struct tipc_name_seq seq ;
int res ;
2010-12-31 21:59:22 +03:00
res = tipc_createport ( NULL , TIPC_CRITICAL_IMPORTANCE ,
2006-01-02 21:04:38 +03:00
NULL , NULL , NULL ,
NULL , cfg_named_msg_event , NULL ,
2010-12-31 21:59:20 +03:00
NULL , & config_port_ref ) ;
2006-01-02 21:04:38 +03:00
if ( res )
goto failed ;
seq . type = TIPC_CFG_SRV ;
seq . lower = seq . upper = tipc_own_addr ;
2010-12-31 21:59:20 +03:00
res = tipc_nametbl_publish_rsv ( config_port_ref , TIPC_ZONE_SCOPE , & seq ) ;
2006-01-02 21:04:38 +03:00
if ( res )
goto failed ;
return 0 ;
failed :
err ( " Unable to create configuration service \n " ) ;
return res ;
}
2006-01-18 02:38:21 +03:00
void tipc_cfg_stop ( void )
2006-01-02 21:04:38 +03:00
{
2010-12-31 21:59:20 +03:00
if ( config_port_ref ) {
tipc_deleteport ( config_port_ref ) ;
config_port_ref = 0 ;
2006-01-02 21:04:38 +03:00
}
}