Skip to contentSkip to conversation

IPv6 IPsec support

PATH In review Kazunori Miyazawa 5 participants 11 messages Mar 5, 2003 – Mar 24, 2003

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

Hello,

I submit the patch to let the kernel support ipv6 ipsec again. It is able to comple ipv6 as module.

This patch incldes a couple of clean-up and
changes of function name.

Sorry, this patch is for linux-2.5.63.

Best Regards,

--Kazunori Miyazawa (Yokogawa Electric Corporation)

Patch-Name: IPsec
Patch-Id: IPSEC_2_5_63_ALL-20030304
Patch-Author: Kazunori Miyazawa <[email protected]>
Credit: Kazunori Miyazawa <[email protected]>,
Mitsuru Kanda <[email protected]>, YOSHIFUJI Hideaki <[email protected]>, Kunihiro Ishiguro

This patch make the kernel process IPv6 packet with IPsec.

- We've introduced a function pointer (xfrm_dst_lookup) for looking up routing table of each address family to comple ipv6 as module.

- We moved some common functions among protocols such as skb_icv_walk() in net/ipv4/{ah.c,esp.c} to net/ipv4/xfrm_algo.c. This is for compling ah / esp and ah6 / esp6 as modules.

- We renamed some IPv4 specific xfrm_XXX() functions to xfrm4_XXX().

include/linux/ipv6.h +15 -0
diff -ruN -x CVS linux-2.5.63/include/linux/ipv6.h linux25/include/linux/ipv6.h
@@ -74,6 +74,21 @@
 #define rt0_type		rt_hdr.type;
 };
 
+struct ipv6_auth_hdr {
+	__u8  nexthdr;
+	__u8  hdrlen;           /* This one is measured in 32 bit units! */
+	__u16 reserved;
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  auth_data[4];     /* Length variable but >=4. Mind the 64 bit alignment! */
+};
+
+struct ipv6_esp_hdr {
+	__u32 spi;
+	__u32 seq_no;           /* Sequence number */
+	__u8  enc_data[8];      /* Length variable but >=8. Mind the 64 bit alignment! */
+};
+
 /*
  *	IPv6 fixed header
  *
include/net/dst.h +3 -0
diff -ruN -x CVS linux-2.5.63/include/net/dst.h linux25/include/net/dst.h
@@ -247,7 +247,10 @@
 struct flowi;
 extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
 		       struct sock *sk, int flags);
+extern int xfrm6_lookup(struct dst_entry **dst_p, struct flowi *fl,
+		       struct sock *sk, int flags);
 extern void xfrm_init(void);
+extern void xfrm6_init(void);
 
 #endif
 
include/net/ip6_route.h +3 -0
diff -ruN -x CVS linux-2.5.63/include/net/ip6_route.h linux25/include/net/ip6_route.h
@@ -38,6 +38,7 @@
 extern int			ipv6_route_ioctl(unsigned int cmd, void *arg);
 
 extern int			ip6_route_add(struct in6_rtmsg *rtmsg);
+extern int			ip6_route_del(struct in6_rtmsg *rtmsg);
 extern int			ip6_del_rt(struct rt6_info *);
 
 extern int			ip6_rt_addr_add(struct in6_addr *addr,
@@ -57,6 +58,8 @@
 					    struct in6_addr *saddr,
 					    int oif, int flags);
 
+extern struct rt6_info		*ndisc_get_dummy_rt(void);
+
 /*
  *	support functions for ND
  *
include/net/xfrm.h +151 -19

241 lines not on this page · raw message

net/ipv4/ah.c +2 -105

126 lines not on this page · raw message

net/ipv4/esp.c +2 -306

321 lines not on this page · raw message

net/ipv4/route.c +9 -0
diff -ruN -x CVS linux-2.5.63/net/ipv4/route.c linux25/net/ipv4/route.c
@@ -96,6 +96,7 @@
 #include <net/arp.h>
 #include <net/tcp.h>
 #include <net/icmp.h>
+#include <net/xfrm.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -2599,6 +2600,13 @@
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
+int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+{
+        int err = 0;
+        err = __ip_route_output_key((struct rtable**)dst, fl);
+        return err;
+}
+
 int __init ip_rt_init(void)
 {
 	int i, order, goal, rc = 0;
@@ -2680,6 +2688,7 @@
 					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
+	xfrm_dst_lookup_register(xfrm_dst_lookup, AF_INET);
 #ifdef CONFIG_PROC_FS
 	if (rt_cache_proc_init())
 		goto out_enomem;
net/ipv4/xfrm_algo.c +332 -0

344 lines not on this page · raw message

net/ipv4/xfrm_input.c +296 -1

310 lines not on this page · raw message

net/ipv4/xfrm_policy.c +528 -51

829 lines not on this page · raw message

net/ipv4/xfrm_state.c +260 -129

470 lines not on this page · raw message

net/ipv4/xfrm_user.c +4 -4
diff -ruN -x CVS linux-2.5.63/net/ipv4/xfrm_user.c linux25/net/ipv4/xfrm_user.c
@@ -234,8 +234,8 @@
 
 	switch (x->props.family) {
 	case AF_INET:
-		x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
-				       x->id.spi, x->id.proto);
+		x1 = xfrm4_state_lookup(x->props.saddr.xfrm4_addr,
+					x->id.spi, x->id.proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -265,7 +265,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
@@ -395,7 +395,7 @@
 
 	switch (p->family) {
 	case AF_INET:
-		x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+		x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
net/ipv6/Kconfig +14 -1
diff -ruN -x CVS linux-2.5.63/net/ipv6/Kconfig linux25/net/ipv6/Kconfig
@@ -17,5 +17,18 @@
 
 	  See <file:Documentation/networking/ip-sysctl.txt> for details.
 
-source "net/ipv6/netfilter/Kconfig"
+config INET6_AH
+	tristate "IPv6: AH transformation"
+	---help---
+	  Support for IPsec AH.
+
+	  If unsure, say Y.
+
+config INET6_ESP
+	tristate "IPv6: ESP transformation"
+	---help---
+	  Support for IPsec ESP.
 
+	  If unsure, say Y.
+
+source "net/ipv6/netfilter/Kconfig"
net/ipv6/Makefile +2 -0
diff -ruN -x CVS linux-2.5.63/net/ipv6/Makefile linux25/net/ipv6/Makefile
@@ -10,4 +10,6 @@
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
 		ip6_flowlabel.o ipv6_syms.o
 
+obj-$(CONFIG_INET6_AH) += ah6.o
+obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
net/ipv6/ah6.c +361 -0

235 lines not on this page · raw message

net/ipv6/esp6.c +526 -0

526 lines not on this page · raw message

net/ipv6/ip6_input.c +2 -1
diff -ruN -x CVS linux-2.5.63/net/ipv6/ip6_input.c linux25/net/ipv6/ip6_input.c

Lines of this file are not shown. View the raw message.

net/ipv6/ip6_output.c +16 -4
diff -ruN -x CVS linux-2.5.63/net/ipv6/ip6_output.c linux25/net/ipv6/ip6_output.c

Lines of this file are not shown. View the raw message.

net/ipv6/ndisc.c +133 -36

169 lines not on this page · raw message

net/ipv6/raw.c +6 -0
diff -ruN -x CVS linux-2.5.63/net/ipv6/raw.c linux25/net/ipv6/raw.c

Lines of this file are not shown. View the raw message.

net/ipv6/route.c +18 -1
diff -ruN -x CVS linux-2.5.63/net/ipv6/route.c linux25/net/ipv6/route.c

Lines of this file are not shown. View the raw message.

net/ipv6/tcp_ipv6.c +14 -1
diff -ruN -x CVS linux-2.5.63/net/ipv6/tcp_ipv6.c linux25/net/ipv6/tcp_ipv6.c

Lines of this file are not shown. View the raw message.

net/ipv6/udp.c +9 -0
diff -ruN -x CVS linux-2.5.63/net/ipv6/udp.c linux25/net/ipv6/udp.c

Lines of this file are not shown. View the raw message.

net/key/af_key.c +3 -14
diff -ruN -x CVS linux-2.5.63/net/key/af_key.c linux25/net/key/af_key.c

Lines of this file are not shown. View the raw message.

net/netsyms.c +16 -3
diff -ruN -x CVS linux-2.5.63/net/netsyms.c linux25/net/netsyms.c

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

#1 lore raw

From: Kazunori Miyazawa <[email protected]>
Date: Wed, 5 Mar 2003 23:30:25 +0900

Hello Miyazawa-san,

I submit the patch to let the kernel support ipv6 ipsec again. It is able to comple ipv6 as module.

This patch incldes a couple of clean-up and
changes of function name.

Excellent work.

I have comments, but they are very minor and can wait. I will apply your patch after basic build testing.

The next large task will be to abstract out more common pieces of code. There is still quite a bit of code duplication between v4 and v6 xfrm methods,

Thank you!

#2 lore raw

Re: (usagi-core 12294) Re: [PATCH] IPv6 IPsec support

In article <[email protected]> (at Wed, 05 Mar 2003 07:21:49 -0800 (PST)), "David S. Miller" <[email protected]> says:

Quoted 1 line

I will apply your patch after basic build testing.

Thank you.

Quoted 3 lines

The next large task will be to abstract out more common pieces of code. There is still quite a bit of code duplication between v4 and v6 xfrm methods,

Yes, we will do that. That patch is first step for reducing duplicate codes between IPv4 and IPv6.

--yoshfuji

#3 lore raw

Re: (usagi-core 12294) Re: [PATCH] IPv6 IPsec support

From: YOSHIFUJI Hideaki / 吉藤英明 <[email protected]>
Date: Thu, 06 Mar 2003 00:48:20 +0900 (JST)

Quoted 3 lines

The next large task will be to abstract out more common pieces of code. There is still quite a bit of code duplication between v4 and v6 xfrm methods,

Yes, we will do that. That patch is first step for reducing duplicate codes between IPv4 and IPv6.

Great. I believe it should be possible, in the end, to make the XFRM engine %100 address-family (v4, v6 etc.) and protocol (ah, esp) independant. If that goal is achieved, we may move generic parts from net/ipv4/xfrm_*.c to net/xfrm_*.c

Note that this coincides with the idea to eventually have an address-family independant flow cache.

Most of the address-family specific areas are:

1) DST lookup (xfrm_dst_lookup_t)

2) selector key comparisons and state lookup (xfrm$(AF)_selector_match, xfrm$(AF)_state_find)

3) receive processing (xfrm${AF}_rcv)

#1 is made for ipv6 by Miyazawa-san's patch. This could logically be extended to handle issues #2 and #3 above.

All protocol specific (ESP, AH) and address-family specific references should go away from places like include/net/xfrm.h

I think you understand all of this, and therefore I cannot wait for the next ipsec cleanup patch from you :)

Finally, note that eventually we will need some reference counting scheme for to allow xfrm address-family modules to be unloaded safely.

Currently, ipv4 cannot be a module and ipv6 as a module is not able to unload :-) So the module unload problem does not exist right at this moment. So ignore this issue for now.

#4 lore raw

Re: (usagi-core 12294) Re: [PATCH] IPv6 IPsec support

Quoted 2 lines · David S. Miller

Note that this coincides with the idea to eventually have an address-family independant flow cache.

Actually... at that point being able to monitor updates to the flow-cache would be useful for various statistical purposes and applications, especially if the flow cache was able to periodically export utilization counters...

--cw

#5 lore raw

Re: (usagi-core 12294) Re: [PATCH] IPv6 IPsec support

From: Chris Wedgwood <[email protected]>
Date: Thu, 6 Mar 2003 13:32:17 -0800

Actually... at that point being able to monitor updates to the flow-cache would be useful for various statistical purposes and applications, especially if the flow cache was able to periodically export utilization counters...

It will keep statistics, just like the route cache keeps them now.

#6 lore raw
In reply to Kazunori Miyazawa

From: Kazunori Miyazawa <[email protected]>
Date: Wed, 5 Mar 2003 23:30:25 +0900

Hello Miyazawa-san,

I submit the patch to let the kernel support ipv6 ipsec again. It is able to comple ipv6 as module.

As promised I applied the patch. I will push it to Linus later this evening, or tomorrow.

In this initial checkin I made only 2 minor fixes, they are attached below:

include/net/ip6_route.h renamed from include/net/ip6_route.h.~1~ +0 -1
@@ -38,7 +38,6 @@
 extern int			ipv6_route_ioctl(unsigned int cmd, void *arg);
 
 extern int			ip6_route_add(struct in6_rtmsg *rtmsg);
-extern int			ip6_route_del(struct in6_rtmsg *rtmsg);
 extern int			ip6_del_rt(struct rt6_info *);
 
 extern int			ip6_rt_addr_add(struct in6_addr *addr,
net/ipv6/Kconfig renamed from net/ipv6/Kconfig.~1~ +2 -0
@@ -19,6 +19,7 @@
 
 config INET6_AH
 	tristate "IPv6: AH transformation"
+	depends on IPV6
 	---help---
 	  Support for IPsec AH.
 
@@ -26,6 +27,7 @@
 
 config INET6_ESP
 	tristate "IPv6: ESP transformation"
+	depends on IPV6
 	---help---
 	  Support for IPsec ESP.
 
#7 lore raw

Hello David,

Quoted 5 lines · On Wed, 05 Mar 2003 15:25:30 -0800 (PST) "David S. Miller" <[email protected]>…

From: Kazunori Miyazawa <[email protected]>
Date: Wed, 5 Mar 2003 23:30:25 +0900

Hello Miyazawa-san,

Quoted 9 lines

I submit the patch to let the kernel support ipv6 ipsec again. It is able to comple ipv6 as module.

As promised I applied the patch. I will push it to Linus later this evening, or tomorrow.

In this initial checkin I made only 2 minor fixes, they are attached below:

Thank you very much.

My patch is the first step.
I think there are these TODOs around IPv6 IPsec as far as I remember.

- 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.

- Fragmentation support on outbound:
We should change ipv6_build_xmit like ip_append_data style to support fragmentation with IPsec.

- Removing duplicate codes, clean up and improveing performance.

- Considering relation of IPv6 IPsec and Mobile IPv6. This is future stuff.

Best regards,

--Kazunori Miyazawa (Yokogawa Electric Corporation)

#8 lore raw

From: Kazunori Miyazawa <[email protected]>
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.

- Fragmentation support on outbound:
We should change ipv6_build_xmit like ip_append_data style to support fragmentation with IPsec.

Please work together with Alexey on this. There are known major problems on ipv4 side, and it must be resolved before ipv6 side may be done.

For example, right now a non-TCP packet can do the following. If it is just slightly smaller than MTU, and when encapsulated in ESP/AH it becomes larger than MTU, we will not fragment it and too-large frame will be sent to device.

In my last round of talks with Alexey I believe we were very close to a possible solution to this problem. The idea was to have a "local dont-fragment" flag, and at the very last stage of IP output we check this and either 1) clear DF and fragment or 2) drop packet and send ICMP message back.

Alexey, what is the current state?

- Removing duplicate codes, clean up and improveing performance.

- Considering relation of IPv6 IPsec and Mobile IPv6. This is future stuff.

Ok.

#9 lore raw

PATCH 1/1 IPv6 Extension headers (Re: [PATCH] IPv6 IPsec support)

Hello,

At Wed, 05 Mar 2003 20:43:48 -0800 (PST),

Quoted 10 lines · David S. Miller

From: Kazunori Miyazawa <[email protected]>
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

net/ipv6.h +0 -4
diff -u -r1.1.1.4 ipv6.h
@@ -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

net/protocol.h +1 -1
diff -u -r1.1.1.3 protocol.h
@@ -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

net/transp_v6.h +8 -0
diff -u -r1.1.1.1 transp_v6.h
@@ -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

net/xfrm.h +1 -1
diff -u -r1.1.1.8 xfrm.h
@@ -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

ipv4/xfrm_input.c +4 -19
diff -u -r1.1.1.4 xfrm_input.c
@@ -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

ipv6/af_inet6.c +7 -0
diff -u -r1.1.1.7 af_inet6.c
@@ -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

ipv6/exthdrs.c +93 -127

348 lines not on this page · raw message

Index: net/ipv6/icmp.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/icmp.c,v retrieving revision 1.1.1.7

ipv6/icmp.c +3 -2
diff -u -r1.1.1.7 icmp.c
@@ -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

ipv6/ip6_input.c +7 -29
diff -u -r1.1.1.6 ip6_input.c
@@ -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

ipv6/reassembly.c +30 -7
diff -u -r1.1.1.4 reassembly.c
@@ -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

ipv6/tcp_ipv6.c +2 -1
diff -u -r1.1.1.8 tcp_ipv6.c
@@ -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

ipv6/udp.c +2 -1
diff -u -r1.1.1.7 udp.c
@@ -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;
#10 lore raw

Re: [PATCH] IPv6 Extension headers

From: Mitsuru KANDA / 神田 充 <[email protected]>
Date: Tue, 18 Mar 2003 10:32:27 -0800

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

I applied this patch with some minor changes.

First, many functions in net/ipv6/exthdrs.c and net/ipv6/reassembly.c can be marked static now.

Second, some local variables (for example, "nhoff" in ip6_input()) can be eliminated entirely because they compute a value in one place and use it in the very next line and nowhere else is it referenced.

Thank you.