diff options
Diffstat (limited to 'net/ipv4/ipmr.c')
| -rw-r--r-- | net/ipv4/ipmr.c | 18 | 
1 files changed, 13 insertions, 5 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8582e12e4a6..ec19a890c9a 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -47,6 +47,7 @@  #include <linux/mroute.h>  #include <linux/init.h>  #include <linux/if_ether.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/ip.h>  #include <net/protocol.h> @@ -753,7 +754,8 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb)  		c->next = mfc_unres_queue;  		mfc_unres_queue = c; -		mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); +		if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1) +			mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);  	}  	/* @@ -802,6 +804,9 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock)  	int line;  	struct mfc_cache *uc, *c, **cp; +	if (mfc->mfcc_parent >= MAXVIFS) +		return -ENFILE; +  	line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr);  	for (cp = &net->ipv4.mfc_cache_array[line]; @@ -1613,17 +1618,20 @@ ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm)  	int ct;  	struct rtnexthop *nhp;  	struct net *net = mfc_net(c); -	struct net_device *dev = net->ipv4.vif_table[c->mfc_parent].dev;  	u8 *b = skb_tail_pointer(skb);  	struct rtattr *mp_head; -	if (dev) -		RTA_PUT(skb, RTA_IIF, 4, &dev->ifindex); +	/* If cache is unresolved, don't try to parse IIF and OIF */ +	if (c->mfc_parent > MAXVIFS) +		return -ENOENT; + +	if (VIF_EXISTS(net, c->mfc_parent)) +		RTA_PUT(skb, RTA_IIF, 4, &net->ipv4.vif_table[c->mfc_parent].dev->ifindex);  	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));  	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { -		if (c->mfc_un.res.ttls[ct] < 255) { +		if (VIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) {  			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))  				goto rtattr_failure;  			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));  |