diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/monitor.c | 2 | ||||
| -rw-r--r-- | net/tipc/name_table.c | 34 | ||||
| -rw-r--r-- | net/tipc/name_table.h | 2 | ||||
| -rw-r--r-- | net/tipc/net.c | 2 | ||||
| -rw-r--r-- | net/tipc/netlink.c | 5 | ||||
| -rw-r--r-- | net/tipc/node.c | 11 | ||||
| -rw-r--r-- | net/tipc/socket.c | 4 | ||||
| -rw-r--r-- | net/tipc/subscr.c | 5 | 
8 files changed, 40 insertions, 25 deletions
diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c index 32dc33a94bc7..5453e564da82 100644 --- a/net/tipc/monitor.c +++ b/net/tipc/monitor.c @@ -777,7 +777,7 @@ int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg,  	ret = tipc_bearer_get_name(net, bearer_name, bearer_id);  	if (ret || !mon) -		return -EINVAL; +		return 0;  	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,  			  NLM_F_MULTI, TIPC_NL_MON_GET); diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index b1fe20972aa9..dd1c4fa2eb78 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -241,7 +241,8 @@ err:  static struct publication *tipc_service_remove_publ(struct net *net,  						    struct tipc_service *sc,  						    u32 lower, u32 upper, -						    u32 node, u32 key) +						    u32 node, u32 key, +						    struct service_range **rng)  {  	struct tipc_subscription *sub, *tmp;  	struct service_range *sr; @@ -275,19 +276,15 @@ static struct publication *tipc_service_remove_publ(struct net *net,  	list_del(&p->all_publ);  	list_del(&p->local_publ); - -	/* Remove service range item if this was its last publication */ -	if (list_empty(&sr->all_publ)) { +	if (list_empty(&sr->all_publ))  		last = true; -		rb_erase(&sr->tree_node, &sc->ranges); -		kfree(sr); -	}  	/* Notify any waiting subscriptions */  	list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {  		tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_WITHDRAWN,  					p->port, p->node, p->scope, last);  	} +	*rng = sr;  	return p;  } @@ -379,13 +376,20 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,  					     u32 node, u32 key)  {  	struct tipc_service *sc = tipc_service_find(net, type); +	struct service_range *sr = NULL;  	struct publication *p = NULL;  	if (!sc)  		return NULL;  	spin_lock_bh(&sc->lock); -	p = tipc_service_remove_publ(net, sc, lower, upper, node, key); +	p = tipc_service_remove_publ(net, sc, lower, upper, node, key, &sr); + +	/* Remove service range item if this was its last publication */ +	if (sr && list_empty(&sr->all_publ)) { +		rb_erase(&sr->tree_node, &sc->ranges); +		kfree(sr); +	}  	/* Delete service item if this no more publications and subscriptions */  	if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) { @@ -665,13 +669,14 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower,  /**   * tipc_nametbl_subscribe - add a subscription object to the name table   */ -void tipc_nametbl_subscribe(struct tipc_subscription *sub) +bool tipc_nametbl_subscribe(struct tipc_subscription *sub)  {  	struct name_table *nt = tipc_name_table(sub->net);  	struct tipc_net *tn = tipc_net(sub->net);  	struct tipc_subscr *s = &sub->evt.s;  	u32 type = tipc_sub_read(s, seq.type);  	struct tipc_service *sc; +	bool res = true;  	spin_lock_bh(&tn->nametbl_lock);  	sc = tipc_service_find(sub->net, type); @@ -685,8 +690,10 @@ void tipc_nametbl_subscribe(struct tipc_subscription *sub)  		pr_warn("Failed to subscribe for {%u,%u,%u}\n", type,  			tipc_sub_read(s, seq.lower),  			tipc_sub_read(s, seq.upper)); +		res = false;  	}  	spin_unlock_bh(&tn->nametbl_lock); +	return res;  }  /** @@ -744,16 +751,17 @@ int tipc_nametbl_init(struct net *net)  static void tipc_service_delete(struct net *net, struct tipc_service *sc)  {  	struct service_range *sr, *tmpr; -	struct publication *p, *tmpb; +	struct publication *p, *tmp;  	spin_lock_bh(&sc->lock);  	rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) { -		list_for_each_entry_safe(p, tmpb, -					 &sr->all_publ, all_publ) { +		list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) {  			tipc_service_remove_publ(net, sc, p->lower, p->upper, -						 p->node, p->key); +						 p->node, p->key, &sr);  			kfree_rcu(p, rcu);  		} +		rb_erase(&sr->tree_node, &sc->ranges); +		kfree(sr);  	}  	hlist_del_init_rcu(&sc->service_list);  	spin_unlock_bh(&sc->lock); diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 4b14fc28d9e2..0febba41da86 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -126,7 +126,7 @@ struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,  struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,  					     u32 lower, u32 upper,  					     u32 node, u32 key); -void tipc_nametbl_subscribe(struct tipc_subscription *s); +bool tipc_nametbl_subscribe(struct tipc_subscription *s);  void tipc_nametbl_unsubscribe(struct tipc_subscription *s);  int tipc_nametbl_init(struct net *net);  void tipc_nametbl_stop(struct net *net); diff --git a/net/tipc/net.c b/net/tipc/net.c index 856f9e97ea29..4fbaa0464405 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -252,6 +252,8 @@ int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)  		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); diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index b76f13f6fea1..6ff2254088f6 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -79,7 +79,10 @@ const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = {  const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {  	[TIPC_NLA_NET_UNSPEC]		= { .type = NLA_UNSPEC }, -	[TIPC_NLA_NET_ID]		= { .type = NLA_U32 } +	[TIPC_NLA_NET_ID]		= { .type = NLA_U32 }, +	[TIPC_NLA_NET_ADDR]		= { .type = NLA_U32 }, +	[TIPC_NLA_NET_NODEID]		= { .type = NLA_U64 }, +	[TIPC_NLA_NET_NODEID_W1]	= { .type = NLA_U64 },  };  const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { diff --git a/net/tipc/node.c b/net/tipc/node.c index c77dd2f3c589..6f98b56dd48e 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -2232,8 +2232,8 @@ int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb)  	struct net *net = sock_net(skb->sk);  	u32 prev_bearer = cb->args[0];  	struct tipc_nl_msg msg; +	int bearer_id;  	int err; -	int i;  	if (prev_bearer == MAX_BEARERS)  		return 0; @@ -2243,16 +2243,13 @@ int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb)  	msg.seq = cb->nlh->nlmsg_seq;  	rtnl_lock(); -	for (i = prev_bearer; i < MAX_BEARERS; i++) { -		prev_bearer = i; +	for (bearer_id = prev_bearer; bearer_id < MAX_BEARERS; bearer_id++) {  		err = __tipc_nl_add_monitor(net, &msg, prev_bearer);  		if (err) -			goto out; +			break;  	} - -out:  	rtnl_unlock(); -	cb->args[0] = prev_bearer; +	cb->args[0] = bearer_id;  	return skb->len;  } diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1fd1c8b5ce03..252a52ae0893 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1278,7 +1278,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)  	struct tipc_msg *hdr = &tsk->phdr;  	struct tipc_name_seq *seq;  	struct sk_buff_head pkts; -	u32 dnode, dport; +	u32 dport, dnode = 0;  	u32 type, inst;  	int mtu, rc; @@ -1348,6 +1348,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)  		msg_set_destnode(hdr, dnode);  		msg_set_destport(hdr, dest->addr.id.ref);  		msg_set_hdr_sz(hdr, BASIC_H_SIZE); +	} else { +		return -EINVAL;  	}  	/* Block or return if destination link is congested */ diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index b7d80bc5f4ab..f340e53da625 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -153,7 +153,10 @@ struct tipc_subscription *tipc_sub_subscribe(struct net *net,  	memcpy(&sub->evt.s, s, sizeof(*s));  	spin_lock_init(&sub->lock);  	kref_init(&sub->kref); -	tipc_nametbl_subscribe(sub); +	if (!tipc_nametbl_subscribe(sub)) { +		kfree(sub); +		return NULL; +	}  	timer_setup(&sub->timer, tipc_sub_timeout, 0);  	timeout = tipc_sub_read(&sub->evt.s, timeout);  	if (timeout != TIPC_WAIT_FOREVER)  | 
