/* SPDX-License-Identifier: GPL-2.0 */
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>

#include <pthread.h>

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>

#include "internal.h"

#define LOGT(t, lvl, fmt, args ...) \
	LOGP(DGT, lvl, "%s: " fmt, (t)->name, ## args)

/***********************************************************************
 * GTP Tunnel
 ***********************************************************************/
struct gtp_tunnel *gtp_tunnel_alloc(struct gtp_daemon *d, const struct gtp_tunnel_params *cpars)
{
	struct gtp_tunnel *t;

	t = talloc_zero(d, struct gtp_tunnel);
	if (!t)
		goto out;
	t->d = d;
	t->name = talloc_asprintf(t, "%s-R%08x-T%08x", cpars->tun_name, cpars->rx_teid, cpars->tx_teid);
	t->tun_dev = tun_device_find_or_create(d, cpars->tun_name, cpars->tun_netns_name);
	if (!t->tun_dev) {
		LOGT(t, LOGL_ERROR, "Cannot find or create tun device %s\n", cpars->tun_name);
		goto out_free;
	}

	t->gtp_ep = gtp_endpoint_find_or_create(d, &cpars->local_udp);
	if (!t->gtp_ep) {
		LOGT(t, LOGL_ERROR, "Cannot find or create GTP endpoint\n");
		goto out_tun;
	}

	pthread_rwlock_wrlock(&d->rwlock);
	/* check if we already have a tunnel with same Rx-TEID + endpoint */
	if (_gtp_tunnel_find_r(d, cpars->rx_teid, t->gtp_ep)) {
		LOGT(t, LOGL_ERROR, "Error: We already have a tunnel for RxTEID 0x%08x "
			"on this endpoint (%s)\n", cpars->rx_teid, t->gtp_ep->name);
		goto out_ep;
	}

	/* FIXME: check if we already have a tunnel with same Tx-TEID + peer */
	/* FIXME: check if we already have a tunnel with same tun + EUA + filter */

	t->rx_teid = cpars->rx_teid;
	t->tx_teid = cpars->tx_teid;
	memcpy(&t->user_addr, &cpars->user_addr, sizeof(t->user_addr));
	memcpy(&t->remote_udp, &cpars->remote_udp, sizeof(t->remote_udp));

	if (netdev_add_addr(t->tun_dev->nl, t->tun_dev->ifindex, &t->user_addr) < 0) {
		LOGT(t, LOGL_ERROR, "Cannot add user addr to tun device: %s\n",
			strerror(errno));
	}

	/* TODO: hash table? */
	llist_add_tail(&t->list, &d->gtp_tunnels);
	pthread_rwlock_unlock(&d->rwlock);
	LOGT(t, LOGL_NOTICE, "Created\n");

	return t;

out_ep:
	pthread_rwlock_unlock(&d->rwlock);
	_gtp_endpoint_release(t->gtp_ep);
out_tun:
	_tun_device_release(t->tun_dev);
out_free:
	talloc_free(t);
out:
	return NULL;
}

#if 0
/* find tunnel by R(x_teid), T(x_teid) + A(ddr) */
static struct gtp_tunnel *
_gtp_tunnel_find_rta(struct gtp_daemon *d, uint32_t rx_teid, uint32_t tx_teid,
		     const struct sockaddr_storage *user_addr)
{
	struct gtp_tunnel *t;
	llist_for_each_entry(t, &d->gtp_tunnels, list) {
		if (t->rx_teid == rx_teid && t->tx_teid == tx_teid &&
		    sockaddr_equals((struct sockaddr *) &t->user_addr, (struct sockaddr *)user_addr))
			return t;
	}
	return NULL;
}
#endif

/* find tunnel by R(x_teid) + optionally local endpoint */
struct gtp_tunnel *
_gtp_tunnel_find_r(struct gtp_daemon *d, uint32_t rx_teid, struct gtp_endpoint *ep)
{
	struct gtp_tunnel *t;
	llist_for_each_entry(t, &d->gtp_tunnels, list) {
		if (t->rx_teid == rx_teid) {
			if (!ep)
				return t;
			if (t->gtp_ep == ep)
				return t;
		}
	}
	return NULL;
}

/* UNLOCKED find tunnel by tun + EUA ip (+proto/port) */
struct gtp_tunnel *
_gtp_tunnel_find_eua(struct tun_device *tun, const struct sockaddr *sa, uint8_t proto)
{
	struct gtp_daemon *d = tun->d;
	struct gtp_tunnel *t;

	llist_for_each_entry(t, &d->gtp_tunnels, list) {
		/* TODO: Find best matching filter */
		if (t->tun_dev == tun && sockaddr_equals(sa, (struct sockaddr *) &t->user_addr))
			return t;
	}
	return NULL;
}

/* UNLOCKED destroy of tunnel; drops references to EP + TUN */
void _gtp_tunnel_destroy(struct gtp_tunnel *t)
{
	LOGT(t, LOGL_NOTICE, "Destroying\n");
	/* talloc is not thread safe, all alloc/free must come from main thread */
	ASSERT_MAIN_THREAD(t->d);

	if (netdev_del_addr(t->tun_dev->nl, t->tun_dev->ifindex, &t->user_addr) < 0)
		LOGT(t, LOGL_ERROR, "Cannot remove user address: %s\n", strerror(errno));

	llist_del(&t->list);

	/* drop reference to endpoint + tun */
	_gtp_endpoint_release(t->gtp_ep);
	_tun_device_release(t->tun_dev);

	talloc_free(t);
}

bool gtp_tunnel_destroy(struct gtp_daemon *d, const struct sockaddr_storage *bind_addr, uint32_t rx_teid)
{
	struct gtp_endpoint *ep;
	bool rc = false;

	pthread_rwlock_wrlock(&d->rwlock);
	/* find endpoint for bind_addr */
	ep = _gtp_endpoint_find(d, bind_addr);
	if (ep) {
		/* find tunnel for rx TEID within endpoint */
		struct gtp_tunnel *t = _gtp_tunnel_find_r(d, rx_teid, ep);
		if (t) {
			_gtp_tunnel_destroy(t);
			rc = true;
		}
	}
	pthread_rwlock_unlock(&d->rwlock);

	return rc;
}
