linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Mitsuru KANDA / 神田 充" <mk@linux-ipv6.org>
To: davem@redhat.com, kuznet@ms2.inr.ac.ru
Cc: linux-kernel@vger.kernel.org, netdev@oss.sgi.com,
	usagi-core@linux-ipv6.org
Subject: [PATCH] IPv6 Extension headers (Re: [PATCH] IPv6 IPsec support)
Date: Tue, 18 Mar 2003 10:32:27 -0800	[thread overview]
Message-ID: <87of48h6f8.wl@karaba.org> (raw)
In-Reply-To: <20030305.204348.130225511.davem@redhat.com>


Hello,

At Wed, 05 Mar 2003 20:43:48 -0800 (PST),
"David S. Miller" <davem@redhat.com> wrote:
> 
>    From: Kazunori Miyazawa <kazunori@miyazawa.org>
>    Date: Thu, 6 Mar 2003 09:32:19 +0900
> 
>    - Extension Header Processing on inbound:
>      As a result of IPv6 IPsec support, Extension Header processing is devided
>      into ipv6_parse_exthdrs and ipproto->handler. I think it is better to merge
>      other Extension Header handling into ipproto->handler.
>    
> Ok.

This patch merges inbound IPv6 extension header processing parts into 
inet6_protocols{} like a IPv6 AH/ESP headers.
As a result of this patch, I removed destopt parsing part in xfrm6_rcv()
and removed ipv6_parse_exthdrs().

Could you check this patch?
(This patch is against 2.5.65.)

Best Regards,
-mk

Index: include/net/ipv6.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/ipv6.h,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 ipv6.h
--- include/net/ipv6.h	9 Jan 2003 11:14:19 -0000	1.1.1.4
+++ include/net/ipv6.h	18 Mar 2003 05:11:39 -0000
@@ -203,11 +203,7 @@
 
 extern int			ip6_call_ra_chain(struct sk_buff *skb, int sel);
 
-extern int			ipv6_reassembly(struct sk_buff **skb, int);
-
 extern int			ipv6_parse_hopopts(struct sk_buff *skb, int);
-
-extern int			ipv6_parse_exthdrs(struct sk_buff **skb, int);
 
 extern struct ipv6_txoptions *  ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
 
Index: include/net/protocol.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/protocol.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 protocol.h
--- include/net/protocol.h	11 Nov 2002 04:08:20 -0000	1.1.1.3
+++ include/net/protocol.h	18 Mar 2003 05:11:39 -0000
@@ -44,7 +44,7 @@
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 struct inet6_protocol 
 {
-	int	(*handler)(struct sk_buff *skb);
+	int	(*handler)(struct sk_buff **skbp);
 
 	void	(*err_handler)(struct sk_buff *skb,
 			       struct inet6_skb_parm *opt,
Index: include/net/transp_v6.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/transp_v6.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 transp_v6.h
--- include/net/transp_v6.h	7 Oct 2002 10:22:46 -0000	1.1.1.1
+++ include/net/transp_v6.h	18 Mar 2003 05:11:39 -0000
@@ -15,6 +15,14 @@
 
 struct flowi;
 
+/* extention headers */
+extern void				ipv6_hopopts_init(void);
+extern void				ipv6_rthdr_init(void);
+extern void				ipv6_frag_init(void);
+extern void				ipv6_nodata_init(void);
+extern void				ipv6_destopt_init(void);
+
+/* transport protocols */
 extern void				rawv6_init(void);
 extern void				udpv6_init(void);
 extern void				tcpv6_init(void);
Index: include/net/xfrm.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/xfrm.h,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 xfrm.h
--- include/net/xfrm.h	13 Mar 2003 17:29:53 -0000	1.1.1.8
+++ include/net/xfrm.h	18 Mar 2003 05:11:39 -0000
@@ -415,7 +415,7 @@
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
 extern int xfrm4_rcv(struct sk_buff *skb);
-extern int xfrm6_rcv(struct sk_buff *skb);
+extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
 
Index: net/ipv4/xfrm_input.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv4/xfrm_input.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 xfrm_input.c
--- net/ipv4/xfrm_input.c	13 Mar 2003 17:29:03 -0000	1.1.1.4
+++ net/ipv4/xfrm_input.c	18 Mar 2003 05:11:39 -0000
@@ -311,8 +311,9 @@
 	return nexthdr;
 }
 
-int xfrm6_rcv(struct sk_buff *skb)
+int xfrm6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	int err;
 	u32 spi, seq;
 	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
@@ -325,12 +326,8 @@
 	u16 nh_offset = 0;
 	u8 nexthdr = 0;
 
-	if (hdr->nexthdr == IPPROTO_AH || hdr->nexthdr == IPPROTO_ESP) {
-		nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
-		hdr_len = sizeof(struct ipv6hdr);
-	} else {
-		hdr_len = skb->h.raw - skb->nh.raw;
-	}
+	nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw;
+	hdr_len = sizeof(struct ipv6hdr);
 
 	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
 	if (!tmp_hdr)
@@ -378,18 +375,6 @@
 		xfrm_vec[xfrm_nr++] = x;
 
 		iph = skb->nh.ipv6h; /* ??? */ 
-
-		if (nexthdr == NEXTHDR_DEST) {
-			if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
-		    	!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
-				err = -EINVAL;
-				goto drop;
-			}
-			nexthdr = skb->h.raw[0];
-			nh_offset = skb->h.raw - skb->nh.raw;
-			skb_pull(skb, (skb->h.raw[1]+1)<<3);
-			skb->h.raw = skb->data;
-		}
 
 		if (x->props.mode) { /* XXX */
 			if (iph->nexthdr != IPPROTO_IPV6)
Index: net/ipv6/af_inet6.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/af_inet6.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 af_inet6.c
--- net/ipv6/af_inet6.c	25 Feb 2003 05:33:26 -0000	1.1.1.7
+++ net/ipv6/af_inet6.c	18 Mar 2003 05:11:40 -0000
@@ -793,6 +793,13 @@
 	addrconf_init();
 	sit_init();
 
+	/* Init v6 extention headers. */
+	ipv6_hopopts_init();
+	ipv6_rthdr_init();
+	ipv6_frag_init();
+	ipv6_nodata_init();
+	ipv6_destopt_init();
+
 	/* Init v6 transport protocols. */
 	udpv6_init();
 	tcpv6_init();
Index: net/ipv6/exthdrs.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/exthdrs.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 exthdrs.c
--- net/ipv6/exthdrs.c	20 Feb 2003 08:34:32 -0000	1.1.1.3
+++ net/ipv6/exthdrs.c	18 Mar 2003 05:11:40 -0000
@@ -18,6 +18,9 @@
 /* Changes:
  *	yoshfuji		: ensure not to overrun while parsing 
  *				  tlv options.
+ *	Mitsuru KANDA @USAGI	: Remove ipv6_parse_exthdrs().
+ *				: Register inbound extention header
+ *				: handlers as inet6_protocol{}.
  */
 
 #include <linux/errno.h>
@@ -44,20 +47,6 @@
 #include <asm/uaccess.h>
 
 /*
- *	Parsing inbound headers.
- *
- *	Parsing function "func" returns offset wrt skb->nh of the place,
- *	where next nexthdr value is stored or NULL, if parsing
- *	failed. It should also update skb->h tp point at the next header.
- */
-
-struct hdrtype_proc
-{
-	int	type;
-	int	(*func) (struct sk_buff **, int offset);
-};
-
-/*
  *	Parsing tlv encoded headers.
  *
  *	Parsing function "func" returns 1, if parsing succeed
@@ -164,49 +153,77 @@
 	{-1,			NULL}
 };
 
-static int ipv6_dest_opt(struct sk_buff **skb_ptr, int nhoff)
+int ipv6_destopt_rcv(struct sk_buff **skbp) 
 {
-	struct sk_buff *skb=*skb_ptr;
+	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
+	u8 nexthdr = 0;
 
 	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
 	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
+	nexthdr = ((struct ipv6_destopt_hdr *)skb->h.raw)->nexthdr;
+	
 	opt->dst1 = skb->h.raw - skb->nh.raw;
 
 	if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
 		skb->h.raw += ((skb->h.raw[1]+1)<<3);
-		return opt->dst1;
+		return -nexthdr;
 	}
+						
+	return 0;
+}
 
-	return -1;
+static struct inet6_protocol destopt_protocol =
+{
+	.handler 	= 	ipv6_destopt_rcv,
+};
+
+void __init ipv6_destopt_init(void)
+{
+	if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0) 
+		printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
 }
 
 /********************************
   NONE header. No data in packet.
  ********************************/
 
-static int ipv6_nodata(struct sk_buff **skb_ptr, int nhoff)
+int ipv6_nodata_rcv(struct sk_buff **skbp)
 {
-	kfree_skb(*skb_ptr);
-	return -1;
+	struct sk_buff *skb = *skbp;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static struct inet6_protocol nodata_protocol =
+{
+	.handler	=	ipv6_nodata_rcv,
+};
+
+void __init ipv6_nodata_init(void)
+{
+	if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
+		printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
 }
 
 /********************************
   Routing header.
  ********************************/
 
-static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
+int ipv6_rthdr_rcv(struct sk_buff **skbp)
 {
-	struct sk_buff *skb = *skb_ptr;
+	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
 	struct in6_addr *addr;
 	struct in6_addr daddr;
 	int addr_type;
 	int n, i;
+	u8 nexthdr = 0;
 
 	struct ipv6_rt_hdr *hdr;
 	struct rt0_hdr *rthdr;
@@ -215,15 +232,16 @@
 	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
 		IP6_INC_STATS_BH(Ip6InHdrErrors);
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 	hdr = (struct ipv6_rt_hdr *) skb->h.raw;
+	nexthdr = hdr->nexthdr;
 
 	if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) ||
 	    skb->pkt_type != PACKET_HOST) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 looped_back:
@@ -232,24 +250,24 @@
 		skb->h.raw += (hdr->hdrlen + 1) << 3;
 		opt->dst0 = opt->dst1;
 		opt->dst1 = 0;
-		return (&hdr->nexthdr) - skb->nh.raw;
+		return -nexthdr;
 	}
 
 	if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1);
-		return -1;
+		return 0;
 	}
 
 	/*
 	 *	This is the routing header forwarding algorithm from
-	 *	RFC 1883, page 17.
+	 *	RFC 2460, page 16.
 	 */
 
 	n = hdr->hdrlen >> 1;
 
 	if (hdr->segments_left > n) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
-		return -1;
+		return 0;
 	}
 
 	/* We are about to mangle packet header. Be careful!
@@ -259,8 +277,8 @@
 		struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
 		kfree_skb(skb);
 		if (skb2 == NULL)
-			return -1;
-		*skb_ptr = skb = skb2;
+			return 0;
+		*skbp = skb = skb2;
 		opt = (struct inet6_skb_parm *)skb2->cb;
 		hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
 	}
@@ -278,7 +296,7 @@
 
 	if (addr_type&IPV6_ADDR_MULTICAST) {
 		kfree_skb(skb);
-		return -1;
+		return 0;
 	}
 
 	ipv6_addr_copy(&daddr, addr);
@@ -289,23 +307,34 @@
 	ip6_route_input(skb);
 	if (skb->dst->error) {
 		dst_input(skb);
-		return -1;
+		return 0;
 	}
 	if (skb->dst->dev->flags&IFF_LOOPBACK) {
 		if (skb->nh.ipv6h->hop_limit <= 1) {
 			icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
 				    0, skb->dev);
 			kfree_skb(skb);
-			return -1;
+			return 0;
 		}
 		skb->nh.ipv6h->hop_limit--;
 		goto looped_back;
 	}
 
 	dst_input(skb);
-	return -1;
+	return 0;
 }
 
+static struct inet6_protocol rthdr_protocol =
+{
+	.handler	=	ipv6_rthdr_rcv,
+};
+
+void __init ipv6_rthdr_init(void)
+{
+	if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
+		printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
+};
+
 /*
    This function inverts received rthdr.
    NOTE: specs allow to make it automatically only if
@@ -371,97 +400,6 @@
 	return opt;
 }
 
-/********************************
-  AUTH header.
- ********************************/
-
-/*
-   rfc1826 said, that if a host does not implement AUTH header
-   it MAY ignore it. We use this hole 8)
-
-   Actually, now we can implement OSPFv6 without kernel IPsec.
-   Authentication for poors may be done in user space with the same success.
-
-   Yes, it means, that we allow application to send/receive
-   raw authentication header. Apparently, we suppose, that it knows
-   what it does and calculates authentication data correctly.
-   Certainly, it is possible only for udp and raw sockets, but not for tcp.
-
-   AUTH header has 4byte granular length, which kills all the idea
-   behind AUTOMATIC 64bit alignment of IPv6. Now we will lose
-   cpu ticks, checking that sender did not something stupid
-   and opt->hdrlen is even. Shit!		--ANK (980730)
- */
-
-static int ipv6_auth_hdr(struct sk_buff **skb_ptr, int nhoff)
-{
-	struct sk_buff *skb=*skb_ptr;
-	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
-	int len;
-
-	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8))
-		goto fail;
-
-	/*
-	 * RFC2402 2.2 Payload Length
-	 * The 8-bit field specifies the length of AH in 32-bit words 
-	 * (4-byte units), minus "2".
-	 * -- Noriaki Takamiya @USAGI Project
-	 */
-	len = (skb->h.raw[1]+2)<<2;
-
-	if (len&7)
-		goto fail;
-
-	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+len))
-		goto fail;
-
-	opt->auth = skb->h.raw - skb->nh.raw;
-	skb->h.raw += len;
-	return opt->auth;
-
-fail:
-	kfree_skb(skb);
-	return -1;
-}
-
-/* This list MUST NOT contain entry for NEXTHDR_HOP.
-   It is parsed immediately after packet received
-   and if it occurs somewhere in another place we must
-   generate error.
- */
-
-static struct hdrtype_proc hdrproc_lst[] = {
-	{NEXTHDR_FRAGMENT,	ipv6_reassembly},
-	{NEXTHDR_ROUTING,	ipv6_routing_header},
-	{NEXTHDR_DEST,		ipv6_dest_opt},
-	{NEXTHDR_NONE,		ipv6_nodata},
-	{NEXTHDR_AUTH,		ipv6_auth_hdr},
-   /*
-	{NEXTHDR_ESP,		ipv6_esp_hdr},
-    */
-	{-1,			NULL}
-};
-
-int ipv6_parse_exthdrs(struct sk_buff **skb_in, int nhoff)
-{
-	struct hdrtype_proc *hdrt;
-	u8 nexthdr = (*skb_in)->nh.raw[nhoff];
-
-restart:
-	for (hdrt=hdrproc_lst; hdrt->type >= 0; hdrt++) {
-		if (hdrt->type == nexthdr) {
-			if ((nhoff = hdrt->func(skb_in, nhoff)) >= 0) {
-				nexthdr = (*skb_in)->nh.raw[nhoff];
-				goto restart;
-			}
-			return -1;
-		}
-	}
-	return nhoff;
-}
-
-
 /**********************************
   Hop-by-hop options.
  **********************************/
@@ -530,6 +468,34 @@
 	if (ip6_parse_tlv(tlvprochopopt_lst, skb))
 		return sizeof(struct ipv6hdr);
 	return -1;
+}
+
+/* This is fake. We have already parsed hopopts in ipv6_rcv(). -mk */
+int ipv6_hopopts_rcv(struct sk_buff **skbp)
+{
+	struct sk_buff *skb = *skbp;
+	u8 nexthdr = 0;
+
+	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
+	    !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
+		kfree_skb(skb);
+		return 0;
+	}
+	nexthdr = ((struct ipv6_hopopt_hdr *)skb->h.raw)->nexthdr;
+	skb->h.raw += (skb->h.raw[1]+1)<<3;
+
+       return -nexthdr;
+}
+
+static struct inet6_protocol hopopts_protocol =
+{
+	.handler	=	ipv6_hopopts_rcv,
+};
+
+void __init ipv6_hopopts_init(void)
+{
+	if (inet6_add_protocol(&hopopts_protocol, IPPROTO_HOPOPTS) < 0)
+		printk(KERN_ERR "ipv6_hopopts_init: Could not register protocol\n");
 }
 
 /*
Index: net/ipv6/icmp.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/icmp.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 icmp.c
--- net/ipv6/icmp.c	13 Mar 2003 17:29:06 -0000	1.1.1.7
+++ net/ipv6/icmp.c	18 Mar 2003 05:11:40 -0000
@@ -74,7 +74,7 @@
 static struct socket *__icmpv6_socket[NR_CPUS];
 #define icmpv6_socket	__icmpv6_socket[smp_processor_id()]
 
-static int icmpv6_rcv(struct sk_buff *skb);
+static int icmpv6_rcv(struct sk_buff **pskb);
 
 static struct inet6_protocol icmpv6_protocol = {
 	.handler	=	icmpv6_rcv,
@@ -458,8 +458,9 @@
  *	Handle icmp messages
  */
 
-static int icmpv6_rcv(struct sk_buff *skb)
+static int icmpv6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct net_device *dev = skb->dev;
 	struct in6_addr *saddr, *daddr;
 	struct ipv6hdr *orig_hdr;
Index: net/ipv6/ip6_input.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ip6_input.c,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 ip6_input.c
--- net/ipv6/ip6_input.c	13 Mar 2003 17:29:06 -0000	1.1.1.6
+++ net/ipv6/ip6_input.c	18 Mar 2003 05:11:40 -0000
@@ -15,6 +15,10 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+/* Changes
+ *
+ * 	Mitsuru KANDA @USAGI	: Remove ipv6_parse_exthdrs().
+ */
 
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -127,38 +131,11 @@
 	struct inet6_protocol *ipprot;
 	struct sock *raw_sk;
 	int nhoff;
-	int nexthdr;
+	int nexthdr = hdr->nexthdr;
 	u8 hash;
 
 	skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
 
-	/*
-	 *	Parse extension headers
-	 */
-
-	nexthdr = hdr->nexthdr;
-	nhoff = offsetof(struct ipv6hdr, nexthdr);
-
-	/* Skip  hop-by-hop options, they are already parsed. */
-	if (nexthdr == NEXTHDR_HOP) {
-		nhoff = sizeof(struct ipv6hdr);
-		nexthdr = skb->h.raw[0];
-		skb->h.raw += (skb->h.raw[1]+1)<<3;
-	}
-
-	/* This check is sort of optimization.
-	   It would be stupid to detect for optional headers,
-	   which are missing with probability of 200%
-	 */
-	if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP &&
-	    nexthdr != NEXTHDR_AUTH && nexthdr != NEXTHDR_ESP) {
-		nhoff = ipv6_parse_exthdrs(&skb, nhoff);
-		if (nhoff < 0)
-			return 0;
-		nexthdr = skb->nh.raw[nhoff];
-		hdr = skb->nh.ipv6h;
-	}
-
 	if (!pskb_pull(skb, skb->h.raw - skb->data))
 		goto discard;
 
@@ -173,7 +150,7 @@
 
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
 	if ((ipprot = inet6_protos[hash]) != NULL) {
-		int ret = ipprot->handler(skb);
+		int ret = ipprot->handler(&skb);
 		if (ret < 0) {
 			nexthdr = -ret;
 			goto resubmit;
@@ -182,6 +159,7 @@
 	} else {
 		if (!raw_sk) {
 			IP6_INC_STATS_BH(Ip6InUnknownProtos);
+			nhoff = offsetof(struct ipv6hdr, nexthdr);
 			icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
 		} else {
 			IP6_INC_STATS_BH(Ip6InDelivers);
Index: net/ipv6/reassembly.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/reassembly.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 reassembly.c
--- net/ipv6/reassembly.c	20 Feb 2003 08:34:32 -0000	1.1.1.4
+++ net/ipv6/reassembly.c	18 Mar 2003 05:11:40 -0000
@@ -23,6 +23,7 @@
  *      Horst von Brand Add missing #include <linux/string.h>
  *	Alexey Kuznetsov	SMP races, threading, cleanup.
  *	Patrick McHardy		LRU queue of frag heads for evictor.
+ *	Mitsuru KANDA @USAGI	Register inet6_protocol{}.
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -525,6 +526,7 @@
 	int    remove_fraghdr = 0;
 	int    payload_len;
 	int    nhoff;
+	u8     nexthdr = 0;
 
 	fq_kill(fq);
 
@@ -535,6 +537,8 @@
 	payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len;
 	nhoff = head->h.raw - head->nh.raw;
 
+	nexthdr = ((struct frag_hdr*)head->h.raw)->nexthdr;
+
 	if (payload_len > 65535) {
 		payload_len -= 8;
 		if (payload_len > 65535)
@@ -609,9 +613,13 @@
 	if (head->ip_summed == CHECKSUM_HW)
 		head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
 
+	if (!pskb_pull(head, head->h.raw - head->data)) {
+		goto out_fail;
+	}
+
 	IP6_INC_STATS_BH(Ip6ReasmOKs);
 	fq->fragments = NULL;
-	return nhoff;
+	return nexthdr;
 
 out_oversize:
 	if (net_ratelimit())
@@ -622,16 +630,18 @@
 		printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
 out_fail:
 	IP6_INC_STATS_BH(Ip6ReasmFails);
-	return -1;
+	return 0;
 }
 
-int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
+int ipv6_frag_rcv(struct sk_buff **skbp)
 {
 	struct sk_buff *skb = *skbp; 
 	struct net_device *dev = skb->dev;
 	struct frag_hdr *fhdr;
 	struct frag_queue *fq;
 	struct ipv6hdr *hdr;
+	int nhoff = skb->h.raw - skb->nh.raw;
+	u8 nexthdr = 0;
 
 	hdr = skb->nh.ipv6h;
 
@@ -640,15 +650,16 @@
 	/* Jumbo payload inhibits frag. header */
 	if (hdr->payload_len==0) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
-		return -1;
+		goto discard;
 	}
 	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) {
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
-		return -1;
+		goto discard;
 	}
 
 	hdr = skb->nh.ipv6h;
 	fhdr = (struct frag_hdr *)skb->h.raw;
+	nexthdr = fhdr->nexthdr;
 
 	if (!(fhdr->frag_off & htons(0xFFF9))) {
 		/* It is not a fragmented frame */
@@ -674,10 +685,22 @@
 
 		spin_unlock(&fq->lock);
 		fq_put(fq);
-		return ret;
+		return -ret;
 	}
 
+discard:
 	IP6_INC_STATS_BH(Ip6ReasmFails);
 	kfree_skb(skb);
-	return -1;
+	return 0;
+}
+
+static struct inet6_protocol frag_protocol =
+{
+	.handler	=	ipv6_frag_rcv,
+};
+
+void __init ipv6_frag_init(void)
+{
+	if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0)
+		printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n");
 }
Index: net/ipv6/tcp_ipv6.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/tcp_ipv6.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 tcp_ipv6.c
--- net/ipv6/tcp_ipv6.c	13 Mar 2003 17:29:06 -0000	1.1.1.8
+++ net/ipv6/tcp_ipv6.c	18 Mar 2003 05:11:40 -0000
@@ -1591,8 +1591,9 @@
 	return 0;
 }
 
-static int tcp_v6_rcv(struct sk_buff *skb)
+static int tcp_v6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct tcphdr *th;	
 	struct sock *sk;
 	int ret;
Index: net/ipv6/udp.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/udp.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 udp.c
--- net/ipv6/udp.c	13 Mar 2003 17:29:06 -0000	1.1.1.7
+++ net/ipv6/udp.c	18 Mar 2003 05:11:40 -0000
@@ -641,8 +641,9 @@
 	read_unlock(&udp_hash_lock);
 }
 
-static int udpv6_rcv(struct sk_buff *skb)
+static int udpv6_rcv(struct sk_buff **pskb)
 {
+	struct sk_buff *skb = *pskb;
 	struct sock *sk;
   	struct udphdr *uh;
 	struct net_device *dev = skb->dev;


  reply	other threads:[~2003-03-18 18:21 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20030305233025.784feb00.kazunori@miyazawa.org>
2003-03-05 15:21 ` [PATH] IPv6 IPsec support David S. Miller
2003-03-05 15:48   ` (usagi-core 12294) Re: [PATCH] " YOSHIFUJI Hideaki / 吉藤英明
2003-03-05 23:41     ` David S. Miller
2003-03-06 21:32       ` Chris Wedgwood
2003-03-06 23:27         ` David S. Miller
2003-03-05 23:25 ` [PATH] " David S. Miller
2003-03-06  0:32   ` Kazunori Miyazawa
2003-03-06  4:43     ` David S. Miller
2003-03-18 18:32       ` Mitsuru KANDA / 神田 充 [this message]
2003-03-24  5:29         ` [PATCH] IPv6 Extension headers 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=87of48h6f8.wl@karaba.org \
    --to=mk@linux-ipv6.org \
    --cc=davem@redhat.com \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@oss.sgi.com \
    --cc=usagi-core@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).