All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Mitsuru KANDA / 神田 充" <mk@linux-ipv6.org>
To: "David S. Miller" <davem@redhat.com>
Cc: netdev@oss.sgi.com, usagi@linux-ipv6.org
Subject: [PATCH] fix esp6 extension headers handling
Date: Sat, 07 Jun 2003 03:17:10 +0900	[thread overview]
Message-ID: <87wufzxe8p.wl@karaba.org> (raw)
In-Reply-To: <873cioqxch.wl@karaba.org> <3EDF36AA.9020403@tml.hut.fi> <3EDF3EB4.8010105@tml.hut.fi>

Hello,

At Thu, 05 Jun 2003 15:59:32 +0300,
Henrik Petander <lpetande@tml.hut.fi> wrote:
> 
> David S. Miller wrote:
> >    From: Henrik Petander <lpetande@tml.hut.fi>
> >    Date: Thu, 05 Jun 2003 15:25:14 +0300
> >    
> >    A possible fix is to change the pointer into an offset from the start of 
> >    the packet and use the offset later to set the nexthdr value in the 
> >    extension header.
> > 
> > Please indicate the version of the sources you are looking
> > at when making reports.
> 
> Sure, esp6.c bitkeeper version was 1.16. Also a fix to the bug report: 
> the problem is with esp6 and not with ah6, which does not use the 
> get_offset function.
> 
> Henrik
> 


The attached diff fixes esp6 extension headers handling bug 
which reported by Henrik.

I introduced ip6_find_1stfragopt() instead of get_offset().

# ip6_found_nexthdr() is just renamed ip6_find_1stfragopt()
# in order to represent collect functionality.

Regards,
-mk

Index: linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/include/net/ipv6.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/ipv6.h,v
retrieving revision 1.1.1.12
retrieving revision 1.1.1.12.8.1
diff -u -r1.1.1.12 -r1.1.1.12.8.1
--- linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/include/net/ipv6.h	31 May 2003 07:30:34 -0000	1.1.1.12
+++ linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/include/net/ipv6.h	6 Jun 2003 15:43:46 -0000	1.1.1.12.8.1
@@ -315,7 +315,7 @@
 					       unsigned length,
 					       struct ipv6_txoptions *opt,
 					       int hlimit, int flags);
-extern int			ip6_found_nexthdr(struct sk_buff *skb, u8 **nexthdr);
+extern int			ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
 
 extern int			ip6_append_data(struct sock *sk,
 						int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
Index: linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/esp6.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/esp6.c,v
retrieving revision 1.1.1.13
retrieving revision 1.1.1.13.12.1
diff -u -r1.1.1.13 -r1.1.1.13.12.1
--- linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/esp6.c	26 May 2003 08:04:11 -0000	1.1.1.13
+++ linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/esp6.c	6 Jun 2003 16:23:01 -0000	1.1.1.13.12.1
@@ -39,57 +39,6 @@
 
 #define MAX_SG_ONSTACK 4
 
-/* BUGS:
- * - we assume replay seqno is always present.
- */
-
-/* Move to common area: it is shared with AH. */
-/* Common with AH after some work on arguments. */
-
-static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr)
-{
-	u16 offset = sizeof(struct ipv6hdr);
-	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(packet + offset);
-	u8 nextnexthdr;
-
-	*nexthdr = ((struct ipv6hdr*)packet)->nexthdr;
-
-	while (offset + 1 < packet_len) {
-
-		switch (*nexthdr) {
-
-		case NEXTHDR_HOP:
-		case NEXTHDR_ROUTING:
-			offset += ipv6_optlen(exthdr);
-			*nexthdr = exthdr->nexthdr;
-			*prevhdr = exthdr;
-			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
-			break;
-
-		case NEXTHDR_DEST:
-			nextnexthdr =
-				((struct ipv6_opt_hdr*)(packet + offset + ipv6_optlen(exthdr)))->nexthdr;
-			/* XXX We know the option is inner dest opt
-			   with next next header check. */
-			if (nextnexthdr != NEXTHDR_HOP &&
-		    	    nextnexthdr != NEXTHDR_ROUTING &&
-			    nextnexthdr != NEXTHDR_DEST) {
-					return offset;
-			}
-			offset += ipv6_optlen(exthdr);
-			*nexthdr = exthdr->nexthdr;
-			*prevhdr = exthdr;
-			exthdr = (struct ipv6_opt_hdr*)(packet + offset);
-			break;
-
-		default :
-			return offset;
-		}
-	}
-
-	return offset;
-}
-
 int esp6_output(struct sk_buff *skb)
 {
 	int err;
@@ -101,12 +50,12 @@
 	struct crypto_tfm *tfm;
 	struct esp_data *esp;
 	struct sk_buff *trailer;
-	struct ipv6_opt_hdr *prevhdr = NULL;
 	int blksize;
 	int clen;
 	int alen;
 	int nfrags;
-	u8 nexthdr;
+	u8 *prevhdr;
+	u8 nexthdr = 0;
 
 	/* First, if the skb is not checksummed, complete checksum. */
 	if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) {
@@ -123,7 +72,9 @@
 	/* Strip IP header in transport mode. Save it. */
 
 	if (!x->props.mode) {
-		hdr_len = get_offset(skb->nh.raw, skb->len, &nexthdr, &prevhdr);
+		hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+		nexthdr = *prevhdr;
+		*prevhdr = IPPROTO_ESP;
 		iph = kmalloc(hdr_len, GFP_ATOMIC);
 		if (!iph) {
 			err = -ENOMEM;
@@ -178,18 +129,12 @@
 		ipv6_addr_copy(&top_iph->daddr,
 			       (struct in6_addr *)&x->id.daddr);
 	} else { 
-		/* XXX exthdr */
 		esph = (struct ipv6_esp_hdr*)skb_push(skb, x->props.header_len);
 		skb->h.raw = (unsigned char*)esph;
 		top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len);
 		memcpy(top_iph, iph, hdr_len);
 		kfree(iph);
 		top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr));
-		if (prevhdr) {
-			prevhdr->nexthdr = IPPROTO_ESP;
-		} else {
-			top_iph->nexthdr = IPPROTO_ESP;
-		}
 		*(u8*)(trailer->tail - 1) = nexthdr;
 	}
 
@@ -302,6 +247,7 @@
 		struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags];
 		struct scatterlist *sg = sgbuf;
 		u8 padlen;
+		u8 *prevhdr;
 
 		if (unlikely(nfrags > MAX_SG_ONSTACK)) {
 			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
@@ -325,11 +271,13 @@
 		}
 		/* ... check padding bits here. Silly. :-) */ 
 
-		ret_nexthdr = ((struct ipv6hdr*)tmp_hdr)->nexthdr = nexthdr[1];
 		pskb_trim(skb, skb->len - alen - padlen - 2);
 		skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen);
 		skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
 		memcpy(skb->nh.raw, tmp_hdr, hdr_len);
+		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+		ip6_find_1stfragopt(skb, &prevhdr);
+		ret_nexthdr = *prevhdr = nexthdr[1];
 	}
 	kfree(tmp_hdr);
 	return ret_nexthdr;
Index: linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ip6_output.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ip6_output.c,v
retrieving revision 1.1.1.16
retrieving revision 1.1.1.16.16.1
diff -u -r1.1.1.16 -r1.1.1.16.16.1
--- linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ip6_output.c	26 May 2003 08:04:10 -0000	1.1.1.16
+++ linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ip6_output.c	6 Jun 2003 15:43:34 -0000	1.1.1.16.16.1
@@ -887,7 +887,7 @@
 #endif
 }
 
-int ip6_found_nexthdr(struct sk_buff *skb, u8 **nexthdr)
+int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
 	u16 offset = sizeof(struct ipv6hdr);
 	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1);
@@ -929,7 +929,7 @@
 	u8 *prevhdr, nexthdr = 0;
 
 	dev = rt->u.dst.dev;
-	hlen = ip6_found_nexthdr(skb, &prevhdr);
+	hlen = ip6_find_1stfragopt(skb, &prevhdr);
 	nexthdr = *prevhdr;
 
 	mtu = dst_pmtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
Index: linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipcomp6.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ipcomp6.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.14.1
diff -u -r1.1.1.2 -r1.1.1.2.14.1
--- linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipcomp6.c	21 May 2003 13:15:20 -0000	1.1.1.2
+++ linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipcomp6.c	6 Jun 2003 15:43:34 -0000	1.1.1.2.14.1
@@ -105,7 +105,7 @@
 	iph = skb->nh.ipv6h;
 	iph->payload_len = htons(skb->len);
 	
-	ip6_found_nexthdr(skb, &prevhdr);
+	ip6_find_1stfragopt(skb, &prevhdr);
 	*prevhdr = nexthdr;
 out:
 	if (tmp_hdr)
@@ -160,7 +160,7 @@
 		skb->nh.raw = skb->data; /* == top_iph */
 		skb->h.raw = skb->nh.raw + hdr_len;
 	} else {
-		hdr_len = ip6_found_nexthdr(skb, &prevhdr);
+		hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
 		nexthdr = *prevhdr;
 	}
 
@@ -203,7 +203,7 @@
 
 	top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 	skb->nh.raw = skb->data; /* top_iph */
-	ip6_found_nexthdr(skb, &prevhdr); 
+	ip6_find_1stfragopt(skb, &prevhdr); 
 	*prevhdr = IPPROTO_COMP;
 
 	ipch = (struct ipv6_comp_hdr *)((unsigned char *)top_iph + hdr_len);
Index: linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipv6_syms.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ipv6_syms.c,v
retrieving revision 1.1.1.12
retrieving revision 1.1.1.12.16.4
diff -u -r1.1.1.12 -r1.1.1.12.16.4
--- linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipv6_syms.c	26 May 2003 08:04:11 -0000	1.1.1.12
+++ linux25-b2_5_70+CS1_1314_IPSEC6_CLEANUP/net/ipv6/ipv6_syms.c	6 Jun 2003 17:38:20 -0000	1.1.1.12.16.4
@@ -35,6 +35,6 @@
 EXPORT_SYMBOL(in6addr_any);
 EXPORT_SYMBOL(in6addr_loopback);
 EXPORT_SYMBOL(in6_dev_finish_destroy);
-EXPORT_SYMBOL(ip6_found_nexthdr);
+EXPORT_SYMBOL(ip6_find_1stfragopt);
 EXPORT_SYMBOL(xfrm6_rcv);
 EXPORT_SYMBOL(xfrm6_clear_mutable_options);

  parent reply	other threads:[~2003-06-06 18:17 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-06-05 12:25 Bug in ipv6 ipsec in handling of packets with extension headers Henrik Petander
2003-06-05 12:17 ` David S. Miller
2003-06-05 12:59   ` Henrik Petander
2003-06-05 16:54     ` Mitsuru KANDA / 神田 充
2003-06-06 18:17     ` Mitsuru KANDA / 神田 充 [this message]
2003-06-07  9:22       ` [PATCH] fix esp6 extension headers handling David S. Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87wufzxe8p.wl@karaba.org \
    --to=mk@linux-ipv6.org \
    --cc=davem@redhat.com \
    --cc=netdev@oss.sgi.com \
    --cc=usagi@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.