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