From: "Mitsuru KANDA / 神田 充" <mk@linux-ipv6.org>
To: davem@redhat.com, jmorris@intercode.com.au, kuznet@ms2.inr.ac.ru
Cc: netdev@oss.sgi.com, usagi@linux-ipv6.org
Subject: [PATCH] xfrm ip6ip6
Date: Sun, 01 Jun 2003 00:20:07 +0900 [thread overview]
Message-ID: <87fzmv5ejc.wl@karaba.org> (raw)
Hello,
Here is the xfrm style ip6ip6 patch,
which is against linux-2.5.70+CS1.1254.2.15.
I honestly have to say it is not tested well.
But I promise I'll test/fix after xfrm tunnel tool will be visible :-)
(Does anyone work on this?)
Anyway, I have one discussion point.
When we use 'setkey -D', xfrm ipip tunnels are displayed as unspec SAs.
Do we need to filter out these xfrm_states other than AH/ESP/IPcomp
in case of PF_KEY based queries?
Regards,
-mk
Index: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/include/net/xfrm.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/xfrm.h,v
retrieving revision 1.1.1.23
retrieving revision 1.1.1.23.10.1
diff -u -r1.1.1.23 -r1.1.1.23.10.1
--- linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/include/net/xfrm.h 26 May 2003 08:04:25 -0000 1.1.1.23
+++ linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/include/net/xfrm.h 31 May 2003 08:52:20 -0000 1.1.1.23.10.1
@@ -493,8 +493,16 @@
}
/* placeholder until xfrm6_tunnel.c is written */
-static inline int xfrm6_tunnel_check_size(struct sk_buff *skb)
-{ return 0; }
+extern int xfrm6_tunnel_check_size(struct sk_buff *skb);
+#define XFRM_ADDR_HSIZE 1024
+static __inline__ /* same as __xfrm6_dst_hash */
+unsigned xfrm6_tunnel_addr_hash(xfrm_address_t *addr)
+{
+ unsigned h;
+ h = ntohl(addr->a6[2]^addr->a6[3]);
+ h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
+ return h;
+}
/* A struct encoding bundle of transformations to apply to some set of flow.
*
Index: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/Makefile
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/Makefile,v
retrieving revision 1.1.1.12
retrieving revision 1.1.1.12.10.1
diff -u -r1.1.1.12 -r1.1.1.12.10.1
--- linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/Makefile 26 May 2003 08:04:11 -0000 1.1.1.12
+++ linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/Makefile 31 May 2003 08:56:24 -0000 1.1.1.12.10.1
@@ -9,7 +9,7 @@
protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
ip6_flowlabel.o ipv6_syms.o \
- xfrm6_policy.o xfrm6_state.o xfrm6_input.o
+ xfrm6_policy.o xfrm6_state.o xfrm6_input.o xfrm6_tunnel.o
obj-$(CONFIG_INET6_AH) += ah6.o
obj-$(CONFIG_INET6_ESP) += esp6.o
Index: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/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.8.2
diff -u -r1.1.1.2 -r1.1.1.2.8.2
--- linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/ipcomp6.c 21 May 2003 13:15:20 -0000 1.1.1.2
+++ linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/ipcomp6.c 31 May 2003 14:19:54 -0000 1.1.1.2.8.2
@@ -254,6 +254,66 @@
xfrm_state_put(x);
}
+static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
+{
+ struct xfrm_state *t = NULL;
+
+ t = xfrm_state_alloc();
+ if (!t)
+ goto out;
+
+ t->id.proto = IPPROTO_IPV6;
+ t->id.spi = xfrm6_tunnel_addr_hash((xfrm_address_t *)&x->props.saddr);
+ memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr));
+ memcpy(&t->sel, &x->sel, sizeof(t->sel));
+ t->props.family = AF_INET6;
+ t->props.mode = 1;
+ memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
+
+ t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
+ if (t->type == NULL)
+ goto error;
+
+ if (t->type->init_state(t, NULL))
+ goto error;
+
+ t->km.state = XFRM_STATE_VALID;
+ atomic_set(&t->tunnel_users, 1);
+
+out:
+ return t;
+
+error:
+ xfrm_state_put(t);
+ goto out;
+}
+
+static int ipcomp6_tunnel_attach(struct xfrm_state *x)
+{
+ int err = 0;
+ struct xfrm_state *t;
+ u32 spi;
+
+ spi = xfrm6_tunnel_addr_hash((xfrm_address_t *)&x->props.saddr);
+
+ t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr,
+ spi, IPPROTO_IPV6, AF_INET6);
+ if (!t) {
+ t = ipcomp6_tunnel_create(x);
+ if (!t) {
+ err = -EINVAL;
+ goto out;
+ }
+ xfrm_state_insert(t);
+ xfrm_state_hold(t);
+ }
+ x->tunnel = t;
+ atomic_inc(&t->tunnel_users);
+
+out:
+ return err;
+}
+
static void ipcomp6_free_data(struct ipcomp_data *ipcd)
{
if (ipcd->tfm)
@@ -292,6 +352,12 @@
ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
if (!ipcd->tfm)
goto error;
+
+ if (x->props.mode) {
+ err = ipcomp6_tunnel_attach(x);
+ if (err)
+ goto error;
+ }
calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
BUG_ON(!calg_desc);
Index: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/xfrm6_tunnel.c
===================================================================
RCS file: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/xfrm6_tunnel.c
diff -N linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/xfrm6_tunnel.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/ipv6/xfrm6_tunnel.c 31 May 2003 14:03:12 -0000 1.1.4.2
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C)2003 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author Mitsuru KANDA <mk@linux-ipv6.org>
+ *
+ * Based on xfrm4_tunnel
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+
+int xfrm6_tunnel_check_size(struct sk_buff *skb)
+{
+ int mtu, ret = 0;
+ struct dst_entry *dst = skb->dst;
+
+ mtu = dst_pmtu(dst) - sizeof(struct ipv6hdr);
+ if (mtu < IPV6_MIN_MTU)
+ mtu = IPV6_MIN_MTU;
+
+ if (skb->len > mtu) {
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
+ ret = -EMSGSIZE;
+ }
+
+ return ret;
+}
+
+static int ip6ip6_output(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct xfrm_state *x = dst->xfrm;
+ struct ipv6hdr *iph, *top_iph;
+ int err;
+
+ if ((err = xfrm6_tunnel_check_size(skb)) != 0)
+ goto error_nolock;
+
+ iph = skb->nh.ipv6h;
+
+ top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len);
+ top_iph->version = 6;
+ top_iph->priority = iph->priority;
+ top_iph->flow_lbl[0] = iph->flow_lbl[0];
+ top_iph->flow_lbl[1] = iph->flow_lbl[1];
+ top_iph->flow_lbl[2] = iph->flow_lbl[2];
+ top_iph->nexthdr = IPPROTO_IPV6;
+ top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+ top_iph->hop_limit = iph->hop_limit;
+ memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
+ memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
+ skb->nh.raw = skb->data;
+ skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
+
+ x->curlft.bytes += skb->len;
+ x->curlft.packets++;
+
+ spin_unlock_bh(&x->lock);
+
+ if ((skb->dst = dst_pop(dst)) == NULL) {
+ kfree_skb(skb);
+ err = -EHOSTUNREACH;
+ goto error_nolock;
+ }
+
+ return NET_XMIT_BYPASS;
+
+error_nolock:
+ kfree_skb(skb);
+ return err;
+}
+
+static int ip6ip6_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+{
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ return -EINVAL;
+
+ skb->mac.raw = skb->nh.raw;
+ skb->nh.raw = skb->data;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ skb->protocol = htons(ETH_P_IPV6);
+ skb->pkt_type = PACKET_HOST;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+ struct sk_buff *skb = *pskb;
+ struct xfrm_state *x = NULL;
+ struct ipv6hdr *iph = skb->nh.ipv6h;
+ int err = 0;
+ u32 spi;
+
+ /* After device-like ip6ip6 tunnel will be implemented,
+ * we do take precedence here.
+ * (currently not yet exist in kernel source tree.)
+ * For more information, see xfrm4_tunnel.c
+ */
+ /* device-like_ip6ip6_handler() */
+
+ spi = xfrm6_tunnel_addr_hash((xfrm_address_t *)&iph->saddr);
+ x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr,
+ spi,
+ IPPROTO_IPV6, AF_INET6);
+
+ if (!x)
+ goto drop;
+
+ spin_lock(&x->lock);
+
+ if (unlikely(x->km.state != XFRM_STATE_VALID))
+ goto drop_unlock;
+
+ err = ip6ip6_xfrm_rcv(x, NULL, skb);
+ if (err)
+ goto drop_unlock;
+
+ x->curlft.bytes += skb->len;
+ x->curlft.packets++;
+ spin_unlock(&x->lock);
+ xfrm_state_put(x);
+
+ *nhoffp = sizeof(struct ipv6hdr);
+
+ return 1;
+
+drop_unlock:
+ spin_unlock(&x->lock);
+ xfrm_state_put(x);
+drop:
+ kfree_skb(skb);
+
+ return -1;
+}
+
+static void ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
+{
+ /* call here first for device-like ip6ip6 err handling */
+ /* foo->err_handler(), see xfrm4_tunnel.c */
+
+ /* xfrm ip6ip6 native err handling */
+ switch (type) {
+ case ICMPV6_DEST_UNREACH:
+ switch (code) {
+ case ICMPV6_NOROUTE:
+ case ICMPV6_ADM_PROHIBITED:
+ case ICMPV6_NOT_NEIGHBOUR:
+ case ICMPV6_ADDR_UNREACH:
+ case ICMPV6_PORT_UNREACH:
+ default:
+ printk(KERN_ERR "xfrm ip6ip6: Destination Unreach.\n");
+ break;
+ }
+ break;
+ case ICMPV6_PKT_TOOBIG:
+ printk(KERN_ERR "xfrm ip6ip6: Packet Too Big.\n");
+ break;
+ case ICMPV6_TIME_EXCEED:
+ switch (code) {
+ case ICMPV6_EXC_HOPLIMIT:
+ printk(KERN_ERR "xfrm ip6ip6: Too small Hoplimit.\n");
+ break;
+ case ICMPV6_EXC_FRAGTIME:
+ default:
+ break;
+ }
+ break;
+ case ICMPV6_PARAMPROB:
+ switch (code) {
+ case ICMPV6_HDR_FIELD: break;
+ case ICMPV6_UNK_NEXTHDR: break;
+ case ICMPV6_UNK_OPTION: break;
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+static int ip6ip6_init_state(struct xfrm_state *x, void *args)
+{
+ if (!x->props.mode)
+ return -EINVAL;
+
+ x->props.header_len = sizeof(struct ipv6hdr);
+
+ return 0;
+}
+
+static void ip6ip6_destroy(struct xfrm_state *x)
+{
+}
+
+static struct xfrm_type ip6ip6_type = {
+ .description = "IP6IP6",
+ .owner = THIS_MODULE,
+ .proto = IPPROTO_IPV6,
+ .init_state = ip6ip6_init_state,
+ .destructor = ip6ip6_destroy,
+ .input = ip6ip6_xfrm_rcv,
+ .output = ip6ip6_output,
+};
+
+static struct inet6_protocol ip6ip6_protocol = {
+ .handler = ip6ip6_rcv,
+ .err_handler = ip6ip6_err,
+ .flags = INET6_PROTO_NOPOLICY,
+};
+
+static int __init ip6ip6_init(void)
+{
+ if (xfrm_register_type(&ip6ip6_type, AF_INET6) < 0) {
+ printk(KERN_INFO "ip6ip6 init: can't add xfrm type\n");
+ return -EAGAIN;
+ }
+ if (inet6_add_protocol(&ip6ip6_protocol, IPPROTO_IPV6) < 0) {
+ printk(KERN_INFO "ip6ip6 init: can't add protocol\n");
+ xfrm_unregister_type(&ip6ip6_type, AF_INET6);
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static void __exit ip6ip6_fini(void)
+{
+ if (inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6) < 0)
+ printk(KERN_INFO "ip6ip6 close: can't remove protocol\n");
+ if (xfrm_unregister_type(&ip6ip6_type, AF_INET6) < 0)
+ printk(KERN_INFO "ip6ip6 close: can't remove xfrm type\n");
+}
+
+module_init(ip6ip6_init);
+module_exit(ip6ip6_fini);
+MODULE_LICENSE("GPL");
Index: linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/xfrm/xfrm_output.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/xfrm/xfrm_output.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.16.1
diff -u -r1.1.1.1 -r1.1.1.1.16.1
--- linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/xfrm/xfrm_output.c 6 May 2003 12:43:55 -0000 1.1.1.1
+++ linux25-b2_5_70+CS1_1254_2_15_XFRM6_TUNNEL_20030531/net/xfrm/xfrm_output.c 31 May 2003 08:54:21 -0000 1.1.1.1.16.1
@@ -28,9 +28,11 @@
err = xfrm4_tunnel_check_size(skb);
break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
err = xfrm6_tunnel_check_size(skb);
break;
+#endif
default:
err = -EINVAL;
next reply other threads:[~2003-05-31 15:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-31 15:20 Mitsuru KANDA / 神田 充 [this message]
2003-05-31 16:01 ` [PATCH] xfrm ip6ip6 James Morris
2003-06-01 8:34 ` David S. Miller
2003-05-31 16:06 ` James Morris
2003-06-01 8:30 ` David S. Miller
2003-06-13 16:03 ` [PATCH] xfrm ip6ip6 (revised) Mitsuru KANDA / 神田 充
2003-06-13 16:11 ` YOSHIFUJI Hideaki / 吉藤英明
2003-06-13 16:13 ` YOSHIFUJI Hideaki / 吉藤英明
2003-06-13 18:08 ` Ville Nuorvala
2003-06-13 19:07 ` David S. Miller
2003-06-13 19:19 ` 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=87fzmv5ejc.wl@karaba.org \
--to=mk@linux-ipv6.org \
--cc=davem@redhat.com \
--cc=jmorris@intercode.com.au \
--cc=kuznet@ms2.inr.ac.ru \
--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 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).