/* 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;
	struct xfrm6_protocol __rcu **head = proto_handlers(protocol);

	if (!head)
		return 0;

	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;

	if (!proto_handlers(protocol) || !netproto(protocol))
		return -EINVAL;

	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;

	if (!proto_handlers(protocol) || !netproto(protocol))
		return -EINVAL;

	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);
}
