ipv4: Use flowi4's {saddr,daddr} in igmpv3_newpack() and igmp_send_report()
[deliverable/linux.git] / net / ipv4 / igmp.c
index e0e77e297de32148356da4c309856dacabee2387..ec03c2fda6ce9204bdfc6099e3e2033060364fc9 100644 (file)
@@ -309,6 +309,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 +322,11 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        }
        igmp_skb_size(skb) = size;
 
-       {
-               struct flowi fl = { .oif = dev->ifindex,
-                                   .fl4_dst = IGMPV3_ALL_MCR,
-                                   .proto = IPPROTO_IGMP };
-               if (ip_route_output_key(net, &rt, &fl)) {
-                       kfree_skb(skb);
-                       return NULL;
-               }
-       }
-       if (rt->rt_src == 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);
-               ip_rt_put(rt);
                return NULL;
        }
 
@@ -350,8 +344,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);
@@ -657,6 +651,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)
@@ -666,17 +661,11 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        else
                dst = group;
 
-       {
-               struct flowi fl = { .oif = dev->ifindex,
-                                   .fl4_dst = dst,
-                                   .proto = IPPROTO_IGMP };
-               if (ip_route_output_key(net, &rt, &fl))
-                       return -1;
-       }
-       if (rt->rt_src == 0) {
-               ip_rt_put(rt);
+       rt = ip_route_output_ports(net, &fl4, NULL, dst, 0,
+                                  0, 0,
+                                  IPPROTO_IGMP, 0, dev->ifindex);
+       if (IS_ERR(rt))
                return -1;
-       }
 
        skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
        if (skb == NULL) {
@@ -698,7 +687,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;
@@ -1439,8 +1428,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
 /* RTNL is locked */
 static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
 {
-       struct flowi fl = { .fl4_dst = imr->imr_multiaddr.s_addr };
-       struct rtable *rt;
        struct net_device *dev = NULL;
        struct in_device *idev = NULL;
 
@@ -1454,9 +1441,14 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
                        return NULL;
        }
 
-       if (!dev && !ip_route_output_key(net, &rt, &fl)) {
-               dev = rt->dst.dev;
-               ip_rt_put(rt);
+       if (!dev) {
+               struct rtable *rt = ip_route_output(net,
+                                                   imr->imr_multiaddr.s_addr,
+                                                   0, 0, 0);
+               if (!IS_ERR(rt)) {
+                       dev = rt->dst.dev;
+                       ip_rt_put(rt);
+               }
        }
        if (dev) {
                imr->imr_ifindex = dev->ifindex;
@@ -2329,13 +2321,13 @@ void ip_mc_drop_socket(struct sock *sk)
        rtnl_unlock();
 }
 
-int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
+/* called with rcu_read_lock() */
+int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
 {
        struct ip_mc_list *im;
        struct ip_sf_list *psf;
        int rv = 0;
 
-       rcu_read_lock();
        for_each_pmc_rcu(in_dev, im) {
                if (im->multiaddr == mc_addr)
                        break;
@@ -2357,7 +2349,6 @@ int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 p
                } else
                        rv = 1; /* unspecified source; tentatively allow */
        }
-       rcu_read_unlock();
        return rv;
 }
 
This page took 0.025984 seconds and 5 git commands to generate.