Commit 4c64242a authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller

ipv6: Fix nexthdr for reinjection

In ip6_input_finish the nexthdr protocol is retrieved from the
next header offset that is returned in the cb of the skb.
This method does not work for UDP encapsulation that may not
even have a concept of a nexthdr field (e.g. FOU).

This patch checks for a final protocol (INET6_PROTO_FINAL) when a
protocol handler returns > 0. If the protocol is not final then
resubmission is performed on nhoff value. If the protocol is final
then the nexthdr is taken to be the return value.
Signed-off-by: default avatarTom Herbert <tom@herbertland.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7e13318d
...@@ -236,6 +236,7 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk ...@@ -236,6 +236,7 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
nhoff = IP6CB(skb)->nhoff; nhoff = IP6CB(skb)->nhoff;
nexthdr = skb_network_header(skb)[nhoff]; nexthdr = skb_network_header(skb)[nhoff];
resubmit_final:
raw = raw6_local_deliver(skb, nexthdr); raw = raw6_local_deliver(skb, nexthdr);
ipprot = rcu_dereference(inet6_protos[nexthdr]); ipprot = rcu_dereference(inet6_protos[nexthdr]);
if (ipprot) { if (ipprot) {
...@@ -263,10 +264,21 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk ...@@ -263,10 +264,21 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
goto discard; goto discard;
ret = ipprot->handler(skb); ret = ipprot->handler(skb);
if (ret > 0) if (ret > 0) {
goto resubmit; if (ipprot->flags & INET6_PROTO_FINAL) {
else if (ret == 0) /* Not an extension header, most likely UDP
* encapsulation. Use return value as nexthdr
* protocol not nhoff (which presumably is
* not set by handler).
*/
nexthdr = ret;
goto resubmit_final;
} else {
goto resubmit;
}
} else if (ret == 0) {
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS); __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS);
}
} else { } else {
if (!raw) { if (!raw) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment