Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[pandora-kernel.git] / net / ipv4 / igmp.c
index 8f62d66..f1d27f6 100644 (file)
@@ -303,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),
@@ -315,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;
@@ -342,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);
@@ -649,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)
@@ -658,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);
@@ -689,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;
@@ -1163,20 +1155,18 @@ static void igmp_group_dropped(struct ip_mc_list *im)
 
        if (!in_dev->dead) {
                if (IGMP_V1_SEEN(in_dev))
-                       goto done;
+                       return;
                if (IGMP_V2_SEEN(in_dev)) {
                        if (reporter)
                                igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
-                       goto done;
+                       return;
                }
                /* IGMPv3 */
                igmpv3_add_delrec(in_dev, im);
 
                igmp_ifc_event(in_dev);
        }
-done:
 #endif
-       ip_mc_clear_src(im);
 }
 
 static void igmp_group_added(struct ip_mc_list *im)
@@ -1313,6 +1303,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
                                *ip = i->next_rcu;
                                in_dev->mc_count--;
                                igmp_group_dropped(i);
+                               ip_mc_clear_src(i);
 
                                if (!in_dev->dead)
                                        ip_rt_multicast_event(in_dev);
@@ -1422,7 +1413,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
                in_dev->mc_list = i->next_rcu;
                in_dev->mc_count--;
 
-               igmp_group_dropped(i);
+               /* We've dropped the groups in ip_mc_down already */
+               ip_mc_clear_src(i);
                ip_ma_put(i);
        }
 }