diff options
Diffstat (limited to 'net/ipv6/mcast.c')
| -rw-r--r-- | net/ipv6/mcast.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index c4f2a0ef7489..f15e04ad026e 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -545,8 +545,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | |||
| 545 | sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max)); | 545 | sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max)); |
| 546 | goto done; | 546 | goto done; |
| 547 | } | 547 | } |
| 548 | } else | 548 | } else { |
| 549 | newpsl = NULL; | 549 | newpsl = NULL; |
| 550 | (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); | ||
| 551 | } | ||
| 550 | psl = pmc->sflist; | 552 | psl = pmc->sflist; |
| 551 | if (psl) { | 553 | if (psl) { |
| 552 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, | 554 | (void) ip6_mc_del_src(idev, group, pmc->sfmode, |
| @@ -1087,7 +1089,7 @@ static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
| 1087 | 1089 | ||
| 1088 | int igmp6_event_query(struct sk_buff *skb) | 1090 | int igmp6_event_query(struct sk_buff *skb) |
| 1089 | { | 1091 | { |
| 1090 | struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw; | 1092 | struct mld2_query *mlh2 = NULL; |
| 1091 | struct ifmcaddr6 *ma; | 1093 | struct ifmcaddr6 *ma; |
| 1092 | struct in6_addr *group; | 1094 | struct in6_addr *group; |
| 1093 | unsigned long max_delay; | 1095 | unsigned long max_delay; |
| @@ -1140,6 +1142,13 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1140 | /* clear deleted report items */ | 1142 | /* clear deleted report items */ |
| 1141 | mld_clear_delrec(idev); | 1143 | mld_clear_delrec(idev); |
| 1142 | } else if (len >= 28) { | 1144 | } else if (len >= 28) { |
| 1145 | int srcs_offset = sizeof(struct mld2_query) - | ||
| 1146 | sizeof(struct icmp6hdr); | ||
| 1147 | if (!pskb_may_pull(skb, srcs_offset)) { | ||
| 1148 | in6_dev_put(idev); | ||
| 1149 | return -EINVAL; | ||
| 1150 | } | ||
| 1151 | mlh2 = (struct mld2_query *) skb->h.raw; | ||
| 1143 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1152 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; |
| 1144 | if (!max_delay) | 1153 | if (!max_delay) |
| 1145 | max_delay = 1; | 1154 | max_delay = 1; |
| @@ -1156,7 +1165,15 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1156 | return 0; | 1165 | return 0; |
| 1157 | } | 1166 | } |
| 1158 | /* mark sources to include, if group & source-specific */ | 1167 | /* mark sources to include, if group & source-specific */ |
| 1159 | mark = mlh2->nsrcs != 0; | 1168 | if (mlh2->nsrcs != 0) { |
| 1169 | if (!pskb_may_pull(skb, srcs_offset + | ||
| 1170 | mlh2->nsrcs * sizeof(struct in6_addr))) { | ||
| 1171 | in6_dev_put(idev); | ||
| 1172 | return -EINVAL; | ||
| 1173 | } | ||
| 1174 | mlh2 = (struct mld2_query *) skb->h.raw; | ||
| 1175 | mark = 1; | ||
| 1176 | } | ||
| 1160 | } else { | 1177 | } else { |
| 1161 | in6_dev_put(idev); | 1178 | in6_dev_put(idev); |
| 1162 | return -EINVAL; | 1179 | return -EINVAL; |
