#include <stdlib.h>

#include "debug.h"
#include "context.h"
#include "handle.h"

#include <sepol/policydb/policydb.h>
#include <sepol/interfaces.h>
#include "iface_internal.h"

/* Create a low level structure from record */
static int iface_from_record(sepol_handle_t * handle,
			     const policydb_t * policydb,
			     ocontext_t ** iface, const sepol_iface_t * record)
{

	ocontext_t *tmp_iface = NULL;
	context_struct_t *tmp_con = NULL;

	tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t));
	if (!tmp_iface)
		goto omem;

	/* Name */
	tmp_iface->u.name = strdup(sepol_iface_get_name(record));
	if (!tmp_iface->u.name)
		goto omem;

	/* Interface Context */
	if (context_from_record(handle, policydb,
				&tmp_con, sepol_iface_get_ifcon(record)) < 0)
		goto err;
	context_cpy(&tmp_iface->context[0], tmp_con);
	context_destroy(tmp_con);
	free(tmp_con);
	tmp_con = NULL;

	/* Message Context */
	if (context_from_record(handle, policydb,
				&tmp_con, sepol_iface_get_msgcon(record)) < 0)
		goto err;
	context_cpy(&tmp_iface->context[1], tmp_con);
	context_destroy(tmp_con);
	free(tmp_con);
	tmp_con = NULL;

	*iface = tmp_iface;
	return STATUS_SUCCESS;

      omem:
	ERR(handle, "out of memory");

      err:
	if (tmp_iface != NULL) {
		free(tmp_iface->u.name);
		context_destroy(&tmp_iface->context[0]);
		context_destroy(&tmp_iface->context[1]);
		free(tmp_iface);
	}
	context_destroy(tmp_con);
	free(tmp_con);
	ERR(handle, "error creating interface structure");
	return STATUS_ERR;
}

static int iface_to_record(sepol_handle_t * handle,
			   const policydb_t * policydb,
			   ocontext_t * iface, sepol_iface_t ** record)
{

	char *name = iface->u.name;
	context_struct_t *ifcon = &iface->context[0];
	context_struct_t *msgcon = &iface->context[1];

	sepol_context_t *tmp_con = NULL;
	sepol_iface_t *tmp_record = NULL;

	if (sepol_iface_create(handle, &tmp_record) < 0)
		goto err;

	if (sepol_iface_set_name(handle, tmp_record, name) < 0)
		goto err;

	if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0)
		goto err;
	if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0)
		goto err;
	sepol_context_free(tmp_con);
	tmp_con = NULL;

	if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0)
		goto err;
	if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0)
		goto err;
	sepol_context_free(tmp_con);
	tmp_con = NULL;

	*record = tmp_record;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not convert interface %s to record", name);
	sepol_context_free(tmp_con);
	sepol_iface_free(tmp_record);
	return STATUS_ERR;
}

/* Check if an interface exists */
int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)),
		       const sepol_policydb_t * p,
		       const sepol_iface_key_t * key, int *response)
{

	const policydb_t *policydb = &p->p;
	ocontext_t *c, *head;

	const char *name;
	sepol_iface_key_unpack(key, &name);

	head = policydb->ocontexts[OCON_NETIF];
	for (c = head; c; c = c->next) {
		if (!strcmp(name, c->u.name)) {
			*response = 1;
			return STATUS_SUCCESS;
		}
	}
	*response = 0;

	handle = NULL;
	return STATUS_SUCCESS;
}

/* Query an interface */
int sepol_iface_query(sepol_handle_t * handle,
		      const sepol_policydb_t * p,
		      const sepol_iface_key_t * key, sepol_iface_t ** response)
{

	const policydb_t *policydb = &p->p;
	ocontext_t *c, *head;

	const char *name;
	sepol_iface_key_unpack(key, &name);

	head = policydb->ocontexts[OCON_NETIF];
	for (c = head; c; c = c->next) {
		if (!strcmp(name, c->u.name)) {

			if (iface_to_record(handle, policydb, c, response) < 0)
				goto err;

			return STATUS_SUCCESS;
		}
	}

	*response = NULL;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not query interface %s", name);
	return STATUS_ERR;
}

/* Load an interface into policy */
int sepol_iface_modify(sepol_handle_t * handle,
		       sepol_policydb_t * p,
		       const sepol_iface_key_t * key,
		       const sepol_iface_t * data)
{

	policydb_t *policydb = &p->p;
	ocontext_t *head, *prev, *c, *iface = NULL;

	const char *name;
	sepol_iface_key_unpack(key, &name);

	if (iface_from_record(handle, policydb, &iface, data) < 0)
		goto err;

	prev = NULL;
	head = policydb->ocontexts[OCON_NETIF];
	for (c = head; c; c = c->next) {
		if (!strcmp(name, c->u.name)) {

			/* Replace */
			iface->next = c->next;
			if (prev == NULL)
				policydb->ocontexts[OCON_NETIF] = iface;
			else
				prev->next = iface;
			free(c->u.name);
			context_destroy(&c->context[0]);
			context_destroy(&c->context[1]);
			free(c);

			return STATUS_SUCCESS;
		}
		prev = c;
	}

	/* Attach to context list */
	iface->next = policydb->ocontexts[OCON_NETIF];
	policydb->ocontexts[OCON_NETIF] = iface;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "error while loading interface %s", name);

	if (iface != NULL) {
		free(iface->u.name);
		context_destroy(&iface->context[0]);
		context_destroy(&iface->context[1]);
		free(iface);
	}
	return STATUS_ERR;
}

/* Return the number of interfaces */
extern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)),
			     const sepol_policydb_t * p, unsigned int *response)
{

	unsigned int count = 0;
	ocontext_t *c, *head;
	const policydb_t *policydb = &p->p;

	head = policydb->ocontexts[OCON_NETIF];
	for (c = head; c != NULL; c = c->next)
		count++;

	*response = count;

	handle = NULL;
	return STATUS_SUCCESS;
}

int sepol_iface_iterate(sepol_handle_t * handle,
			const sepol_policydb_t * p,
			int (*fn) (const sepol_iface_t * iface,
				   void *fn_arg), void *arg)
{

	const policydb_t *policydb = &p->p;
	ocontext_t *c, *head;
	sepol_iface_t *iface = NULL;

	head = policydb->ocontexts[OCON_NETIF];
	for (c = head; c; c = c->next) {
		int status;

		if (iface_to_record(handle, policydb, c, &iface) < 0)
			goto err;

		/* Invoke handler */
		status = fn(iface, arg);
		if (status < 0)
			goto err;

		sepol_iface_free(iface);
		iface = NULL;

		/* Handler requested exit */
		if (status > 0)
			break;
	}

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not iterate over interfaces");
	sepol_iface_free(iface);
	return STATUS_ERR;
}
