Subject: Re: [PATCH net-next 06/13] ipv6: Fix nexthdr for reinjection

From: Shmulik Ladkani <[email-masked]>
Date: Fri, 13 May 2016 14:00:14 +0300

Hi,

On Fri, 13 May 2016 09:28:50 +0300 Shmulik Ladkani <[email-masked]> wrote:
> On Thu, 12 May 2016 14:45:36 -0700 Tom Herbert <[email-masked]> wrote:
> > Is there any reason why the EH handlers can't read the nexthdr and return that?  
> 
> One additional thing:
> 
> Seems the
> 
>     if (!pskb_pull(skb, skb_transport_offset(skb)))
> 
> located at the original resubmit label was also necessary, as the EH
> handlers may increment skb->transport_header (both ipv6_destopt_rcv and
> ipv6_rthdr_rcv do so).
> 
> So if we'd like to read the nexthdr at the EH handlers we should repeat
> the "skb pull; read nexthdr from skb_network_header(skb)[new nhoff];
> return nexhdr;" prior each positive return from EH handlers.

Alternatively, instead of modifying EH handlers adding this repeated
logic, we can rearrange ip6_input_finish code, under the premise that
"EH handling iff !INET6_PROTO_FINAL", as follows:

@@ -229,13 +229,14 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
 	 */
 
 	rcu_read_lock();
-resubmit:
+nexthdr_read:
 	idev = ip6_dst_idev(skb_dst(skb));
 	if (!pskb_pull(skb, skb_transport_offset(skb)))
 		goto discard;
 	nhoff = IP6CB(skb)->nhoff;
 	nexthdr = skb_network_header(skb)[nhoff];
 
+resubmit:
 	raw = raw6_local_deliver(skb, nexthdr);
 	ipprot = rcu_dereference(inet6_protos[nexthdr]);
 	if (ipprot) {
@@ -263,8 +264,12 @@ resubmit:
 			goto discard;
 
 		ret = ipprot->handler(skb);
-		if (ret > 0)
+		if (ret > 0) {
+			if (!(ipprot->flags & INET6_PROTO_FINAL))
+				goto nexthdr_read;
+			nexthdr = ret;
 			goto resubmit;
+		}
 		else if (ret == 0)
 			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS);

Meaning, for EH (identified by !INET6_PROTO_FINAL), act as originally
was (skbpull and refetch nexthdr); For non INET6_PROTO_FINAL, ret code
is the proto itself, so go directly to resubmit.

Less modifications, but (1) creates a coupling (wasn't there already?)
between EH handlers and the !INET6_PROTO_FINAL flag, (2) anchors the
dual semantics WRT ret code of inet6_protocol->handler.

Regards,
Shmulik