Loading include/net/mld.h 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line #ifndef LINUX_MLD_H #define LINUX_MLD_H #include <linux/in6.h> #include <linux/icmpv6.h> /* MLDv1 Query/Report/Done */ struct mld_msg { struct icmp6hdr mld_hdr; struct in6_addr mld_mca; }; #define mld_type mld_hdr.icmp6_type #define mld_code mld_hdr.icmp6_code #define mld_cksum mld_hdr.icmp6_cksum #define mld_maxdelay mld_hdr.icmp6_maxdelay #define mld_reserved mld_hdr.icmp6_dataun.un_data16[1] /* Multicast Listener Discovery version 2 headers */ /* MLDv2 Report */ struct mld2_grec { __u8 grec_type; __u8 grec_auxwords; __be16 grec_nsrcs; struct in6_addr grec_mca; struct in6_addr grec_src[0]; }; struct mld2_report { struct icmp6hdr mld2r_hdr; struct mld2_grec mld2r_grec[0]; }; #define mld2r_type mld2r_hdr.icmp6_type #define mld2r_resv1 mld2r_hdr.icmp6_code #define mld2r_cksum mld2r_hdr.icmp6_cksum #define mld2r_resv2 mld2r_hdr.icmp6_dataun.un_data16[0] #define mld2r_ngrec mld2r_hdr.icmp6_dataun.un_data16[1] /* MLDv2 Query */ struct mld2_query { struct icmp6hdr mld2q_hdr; struct in6_addr mld2q_mca; #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 mld2q_qrv:3, mld2q_suppress:1, mld2q_resv2:4; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 mld2q_resv2:4, mld2q_suppress:1, mld2q_qrv:3; #else #error "Please fix <asm/byteorder.h>" #endif __u8 mld2q_qqic; __be16 mld2q_nsrcs; struct in6_addr mld2q_srcs[0]; }; #define mld2q_type mld2q_hdr.icmp6_type #define mld2q_code mld2q_hdr.icmp6_code #define mld2q_cksum mld2q_hdr.icmp6_cksum #define mld2q_mrc mld2q_hdr.icmp6_maxdelay #define mld2q_resv1 mld2q_hdr.icmp6_dataun.un_data16[1] /* Max Response Code */ #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ ((value) < (thresh) ? (value) : \ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) #endif net/ipv6/mcast.c +40 −95 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,7 @@ #include <linux/proc_fs.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/slab.h> #include <net/mld.h> #include <linux/netfilter.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> #include <linux/netfilter_ipv6.h> Loading Loading @@ -71,54 +72,11 @@ #define MDBG(x) #define MDBG(x) #endif #endif /* /* Ensure that we have struct in6_addr aligned on 32bit word. */ * These header formats should be in a separate include file, but icmpv6.h static void *__mld2_query_bugs[] __attribute__((__unused__)) = { * doesn't have in6_addr defined in all cases, there is no __u128, and no BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4), * other files reference these. BUILD_BUG_ON_NULL(offsetof(struct mld2_report, mld2r_grec) % 4), * BUILD_BUG_ON_NULL(offsetof(struct mld2_grec, grec_mca) % 4) * +-DLS 4/14/03 */ /* Multicast Listener Discovery version 2 headers */ struct mld2_grec { __u8 grec_type; __u8 grec_auxwords; __be16 grec_nsrcs; struct in6_addr grec_mca; struct in6_addr grec_src[0]; }; struct mld2_report { __u8 type; __u8 resv1; __sum16 csum; __be16 resv2; __be16 ngrec; struct mld2_grec grec[0]; }; struct mld2_query { __u8 type; __u8 code; __sum16 csum; __be16 mrc; __be16 resv1; struct in6_addr mca; #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 qrv:3, suppress:1, resv2:4; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 resv2:4, suppress:1, qrv:3; #else #error "Please fix <asm/byteorder.h>" #endif __u8 qqic; __be16 nsrcs; struct in6_addr srcs[0]; }; }; static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; Loading Loading @@ -157,14 +115,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, ((idev)->mc_v1_seen && \ ((idev)->mc_v1_seen && \ time_before(jiffies, (idev)->mc_v1_seen))) time_before(jiffies, (idev)->mc_v1_seen))) #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ ((value) < (thresh) ? (value) : \ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) #define IPV6_MLD_MAX_MSF 64 #define IPV6_MLD_MAX_MSF 64 int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; Loading Loading @@ -1161,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) struct in6_addr *group; struct in6_addr *group; unsigned long max_delay; unsigned long max_delay; struct inet6_dev *idev; struct inet6_dev *idev; struct icmp6hdr *hdr; struct mld_msg *mld; int group_type; int group_type; int mark = 0; int mark = 0; int len; int len; Loading @@ -1182,8 +1132,8 @@ int igmp6_event_query(struct sk_buff *skb) if (idev == NULL) if (idev == NULL) return 0; return 0; hdr = icmp6_hdr(skb); mld = (struct mld_msg *)icmp6_hdr(skb); group = (struct in6_addr *) (hdr + 1); group = &mld->mld_mca; group_type = ipv6_addr_type(group); group_type = ipv6_addr_type(group); if (group_type != IPV6_ADDR_ANY && if (group_type != IPV6_ADDR_ANY && Loading @@ -1197,7 +1147,7 @@ int igmp6_event_query(struct sk_buff *skb) /* MLDv1 router present */ /* MLDv1 router present */ /* Translate milliseconds to jiffies */ /* Translate milliseconds to jiffies */ max_delay = (ntohs(hdr->icmp6_maxdelay)*HZ)/1000; max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000; switchback = (idev->mc_qrv + 1) * max_delay; switchback = (idev->mc_qrv + 1) * max_delay; idev->mc_v1_seen = jiffies + switchback; idev->mc_v1_seen = jiffies + switchback; Loading @@ -1216,14 +1166,14 @@ int igmp6_event_query(struct sk_buff *skb) return -EINVAL; return -EINVAL; } } mlh2 = (struct mld2_query *)skb_transport_header(skb); mlh2 = (struct mld2_query *)skb_transport_header(skb); max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; if (!max_delay) if (!max_delay) max_delay = 1; max_delay = 1; idev->mc_maxdelay = max_delay; idev->mc_maxdelay = max_delay; if (mlh2->qrv) if (mlh2->mld2q_qrv) idev->mc_qrv = mlh2->qrv; idev->mc_qrv = mlh2->mld2q_qrv; if (group_type == IPV6_ADDR_ANY) { /* general query */ if (group_type == IPV6_ADDR_ANY) { /* general query */ if (mlh2->nsrcs) { if (mlh2->mld2q_nsrcs) { in6_dev_put(idev); in6_dev_put(idev); return -EINVAL; /* no sources allowed */ return -EINVAL; /* no sources allowed */ } } Loading @@ -1232,9 +1182,9 @@ int igmp6_event_query(struct sk_buff *skb) return 0; return 0; } } /* mark sources to include, if group & source-specific */ /* mark sources to include, if group & source-specific */ if (mlh2->nsrcs != 0) { if (mlh2->mld2q_nsrcs != 0) { if (!pskb_may_pull(skb, srcs_offset + if (!pskb_may_pull(skb, srcs_offset + ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { in6_dev_put(idev); in6_dev_put(idev); return -EINVAL; return -EINVAL; } } Loading Loading @@ -1270,7 +1220,7 @@ int igmp6_event_query(struct sk_buff *skb) ma->mca_flags &= ~MAF_GSQUERY; ma->mca_flags &= ~MAF_GSQUERY; } } if (!(ma->mca_flags & MAF_GSQUERY) || if (!(ma->mca_flags & MAF_GSQUERY) || mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) igmp6_group_queried(ma, max_delay); igmp6_group_queried(ma, max_delay); spin_unlock_bh(&ma->mca_lock); spin_unlock_bh(&ma->mca_lock); break; break; Loading @@ -1286,9 +1236,8 @@ int igmp6_event_query(struct sk_buff *skb) int igmp6_event_report(struct sk_buff *skb) int igmp6_event_report(struct sk_buff *skb) { { struct ifmcaddr6 *ma; struct ifmcaddr6 *ma; struct in6_addr *addrp; struct inet6_dev *idev; struct inet6_dev *idev; struct icmp6hdr *hdr; struct mld_msg *mld; int addr_type; int addr_type; /* Our own report looped back. Ignore it. */ /* Our own report looped back. Ignore it. */ Loading @@ -1300,10 +1249,10 @@ int igmp6_event_report(struct sk_buff *skb) skb->pkt_type != PACKET_BROADCAST) skb->pkt_type != PACKET_BROADCAST) return 0; return 0; if (!pskb_may_pull(skb, sizeof(struct in6_addr))) if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) return -EINVAL; return -EINVAL; hdr = icmp6_hdr(skb); mld = (struct mld_msg *)icmp6_hdr(skb); /* Drop reports with not link local source */ /* Drop reports with not link local source */ addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); Loading @@ -1311,8 +1260,6 @@ int igmp6_event_report(struct sk_buff *skb) !(addr_type&IPV6_ADDR_LINKLOCAL)) !(addr_type&IPV6_ADDR_LINKLOCAL)) return -EINVAL; return -EINVAL; addrp = (struct in6_addr *) (hdr + 1); idev = in6_dev_get(skb->dev); idev = in6_dev_get(skb->dev); if (idev == NULL) if (idev == NULL) return -ENODEV; return -ENODEV; Loading @@ -1323,7 +1270,7 @@ int igmp6_event_report(struct sk_buff *skb) read_lock_bh(&idev->lock); read_lock_bh(&idev->lock); for (ma = idev->mc_list; ma; ma=ma->next) { for (ma = idev->mc_list; ma; ma=ma->next) { if (ipv6_addr_equal(&ma->mca_addr, addrp)) { if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { spin_lock(&ma->mca_lock); spin_lock(&ma->mca_lock); if (del_timer(&ma->mca_timer)) if (del_timer(&ma->mca_timer)) atomic_dec(&ma->mca_refcnt); atomic_dec(&ma->mca_refcnt); Loading Loading @@ -1432,11 +1379,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); skb_put(skb, sizeof(*pmr)); skb_put(skb, sizeof(*pmr)); pmr = (struct mld2_report *)skb_transport_header(skb); pmr = (struct mld2_report *)skb_transport_header(skb); pmr->type = ICMPV6_MLD2_REPORT; pmr->mld2r_type = ICMPV6_MLD2_REPORT; pmr->resv1 = 0; pmr->mld2r_resv1 = 0; pmr->csum = 0; pmr->mld2r_cksum = 0; pmr->resv2 = 0; pmr->mld2r_resv2 = 0; pmr->ngrec = 0; pmr->mld2r_ngrec = 0; return skb; return skb; } } Loading @@ -1458,8 +1405,9 @@ static void mld_sendpack(struct sk_buff *skb) mldlen = skb->tail - skb->transport_header; mldlen = skb->tail - skb->transport_header; pip6->payload_len = htons(payload_len); pip6->payload_len = htons(payload_len); pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), mldlen, 0)); mldlen, 0)); dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); Loading Loading @@ -1521,7 +1469,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, pgr->grec_nsrcs = 0; pgr->grec_nsrcs = 0; pgr->grec_mca = pmc->mca_addr; /* structure copy */ pgr->grec_mca = pmc->mca_addr; /* structure copy */ pmr = (struct mld2_report *)skb_transport_header(skb); pmr = (struct mld2_report *)skb_transport_header(skb); pmr->ngrec = htons(ntohs(pmr->ngrec)+1); pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); *ppgr = pgr; *ppgr = pgr; return skb; return skb; } } Loading Loading @@ -1557,7 +1505,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, /* EX and TO_EX get a fresh packet, if needed */ /* EX and TO_EX get a fresh packet, if needed */ if (truncate) { if (truncate) { if (pmr && pmr->ngrec && if (pmr && pmr->mld2r_ngrec && AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) if (skb) mld_sendpack(skb); mld_sendpack(skb); Loading Loading @@ -1770,9 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) struct sock *sk = net->ipv6.igmp_sk; struct sock *sk = net->ipv6.igmp_sk; struct inet6_dev *idev; struct inet6_dev *idev; struct sk_buff *skb; struct sk_buff *skb; struct icmp6hdr *hdr; struct mld_msg *hdr; const struct in6_addr *snd_addr, *saddr; const struct in6_addr *snd_addr, *saddr; struct in6_addr *addrp; struct in6_addr addr_buf; struct in6_addr addr_buf; int err, len, payload_len, full_len; int err, len, payload_len, full_len; u8 ra[8] = { IPPROTO_ICMPV6, 0, u8 ra[8] = { IPPROTO_ICMPV6, 0, Loading Loading @@ -1820,14 +1767,12 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr)); hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); memset(hdr, 0, sizeof(struct icmp6hdr)); memset(hdr, 0, sizeof(struct mld_msg)); hdr->icmp6_type = type; hdr->mld_type = type; ipv6_addr_copy(&hdr->mld_mca, addr); addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); ipv6_addr_copy(addrp, addr); hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, IPPROTO_ICMPV6, IPPROTO_ICMPV6, csum_partial(hdr, len, 0)); csum_partial(hdr, len, 0)); Loading Loading
include/net/mld.h 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line #ifndef LINUX_MLD_H #define LINUX_MLD_H #include <linux/in6.h> #include <linux/icmpv6.h> /* MLDv1 Query/Report/Done */ struct mld_msg { struct icmp6hdr mld_hdr; struct in6_addr mld_mca; }; #define mld_type mld_hdr.icmp6_type #define mld_code mld_hdr.icmp6_code #define mld_cksum mld_hdr.icmp6_cksum #define mld_maxdelay mld_hdr.icmp6_maxdelay #define mld_reserved mld_hdr.icmp6_dataun.un_data16[1] /* Multicast Listener Discovery version 2 headers */ /* MLDv2 Report */ struct mld2_grec { __u8 grec_type; __u8 grec_auxwords; __be16 grec_nsrcs; struct in6_addr grec_mca; struct in6_addr grec_src[0]; }; struct mld2_report { struct icmp6hdr mld2r_hdr; struct mld2_grec mld2r_grec[0]; }; #define mld2r_type mld2r_hdr.icmp6_type #define mld2r_resv1 mld2r_hdr.icmp6_code #define mld2r_cksum mld2r_hdr.icmp6_cksum #define mld2r_resv2 mld2r_hdr.icmp6_dataun.un_data16[0] #define mld2r_ngrec mld2r_hdr.icmp6_dataun.un_data16[1] /* MLDv2 Query */ struct mld2_query { struct icmp6hdr mld2q_hdr; struct in6_addr mld2q_mca; #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 mld2q_qrv:3, mld2q_suppress:1, mld2q_resv2:4; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 mld2q_resv2:4, mld2q_suppress:1, mld2q_qrv:3; #else #error "Please fix <asm/byteorder.h>" #endif __u8 mld2q_qqic; __be16 mld2q_nsrcs; struct in6_addr mld2q_srcs[0]; }; #define mld2q_type mld2q_hdr.icmp6_type #define mld2q_code mld2q_hdr.icmp6_code #define mld2q_cksum mld2q_hdr.icmp6_cksum #define mld2q_mrc mld2q_hdr.icmp6_maxdelay #define mld2q_resv1 mld2q_hdr.icmp6_dataun.un_data16[1] /* Max Response Code */ #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ ((value) < (thresh) ? (value) : \ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) #endif
net/ipv6/mcast.c +40 −95 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,7 @@ #include <linux/proc_fs.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/slab.h> #include <net/mld.h> #include <linux/netfilter.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> #include <linux/netfilter_ipv6.h> Loading Loading @@ -71,54 +72,11 @@ #define MDBG(x) #define MDBG(x) #endif #endif /* /* Ensure that we have struct in6_addr aligned on 32bit word. */ * These header formats should be in a separate include file, but icmpv6.h static void *__mld2_query_bugs[] __attribute__((__unused__)) = { * doesn't have in6_addr defined in all cases, there is no __u128, and no BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4), * other files reference these. BUILD_BUG_ON_NULL(offsetof(struct mld2_report, mld2r_grec) % 4), * BUILD_BUG_ON_NULL(offsetof(struct mld2_grec, grec_mca) % 4) * +-DLS 4/14/03 */ /* Multicast Listener Discovery version 2 headers */ struct mld2_grec { __u8 grec_type; __u8 grec_auxwords; __be16 grec_nsrcs; struct in6_addr grec_mca; struct in6_addr grec_src[0]; }; struct mld2_report { __u8 type; __u8 resv1; __sum16 csum; __be16 resv2; __be16 ngrec; struct mld2_grec grec[0]; }; struct mld2_query { __u8 type; __u8 code; __sum16 csum; __be16 mrc; __be16 resv1; struct in6_addr mca; #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 qrv:3, suppress:1, resv2:4; #elif defined(__BIG_ENDIAN_BITFIELD) __u8 resv2:4, suppress:1, qrv:3; #else #error "Please fix <asm/byteorder.h>" #endif __u8 qqic; __be16 nsrcs; struct in6_addr srcs[0]; }; }; static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; Loading Loading @@ -157,14 +115,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, ((idev)->mc_v1_seen && \ ((idev)->mc_v1_seen && \ time_before(jiffies, (idev)->mc_v1_seen))) time_before(jiffies, (idev)->mc_v1_seen))) #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ ((value) < (thresh) ? (value) : \ ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) #define IPV6_MLD_MAX_MSF 64 #define IPV6_MLD_MAX_MSF 64 int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; Loading Loading @@ -1161,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) struct in6_addr *group; struct in6_addr *group; unsigned long max_delay; unsigned long max_delay; struct inet6_dev *idev; struct inet6_dev *idev; struct icmp6hdr *hdr; struct mld_msg *mld; int group_type; int group_type; int mark = 0; int mark = 0; int len; int len; Loading @@ -1182,8 +1132,8 @@ int igmp6_event_query(struct sk_buff *skb) if (idev == NULL) if (idev == NULL) return 0; return 0; hdr = icmp6_hdr(skb); mld = (struct mld_msg *)icmp6_hdr(skb); group = (struct in6_addr *) (hdr + 1); group = &mld->mld_mca; group_type = ipv6_addr_type(group); group_type = ipv6_addr_type(group); if (group_type != IPV6_ADDR_ANY && if (group_type != IPV6_ADDR_ANY && Loading @@ -1197,7 +1147,7 @@ int igmp6_event_query(struct sk_buff *skb) /* MLDv1 router present */ /* MLDv1 router present */ /* Translate milliseconds to jiffies */ /* Translate milliseconds to jiffies */ max_delay = (ntohs(hdr->icmp6_maxdelay)*HZ)/1000; max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000; switchback = (idev->mc_qrv + 1) * max_delay; switchback = (idev->mc_qrv + 1) * max_delay; idev->mc_v1_seen = jiffies + switchback; idev->mc_v1_seen = jiffies + switchback; Loading @@ -1216,14 +1166,14 @@ int igmp6_event_query(struct sk_buff *skb) return -EINVAL; return -EINVAL; } } mlh2 = (struct mld2_query *)skb_transport_header(skb); mlh2 = (struct mld2_query *)skb_transport_header(skb); max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; if (!max_delay) if (!max_delay) max_delay = 1; max_delay = 1; idev->mc_maxdelay = max_delay; idev->mc_maxdelay = max_delay; if (mlh2->qrv) if (mlh2->mld2q_qrv) idev->mc_qrv = mlh2->qrv; idev->mc_qrv = mlh2->mld2q_qrv; if (group_type == IPV6_ADDR_ANY) { /* general query */ if (group_type == IPV6_ADDR_ANY) { /* general query */ if (mlh2->nsrcs) { if (mlh2->mld2q_nsrcs) { in6_dev_put(idev); in6_dev_put(idev); return -EINVAL; /* no sources allowed */ return -EINVAL; /* no sources allowed */ } } Loading @@ -1232,9 +1182,9 @@ int igmp6_event_query(struct sk_buff *skb) return 0; return 0; } } /* mark sources to include, if group & source-specific */ /* mark sources to include, if group & source-specific */ if (mlh2->nsrcs != 0) { if (mlh2->mld2q_nsrcs != 0) { if (!pskb_may_pull(skb, srcs_offset + if (!pskb_may_pull(skb, srcs_offset + ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { in6_dev_put(idev); in6_dev_put(idev); return -EINVAL; return -EINVAL; } } Loading Loading @@ -1270,7 +1220,7 @@ int igmp6_event_query(struct sk_buff *skb) ma->mca_flags &= ~MAF_GSQUERY; ma->mca_flags &= ~MAF_GSQUERY; } } if (!(ma->mca_flags & MAF_GSQUERY) || if (!(ma->mca_flags & MAF_GSQUERY) || mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) igmp6_group_queried(ma, max_delay); igmp6_group_queried(ma, max_delay); spin_unlock_bh(&ma->mca_lock); spin_unlock_bh(&ma->mca_lock); break; break; Loading @@ -1286,9 +1236,8 @@ int igmp6_event_query(struct sk_buff *skb) int igmp6_event_report(struct sk_buff *skb) int igmp6_event_report(struct sk_buff *skb) { { struct ifmcaddr6 *ma; struct ifmcaddr6 *ma; struct in6_addr *addrp; struct inet6_dev *idev; struct inet6_dev *idev; struct icmp6hdr *hdr; struct mld_msg *mld; int addr_type; int addr_type; /* Our own report looped back. Ignore it. */ /* Our own report looped back. Ignore it. */ Loading @@ -1300,10 +1249,10 @@ int igmp6_event_report(struct sk_buff *skb) skb->pkt_type != PACKET_BROADCAST) skb->pkt_type != PACKET_BROADCAST) return 0; return 0; if (!pskb_may_pull(skb, sizeof(struct in6_addr))) if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) return -EINVAL; return -EINVAL; hdr = icmp6_hdr(skb); mld = (struct mld_msg *)icmp6_hdr(skb); /* Drop reports with not link local source */ /* Drop reports with not link local source */ addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); Loading @@ -1311,8 +1260,6 @@ int igmp6_event_report(struct sk_buff *skb) !(addr_type&IPV6_ADDR_LINKLOCAL)) !(addr_type&IPV6_ADDR_LINKLOCAL)) return -EINVAL; return -EINVAL; addrp = (struct in6_addr *) (hdr + 1); idev = in6_dev_get(skb->dev); idev = in6_dev_get(skb->dev); if (idev == NULL) if (idev == NULL) return -ENODEV; return -ENODEV; Loading @@ -1323,7 +1270,7 @@ int igmp6_event_report(struct sk_buff *skb) read_lock_bh(&idev->lock); read_lock_bh(&idev->lock); for (ma = idev->mc_list; ma; ma=ma->next) { for (ma = idev->mc_list; ma; ma=ma->next) { if (ipv6_addr_equal(&ma->mca_addr, addrp)) { if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { spin_lock(&ma->mca_lock); spin_lock(&ma->mca_lock); if (del_timer(&ma->mca_timer)) if (del_timer(&ma->mca_timer)) atomic_dec(&ma->mca_refcnt); atomic_dec(&ma->mca_refcnt); Loading Loading @@ -1432,11 +1379,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); skb_put(skb, sizeof(*pmr)); skb_put(skb, sizeof(*pmr)); pmr = (struct mld2_report *)skb_transport_header(skb); pmr = (struct mld2_report *)skb_transport_header(skb); pmr->type = ICMPV6_MLD2_REPORT; pmr->mld2r_type = ICMPV6_MLD2_REPORT; pmr->resv1 = 0; pmr->mld2r_resv1 = 0; pmr->csum = 0; pmr->mld2r_cksum = 0; pmr->resv2 = 0; pmr->mld2r_resv2 = 0; pmr->ngrec = 0; pmr->mld2r_ngrec = 0; return skb; return skb; } } Loading @@ -1458,8 +1405,9 @@ static void mld_sendpack(struct sk_buff *skb) mldlen = skb->tail - skb->transport_header; mldlen = skb->tail - skb->transport_header; pip6->payload_len = htons(payload_len); pip6->payload_len = htons(payload_len); pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), mldlen, 0)); mldlen, 0)); dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); Loading Loading @@ -1521,7 +1469,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, pgr->grec_nsrcs = 0; pgr->grec_nsrcs = 0; pgr->grec_mca = pmc->mca_addr; /* structure copy */ pgr->grec_mca = pmc->mca_addr; /* structure copy */ pmr = (struct mld2_report *)skb_transport_header(skb); pmr = (struct mld2_report *)skb_transport_header(skb); pmr->ngrec = htons(ntohs(pmr->ngrec)+1); pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); *ppgr = pgr; *ppgr = pgr; return skb; return skb; } } Loading Loading @@ -1557,7 +1505,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, /* EX and TO_EX get a fresh packet, if needed */ /* EX and TO_EX get a fresh packet, if needed */ if (truncate) { if (truncate) { if (pmr && pmr->ngrec && if (pmr && pmr->mld2r_ngrec && AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) if (skb) mld_sendpack(skb); mld_sendpack(skb); Loading Loading @@ -1770,9 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) struct sock *sk = net->ipv6.igmp_sk; struct sock *sk = net->ipv6.igmp_sk; struct inet6_dev *idev; struct inet6_dev *idev; struct sk_buff *skb; struct sk_buff *skb; struct icmp6hdr *hdr; struct mld_msg *hdr; const struct in6_addr *snd_addr, *saddr; const struct in6_addr *snd_addr, *saddr; struct in6_addr *addrp; struct in6_addr addr_buf; struct in6_addr addr_buf; int err, len, payload_len, full_len; int err, len, payload_len, full_len; u8 ra[8] = { IPPROTO_ICMPV6, 0, u8 ra[8] = { IPPROTO_ICMPV6, 0, Loading Loading @@ -1820,14 +1767,12 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr)); hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); memset(hdr, 0, sizeof(struct icmp6hdr)); memset(hdr, 0, sizeof(struct mld_msg)); hdr->icmp6_type = type; hdr->mld_type = type; ipv6_addr_copy(&hdr->mld_mca, addr); addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); ipv6_addr_copy(addrp, addr); hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, IPPROTO_ICMPV6, IPPROTO_ICMPV6, csum_partial(hdr, len, 0)); csum_partial(hdr, len, 0)); Loading