# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef
#endif
-static rwlock_t xfrm6_tunnel_spi_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(xfrm6_tunnel_spi_lock);
static u32 xfrm6_tunnel_spi;
#define XFRM6_TUNNEL_SPI_MIN 1
#define XFRM6_TUNNEL_SPI_MAX 0xffffffff
-static kmem_cache_t *xfrm6_tunnel_spi_kmem;
+static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly;
#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256
#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256
spi = 0;
goto out;
alloc_spi:
- X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n",
__FUNCTION__,
NIP6(*(struct in6_addr *)saddr));
x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
list_byaddr)
{
if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
- X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
- "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
- "found at %p\n",
+ X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT
+ " found at %p\n",
__FUNCTION__,
NIP6(*(struct in6_addr *)saddr),
x6spi);
EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
-static int xfrm6_tunnel_output(struct sk_buff **pskb)
+static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct ipv6hdr *top_iph;
top_iph = (struct ipv6hdr *)skb->data;
static int xfrm6_tunnel_input(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;
}
EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler = xfrm6_tunnel_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;
- }
+ if (handler && handler->handler(pskb) == 0)
+ return 0;
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 = xfrm6_tunnel_input(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;
+ return xfrm6_rcv_spi(pskb, spi);
}
static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return;
}
-static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+static int xfrm6_tunnel_init_state(struct xfrm_state *x)
{
if (!x->props.mode)
return -EINVAL;
+ if (x->encap)
+ return -EINVAL;
+
x->props.header_len = sizeof(struct ipv6hdr);
return 0;
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
-void __init xfrm6_tunnel_init(void)
+static int __init xfrm6_tunnel_init(void)
{
X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel init: can't add xfrm type\n");
- return;
+ return -EAGAIN;
}
if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel init(): can't add protocol\n");
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
- return;
+ return -EAGAIN;
}
if (xfrm6_tunnel_spi_init() < 0) {
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel init: failed to initialize spi\n");
inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
- return;
+ return -EAGAIN;
}
+ return 0;
}
-void __exit xfrm6_tunnel_fini(void)
+static void __exit xfrm6_tunnel_fini(void)
{
X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
X6TPRINTK1(KERN_ERR
"xfrm6_tunnel close: can't remove xfrm type\n");
}
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_fini);
+MODULE_LICENSE("GPL");