diff options
Diffstat (limited to 'net/ipv4/igmp.c')
| -rw-r--r-- | net/ipv4/igmp.c | 54 | 
1 files changed, 13 insertions, 41 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 1fd3d9ce839..672e476c8c8 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -149,17 +149,11 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc);  static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,  			 int sfcount, __be32 *psfsrc, int delta); - -static void ip_mc_list_reclaim(struct rcu_head *head) -{ -	kfree(container_of(head, struct ip_mc_list, rcu)); -} -  static void ip_ma_put(struct ip_mc_list *im)  {  	if (atomic_dec_and_test(&im->refcnt)) {  		in_dev_put(im->interface); -		call_rcu(&im->rcu, ip_mc_list_reclaim); +		kfree_rcu(im, rcu);  	}  } @@ -309,6 +303,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)  	struct iphdr *pip;  	struct igmpv3_report *pig;  	struct net *net = dev_net(dev); +	struct flowi4 fl4;  	while (1) {  		skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), @@ -321,18 +316,13 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)  	}  	igmp_skb_size(skb) = size; -	rt = ip_route_output_ports(net, NULL, IGMPV3_ALL_MCR, 0, +	rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0,  				   0, 0,  				   IPPROTO_IGMP, 0, dev->ifindex);  	if (IS_ERR(rt)) {  		kfree_skb(skb);  		return NULL;  	} -	if (rt->rt_src == 0) { -		kfree_skb(skb); -		ip_rt_put(rt); -		return NULL; -	}  	skb_dst_set(skb, &rt->dst);  	skb->dev = dev; @@ -348,8 +338,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)  	pip->tos      = 0xc0;  	pip->frag_off = htons(IP_DF);  	pip->ttl      = 1; -	pip->daddr    = rt->rt_dst; -	pip->saddr    = rt->rt_src; +	pip->daddr    = fl4.daddr; +	pip->saddr    = fl4.saddr;  	pip->protocol = IPPROTO_IGMP;  	pip->tot_len  = 0;	/* filled in later */  	ip_select_ident(pip, &rt->dst, NULL); @@ -655,6 +645,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,  	struct net_device *dev = in_dev->dev;  	struct net *net = dev_net(dev);  	__be32	group = pmc ? pmc->multiaddr : 0; +	struct flowi4 fl4;  	__be32	dst;  	if (type == IGMPV3_HOST_MEMBERSHIP_REPORT) @@ -664,17 +655,12 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,  	else  		dst = group; -	rt = ip_route_output_ports(net, NULL, dst, 0, +	rt = ip_route_output_ports(net, &fl4, NULL, dst, 0,  				   0, 0,  				   IPPROTO_IGMP, 0, dev->ifindex);  	if (IS_ERR(rt))  		return -1; -	if (rt->rt_src == 0) { -		ip_rt_put(rt); -		return -1; -	} -  	skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);  	if (skb == NULL) {  		ip_rt_put(rt); @@ -695,7 +681,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,  	iph->frag_off = htons(IP_DF);  	iph->ttl      = 1;  	iph->daddr    = dst; -	iph->saddr    = rt->rt_src; +	iph->saddr    = fl4.saddr;  	iph->protocol = IPPROTO_IGMP;  	ip_select_ident(iph, &rt->dst, NULL);  	((u8*)&iph[1])[0] = IPOPT_RA; @@ -1836,12 +1822,6 @@ done:  }  EXPORT_SYMBOL(ip_mc_join_group); -static void ip_sf_socklist_reclaim(struct rcu_head *rp) -{ -	kfree(container_of(rp, struct ip_sf_socklist, rcu)); -	/* sk_omem_alloc should have been decreased by the caller*/ -} -  static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,  			   struct in_device *in_dev)  { @@ -1858,18 +1838,10 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,  	rcu_assign_pointer(iml->sflist, NULL);  	/* decrease mem now to avoid the memleak warning */  	atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc); -	call_rcu(&psf->rcu, ip_sf_socklist_reclaim); +	kfree_rcu(psf, rcu);  	return err;  } - -static void ip_mc_socklist_reclaim(struct rcu_head *rp) -{ -	kfree(container_of(rp, struct ip_mc_socklist, rcu)); -	/* sk_omem_alloc should have been decreased by the caller*/ -} - -  /*   *	Ask a socket to leave a group.   */ @@ -1909,7 +1881,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)  		rtnl_unlock();  		/* decrease mem now to avoid the memleak warning */  		atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); -		call_rcu(&iml->rcu, ip_mc_socklist_reclaim); +		kfree_rcu(iml, rcu);  		return 0;  	}  	if (!in_dev) @@ -2026,7 +1998,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct  				newpsl->sl_addr[i] = psl->sl_addr[i];  			/* decrease mem now to avoid the memleak warning */  			atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); -			call_rcu(&psl->rcu, ip_sf_socklist_reclaim); +			kfree_rcu(psl, rcu);  		}  		rcu_assign_pointer(pmc->sflist, newpsl);  		psl = newpsl; @@ -2127,7 +2099,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)  			psl->sl_count, psl->sl_addr, 0);  		/* decrease mem now to avoid the memleak warning */  		atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); -		call_rcu(&psl->rcu, ip_sf_socklist_reclaim); +		kfree_rcu(psl, rcu);  	} else  		(void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,  			0, NULL, 0); @@ -2324,7 +2296,7 @@ void ip_mc_drop_socket(struct sock *sk)  			ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);  		/* decrease mem now to avoid the memleak warning */  		atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); -		call_rcu(&iml->rcu, ip_mc_socklist_reclaim); +		kfree_rcu(iml, rcu);  	}  	rtnl_unlock();  }  |