Message ID | 5086B721.1090905@gmail.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, Oct 23, 2012 at 11:26:25PM +0800, Duan Jiong wrote: > > Before using icmpv6_notify() to propagate redirect, change skb->data > to poing the IP packet that triggered the sending of the Redirect. > > Signed-off-by: Duan Jiong <djduanjiong@gmail.com> > --- > net/ipv6/ndisc.c | 39 +++++++++++++++++++++++++++++++++++++++ > 1 files changed, 39 insertions(+), 0 deletions(-) > > diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c > index ff36194..0f73303 100644 > --- a/net/ipv6/ndisc.c > +++ b/net/ipv6/ndisc.c > @@ -1334,6 +1334,11 @@ out: > > static void ndisc_redirect_rcv(struct sk_buff *skb) > { > + int opt_len; > + int opt_offset; > + int ndisc_head_len; > + struct nd_opt_hdr *nd_opt; > + > #ifdef CONFIG_IPV6_NDISC_NODETYPE > switch (skb->ndisc_nodetype) { > case NDISC_NODETYPE_HOST: > @@ -1350,6 +1355,40 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) > return; > } > > + ndisc_head_len = sizeof(struct icmp6hdr) + 2*sizeof(struct in6_addr); > + if (!pskb_may_pull(skb, ndisc_head_len)) { > + return; > + } > + > + nd_opt = (struct nd_opt_hdr *)(skb->data + ndisc_head_len); > + > + opt_len = skb->tail - skb->transport_header - ndisc_head_len; > + if (opt_len < 0) { > + return; > + } > + while (opt_len) { > + int l; > + > + if (opt_len < sizeof(struct nd_opt_hdr)) { > + return; > + } > + l = nd_opt->nd_opt_len << 3; > + if (opt_len < l || l == 0) { > + return; > + } > + if (nd_opt->nd_opt_type == ND_OPT_REDIRECT_HDR) { > + __skb_pull(skb, ndisc_head_len + opt_offset + 8); > + break; > + } > + opt_len -= l; > + nd_opt = ((void *)nd_opt) + 1; > + opt_offset += 1; > + } Instead of the above loop, you could use ndisc_parse_options(). This does the same what you are doing here and it would make it a bit clearer what's going on. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Oct 24, 2012 at 06:54:10AM +0200, Steffen Klassert wrote: > On Tue, Oct 23, 2012 at 11:26:25PM +0800, Duan Jiong wrote: > > + while (opt_len) { > > + int l; > > + > > + if (opt_len < sizeof(struct nd_opt_hdr)) { > > + return; > > + } > > + l = nd_opt->nd_opt_len << 3; > > + if (opt_len < l || l == 0) { > > + return; > > + } > > + if (nd_opt->nd_opt_type == ND_OPT_REDIRECT_HDR) { > > + __skb_pull(skb, ndisc_head_len + opt_offset + 8); > > + break; > > + } > > + opt_len -= l; > > + nd_opt = ((void *)nd_opt) + 1; > > + opt_offset += 1; > > + } > > Instead of the above loop, you could use ndisc_parse_options(). > This does the same what you are doing here and it would make it > a bit clearer what's going on. > Duan, are you going to update your patches? We really need fixes for the problems you have discovered. Thanks! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
δΊ 2012/10/24 12:54, Steffen Klassert ει: > On Tue, Oct 23, 2012 at 11:26:25PM +0800, Duan Jiong wrote: >> >> Before using icmpv6_notify() to propagate redirect, change skb->data >> to poing the IP packet that triggered the sending of the Redirect. >> >> Signed-off-by: Duan Jiong <djduanjiong@gmail.com> >> --- >> net/ipv6/ndisc.c | 39 +++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 39 insertions(+), 0 deletions(-) >> >> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c >> index ff36194..0f73303 100644 >> --- a/net/ipv6/ndisc.c >> +++ b/net/ipv6/ndisc.c >> @@ -1334,6 +1334,11 @@ out: >> >> static void ndisc_redirect_rcv(struct sk_buff *skb) >> { >> + int opt_len; >> + int opt_offset; >> + int ndisc_head_len; >> + struct nd_opt_hdr *nd_opt; >> + >> #ifdef CONFIG_IPV6_NDISC_NODETYPE >> switch (skb->ndisc_nodetype) { >> case NDISC_NODETYPE_HOST: >> @@ -1350,6 +1355,40 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) >> return; >> } >> >> + ndisc_head_len = sizeof(struct icmp6hdr) + 2*sizeof(struct in6_addr); >> + if (!pskb_may_pull(skb, ndisc_head_len)) { >> + return; >> + } >> + >> + nd_opt = (struct nd_opt_hdr *)(skb->data + ndisc_head_len); >> + >> + opt_len = skb->tail - skb->transport_header - ndisc_head_len; >> + if (opt_len < 0) { >> + return; >> + } >> + while (opt_len) { >> + int l; >> + >> + if (opt_len < sizeof(struct nd_opt_hdr)) { >> + return; >> + } >> + l = nd_opt->nd_opt_len << 3; >> + if (opt_len < l || l == 0) { >> + return; >> + } >> + if (nd_opt->nd_opt_type == ND_OPT_REDIRECT_HDR) { >> + __skb_pull(skb, ndisc_head_len + opt_offset + 8); >> + break; >> + } >> + opt_len -= l; >> + nd_opt = ((void *)nd_opt) + 1; >> + opt_offset += 1; >> + } > > Instead of the above loop, you could use ndisc_parse_options(). > This does the same what you are doing here and it would make it > a bit clearer what's going on. > I apologize for not replying to you earlier,and i will continue to update my patches. Just like you said, i try to use ndisc_parse_options() to instead of the loop, but i find the skb->data can't be changed in function ndisc_parse_options() due to lack of arguments. So i think it is better to continue to use the loop. How do you think this? Thanks! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ff36194..0f73303 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1334,6 +1334,11 @@ out: static void ndisc_redirect_rcv(struct sk_buff *skb) { + int opt_len; + int opt_offset; + int ndisc_head_len; + struct nd_opt_hdr *nd_opt; + #ifdef CONFIG_IPV6_NDISC_NODETYPE switch (skb->ndisc_nodetype) { case NDISC_NODETYPE_HOST: @@ -1350,6 +1355,40 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) return; } + ndisc_head_len = sizeof(struct icmp6hdr) + 2*sizeof(struct in6_addr); + if (!pskb_may_pull(skb, ndisc_head_len)) { + return; + } + + nd_opt = (struct nd_opt_hdr *)(skb->data + ndisc_head_len); + + opt_len = skb->tail - skb->transport_header - ndisc_head_len; + if (opt_len < 0) { + return; + } + while (opt_len) { + int l; + + if (opt_len < sizeof(struct nd_opt_hdr)) { + return; + } + l = nd_opt->nd_opt_len << 3; + if (opt_len < l || l == 0) { + return; + } + if (nd_opt->nd_opt_type == ND_OPT_REDIRECT_HDR) { + __skb_pull(skb, ndisc_head_len + opt_offset + 8); + break; + } + opt_len -= l; + nd_opt = ((void *)nd_opt) + 1; + opt_offset += 1; + } + + if (opt_len == 0) { + return; + } + icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); }
Before using icmpv6_notify() to propagate redirect, change skb->data to poing the IP packet that triggered the sending of the Redirect. Signed-off-by: Duan Jiong <djduanjiong@gmail.com> --- net/ipv6/ndisc.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-)