From: "Mitsuru KANDA / 神田 充" <mk@linux-ipv6.org>
To: "David S. Miller" <davem@redhat.com>
Cc: jmorris@intercode.com.au, kuznet@ms2.inr.ac.ru,
netdev@oss.sgi.com, usagi@linux-ipv6.org
Subject: [PATCH] xfrm ip6ip6 (revised)
Date: Sat, 14 Jun 2003 01:03:50 +0900 [thread overview]
Message-ID: <87smqerml5.wl@karaba.org> (raw)
In-Reply-To: <20030601.013040.116362760.davem@redhat.com>
Hello,
I recreated a xfrm ip6ip6 patch.
The changes to the previous patch are:
- to allocate unique spi values in xfrm6_tunnel.c
by using just simple open addressing hash,
- to introduce device-like ip6ip6 handling, and
- to fix some bugs.
This patch is against CS1.1304.
Chould you check this?
Regards,
-mk
At Sun, 01 Jun 2003 01:30:40 -0700 (PDT),
"David S. Miller" <davem@redhat.com> wrote:
(snipped)
> I would suggest following implementation:
>
> 1) Implement something similar to xfrm_alloc_spi(t, 1, ~(u32)0)
>
> It just needs to allocate unique SPI numbers local to
> xfrm6_tunnel.c We mark "SPI" value zero as reserved and
> to indicate failed lookup.
>
> 2) Create hash table, it is keyed by ipv6 address and hash table
> entries give SPI values.
>
> So on input you would say something like:
>
> u32 spi;
>
> spi = spihash_lookup(&iph->saddr);
> if (!spi)
> goto drop;
> x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
> IPPROTO_IPV6, AF_INET6);
(snipped)
Index: linux25-XFRM6_TUNNEL-20030612/include/net/xfrm.h
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/include/net/xfrm.h,v
retrieving revision 1.1.1.25
retrieving revision 1.1.1.25.2.1
diff -u -r1.1.1.25 -r1.1.1.25.2.1
--- linux25-XFRM6_TUNNEL-20030612/include/net/xfrm.h 10 Jun 2003 13:21:39 -0000 1.1.1.25
+++ linux25-XFRM6_TUNNEL-20030612/include/net/xfrm.h 12 Jun 2003 15:30:16 -0000 1.1.1.25.2.1
@@ -494,10 +494,6 @@
return 0;
}
-/* placeholder until xfrm6_tunnel.c is written */
-static inline int xfrm6_tunnel_check_size(struct sk_buff *skb)
-{ return 0; }
-
/* A struct encoding bundle of transformations to apply to some set of flow.
*
* dst->child points to the next element of bundle.
@@ -748,6 +744,12 @@
void (*err_handler)(struct sk_buff *skb, void *info);
};
+struct xfrm6_tunnel {
+ int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp);
+ void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info);
+};
+
extern void xfrm_init(void);
extern void xfrm4_init(void);
extern void xfrm4_fini(void);
@@ -781,6 +783,11 @@
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_check_size(struct sk_buff *skb);
+extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
+extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
+extern int xfrm6_tunnel_check_size(struct sk_buff *skb);
+extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
+extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
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: linux25-XFRM6_TUNNEL-20030612/net/ipv6/Makefile
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/Makefile,v
retrieving revision 1.1.1.13
retrieving revision 1.1.1.13.2.1
diff -u -r1.1.1.13 -r1.1.1.13.2.1
--- linux25-XFRM6_TUNNEL-20030612/net/ipv6/Makefile 10 Jun 2003 13:21:55 -0000 1.1.1.13
+++ linux25-XFRM6_TUNNEL-20030612/net/ipv6/Makefile 12 Jun 2003 15:29:53 -0000 1.1.1.13.2.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-XFRM6_TUNNEL-20030612/net/ipv6/ip6_tunnel.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ip6_tunnel.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- linux25-XFRM6_TUNNEL-20030612/net/ipv6/ip6_tunnel.c 10 Jun 2003 13:21:55 -0000 1.1.1.1
+++ linux25-XFRM6_TUNNEL-20030612/net/ipv6/ip6_tunnel.c 12 Jun 2003 15:29:53 -0000 1.1.1.1.2.1
@@ -48,6 +48,7 @@
#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/ip6_tunnel.h>
+#include <net/xfrm.h>
MODULE_AUTHOR("Ville Nuorvala");
MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
@@ -1174,10 +1175,9 @@
return 0;
}
-static struct inet6_protocol ip6ip6_protocol = {
+static struct xfrm_tunnel ip6ip6_handler = {
.handler = ip6ip6_rcv,
.err_handler = ip6ip6_err,
- .flags = INET6_PROTO_FINAL
};
/**
@@ -1192,6 +1192,11 @@
struct sock *sk;
struct ipv6_pinfo *np;
+ if (xfrm6_tunnel_register(&ip6ip6_handler) < 0) {
+ printk(KERN_INFO "ip6ip6 init: can't register tunnel\n");
+ return -EAGAIN;
+ }
+
ip6ip6_fb_tnl_dev.priv = (void *) &ip6ip6_fb_tnl;
for (i = 0; i < NR_CPUS; i++) {
@@ -1216,10 +1221,6 @@
sk->sk_prot->unhash(sk);
}
- if ((err = inet6_add_protocol(&ip6ip6_protocol, IPPROTO_IPV6)) < 0) {
- printk(KERN_ERR "Failed to register IPv6 protocol\n");
- goto fail;
- }
SET_MODULE_OWNER(&ip6ip6_fb_tnl_dev);
register_netdev(&ip6ip6_fb_tnl_dev);
@@ -1243,9 +1244,10 @@
{
int i;
- unregister_netdev(&ip6ip6_fb_tnl_dev);
+ if (xfrm6_tunnel_deregister(&ip6ip6_handler) < 0)
+ printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
- inet6_del_protocol(&ip6ip6_protocol, IPPROTO_IPV6);
+ unregister_netdev(&ip6ip6_fb_tnl_dev);
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_possible(i))
Index: linux25-XFRM6_TUNNEL-20030612/net/ipv6/ipcomp6.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ipcomp6.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 ipcomp6.c
--- linux25-XFRM6_TUNNEL-20030612/net/ipv6/ipcomp6.c 10 Jun 2003 13:21:54 -0000 1.1.1.3
+++ linux25-XFRM6_TUNNEL-20030612/net/ipv6/ipcomp6.c 13 Jun 2003 09:44:59 -0000
@@ -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_alloc_spi((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 = NULL;
+ u32 spi;
+
+ spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr);
+ if (spi)
+ 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-XFRM6_TUNNEL-20030612/net/ipv6/ipv6_syms.c
===================================================================
RCS file: /cvsroot/usagi/usagi-backport/linux25/net/ipv6/ipv6_syms.c,v
retrieving revision 1.1.1.13
retrieving revision 1.1.1.13.2.1
diff -u -r1.1.1.13 -r1.1.1.13.2.1
--- linux25-XFRM6_TUNNEL-20030612/net/ipv6/ipv6_syms.c 10 Jun 2003 13:21:55 -0000 1.1.1.13
+++ linux25-XFRM6_TUNNEL-20030612/net/ipv6/ipv6_syms.c 12 Jun 2003 15:29:53 -0000 1.1.1.13.2.1
@@ -38,6 +38,11 @@
EXPORT_SYMBOL(ip6_find_1stfragopt);
EXPORT_SYMBOL(xfrm6_rcv);
EXPORT_SYMBOL(xfrm6_clear_mutable_options);
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+EXPORT_SYMBOL(xfrm6_tunnel_check_size);
+EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);
+EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
EXPORT_SYMBOL(rt6_lookup);
EXPORT_SYMBOL(fl6_sock_lookup);
EXPORT_SYMBOL(ipv6_ext_hdr);
Index: linux25-XFRM6_TUNNEL-20030612/net/ipv6/xfrm6_tunnel.c
===================================================================
RCS file: linux25-XFRM6_TUNNEL-20030612/net/ipv6/xfrm6_tunnel.c
diff -N linux25-XFRM6_TUNNEL-20030612/net/ipv6/xfrm6_tunnel.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ linux25-XFRM6_TUNNEL-20030612/net/ipv6/xfrm6_tunnel.c 13 Jun 2003 09:44:59 -0000
@@ -0,0 +1,380 @@
+/*
+ * 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 <linux/xfrm.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>
+
+#define XFRM6_TUNNEL_HSIZE 1024
+/* note: we assume index of xfrm_tunnel_table[] == spi */
+static xfrm_address_t *xfrm6_tunnel_table[XFRM6_TUNNEL_HSIZE];
+
+static spinlock_t xfrm6_tunnel_lock = SPIN_LOCK_UNLOCKED;
+
+static unsigned xfrm6_addr_hash(xfrm_address_t *addr)
+{
+ unsigned h;
+ h = ntohl(addr->a6[0]^addr->a6[1]^addr->a6[2]^addr->a6[3]);
+ h = (h ^ (h>>16)) % XFRM6_TUNNEL_HSIZE;
+ return h;
+}
+
+static void xfrm6_tunnel_htable_init(void)
+{
+ int i;
+ for (i=0; i<XFRM6_TUNNEL_HSIZE; i++)
+ xfrm6_tunnel_table[i] = NULL;
+}
+
+u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+{
+ u32 spi = 0;
+ u32 index = xfrm6_addr_hash(saddr);
+ xfrm_address_t *index_addr;
+ int i;
+
+ spin_lock(&xfrm6_tunnel_lock);
+ for (i = index; i < XFRM6_TUNNEL_HSIZE; i++) {
+ index_addr = xfrm6_tunnel_table[i];
+ if (index_addr == NULL)
+ continue;
+ if (!memcmp(index_addr, saddr, sizeof(xfrm_address_t))) {
+ spi = htonl(i);
+ goto out;
+ }
+ }
+out:
+ spin_unlock(&xfrm6_tunnel_lock);
+ return spi;
+}
+
+u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+{
+ u32 spi = 0;
+ u32 index = xfrm6_addr_hash(saddr);
+ xfrm_address_t *index_addr;
+ int i;
+
+ spin_lock(&xfrm6_tunnel_lock);
+ for (i = index; i < XFRM6_TUNNEL_HSIZE; i++) {
+ if (xfrm6_tunnel_table[i] == NULL) {
+ index_addr = kmalloc(sizeof(xfrm_address_t), GFP_ATOMIC);
+ memcpy(index_addr, saddr, sizeof(xfrm_address_t));
+ xfrm6_tunnel_table[i] = index_addr;
+ spi = htonl(i);
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock(&xfrm6_tunnel_lock);
+ return spi;
+}
+
+static void xfrm6_tunnel_free_spi(xfrm_address_t *saddr){
+ u32 index = ntohl(xfrm6_tunnel_spi_lookup(saddr));
+
+ if (index) {
+ spin_lock(&xfrm6_tunnel_lock);
+ kfree(xfrm6_tunnel_table[index]);
+ xfrm6_tunnel_table[index] = NULL;
+ spin_unlock(&xfrm6_tunnel_lock);
+ }
+}
+
+
+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;
+ ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+ ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+ 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 struct xfrm6_tunnel *ip6ip6_handler;
+static DECLARE_MUTEX(xfrm6_tunnel_sem);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+ int ret;
+
+ down(&xfrm6_tunnel_sem);
+ ret = 0;
+ if (ip6ip6_handler != NULL)
+ ret = -EINVAL;
+ if (!ret)
+ ip6ip6_handler = handler;
+ up(&xfrm6_tunnel_sem);
+
+ return ret;
+}
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+ int ret;
+
+ down(&xfrm6_tunnel_sem);
+ ret = 0;
+ if (ip6ip6_handler != handler)
+ ret = -EINVAL;
+ if (!ret)
+ ip6ip6_handler = NULL;
+ up(&xfrm6_tunnel_sem);
+
+ synchronize_net();
+
+ return ret;
+}
+
+static int ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+ struct sk_buff *skb = *pskb;
+ struct xfrm6_tunnel *handler = ip6ip6_handler;
+ struct xfrm_state *x = NULL;
+ struct ipv6hdr *iph = skb->nh.ipv6h;
+ int err = 0;
+ u32 spi;
+
+ /* device-like_ip6ip6_handler() */
+ if (handler) {
+ err = handler->handler(pskb, nhoffp);
+ if (!err)
+ goto out;
+ }
+
+ spi = xfrm6_tunnel_spi_lookup((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);
+
+out:
+ return 0;
+
+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)
+{
+ struct xfrm6_tunnel *handler = ip6ip6_handler;
+
+ /* call here first for device-like ip6ip6 err handling */
+ if (handler) {
+ handler->err_handler(skb, opt, type, code, offset, info);
+ return;
+ }
+
+ /* 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)
+{
+ xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
+}
+
+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|INET6_PROTO_FINAL,
+};
+
+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;
+ }
+ xfrm6_tunnel_htable_init();
+ 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-XFRM6_TUNNEL-20030612/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.24.1
diff -u -r1.1.1.1 -r1.1.1.1.24.1
--- linux25-XFRM6_TUNNEL-20030612/net/xfrm/xfrm_output.c 6 May 2003 12:43:55 -0000 1.1.1.1
+++ linux25-XFRM6_TUNNEL-20030612/net/xfrm/xfrm_output.c 12 Jun 2003 15:29:06 -0000 1.1.1.1.24.1
@@ -27,11 +27,11 @@
case AF_INET:
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 prev parent reply other threads:[~2003-06-13 16:03 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-31 15:20 [PATCH] xfrm ip6ip6 Mitsuru KANDA / 神田 充
2003-05-31 16:01 ` 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 ` Mitsuru KANDA / 神田 充 [this message]
2003-06-13 16:11 ` [PATCH] xfrm ip6ip6 (revised) 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=87smqerml5.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.