diff options
Diffstat (limited to 'net/tipc/net.c')
| -rw-r--r-- | net/tipc/net.c | 82 | 
1 files changed, 48 insertions, 34 deletions
diff --git a/net/tipc/net.c b/net/tipc/net.c index 1a2fde0d6f61..4fbaa0464405 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -104,38 +104,39 @@   *     - A local spin_lock protecting the queue of subscriber events.  */ -int tipc_net_start(struct net *net, u32 addr) +int tipc_net_init(struct net *net, u8 *node_id, u32 addr)  { -	struct tipc_net *tn = net_generic(net, tipc_net_id); -	char addr_string[16]; +	if (tipc_own_id(net)) { +		pr_info("Cannot configure node identity twice\n"); +		return -1; +	} +	pr_info("Started in network mode\n"); -	tn->own_addr = addr; +	if (node_id) +		tipc_set_node_id(net, node_id); +	if (addr) +		tipc_net_finalize(net, addr); +	return 0; +} -	/* Ensure that the new address is visible before we reinit. */ +void tipc_net_finalize(struct net *net, u32 addr) +{ +	tipc_set_node_addr(net, addr);  	smp_mb(); -  	tipc_named_reinit(net);  	tipc_sk_reinit(net); - -	tipc_nametbl_publish(net, TIPC_CFG_SRV, tn->own_addr, tn->own_addr, -			     TIPC_ZONE_SCOPE, 0, tn->own_addr); - -	pr_info("Started in network mode\n"); -	pr_info("Own node address %s, network identity %u\n", -		tipc_addr_string_fill(addr_string, tn->own_addr), -		tn->net_id); -	return 0; +	tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr, +			     TIPC_CLUSTER_SCOPE, 0, addr);  }  void tipc_net_stop(struct net *net)  { -	struct tipc_net *tn = net_generic(net, tipc_net_id); +	u32 self = tipc_own_addr(net); -	if (!tn->own_addr) +	if (!self)  		return; -	tipc_nametbl_withdraw(net, TIPC_CFG_SRV, tn->own_addr, 0, -			      tn->own_addr); +	tipc_nametbl_withdraw(net, TIPC_CFG_SRV, self, self, self);  	rtnl_lock();  	tipc_bearer_stop(net);  	tipc_node_stop(net); @@ -147,8 +148,10 @@ void tipc_net_stop(struct net *net)  static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg)  {  	struct tipc_net *tn = net_generic(net, tipc_net_id); -	void *hdr; +	u64 *w0 = (u64 *)&tn->node_id[0]; +	u64 *w1 = (u64 *)&tn->node_id[8];  	struct nlattr *attrs; +	void *hdr;  	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,  			  NLM_F_MULTI, TIPC_NL_NET_GET); @@ -161,7 +164,10 @@ static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg)  	if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tn->net_id))  		goto attr_msg_full; - +	if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID, *w0, 0)) +		goto attr_msg_full; +	if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID_W1, *w1, 0)) +		goto attr_msg_full;  	nla_nest_end(msg->skb, attrs);  	genlmsg_end(msg->skb, hdr); @@ -202,9 +208,9 @@ out:  int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)  { -	struct net *net = sock_net(skb->sk); -	struct tipc_net *tn = net_generic(net, tipc_net_id);  	struct nlattr *attrs[TIPC_NLA_NET_MAX + 1]; +	struct net *net = sock_net(skb->sk); +	struct tipc_net *tn = tipc_net(net);  	int err;  	if (!info->attrs[TIPC_NLA_NET]) @@ -213,16 +219,17 @@ int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)  	err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX,  			       info->attrs[TIPC_NLA_NET], tipc_nl_net_policy,  			       info->extack); +  	if (err)  		return err; +	/* Can't change net id once TIPC has joined a network */ +	if (tipc_own_addr(net)) +		return -EPERM; +  	if (attrs[TIPC_NLA_NET_ID]) {  		u32 val; -		/* Can't change net id once TIPC has joined a network */ -		if (tn->own_addr) -			return -EPERM; -  		val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);  		if (val < 1 || val > 9999)  			return -EINVAL; @@ -233,17 +240,24 @@ int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)  	if (attrs[TIPC_NLA_NET_ADDR]) {  		u32 addr; -		/* Can't change net addr once TIPC has joined a network */ -		if (tn->own_addr) -			return -EPERM; -  		addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]); -		if (!tipc_addr_node_valid(addr)) +		if (!addr)  			return -EINVAL; - -		tipc_net_start(net, addr); +		tn->legacy_addr_format = true; +		tipc_net_init(net, NULL, addr);  	} +	if (attrs[TIPC_NLA_NET_NODEID]) { +		u8 node_id[NODE_ID_LEN]; +		u64 *w0 = (u64 *)&node_id[0]; +		u64 *w1 = (u64 *)&node_id[8]; + +		if (!attrs[TIPC_NLA_NET_NODEID_W1]) +			return -EINVAL; +		*w0 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID]); +		*w1 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID_W1]); +		tipc_net_init(net, node_id, 0); +	}  	return 0;  }  | 
