X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fxfrm6_tunnel.c;h=12e426b9aacd19d2b03e3d35bfc230dcd3c42897;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=8cfc58b96fc2553cbb946765a70c8c6932ba0cff;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 8cfc58b96..12e426b9a 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -21,37 +21,15 @@ * Based on net/ipv4/xfrm4_tunnel.c * */ -#include #include #include #include #include #include #include -#include #include #include - -#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG -# define X6TDEBUG 3 -#else -# define X6TDEBUG 1 -#endif - -#define X6TPRINTK(fmt, args...) printk(fmt, ## args) -#define X6TNOPRINTK(fmt, args...) do { ; } while(0) - -#if X6TDEBUG >= 1 -# define X6TPRINTK1 X6TPRINTK -#else -# define X6TPRINTK1 X6TNOPRINTK -#endif - -#if X6TDEBUG >= 3 -# define X6TPRINTK3 X6TPRINTK -#else -# define X6TPRINTK3 X6TNOPRINTK -#endif +#include /* * xfrm_tunnel_spi things are for allocating unique id ("spi") @@ -63,15 +41,8 @@ struct xfrm6_tunnel_spi { xfrm_address_t addr; u32 spi; atomic_t refcnt; -#ifdef XFRM6_TUNNEL_SPI_MAGIC - u32 magic; -#endif }; -#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG -# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef -#endif - static DEFINE_RWLOCK(xfrm6_tunnel_spi_lock); static u32 xfrm6_tunnel_spi; @@ -79,7 +50,7 @@ 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 __read_mostly; +static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; #define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 #define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 @@ -87,43 +58,15 @@ static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly; static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; -#ifdef XFRM6_TUNNEL_SPI_MAGIC -static int x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi, - const char *name) -{ - if (unlikely(x6spi->magic != XFRM6_TUNNEL_SPI_MAGIC)) { - X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " - "at %p has corrupted magic %08x " - "(should be %08x)\n", - name, x6spi, x6spi->magic, XFRM6_TUNNEL_SPI_MAGIC); - return -1; - } - return 0; -} -#else -static int inline x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi, - const char *name) -{ - return 0; -} -#endif - -#define X6SPI_CHECK_MAGIC(x6spi) x6spi_check_magic((x6spi), __FUNCTION__) - - static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) { unsigned h; - X6TPRINTK3(KERN_DEBUG "%s(addr=%p)\n", __FUNCTION__, addr); - - h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]; + h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]); h ^= h >> 16; h ^= h >> 8; h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1; - X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, h); - return h; } @@ -137,19 +80,13 @@ static int xfrm6_tunnel_spi_init(void) { int i; - X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); - xfrm6_tunnel_spi = 0; xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", sizeof(struct xfrm6_tunnel_spi), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!xfrm6_tunnel_spi_kmem) { - X6TPRINTK1(KERN_ERR - "%s(): failed to allocate xfrm6_tunnel_spi_kmem\n", - __FUNCTION__); + if (!xfrm6_tunnel_spi_kmem) return -ENOMEM; - } for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]); @@ -162,22 +99,16 @@ static void xfrm6_tunnel_spi_fini(void) { int i; - X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) { if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i])) - goto err; + return; } for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) { if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i])) - goto err; + return; } kmem_cache_destroy(xfrm6_tunnel_spi_kmem); xfrm6_tunnel_spi_kmem = NULL; - return; -err: - X6TPRINTK1(KERN_ERR "%s(): table is not empty\n", __FUNCTION__); - return; } static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) @@ -185,34 +116,26 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos; - X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); - hlist_for_each_entry(x6spi, pos, &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], list_byaddr) { - if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { - X6SPI_CHECK_MAGIC(x6spi); - X6TPRINTK3(KERN_DEBUG "%s() = %p(%u)\n", __FUNCTION__, x6spi, x6spi->spi); + if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) return x6spi; - } } - X6TPRINTK3(KERN_DEBUG "%s() = NULL(0)\n", __FUNCTION__); return NULL; } -u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; - X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); - read_lock_bh(&xfrm6_tunnel_spi_lock); x6spi = __xfrm6_tunnel_spi_lookup(saddr); spi = x6spi ? x6spi->spi : 0; read_unlock_bh(&xfrm6_tunnel_spi_lock); - return spi; + return htonl(spi); } EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); @@ -224,8 +147,6 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) struct hlist_node *pos; unsigned index; - X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); - if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN; @@ -259,18 +180,10 @@ try_next_2:; spi = 0; goto out; alloc_spi: - 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); - if (!x6spi) { - X6TPRINTK1(KERN_ERR "%s(): kmem_cache_alloc() failed\n", - __FUNCTION__); + x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); + if (!x6spi) goto out; - } -#ifdef XFRM6_TUNNEL_SPI_MAGIC - x6spi->magic = XFRM6_TUNNEL_SPI_MAGIC; -#endif + memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr)); x6spi->spi = spi; atomic_set(&x6spi->refcnt, 1); @@ -279,19 +192,15 @@ alloc_spi: index = xfrm6_tunnel_spi_hash_byaddr(saddr); hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]); - X6SPI_CHECK_MAGIC(x6spi); out: - X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi); return spi; } -u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; - X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); - write_lock_bh(&xfrm6_tunnel_spi_lock); x6spi = __xfrm6_tunnel_spi_lookup(saddr); if (x6spi) { @@ -301,9 +210,7 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) spi = __xfrm6_tunnel_alloc_spi(saddr); write_unlock_bh(&xfrm6_tunnel_spi_lock); - X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi); - - return spi; + return htonl(spi); } EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); @@ -313,8 +220,6 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos, *n; - X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr); - write_lock_bh(&xfrm6_tunnel_spi_lock); hlist_for_each_entry_safe(x6spi, pos, n, @@ -322,12 +227,6 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { - X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT - " found at %p\n", - __FUNCTION__, - NIP6(*(struct in6_addr *)saddr), - x6spi); - X6SPI_CHECK_MAGIC(x6spi); if (atomic_dec_and_test(&x6spi->refcnt)) { hlist_del(&x6spi->list_byaddr); hlist_del(&x6spi->list_byspi); @@ -351,76 +250,23 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) { return 0; } -static struct xfrm6_tunnel *xfrm6_tunnel_handler; -static DECLARE_MUTEX(xfrm6_tunnel_sem); - -int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) -{ - int ret; - - down(&xfrm6_tunnel_sem); - ret = 0; - if (xfrm6_tunnel_handler != NULL) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = handler; - up(&xfrm6_tunnel_sem); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_register); - -int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) -{ - int ret; - - down(&xfrm6_tunnel_sem); - ret = 0; - if (xfrm6_tunnel_handler != handler) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = NULL; - up(&xfrm6_tunnel_sem); - - synchronize_net(); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_deregister); - -static int xfrm6_tunnel_rcv(struct sk_buff **pskb) +static int xfrm6_tunnel_rcv(struct sk_buff *skb) { - struct sk_buff *skb = *pskb; - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; struct ipv6hdr *iph = skb->nh.ipv6h; - u32 spi; - - /* device-like_ip6ip6_handler() */ - if (handler && handler->handler(pskb) == 0) - return 0; + __be32 spi; spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); - return xfrm6_rcv_spi(pskb, spi); + return xfrm6_rcv_spi(skb, spi); } -static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) +static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info) { - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; - - /* call here first for device-like ip6ip6 err handling */ - if (handler) { - handler->err_handler(skb, opt, type, code, offset, info); - return; - } - /* xfrm6_tunnel native err handling */ switch (type) { case ICMPV6_DEST_UNREACH: @@ -431,20 +277,14 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case ICMPV6_ADDR_UNREACH: case ICMPV6_PORT_UNREACH: default: - X6TPRINTK3(KERN_DEBUG - "xfrm6_tunnel: Destination Unreach.\n"); break; } break; case ICMPV6_PKT_TOOBIG: - X6TPRINTK3(KERN_DEBUG - "xfrm6_tunnel: Packet Too Big.\n"); break; case ICMPV6_TIME_EXCEED: switch (code) { case ICMPV6_EXC_HOPLIMIT: - X6TPRINTK3(KERN_DEBUG - "xfrm6_tunnel: Too small Hoplimit.\n"); break; case ICMPV6_EXC_FRAGTIME: default: @@ -461,12 +301,13 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, default: break; } - return; + + return 0; } static int xfrm6_tunnel_init_state(struct xfrm_state *x) { - if (!x->props.mode) + if (x->props.mode != XFRM_MODE_TUNNEL) return -EINVAL; if (x->encap) @@ -492,31 +333,23 @@ static struct xfrm_type xfrm6_tunnel_type = { .output = xfrm6_tunnel_output, }; -static struct inet6_protocol xfrm6_tunnel_protocol = { +static struct xfrm6_tunnel xfrm6_tunnel_handler = { .handler = xfrm6_tunnel_rcv, - .err_handler = xfrm6_tunnel_err, - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + .err_handler = xfrm6_tunnel_err, + .priority = 2, }; 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"); + if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) return -EAGAIN; - } - if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) { - X6TPRINTK1(KERN_ERR - "xfrm6_tunnel init(): can't add protocol\n"); + + if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); 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); + xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); return -EAGAIN; } @@ -525,15 +358,9 @@ static int __init xfrm6_tunnel_init(void) static void __exit xfrm6_tunnel_fini(void) { - X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); - xfrm6_tunnel_spi_fini(); - if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) - X6TPRINTK1(KERN_ERR - "xfrm6_tunnel close: can't remove protocol\n"); - if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) - X6TPRINTK1(KERN_ERR - "xfrm6_tunnel close: can't remove xfrm type\n"); + xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); } module_init(xfrm6_tunnel_init);