/* NHRP virtual connection
 * Copyright (c) 2014-2015 Timo Teräs
 *
 * This file is free software: you may copy, redistribute 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 "zebra.h"
#include "memory.h"
#include "stream.h"
#include "hash.h"
#include "thread.h"
#include "jhash.h"

#include "nhrpd.h"
#include "os.h"

struct child_sa {
	uint32_t id;
	struct nhrp_vc *vc;
	struct list_head childlist_entry;
};

static struct hash *nhrp_vc_hash;
static struct list_head childlist_head[512];

static unsigned int nhrp_vc_key(void *peer_data)
{
	struct nhrp_vc *vc = peer_data;
	return jhash_2words(
		sockunion_hash(&vc->local.nbma),
		sockunion_hash(&vc->remote.nbma),
		0);
}

static int nhrp_vc_cmp(const void *cache_data, const void *key_data)
{
	const struct nhrp_vc *a = cache_data;
	const struct nhrp_vc *b = key_data;
	return	sockunion_same(&a->local.nbma, &b->local.nbma) &&
		sockunion_same(&a->remote.nbma, &b->remote.nbma);
}

static void *nhrp_vc_alloc(void *data)
{
	struct nhrp_vc *vc, *key = data;

	vc = XMALLOC(MTYPE_NHRP_VC, sizeof(struct nhrp_vc));
	if (vc) {
		*vc = (struct nhrp_vc) {
			.local.nbma = key->local.nbma,
			.remote.nbma = key->remote.nbma,
			.notifier_list = NOTIFIER_LIST_INITIALIZER(&vc->notifier_list),
		};
	}

	return vc;
}

static void nhrp_vc_free(void *data)
{
	XFREE(MTYPE_NHRP_VC, data);
}

struct nhrp_vc *nhrp_vc_get(const union sockunion *src, const union sockunion *dst, int create)
{
	struct nhrp_vc key;
	key.local.nbma = *src;
	key.remote.nbma = *dst;
	return hash_get(nhrp_vc_hash, &key, create ? nhrp_vc_alloc : 0);
}

static void nhrp_vc_check_delete(struct nhrp_vc *vc)
{
	if (vc->updating || vc->ipsec || notifier_active(&vc->notifier_list))
		return;
	hash_release(nhrp_vc_hash, vc);
	nhrp_vc_free(vc);
}

static void nhrp_vc_update(struct nhrp_vc *vc, long cmd)
{
	vc->updating = 1;
	notifier_call(&vc->notifier_list, cmd);
	vc->updating = 0;
	nhrp_vc_check_delete(vc);
}

static void nhrp_vc_ipsec_reset(struct nhrp_vc *vc)
{
	vc->local.id[0] = 0;
	vc->local.certlen = 0;
	vc->remote.id[0] = 0;
	vc->remote.certlen = 0;
}

int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
{
	char buf[2][SU_ADDRSTRLEN];
	struct child_sa *sa = NULL, *lsa;
	uint32_t child_hash = child_id % ZEBRA_NUM_OF(childlist_head);
	int abort_migration = 0;

	list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry) {
		if (lsa->id == child_id) {
			sa = lsa;
			break;
		}
	}

	if (!sa) {
		if (!vc) return 0;

		sa = XMALLOC(MTYPE_NHRP_VC, sizeof(struct child_sa));
		if (!sa) return 0;

		*sa = (struct child_sa) {
			.id = child_id,
			.childlist_entry = LIST_INITIALIZER(sa->childlist_entry),
			.vc = NULL,
		};
		list_add_tail(&sa->childlist_entry, &childlist_head[child_hash]);
	}

	if (sa->vc == vc)
		return 0;

	if (vc) {
		/* Attach first to new VC */
		vc->ipsec++;
		nhrp_vc_update(vc, NOTIFY_VC_IPSEC_CHANGED);
	}
	if (sa->vc && vc) {
		/* Notify old VC of migration */
		sa->vc->abort_migration = 0;
		debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %s to %s",
			sockunion2str(&sa->vc->remote.nbma, buf[0], sizeof buf[0]),
			sockunion2str(&vc->remote.nbma, buf[1], sizeof buf[1]));
		nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_UPDATE_NBMA);
		abort_migration = sa->vc->abort_migration;
	}
	if (sa->vc) {
		/* Deattach old VC */
		sa->vc->ipsec--;
		if (!sa->vc->ipsec) nhrp_vc_ipsec_reset(sa->vc);
		nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_CHANGED);
	}

	/* Update */
	sa->vc = vc;
	if (!vc) {
		list_del(&sa->childlist_entry);
		XFREE(MTYPE_NHRP_VC, sa);
	}

	return abort_migration;
}

void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n, notifier_fn_t action)
{
	notifier_add(n, &vc->notifier_list, action);
}

void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
{
	notifier_del(n);
	nhrp_vc_check_delete(vc);
}


struct nhrp_vc_iterator_ctx {
	void (*cb)(struct nhrp_vc *, void *);
	void *ctx;
};

static void nhrp_vc_iterator(struct hash_backet *b, void *ctx)
{
	struct nhrp_vc_iterator_ctx *ic = ctx;
	ic->cb(b->data, ic->ctx);
}

void nhrp_vc_foreach(void (*cb)(struct nhrp_vc *, void *), void *ctx)
{
	struct nhrp_vc_iterator_ctx ic = {
		.cb = cb,
		.ctx = ctx,
	};
	hash_iterate(nhrp_vc_hash, nhrp_vc_iterator, &ic);
}

void nhrp_vc_init(void)
{
	size_t i;

	nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp);
	for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++)
		list_init(&childlist_head[i]);
}

void nhrp_vc_reset(void)
{
	struct child_sa *sa, *n;
	size_t i;

	for (i = 0; i < ZEBRA_NUM_OF(childlist_head); i++) {
		list_for_each_entry_safe(sa, n, &childlist_head[i], childlist_entry)
			nhrp_vc_ipsec_updown(sa->id, 0);
	}
}

void nhrp_vc_terminate(void)
{
	nhrp_vc_reset();
	hash_clean(nhrp_vc_hash, nhrp_vc_free);
}
