fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / ipv6 / mcast.c
index c75cd1c..e3ec216 100644 (file)
@@ -28,7 +28,6 @@
  *             - MLDv2 support
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -84,7 +83,7 @@
 struct mld2_grec {
        __u8            grec_type;
        __u8            grec_auxwords;
-       __u16           grec_nsrcs;
+       __be16          grec_nsrcs;
        struct in6_addr grec_mca;
        struct in6_addr grec_src[0];
 };
@@ -92,18 +91,18 @@ struct mld2_grec {
 struct mld2_report {
        __u8    type;
        __u8    resv1;
-       __u16   csum;
-       __u16   resv2;
-       __u16   ngrec;
+       __sum16 csum;
+       __be16  resv2;
+       __be16  ngrec;
        struct mld2_grec grec[0];
 };
 
 struct mld2_query {
        __u8 type;
        __u8 code;
-       __u16 csum;
-       __u16 mrc;
-       __u16 resv1;
+       __sum16 csum;
+       __be16 mrc;
+       __be16 resv1;
        struct in6_addr mca;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8 qrv:3,
@@ -117,7 +116,7 @@ struct mld2_query {
 #error "Please fix <asm/byteorder.h>"
 #endif
        __u8 qqic;
-       __u16 nsrcs;
+       __be16 nsrcs;
        struct in6_addr srcs[0];
 };
 
@@ -172,7 +171,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
 
 #define IPV6_MLD_MAX_MSF       64
 
-int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF;
+int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
 
 /*
  *     socket join on multicast group
@@ -269,13 +268,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
                        if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
                                struct inet6_dev *idev = in6_dev_get(dev);
 
+                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
                                if (idev) {
-                                       (void) ip6_mc_leave_src(sk,mc_lst,idev);
                                        __ipv6_dev_mc_dec(idev, &mc_lst->addr);
                                        in6_dev_put(idev);
                                }
                                dev_put(dev);
-                       }
+                       } else
+                               (void) ip6_mc_leave_src(sk, mc_lst, NULL);
                        sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
                        return 0;
                }
@@ -335,13 +335,14 @@ void ipv6_sock_mc_close(struct sock *sk)
                if (dev) {
                        struct inet6_dev *idev = in6_dev_get(dev);
 
+                       (void) ip6_mc_leave_src(sk, mc_lst, idev);
                        if (idev) {
-                               (void) ip6_mc_leave_src(sk, mc_lst, idev);
                                __ipv6_dev_mc_dec(idev, &mc_lst->addr);
                                in6_dev_put(idev);
                        }
                        dev_put(dev);
-               }
+               } else
+                       (void) ip6_mc_leave_src(sk, mc_lst, NULL);
 
                sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 
@@ -767,10 +768,10 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
         * for deleted items allows change reports to use common code with
         * non-deleted or query-response MCA's.
         */
-       pmc = kmalloc(sizeof(*pmc), GFP_ATOMIC);
+       pmc = kzalloc(sizeof(*pmc), GFP_ATOMIC);
        if (!pmc)
                return;
-       memset(pmc, 0, sizeof(*pmc));
+
        spin_lock_bh(&im->mca_lock);
        spin_lock_init(&pmc->mca_lock);
        pmc->idev = im->idev;
@@ -893,7 +894,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
         *      not found: create a new one.
         */
 
-       mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
+       mc = kzalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
 
        if (mc == NULL) {
                write_unlock_bh(&idev->lock);
@@ -901,7 +902,6 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
                return -ENOMEM;
        }
 
-       memset(mc, 0, sizeof(struct ifmcaddr6));
        init_timer(&mc->mca_timer);
        mc->mca_timer.function = igmp6_timer_handler;
        mc->mca_timer.data = (unsigned long) mc;
@@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb)
        struct inet6_dev *idev = in6_dev_get(skb->dev);
        int err;
 
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+       IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
        payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h -
                sizeof(struct ipv6hdr);
        mldlen = skb->tail - skb->h.raw;
@@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb)
                mld_dev_queue_xmit);
        if (!err) {
                ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
-               IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
+               IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
        } else
-               IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+               IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
 
        if (likely(idev != NULL))
                in6_dev_put(idev);
@@ -1582,6 +1582,8 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
                        skb = add_grhead(skb, pmc, type, &pgr);
                        first = 0;
                }
+               if (!skb)
+                       return NULL;
                psrc = (struct in6_addr *)skb_put(skb, sizeof(*psrc));
                *psrc = psf->sf_addr;
                scount++; stotal++;
@@ -1763,7 +1765,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
                     IPV6_TLV_ROUTERALERT, 2, 0, 0,
                     IPV6_TLV_PADN, 0 };
 
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+       rcu_read_lock();
+       IP6_INC_STATS(__in6_dev_get(dev),
+                     IPSTATS_MIB_OUTREQUESTS);
+       rcu_read_unlock();
        snd_addr = addr;
        if (type == ICMPV6_MGM_REDUCTION) {
                snd_addr = &all_routers;
@@ -1777,7 +1782,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
        skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err);
 
        if (skb == NULL) {
-               IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+               rcu_read_lock();
+               IP6_INC_STATS(__in6_dev_get(dev),
+                             IPSTATS_MIB_OUTDISCARDS);
+               rcu_read_unlock();
                return;
        }
 
@@ -1816,9 +1824,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
                else
                        ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES);
                ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
-               IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
+               IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS);
        } else
-               IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
+               IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
 
        if (likely(idev != NULL))
                in6_dev_put(idev);
@@ -1934,10 +1942,10 @@ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
                psf_prev = psf;
        }
        if (!psf) {
-               psf = kmalloc(sizeof(*psf), GFP_ATOMIC);
+               psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
                if (!psf)
                        return -ENOBUFS;
-               memset(psf, 0, sizeof(*psf));
+
                psf->sf_addr = *psfsrc;
                if (psf_prev) {
                        psf_prev->sf_next = psf;
@@ -2425,7 +2433,7 @@ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct igmp6_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct igmp6_mc_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
 
        if (!s)
                goto out;
@@ -2436,7 +2444,6 @@ static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
 
        seq = file->private_data;
        seq->private = s;
-       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree:
@@ -2600,7 +2607,7 @@ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct igmp6_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct igmp6_mcf_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
        
        if (!s)
                goto out;
@@ -2611,7 +2618,6 @@ static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
 
        seq = file->private_data;
        seq->private = s;
-       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree: