/* Handling for loading a re-write file/database */
/*
 * (C) 2013 by On-Waves
 * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <openbsc/nat_rewrite_trie.h>
#include <openbsc/debug.h>
#include <openbsc/vty.h>

#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define CHECK_IS_DIGIT_OR_FAIL(prefix, pos)						\
	if (!isdigit(prefix[pos]) && prefix[pos] != '+') {				\
			LOGP(DNAT, LOGL_ERROR,						\
				"Prefix(%s) contains non ascii text at(%d=%c)\n",	\
				prefix, pos, prefix[pos]);				\
			goto fail;							\
	}
#define TO_INT(c) \
	((c) == '+' ? 10 : ((c - '0') % 10))

static void insert_rewrite_node(struct nat_rewrite_rule *rule, struct nat_rewrite *root)
{
	struct nat_rewrite_rule *new = &root->rule;

	const int len = strlen(rule->prefix);
	int i;

	if (len <= 0) {
		LOGP(DNAT, LOGL_ERROR, "An empty prefix does not make sense.\n");
		goto fail;
	}

	for (i = 0; i < len - 1; ++i) {
		int pos;

		/* check if the input is valid */
		CHECK_IS_DIGIT_OR_FAIL(rule->prefix, i);

		/* check if the next node is already valid */
		pos = TO_INT(rule->prefix[i]);
		if (!new->rules[pos]) {
			new->rules[pos] = talloc_zero(root, struct nat_rewrite_rule);
			if (!new->rules[pos]) {
				LOGP(DNAT, LOGL_ERROR,
					"Failed to allocate memory.\n");
				goto fail;
			}

			new->rules[pos]->empty = 1;
		}

		/* we continue here */
		new = new->rules[pos];
	}

	/* new now points to the place where we want to add it */
	int pos;

	/* check if the input is valid */
	CHECK_IS_DIGIT_OR_FAIL(rule->prefix, (len - 1));

	/* check if the next node is already valid */
	pos = TO_INT(rule->prefix[len - 1]);
	if (!new->rules[pos])
		new->rules[pos] = rule;
	else if (new->rules[pos]->empty) {
		/* copy over entries */
		new->rules[pos]->empty = 0;
		memcpy(new->rules[pos]->prefix, rule->prefix, sizeof(rule->prefix));
		memcpy(new->rules[pos]->rewrite, rule->rewrite, sizeof(rule->rewrite));
		talloc_free(rule);
	} else {
		LOGP(DNAT, LOGL_ERROR,
			"Prefix(%s) is already installed\n", rule->prefix);
		goto fail;
	}

	root->prefixes += 1;
	return;

fail:
	talloc_free(rule);
	return;
}

static void handle_line(struct nat_rewrite *rewrite, char *line)
{
	char *split;
	struct nat_rewrite_rule *rule;
	size_t size_prefix, size_end, len;


	/* Find the ',' in the line */
	len = strlen(line);
	split = strstr(line, ",");
	if (!split) {
		LOGP(DNAT, LOGL_ERROR, "Line doesn't contain ','\n");
		return;
	}

	/* Check if there is space for the rewrite rule */
	size_prefix = split - line;
	if (len - size_prefix <= 2) {
		LOGP(DNAT, LOGL_ERROR, "No rewrite available.\n");
		return;
	}

	/* Continue after the ',' to the end */
	split = &line[size_prefix + 1];
	size_end = strlen(split) - 1;

	/* Check if both strings can fit into the static array */
	if (size_prefix > sizeof(rule->prefix) - 1) {
		LOGP(DNAT, LOGL_ERROR,
			"Prefix is too long with %zu\n", size_prefix);
		return;
	}

	if (size_end > sizeof(rule->rewrite) - 1) {
		LOGP(DNAT, LOGL_ERROR,
			"Rewrite is too long with %zu on %s\n",
			size_end, &line[size_prefix + 1]);
		return;
	}

	/* Now create the entry and insert it into the trie */
	rule = talloc_zero(rewrite, struct nat_rewrite_rule);
	if (!rule) {
		LOGP(DNAT, LOGL_ERROR, "Can not allocate memory\n");
		return;
	}

	memcpy(rule->prefix, line, size_prefix);
	assert(size_prefix < sizeof(rule->prefix));
	rule->prefix[size_prefix] = '\0';

	memcpy(rule->rewrite, split, size_end);
	assert(size_end < sizeof(rule->rewrite));
	rule->rewrite[size_end] = '\0';

	/* now insert and balance the tree */
	insert_rewrite_node(rule, rewrite);
}

struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename)
{
	FILE *file;
	char *line = NULL;
	size_t n = 2342;
	struct nat_rewrite *res;

	file = fopen(filename, "r");
	if (!file)
		return NULL;

	res = talloc_zero(ctx, struct nat_rewrite);
	if (!res) {
		fclose(file);
		return NULL;
	}

	/* mark the root as empty */
	res->rule.empty = 1;

	while (getline(&line, &n, file) != -1) {
		handle_line(res, line);
	}

	free(line);
	fclose(file);
	return res;
}

/**
 * Simple find that tries to do a longest match...
 */
struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *rewrite,
					const char *prefix)
{
	struct nat_rewrite_rule *rule = &rewrite->rule;
	struct nat_rewrite_rule *last = NULL;
	const int len = OSMO_MIN(strlen(prefix), (sizeof(rule->prefix) - 1));
	int i;

	for (i = 0; rule && i < len; ++i) {
		int pos;

		CHECK_IS_DIGIT_OR_FAIL(prefix, i);
		pos = TO_INT(prefix[i]);

		rule = rule->rules[pos];
		if (rule && !rule->empty)
			last = rule;
	}

	return last;

fail:
	return NULL;
}

static void nat_rewrite_dump_rec(struct nat_rewrite_rule *rule)
{
	int i;
	if (!rule->empty)
		printf("%s,%s\n", rule->prefix, rule->rewrite);

	for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
		if (!rule->rules[i])
			continue;
		nat_rewrite_dump_rec(rule->rules[i]);
	}
}

void nat_rewrite_dump(struct nat_rewrite *rewrite)
{
	nat_rewrite_dump_rec(&rewrite->rule);
}

static void nat_rewrite_dump_rec_vty(struct vty *vty, struct nat_rewrite_rule *rule)
{
	int i;
	if (!rule->empty)
		vty_out(vty, "%s,%s%s", rule->prefix, rule->rewrite, VTY_NEWLINE);

	for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
		if (!rule->rules[i])
			continue;
		nat_rewrite_dump_rec_vty(vty, rule->rules[i]);
	}
}

void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewrite)
{
	nat_rewrite_dump_rec_vty(vty, &rewrite->rule);
}
