diff options
Diffstat (limited to 'net/tipc/bearer.c')
| -rw-r--r-- | net/tipc/bearer.c | 64 | 
1 files changed, 64 insertions, 0 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index a809c0ec8d15..0214aa1c4427 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -389,6 +389,11 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,  		dev_put(dev);  		return -EINVAL;  	} +	if (dev == net->loopback_dev) { +		dev_put(dev); +		pr_info("Enabling <%s> not permitted\n", b->name); +		return -EINVAL; +	}  	/* Autoconfigure own node identity if needed */  	if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { @@ -674,6 +679,65 @@ void tipc_bearer_stop(struct net *net)  	}  } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) +{ +	struct net_device *dev = net->loopback_dev; +	struct sk_buff *skb, *_skb; +	int exp; + +	skb_queue_walk(pkts, _skb) { +		skb = pskb_copy(_skb, GFP_ATOMIC); +		if (!skb) +			continue; + +		exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); +		if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { +			kfree_skb(skb); +			continue; +		} + +		skb_reset_network_header(skb); +		dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, +				dev->dev_addr, skb->len); +		skb->dev = dev; +		skb->pkt_type = PACKET_HOST; +		skb->ip_summed = CHECKSUM_UNNECESSARY; +		skb->protocol = eth_type_trans(skb, dev); +		netif_rx_ni(skb); +	} +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, +				 struct packet_type *pt, struct net_device *od) +{ +	consume_skb(skb); +	return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ +	struct net_device *dev = net->loopback_dev; +	struct tipc_net *tn = tipc_net(net); + +	if (!dev) +		return -ENODEV; + +	dev_hold(dev); +	tn->loopback_pt.dev = dev; +	tn->loopback_pt.type = htons(ETH_P_TIPC); +	tn->loopback_pt.func = tipc_loopback_rcv_pkt; +	dev_add_pack(&tn->loopback_pt); +	return 0; +} + +void tipc_detach_loopback(struct net *net) +{ +	struct tipc_net *tn = tipc_net(net); + +	dev_remove_pack(&tn->loopback_pt); +	dev_put(net->loopback_dev); +} +  /* Caller should hold rtnl_lock to protect the bearer */  static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,  				struct tipc_bearer *bearer, int nlflags)  |