diff options
Diffstat (limited to 'net/tipc/config.c')
| -rw-r--r-- | net/tipc/config.c | 359 | 
1 files changed, 53 insertions, 306 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index bdde39f0436..2b42403ad33 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -2,7 +2,7 @@   * net/tipc/config.c: TIPC configuration management code   *   * Copyright (c) 2002-2006, Ericsson AB - * Copyright (c) 2004-2007, Wind River Systems + * Copyright (c) 2004-2007, 2010-2013, Wind River Systems   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -36,25 +36,16 @@  #include "core.h"  #include "port.h" -#include "link.h"  #include "name_table.h" -#include "user_reg.h"  #include "config.h" +#include "server.h" -struct manager { -	u32 user_ref; -	u32 port_ref; -}; - -static struct manager mng = { 0}; - -static DEFINE_SPINLOCK(config_lock); +#define REPLY_TRUNCATED "<truncated>\n"  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 */ -  struct sk_buff *tipc_cfg_reply_alloc(int payload_size)  {  	struct sk_buff *buf; @@ -71,10 +62,8 @@ int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,  	struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf);  	int new_tlv_space = TLV_SPACE(tlv_data_size); -	if (skb_tailroom(buf) < new_tlv_space) { -		dbg("tipc_cfg_append_tlv unable to append TLV\n"); +	if (skb_tailroom(buf) < new_tlv_space)  		return 0; -	}  	skb_put(buf, new_tlv_space);  	tlv->tlv_type = htons(tlv_type);  	tlv->tlv_len  = htons(TLV_LENGTH(tlv_data_size)); @@ -113,13 +102,12 @@ struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)  	return buf;  } -#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; +	char *pb; +	int pb_len;  	int str_len;  	u32 value; @@ -130,18 +118,16 @@ static struct sk_buff *tipc_show_stats(void)  	if (value != 0)  		return tipc_cfg_reply_error_string("unsupported argument"); -	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); +	buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));  	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"); +	pb = TLV_DATA(rep_tlv); +	pb_len = ULTRA_STRING_MAX_LEN; -	/* Use additional tipc_printf()'s to return more info ... */ - -	str_len = tipc_printbuf_validate(&pb); +	str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n"); +	str_len += 1;	/* for "\0" */  	skb_put(buf, TLV_SPACE(str_len));  	TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); @@ -157,7 +143,7 @@ static struct sk_buff *cfg_enable_bearer(void)  	args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);  	if (tipc_enable_bearer(args->name, -			       ntohl(args->detect_scope), +			       ntohl(args->disc_domain),  			       ntohl(args->priority)))  		return tipc_cfg_reply_error_string("unable to enable bearer"); @@ -188,66 +174,13 @@ static struct sk_buff *cfg_set_own_addr(void)  	if (!tipc_addr_node_valid(addr))  		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE  						   " (node address)"); -	if (tipc_mode == TIPC_NET_MODE) +	if (tipc_own_addr)  		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED  						   " (cannot change node address once assigned)"); +	if (!tipc_net_start(addr)) +		return tipc_cfg_reply_none(); -	/* -	 * 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. -	 */ - -	spin_unlock_bh(&config_lock); -	tipc_core_start_net(addr); -	spin_lock_bh(&config_lock); -	return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_remote_mng(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	tipc_remote_management = (value != 0); -	return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_publications(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value != delimit(value, 1, 65535)) -		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE -						   " (max publications must be 1-65535)"); -	tipc_max_publications = value; -	return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_subscriptions(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value != delimit(value, 1, 65535)) -		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE -						   " (max subscriptions must be 1-65535"); -	tipc_max_subscriptions = value; -	return tipc_cfg_reply_none(); +	return tipc_cfg_reply_error_string("cannot change to network mode");  }  static struct sk_buff *cfg_set_max_ports(void) @@ -259,78 +192,11 @@ static struct sk_buff *cfg_set_max_ports(void)  	value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));  	if (value == tipc_max_ports)  		return tipc_cfg_reply_none(); -	if (value != delimit(value, 127, 65535)) +	if (value < 127 || value > 65535)  		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE  						   " (max ports must be 127-65535)"); -	if (tipc_mode != TIPC_NOT_RUNNING) -		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED -			" (cannot change max ports while TIPC is active)"); -	tipc_max_ports = value; -	return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_zones(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value == tipc_max_zones) -		return tipc_cfg_reply_none(); -	if (value != delimit(value, 1, 255)) -		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE -						   " (max zones must be 1-255)"); -	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(); -} - -static struct sk_buff *cfg_set_max_clusters(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value != delimit(value, 1, 1)) -		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE -						   " (max clusters fixed at 1)"); -	return tipc_cfg_reply_none(); -} - -static struct sk_buff *cfg_set_max_nodes(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value == tipc_max_nodes) -		return tipc_cfg_reply_none(); -	if (value != delimit(value, 8, 2047)) -		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE -						   " (max nodes must be 8-2047)"); -	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(); -} - -static struct sk_buff *cfg_set_max_slaves(void) -{ -	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(*(__be32 *)TLV_DATA(req_tlv_area)); -	if (value != 0) -		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED -						   " (max secondary nodes fixed at 0)"); -	return tipc_cfg_reply_none(); +	return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED +		" (cannot change max ports while TIPC is active)");  }  static struct sk_buff *cfg_set_netid(void) @@ -342,10 +208,10 @@ static struct sk_buff *cfg_set_netid(void)  	value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));  	if (value == tipc_net_id)  		return tipc_cfg_reply_none(); -	if (value != delimit(value, 1, 9999)) +	if (value < 1 || value > 9999)  		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE  						   " (network id must be 1-9999)"); -	if (tipc_mode == TIPC_NET_MODE) +	if (tipc_own_addr)  		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED  			" (cannot change network id once TIPC has joined a network)");  	tipc_net_id = value; @@ -357,38 +223,23 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area  {  	struct sk_buff *rep_tlv_buf; -	spin_lock_bh(&config_lock); +	rtnl_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)) { +	if (likely(in_own_node(orig_node))) {  		/* command is permitted */ -	} else if (cmd >= 0x8000) { +	} else {  		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED  							  " (cannot be done remotely)");  		goto exit; -	} else if (!tipc_remote_management) { -		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); -		goto exit; -	} -	else if (cmd >= 0x4000) { -		u32 domain = 0; - -		if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || -		    (domain != orig_node)) { -			rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); -			goto exit; -		}  	}  	/* Call appropriate processing routine */ -  	switch (cmd) {  	case TIPC_CMD_NOOP:  		rep_tlv_buf = tipc_cfg_reply_none(); @@ -417,12 +268,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area  	case TIPC_CMD_SHOW_PORTS:  		rep_tlv_buf = tipc_port_get_ports();  		break; -	case TIPC_CMD_SET_LOG_SIZE: -		rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); -		break; -	case TIPC_CMD_DUMP_LOG: -		rep_tlv_buf = tipc_log_dump(); -		break;  	case TIPC_CMD_SHOW_STATS:  		rep_tlv_buf = tipc_show_stats();  		break; @@ -440,57 +285,15 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area  	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: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); -		break;  	case TIPC_CMD_GET_MAX_PORTS:  		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);  		break; -	case TIPC_CMD_GET_MAX_PUBL: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); -		break; -	case TIPC_CMD_GET_MAX_SUBSCR: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); -		break; -	case TIPC_CMD_GET_MAX_ZONES: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones); -		break; -	case TIPC_CMD_GET_MAX_CLUSTERS: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters); -		break; -	case TIPC_CMD_GET_MAX_NODES: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); -		break; -	case TIPC_CMD_GET_MAX_SLAVES: -		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves); -		break;  	case TIPC_CMD_GET_NETID:  		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);  		break; @@ -498,98 +301,42 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area  		rep_tlv_buf =  			tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);  		break; +	case TIPC_CMD_SET_MAX_ZONES: +	case TIPC_CMD_GET_MAX_ZONES: +	case TIPC_CMD_SET_MAX_SLAVES: +	case TIPC_CMD_GET_MAX_SLAVES: +	case TIPC_CMD_SET_MAX_CLUSTERS: +	case TIPC_CMD_GET_MAX_CLUSTERS: +	case TIPC_CMD_SET_MAX_NODES: +	case TIPC_CMD_GET_MAX_NODES: +	case TIPC_CMD_SET_MAX_SUBSCR: +	case TIPC_CMD_GET_MAX_SUBSCR: +	case TIPC_CMD_SET_MAX_PUBL: +	case TIPC_CMD_GET_MAX_PUBL: +	case TIPC_CMD_SET_LOG_SIZE: +	case TIPC_CMD_SET_REMOTE_MNG: +	case TIPC_CMD_GET_REMOTE_MNG: +	case TIPC_CMD_DUMP_LOG: +		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED +							  " (obsolete command)"); +		break;  	default:  		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED  							  " (unknown command)");  		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)) { -		warn("Invalid configuration message discarded\n"); -		return; -	} +	WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN)); -	/* Generate reply for request (if can't, return request) */ - -	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)); -	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; +	/* Append an error message if we cannot return all requested data */ +	if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) { +		if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0') +			sprintf(rep_tlv_buf->data + rep_tlv_buf->len - +				sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);  	} -	/* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ -	tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); -} - -int tipc_cfg_init(void) -{ -	struct tipc_name_seq seq; -	int res; - -	res = tipc_attach(&mng.user_ref); -	if (res) -		goto failed; - -	res = tipc_createport(mng.user_ref, NULL, TIPC_CRITICAL_IMPORTANCE, -			      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; -	res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); -	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; -} - -void tipc_cfg_stop(void) -{ -	if (mng.user_ref) { -		tipc_detach(mng.user_ref); -		mng.user_ref = 0; -	} +	/* Return reply buffer */ +exit: +	rtnl_unlock(); +	return rep_tlv_buf;  }  | 
