summaryrefslogtreecommitdiff
path: root/net/ipv4/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/xfrm_policy.c')
-rw-r--r--net/ipv4/xfrm_policy.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
index 9d015cbbab..02d7ce7797 100644
--- a/net/ipv4/xfrm_policy.c
+++ b/net/ipv4/xfrm_policy.c
@@ -1,3 +1,4 @@
+#include <linux/config.h>
#include <net/xfrm.h>
#include <net/ip.h>
@@ -198,6 +199,49 @@ struct xfrm_type *xfrm_get_type(u8 proto)
return type;
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct xfrm_type *xfrm6_type_map[256];
+static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
+
+int xfrm6_register_type(struct xfrm_type *type)
+{
+ int err = 0;
+
+ write_lock(&xfrm6_type_lock);
+ if (xfrm6_type_map[type->proto] == NULL)
+ xfrm6_type_map[type->proto] = type;
+ else
+ err = -EEXIST;
+ write_unlock(&xfrm6_type_lock);
+ return err;
+}
+
+int xfrm6_unregister_type(struct xfrm_type *type)
+{
+ int err = 0;
+
+ write_lock(&xfrm6_type_lock);
+ if (xfrm6_type_map[type->proto] != type)
+ err = -ENOENT;
+ else
+ xfrm6_type_map[type->proto] = NULL;
+ write_unlock(&xfrm6_type_lock);
+ return err;
+}
+
+struct xfrm_type *xfrm6_get_type(u8 proto)
+{
+ struct xfrm_type *type;
+
+ read_lock(&xfrm6_type_lock);
+ type = xfrm6_type_map[proto];
+ if (type && !try_module_get(type->owner))
+ type = NULL;
+ read_unlock(&xfrm6_type_lock);
+ return type;
+}
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
void xfrm_put_type(struct xfrm_type *type)
{
module_put(type->owner);