/* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
 *
 * Copyright (C) 2013 secunet Security Networks AG
 *
 * Author:
 * Steffen Klassert <steffen.klassert@secunet.com>
 *
 * Based on:
 * net/ipv4/xfrm4_protocol.c
 *
 *	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.
 */

#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/skbuff.h>
#include <linux/icmpv6.h>
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>

static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly;
static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly;
static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly;
static DEFINE_MUTEX(xfrm6_protocol_mutex);

static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
{
	switch (protocol) {
	case IPPROTO_ESP:
		return &esp6_handlers;
	case IPPROTO_AH:
		return &ah6_handlers;
	case IPPROTO_COMP:
		return &ipcomp6_handlers;
	}

	return NULL;
}

#define for_each_protocol_rcu(head, handler)		\
	for (handler = rcu_dereference(head);		\
	     handler != NULL;				\
	     handler = rcu_dereference(handler->next))	\

int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
{
	int ret;
	struct xfrm6_protocol *handler;

	for_each_protocol_rcu(*proto_handlers(protocol), handler)
		if ((ret = handler->cb_handler(skb, err)) <= 0)
			return ret;

	return 0;
}
EXPORT_SYMBOL(xfrm6_rcv_cb);

static int xfrm6_esp_rcv(struct sk_buff *skb)
{
	int ret;
	struct xfrm6_protocol *handler;

	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;

	for_each_protocol_rcu(esp6_handlers, handler)
		if ((ret = handler->handler(skb)) != -EINVAL)
			return ret;

	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);

	kfree_skb(skb);
	return 0;
}

static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
			  u8 type, u8 code, int offset, __be32 info)
{
	struct xfrm6_protocol *handler;

	for_each_protocol_rcu(esp6_handlers, handler)
		if (!handler->err_handler(skb, opt, type, code, offset, info))
			break;
}

static int xfrm6_ah_rcv(struct sk_buff *skb)
{
	int ret;
	struct xfrm6_protocol *handler;

	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;

	for_each_protocol_rcu(ah6_handlers, handler)
		if ((ret = handler->handler(skb)) != -EINVAL)
			return ret;

	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);

	kfree_skb(skb);
	return 0;
}

static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
			 u8 type, u8 code, int offset, __be32 info)
{
	struct xfrm6_protocol *handler;

	for_each_protocol_rcu(ah6_handlers, handler)
		if (!handler->err_handler(skb, opt, type, code, offset, info))
			break;
}

static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
{
	int ret;
	struct xfrm6_protocol *handler;

	XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;

	for_each_protocol_rcu(ipcomp6_handlers, handler)
		if ((ret = handler->handler(skb)) != -EINVAL)
			return ret;

	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);

	kfree_skb(skb);
	return 0;
}

static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
			     u8 type, u8 code, int offset, __be32 info)
{
	struct xfrm6_protocol *handler;

	for_each_protocol_rcu(ipcomp6_handlers, handler)
		if (!handler->err_handler(skb, opt, type, code, offset, info))
			break;
}

static const struct inet6_protocol esp6_protocol = {
	.handler	=	xfrm6_esp_rcv,
	.err_handler	=	xfrm6_esp_err,
	.flags		=	INET6_PROTO_NOPOLICY,
};

static const struct inet6_protocol ah6_protocol = {
	.handler	=	xfrm6_ah_rcv,
	.err_handler	=	xfrm6_ah_err,
	.flags		=	INET6_PROTO_NOPOLICY,
};

static const struct inet6_protocol ipcomp6_protocol = {
	.handler	=	xfrm6_ipcomp_rcv,
	.err_handler	=	xfrm6_ipcomp_err,
	.flags		=	INET6_PROTO_NOPOLICY,
};

static struct xfrm_input_afinfo xfrm6_input_afinfo = {
	.family		=	AF_INET6,
	.owner		=	THIS_MODULE,
	.callback	=	xfrm6_rcv_cb,
};

static inline const struct inet6_protocol *netproto(unsigned char protocol)
{
	switch (protocol) {
	case IPPROTO_ESP:
		return &esp6_protocol;
	case IPPROTO_AH:
		return &ah6_protocol;
	case IPPROTO_COMP:
		return &ipcomp6_protocol;
	}

	return NULL;
}

int xfrm6_protocol_register(struct xfrm6_protocol *handler,
			    unsigned char protocol)
{
	struct xfrm6_protocol __rcu **pprev;
	struct xfrm6_protocol *t;
	bool add_netproto = false;

	int ret = -EEXIST;
	int priority = handler->priority;

	mutex_lock(&xfrm6_protocol_mutex);

	if (!rcu_dereference_protected(*proto_handlers(protocol),
				       lockdep_is_held(&xfrm6_protocol_mutex)))
		add_netproto = true;

	for (pprev = proto_handlers(protocol);
	     (t = rcu_dereference_protected(*pprev,
			lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
	     pprev = &t->next) {
		if (t->priority < priority)
			break;
		if (t->priority == priority)
			goto err;
	}

	handler->next = *pprev;
	rcu_assign_pointer(*pprev, handler);

	ret = 0;

err:
	mutex_unlock(&xfrm6_protocol_mutex);

	if (add_netproto) {
		if (inet6_add_protocol(netproto(protocol), protocol)) {
			pr_err("%s: can't add protocol\n", __func__);
			ret = -EAGAIN;
		}
	}

	return ret;
}
EXPORT_SYMBOL(xfrm6_protocol_register);

int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
			      unsigned char protocol)
{
	struct xfrm6_protocol __rcu **pprev;
	struct xfrm6_protocol *t;
	int ret = -ENOENT;

	mutex_lock(&xfrm6_protocol_mutex);

	for (pprev = proto_handlers(protocol);
	     (t = rcu_dereference_protected(*pprev,
			lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
	     pprev = &t->next) {
		if (t == handler) {
			*pprev = handler->next;
			ret = 0;
			break;
		}
	}

	if (!rcu_dereference_protected(*proto_handlers(protocol),
				       lockdep_is_held(&xfrm6_protocol_mutex))) {
		if (inet6_del_protocol(netproto(protocol), protocol) < 0) {
			pr_err("%s: can't remove protocol\n", __func__);
			ret = -EAGAIN;
		}
	}

	mutex_unlock(&xfrm6_protocol_mutex);

	synchronize_net();

	return ret;
}
EXPORT_SYMBOL(xfrm6_protocol_deregister);

int __init xfrm6_protocol_init(void)
{
	return xfrm_input_register_afinfo(&xfrm6_input_afinfo);
}

void xfrm6_protocol_fini(void)
{
	xfrm_input_unregister_afinfo(&xfrm6_input_afinfo);
}
