Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 889750bd authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tipc-next'



Jon Maloy says:

====================
tipc: some small fixes

When fix a minor buffer leak, and ensure that bearers filter packets
correctly while they are being shut down.

v2: Corrected typos in commit #3, as per feedback from S. Shtylyov
v3: Removed commit #3 from the series. Improved version will be
    re-submitted later.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ba35855e 5b7066c3
Loading
Loading
Loading
Loading
+59 −42
Original line number Original line Diff line number Diff line
@@ -205,6 +205,7 @@ static int tipc_enable_bearer(struct net *net, const char *name,
	struct tipc_bearer *b;
	struct tipc_bearer *b;
	struct tipc_media *m;
	struct tipc_media *m;
	struct tipc_bearer_names b_names;
	struct tipc_bearer_names b_names;
	struct sk_buff *skb;
	char addr_string[16];
	char addr_string[16];
	u32 bearer_id;
	u32 bearer_id;
	u32 with_this_prio;
	u32 with_this_prio;
@@ -301,7 +302,7 @@ static int tipc_enable_bearer(struct net *net, const char *name,
	b->net_plane = bearer_id + 'A';
	b->net_plane = bearer_id + 'A';
	b->priority = priority;
	b->priority = priority;


	res = tipc_disc_create(net, b, &b->bcast_addr);
	res = tipc_disc_create(net, b, &b->bcast_addr, &skb);
	if (res) {
	if (res) {
		bearer_disable(net, b);
		bearer_disable(net, b);
		pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
		pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
@@ -310,7 +311,8 @@ static int tipc_enable_bearer(struct net *net, const char *name,
	}
	}


	rcu_assign_pointer(tn->bearer_list[bearer_id], b);
	rcu_assign_pointer(tn->bearer_list[bearer_id], b);

	if (skb)
		tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr);
	pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
	pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
		name,
		name,
		tipc_addr_string_fill(addr_string, disc_domain), priority);
		tipc_addr_string_fill(addr_string, disc_domain), priority);
@@ -335,23 +337,16 @@ static int tipc_reset_bearer(struct net *net, struct tipc_bearer *b)
 */
 */
static void bearer_disable(struct net *net, struct tipc_bearer *b)
static void bearer_disable(struct net *net, struct tipc_bearer *b)
{
{
	struct tipc_net *tn = net_generic(net, tipc_net_id);
	struct tipc_net *tn = tipc_net(net);
	u32 i;
	int bearer_id = b->identity;


	pr_info("Disabling bearer <%s>\n", b->name);
	pr_info("Disabling bearer <%s>\n", b->name);
	b->media->disable_media(b);
	b->media->disable_media(b);

	tipc_node_delete_links(net, bearer_id);
	tipc_node_delete_links(net, b->identity);
	RCU_INIT_POINTER(b->media_ptr, NULL);
	RCU_INIT_POINTER(b->media_ptr, NULL);
	if (b->link_req)
	if (b->link_req)
		tipc_disc_delete(b->link_req);
		tipc_disc_delete(b->link_req);

	RCU_INIT_POINTER(tn->bearer_list[bearer_id], NULL);
	for (i = 0; i < MAX_BEARERS; i++) {
		if (b == rtnl_dereference(tn->bearer_list[i])) {
			RCU_INIT_POINTER(tn->bearer_list[i], NULL);
			break;
		}
	}
	kfree_rcu(b, rcu);
	kfree_rcu(b, rcu);
}
}


@@ -394,7 +389,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b)


/**
/**
 * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
 * tipc_l2_send_msg - send a TIPC packet out over an L2 interface
 * @buf: the packet to be sent
 * @skb: the packet to be sent
 * @b: the bearer through which the packet is to be sent
 * @b: the bearer through which the packet is to be sent
 * @dest: peer destination address
 * @dest: peer destination address
 */
 */
@@ -403,17 +398,21 @@ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb,
{
{
	struct net_device *dev;
	struct net_device *dev;
	int delta;
	int delta;
	void *tipc_ptr;


	dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
	dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr);
	if (!dev)
	if (!dev)
		return 0;
		return 0;


	/* Send RESET message even if bearer is detached from device */
	tipc_ptr = rtnl_dereference(dev->tipc_ptr);
	if (unlikely(!tipc_ptr && !msg_is_reset(buf_msg(skb))))
		goto drop;

	delta = dev->hard_header_len - skb_headroom(skb);
	delta = dev->hard_header_len - skb_headroom(skb);
	if ((delta > 0) &&
	if ((delta > 0) &&
	    pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
	    pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC))
		kfree_skb(skb);
		goto drop;
		return 0;
	}


	skb_reset_network_header(skb);
	skb_reset_network_header(skb);
	skb->dev = dev;
	skb->dev = dev;
@@ -422,6 +421,9 @@ int tipc_l2_send_msg(struct net *net, struct sk_buff *skb,
			dev->dev_addr, skb->len);
			dev->dev_addr, skb->len);
	dev_queue_xmit(skb);
	dev_queue_xmit(skb);
	return 0;
	return 0;
drop:
	kfree_skb(skb);
	return 0;
}
}


int tipc_bearer_mtu(struct net *net, u32 bearer_id)
int tipc_bearer_mtu(struct net *net, u32 bearer_id)
@@ -450,6 +452,8 @@ void tipc_bearer_xmit_skb(struct net *net, u32 bearer_id,
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (likely(b))
	if (likely(b))
		b->media->send_msg(net, skb, b, dest);
		b->media->send_msg(net, skb, b, dest);
	else
		kfree_skb(skb);
	rcu_read_unlock();
	rcu_read_unlock();
}
}


@@ -468,12 +472,12 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,


	rcu_read_lock();
	rcu_read_lock();
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (likely(b)) {
	if (unlikely(!b))
		__skb_queue_purge(xmitq);
	skb_queue_walk_safe(xmitq, skb, tmp) {
	skb_queue_walk_safe(xmitq, skb, tmp) {
		__skb_dequeue(xmitq);
		__skb_dequeue(xmitq);
		b->media->send_msg(net, skb, b, dst);
		b->media->send_msg(net, skb, b, dst);
	}
	}
	}
	rcu_read_unlock();
	rcu_read_unlock();
}
}


@@ -490,7 +494,8 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,


	rcu_read_lock();
	rcu_read_lock();
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	b = rcu_dereference_rtnl(tn->bearer_list[bearer_id]);
	if (likely(b)) {
	if (unlikely(!b))
		__skb_queue_purge(xmitq);
	skb_queue_walk_safe(xmitq, skb, tmp) {
	skb_queue_walk_safe(xmitq, skb, tmp) {
		hdr = buf_msg(skb);
		hdr = buf_msg(skb);
		msg_set_non_seq(hdr, 1);
		msg_set_non_seq(hdr, 1);
@@ -498,7 +503,6 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
		__skb_dequeue(xmitq);
		__skb_dequeue(xmitq);
		b->media->send_msg(net, skb, b, &b->bcast_addr);
		b->media->send_msg(net, skb, b, &b->bcast_addr);
	}
	}
	}
	rcu_read_unlock();
	rcu_read_unlock();
}
}


@@ -513,24 +517,21 @@ void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
 * ignores packets sent using interface multicast, and traffic sent to other
 * ignores packets sent using interface multicast, and traffic sent to other
 * nodes (which can happen if interface is running in promiscuous mode).
 * nodes (which can happen if interface is running in promiscuous mode).
 */
 */
static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
static int tipc_l2_rcv_msg(struct sk_buff *skb, struct net_device *dev,
			   struct packet_type *pt, struct net_device *orig_dev)
			   struct packet_type *pt, struct net_device *orig_dev)
{
{
	struct tipc_bearer *b;
	struct tipc_bearer *b;


	rcu_read_lock();
	rcu_read_lock();
	b = rcu_dereference_rtnl(dev->tipc_ptr);
	b = rcu_dereference_rtnl(dev->tipc_ptr);
	if (likely(b)) {
	if (likely(b && (skb->pkt_type <= PACKET_BROADCAST))) {
		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
		skb->next = NULL;
			buf->next = NULL;
		tipc_rcv(dev_net(dev), skb, b);
			tipc_rcv(dev_net(dev), buf, b);
		rcu_read_unlock();
		rcu_read_unlock();
		return NET_RX_SUCCESS;
		return NET_RX_SUCCESS;
	}
	}
	}
	rcu_read_unlock();
	rcu_read_unlock();

	kfree_skb(skb);
	kfree_skb(buf);
	return NET_RX_DROP;
	return NET_RX_DROP;
}
}


@@ -548,9 +549,18 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
{
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct net *net = dev_net(dev);
	struct net *net = dev_net(dev);
	struct tipc_net *tn = tipc_net(net);
	struct tipc_bearer *b;
	struct tipc_bearer *b;
	int i;


	b = rtnl_dereference(dev->tipc_ptr);
	b = rtnl_dereference(dev->tipc_ptr);
	if (!b) {
		for (i = 0; i < MAX_BEARERS; b = NULL, i++) {
			b = rtnl_dereference(tn->bearer_list[i]);
			if (b && (b->media_ptr == dev))
				break;
		}
	}
	if (!b)
	if (!b)
		return NOTIFY_DONE;
		return NOTIFY_DONE;


@@ -560,7 +570,14 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
	case NETDEV_CHANGE:
	case NETDEV_CHANGE:
		if (netif_carrier_ok(dev))
		if (netif_carrier_ok(dev))
			break;
			break;
	case NETDEV_UP:
		rcu_assign_pointer(dev->tipc_ptr, b);
		break;
	case NETDEV_GOING_DOWN:
	case NETDEV_GOING_DOWN:
		RCU_INIT_POINTER(dev->tipc_ptr, NULL);
		synchronize_net();
		tipc_reset_bearer(net, b);
		break;
	case NETDEV_CHANGEMTU:
	case NETDEV_CHANGEMTU:
		tipc_reset_bearer(net, b);
		tipc_reset_bearer(net, b);
		break;
		break;
+2 −5
Original line number Original line Diff line number Diff line
@@ -268,10 +268,9 @@ static void disc_timeout(unsigned long data)
 * Returns 0 if successful, otherwise -errno.
 * Returns 0 if successful, otherwise -errno.
 */
 */
int tipc_disc_create(struct net *net, struct tipc_bearer *b,
int tipc_disc_create(struct net *net, struct tipc_bearer *b,
		     struct tipc_media_addr *dest)
		     struct tipc_media_addr *dest, struct sk_buff **skb)
{
{
	struct tipc_link_req *req;
	struct tipc_link_req *req;
	struct sk_buff *skb;


	req = kmalloc(sizeof(*req), GFP_ATOMIC);
	req = kmalloc(sizeof(*req), GFP_ATOMIC);
	if (!req)
	if (!req)
@@ -293,9 +292,7 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b,
	setup_timer(&req->timer, disc_timeout, (unsigned long)req);
	setup_timer(&req->timer, disc_timeout, (unsigned long)req);
	mod_timer(&req->timer, jiffies + req->timer_intv);
	mod_timer(&req->timer, jiffies + req->timer_intv);
	b->link_req = req;
	b->link_req = req;
	skb = skb_clone(req->buf, GFP_ATOMIC);
	*skb = skb_clone(req->buf, GFP_ATOMIC);
	if (skb)
		tipc_bearer_xmit_skb(net, req->bearer_id, skb, &req->dest);
	return 0;
	return 0;
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,7 @@
struct tipc_link_req;
struct tipc_link_req;


int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr,
int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr,
		     struct tipc_media_addr *dest);
		     struct tipc_media_addr *dest, struct sk_buff **skb);
void tipc_disc_delete(struct tipc_link_req *req);
void tipc_disc_delete(struct tipc_link_req *req);
void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr);
void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr);
void tipc_disc_add_dest(struct tipc_link_req *req);
void tipc_disc_add_dest(struct tipc_link_req *req);
+5 −0
Original line number Original line Diff line number Diff line
@@ -779,6 +779,11 @@ static inline bool msg_peer_node_is_up(struct tipc_msg *m)
	return msg_redundant_link(m);
	return msg_redundant_link(m);
}
}


static inline bool msg_is_reset(struct tipc_msg *hdr)
{
	return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG);
}

struct sk_buff *tipc_buf_acquire(u32 size);
struct sk_buff *tipc_buf_acquire(u32 size);
bool tipc_msg_validate(struct sk_buff *skb);
bool tipc_msg_validate(struct sk_buff *skb);
bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);