2006-01-02 21:04:38 +03:00
/*
* net / tipc / config . c : TIPC configuration management code
*
2006-01-11 21:14:19 +03:00
* Copyright ( c ) 2002 - 2006 , Ericsson AB
2006-01-02 21:04:38 +03:00
* Copyright ( c ) 2004 - 2005 , Wind River Systems
* 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 "dbg.h"
# include "bearer.h"
# include "port.h"
# include "link.h"
# include "zone.h"
# include "addr.h"
# include "name_table.h"
# include "node.h"
# include "config.h"
# include "discover.h"
struct subscr_data {
char usr_handle [ 8 ] ;
u32 domain ;
u32 port_ref ;
struct list_head subd_list ;
} ;
struct manager {
u32 user_ref ;
u32 port_ref ;
u32 subscr_ref ;
u32 link_subscriptions ;
struct list_head link_subscribers ;
} ;
static struct manager mng = { 0 } ;
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
void tipc_cfg_link_event ( u32 addr , char * name , int up )
2006-01-02 21:04:38 +03:00
{
/* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
}
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 ;
}
2006-01-18 02:38:21 +03:00
int tipc_cfg_append_tlv ( struct sk_buff * buf , int tlv_type ,
void * tlv_data , int tlv_data_size )
2006-01-02 21:04:38 +03:00
{
struct tlv_desc * tlv = ( struct tlv_desc * ) buf - > tail ;
int new_tlv_space = TLV_SPACE ( tlv_data_size ) ;
if ( skb_tailroom ( buf ) < new_tlv_space ) {
2006-01-18 02:38:21 +03:00
dbg ( " tipc_cfg_append_tlv unable to append TLV \n " ) ;
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 ;
}
2006-01-18 02:38:21 +03:00
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 ;
u32 value_net ;
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 ) ;
2006-01-18 02:38:21 +03:00
tipc_cfg_append_tlv ( buf , tlv_type , & value_net ,
sizeof ( value_net ) ) ;
2006-01-02 21:04:38 +03:00
}
return buf ;
}
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 ;
}
#if 0
/* Now obsolete code for handling commands not yet implemented the new way */
int tipc_cfg_cmd ( const struct tipc_cmd_msg * msg ,
char * data ,
u32 sz ,
u32 * ret_size ,
struct tipc_portid * orig )
{
int rv = - EINVAL ;
u32 cmd = msg - > cmd ;
* ret_size = 0 ;
switch ( cmd ) {
case TIPC_REMOVE_LINK :
case TIPC_CMD_BLOCK_LINK :
case TIPC_CMD_UNBLOCK_LINK :
if ( ! cfg_check_connection ( orig ) )
rv = link_control ( msg - > argv . link_name , msg - > cmd , 0 ) ;
break ;
case TIPC_ESTABLISH :
{
int connected ;
tipc_isconnected ( mng . conn_port_ref , & connected ) ;
if ( connected | | ! orig ) {
rv = TIPC_FAILURE ;
break ;
}
rv = tipc_connect2port ( mng . conn_port_ref , orig ) ;
if ( rv = = TIPC_OK )
orig = 0 ;
break ;
}
case TIPC_GET_PEER_ADDRESS :
* ret_size = link_peer_addr ( msg - > argv . link_name , data , sz ) ;
break ;
case TIPC_GET_ROUTES :
rv = TIPC_OK ;
break ;
default : { }
}
if ( * ret_size )
rv = TIPC_OK ;
return rv ;
}
static void cfg_cmd_event ( struct tipc_cmd_msg * msg ,
char * data ,
u32 sz ,
struct tipc_portid const * orig )
{
int rv = - EINVAL ;
struct tipc_cmd_result_msg rmsg ;
struct iovec msg_sect [ 2 ] ;
int * arg ;
msg - > cmd = ntohl ( msg - > cmd ) ;
cfg_prepare_res_msg ( msg - > cmd , msg - > usr_handle , rv , & rmsg , msg_sect ,
data , 0 ) ;
if ( ntohl ( msg - > magic ) ! = TIPC_MAGIC )
goto exit ;
switch ( msg - > cmd ) {
case TIPC_CREATE_LINK :
if ( ! cfg_check_connection ( orig ) )
rv = disc_create_link ( & msg - > argv . create_link ) ;
break ;
case TIPC_LINK_SUBSCRIBE :
{
struct subscr_data * sub ;
if ( mng . link_subscriptions > 64 )
break ;
sub = ( struct subscr_data * ) kmalloc ( sizeof ( * sub ) ,
GFP_ATOMIC ) ;
if ( sub = = NULL ) {
warn ( " Memory squeeze; dropped remote link subscription \n " ) ;
break ;
}
INIT_LIST_HEAD ( & sub - > subd_list ) ;
tipc_createport ( mng . user_ref ,
( void * ) sub ,
TIPC_HIGH_IMPORTANCE ,
0 ,
0 ,
( tipc_conn_shutdown_event ) cfg_linksubscr_cancel ,
0 ,
0 ,
( tipc_conn_msg_event ) cfg_linksubscr_cancel ,
0 ,
& sub - > port_ref ) ;
if ( ! sub - > port_ref ) {
kfree ( sub ) ;
break ;
}
memcpy ( sub - > usr_handle , msg - > usr_handle ,
sizeof ( sub - > usr_handle ) ) ;
sub - > domain = msg - > argv . domain ;
list_add_tail ( & sub - > subd_list , & mng . link_subscribers ) ;
tipc_connect2port ( sub - > port_ref , orig ) ;
rmsg . retval = TIPC_OK ;
tipc_send ( sub - > port_ref , 2u , msg_sect ) ;
mng . link_subscriptions + + ;
return ;
}
default :
rv = tipc_cfg_cmd ( msg , data , sz , ( u32 * ) & msg_sect [ 1 ] . iov_len , orig ) ;
}
exit :
rmsg . result_len = htonl ( msg_sect [ 1 ] . iov_len ) ;
rmsg . retval = htonl ( rv ) ;
2006-01-18 02:38:21 +03:00
tipc_cfg_respond ( msg_sect , 2u , orig ) ;
2006-01-02 21:04:38 +03:00
}
# endif
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 ,
ntohl ( args - > detect_scope ) ,
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
addr = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
addr = ntohl ( addr ) ;
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
tipc_own_addr = addr ;
/*
* Must release all spinlocks before calling start_net ( ) because
* Linux version of TIPC calls eth_media_start ( ) which calls
* register_netdevice_notifier ( ) which may block !
*
* Temporarily releasing the lock should be harmless for non - Linux TIPC ,
* but Linux version of eth_media_start ( ) should really be reworked
* so that it can be called with spinlocks held .
*/
2006-01-02 21:04:38 +03:00
spin_unlock_bh ( & config_lock ) ;
2006-01-18 02:38:21 +03:00
tipc_core_start_net ( ) ;
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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
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-01-02 21:04:38 +03:00
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
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_max_zones ( 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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
2006-06-26 10:51:08 +04:00
if ( value = = tipc_max_zones )
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 1 , 255 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (max zones must be 1-255) " ) ;
2006-06-26 10:51:08 +04:00
if ( tipc_mode = = TIPC_NET_MODE )
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (cannot change max zones once TIPC has joined a network) " ) ;
tipc_max_zones = value ;
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_clusters ( 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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
2006-06-26 10:51:08 +04:00
if ( value ! = delimit ( value , 1 , 1 ) )
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
2006-01-18 02:38:21 +03:00
" (max clusters fixed at 1) " ) ;
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_nodes ( 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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
2006-06-26 10:51:08 +04:00
if ( value = = tipc_max_nodes )
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
if ( value ! = delimit ( value , 8 , 2047 ) )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_INVALID_VALUE
" (max nodes must be 8-2047) " ) ;
2006-06-26 10:51:08 +04:00
if ( tipc_mode = = TIPC_NET_MODE )
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (cannot change max nodes once TIPC has joined a network) " ) ;
tipc_max_nodes = value ;
return tipc_cfg_reply_none ( ) ;
2006-01-02 21:04:38 +03:00
}
static struct sk_buff * cfg_set_max_slaves ( 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
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
if ( value ! = 0 )
2006-01-18 02:38:21 +03:00
return tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED
" (max secondary nodes fixed at 0) " ) ;
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-01-02 21:04:38 +03:00
value = * ( u32 * ) TLV_DATA ( req_tlv_area ) ;
value = ntohl ( value ) ;
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 ;
}
else if ( cmd > = 0x4000 ) {
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 ;
#if 0
case TIPC_CMD_SHOW_PORT_STATS :
rep_tlv_buf = port_show_stats ( req_tlv_area , req_tlv_space ) ;
break ;
case TIPC_CMD_RESET_PORT_STATS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_error_string ( TIPC_CFG_NOT_SUPPORTED ) ;
2006-01-02 21:04:38 +03:00
break ;
# endif
case TIPC_CMD_SET_LOG_SIZE :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_log_resize ( 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 ;
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_MAX_ZONES :
rep_tlv_buf = cfg_set_max_zones ( ) ;
break ;
case TIPC_CMD_SET_MAX_CLUSTERS :
rep_tlv_buf = cfg_set_max_clusters ( ) ;
break ;
case TIPC_CMD_SET_MAX_NODES :
rep_tlv_buf = cfg_set_max_nodes ( ) ;
break ;
case TIPC_CMD_SET_MAX_SLAVES :
rep_tlv_buf = cfg_set_max_slaves ( ) ;
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_MAX_ZONES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_zones ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_CLUSTERS :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_clusters ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_NODES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_nodes ) ;
2006-01-02 21:04:38 +03:00
break ;
case TIPC_CMD_GET_MAX_SLAVES :
2006-01-18 02:38:21 +03:00
rep_tlv_buf = tipc_cfg_reply_unsigned ( tipc_max_slaves ) ;
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 ;
default :
rep_tlv_buf = NULL ;
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 ,
u32 importance ,
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 ,
ntohs ( req_hdr - > tcm_type ) ,
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 ;
memset ( & mng , 0 , sizeof ( mng ) ) ;
INIT_LIST_HEAD ( & mng . link_subscribers ) ;
2006-03-21 09:36:47 +03:00
res = tipc_attach ( & mng . user_ref , NULL , NULL ) ;
2006-01-02 21:04:38 +03:00
if ( res )
goto failed ;
2006-03-21 09:36:47 +03:00
res = tipc_createport ( mng . user_ref , NULL , TIPC_CRITICAL_IMPORTANCE ,
2006-01-02 21:04:38 +03:00
NULL , NULL , NULL ,
NULL , cfg_named_msg_event , NULL ,
NULL , & mng . port_ref ) ;
if ( res )
goto failed ;
seq . type = TIPC_CFG_SRV ;
seq . lower = seq . upper = tipc_own_addr ;
2006-01-18 02:38:21 +03:00
res = tipc_nametbl_publish_rsv ( mng . 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 " ) ;
tipc_detach ( mng . user_ref ) ;
mng . user_ref = 0 ;
return res ;
}
2006-01-18 02:38:21 +03:00
void tipc_cfg_stop ( void )
2006-01-02 21:04:38 +03:00
{
if ( mng . user_ref ) {
tipc_detach ( mng . user_ref ) ;
mng . user_ref = 0 ;
}
}