|
@@ -1147,6 +1147,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
|
|
|
int type;
|
|
int type;
|
|
|
int err = 0;
|
|
int err = 0;
|
|
|
__be32 group;
|
|
__be32 group;
|
|
|
|
|
+ u16 nsrcs;
|
|
|
|
|
|
|
|
ih = igmpv3_report_hdr(skb);
|
|
ih = igmpv3_report_hdr(skb);
|
|
|
num = ntohs(ih->ngrec);
|
|
num = ntohs(ih->ngrec);
|
|
@@ -1160,8 +1161,9 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
|
|
|
grec = (void *)(skb->data + len - sizeof(*grec));
|
|
grec = (void *)(skb->data + len - sizeof(*grec));
|
|
|
group = grec->grec_mca;
|
|
group = grec->grec_mca;
|
|
|
type = grec->grec_type;
|
|
type = grec->grec_type;
|
|
|
|
|
+ nsrcs = ntohs(grec->grec_nsrcs);
|
|
|
|
|
|
|
|
- len += ntohs(grec->grec_nsrcs) * 4;
|
|
|
|
|
|
|
+ len += nsrcs * 4;
|
|
|
if (!pskb_may_pull(skb, len))
|
|
if (!pskb_may_pull(skb, len))
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
@@ -1182,7 +1184,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
|
|
|
src = eth_hdr(skb)->h_source;
|
|
src = eth_hdr(skb)->h_source;
|
|
|
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
|
|
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
|
|
|
type == IGMPV3_MODE_IS_INCLUDE) &&
|
|
type == IGMPV3_MODE_IS_INCLUDE) &&
|
|
|
- ntohs(grec->grec_nsrcs) == 0) {
|
|
|
|
|
|
|
+ nsrcs == 0) {
|
|
|
br_ip4_multicast_leave_group(br, port, group, vid, src);
|
|
br_ip4_multicast_leave_group(br, port, group, vid, src);
|
|
|
} else {
|
|
} else {
|
|
|
err = br_ip4_multicast_add_group(br, port, group, vid,
|
|
err = br_ip4_multicast_add_group(br, port, group, vid,
|
|
@@ -1217,23 +1219,26 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
|
|
|
len = skb_transport_offset(skb) + sizeof(*icmp6h);
|
|
len = skb_transport_offset(skb) + sizeof(*icmp6h);
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
for (i = 0; i < num; i++) {
|
|
|
- __be16 *nsrcs, _nsrcs;
|
|
|
|
|
-
|
|
|
|
|
- nsrcs = skb_header_pointer(skb,
|
|
|
|
|
- len + offsetof(struct mld2_grec,
|
|
|
|
|
- grec_nsrcs),
|
|
|
|
|
- sizeof(_nsrcs), &_nsrcs);
|
|
|
|
|
- if (!nsrcs)
|
|
|
|
|
|
|
+ __be16 *_nsrcs, __nsrcs;
|
|
|
|
|
+ u16 nsrcs;
|
|
|
|
|
+
|
|
|
|
|
+ _nsrcs = skb_header_pointer(skb,
|
|
|
|
|
+ len + offsetof(struct mld2_grec,
|
|
|
|
|
+ grec_nsrcs),
|
|
|
|
|
+ sizeof(__nsrcs), &__nsrcs);
|
|
|
|
|
+ if (!_nsrcs)
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
+ nsrcs = ntohs(*_nsrcs);
|
|
|
|
|
+
|
|
|
if (!pskb_may_pull(skb,
|
|
if (!pskb_may_pull(skb,
|
|
|
len + sizeof(*grec) +
|
|
len + sizeof(*grec) +
|
|
|
- sizeof(struct in6_addr) * ntohs(*nsrcs)))
|
|
|
|
|
|
|
+ sizeof(struct in6_addr) * nsrcs))
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
grec = (struct mld2_grec *)(skb->data + len);
|
|
grec = (struct mld2_grec *)(skb->data + len);
|
|
|
len += sizeof(*grec) +
|
|
len += sizeof(*grec) +
|
|
|
- sizeof(struct in6_addr) * ntohs(*nsrcs);
|
|
|
|
|
|
|
+ sizeof(struct in6_addr) * nsrcs;
|
|
|
|
|
|
|
|
/* We treat these as MLDv1 reports for now. */
|
|
/* We treat these as MLDv1 reports for now. */
|
|
|
switch (grec->grec_type) {
|
|
switch (grec->grec_type) {
|
|
@@ -1252,7 +1257,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
|
|
|
src = eth_hdr(skb)->h_source;
|
|
src = eth_hdr(skb)->h_source;
|
|
|
if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE ||
|
|
if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE ||
|
|
|
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
|
|
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
|
|
|
- ntohs(*nsrcs) == 0) {
|
|
|
|
|
|
|
+ nsrcs == 0) {
|
|
|
br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
|
|
br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
|
|
|
vid, src);
|
|
vid, src);
|
|
|
} else {
|
|
} else {
|