ipv6: Fix nexthdr for reinjection
[cascardo/linux.git] / net / ipv6 / ip6_input.c
index f185cbc..d35dff2 100644 (file)
@@ -236,6 +236,7 @@ resubmit:
        nhoff = IP6CB(skb)->nhoff;
        nexthdr = skb_network_header(skb)[nhoff];
 
+resubmit_final:
        raw = raw6_local_deliver(skb, nexthdr);
        ipprot = rcu_dereference(inet6_protos[nexthdr]);
        if (ipprot) {
@@ -263,10 +264,21 @@ resubmit:
                        goto discard;
 
                ret = ipprot->handler(skb);
-               if (ret > 0)
-                       goto resubmit;
-               else if (ret == 0)
+               if (ret > 0) {
+                       if (ipprot->flags & INET6_PROTO_FINAL) {
+                               /* 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);
+               }
        } else {
                if (!raw) {
                        if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {