2003-03-05 23:33:40

by David Miller

[permalink] [raw]
Subject: Re: [PATH] IPv6 IPsec support

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.~1~ Wed Mar 5 15:32:41 2003
+++ ./include/net/ip6_route.h Wed Mar 5 15:40:42 2003
@@ -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.~1~ Wed Mar 5 15:32:41 2003
+++ ./net/ipv6/Kconfig Wed Mar 5 15:35:27 2003
@@ -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.


2003-03-06 00:21:38

by Kazunori Miyazawa

[permalink] [raw]
Subject: Re: [PATH] IPv6 IPsec support

Hello David,

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

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

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)

2003-03-06 04:52:15

by David Miller

[permalink] [raw]
Subject: Re: [PATH] IPv6 IPsec support

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.

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


Hello,

At Wed, 05 Mar 2003 20:43:48 -0800 (PST),
"David S. Miller" <[email protected]> wrote:
>
> 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
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;

2003-03-24 05:21:32

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] IPv6 Extension headers

From: Mitsuru KANDA / $B?@ED(B $B=<(B <[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.