#include <netinet/in.h>
#include <stdlib.h>

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

#include <sepol/policydb/policydb.h>
#include "port_internal.h"

static inline int sepol2ipproto(sepol_handle_t * handle, int proto)
{

	switch (proto) {
	case SEPOL_PROTO_TCP:
		return IPPROTO_TCP;
	case SEPOL_PROTO_UDP:
		return IPPROTO_UDP;
	default:
		ERR(handle, "unsupported protocol %u", proto);
		return STATUS_ERR;
	}
}

static inline int ipproto2sepol(sepol_handle_t * handle, int proto)
{

	switch (proto) {
	case IPPROTO_TCP:
		return SEPOL_PROTO_TCP;
	case IPPROTO_UDP:
		return SEPOL_PROTO_UDP;
	default:
		ERR(handle, "invalid protocol %u " "found in policy", proto);
		return STATUS_ERR;
	}
}

/* Create a low level port structure from
 * a high level representation */
static int port_from_record(sepol_handle_t * handle,
			    const policydb_t * policydb,
			    ocontext_t ** port, const sepol_port_t * data)
{

	ocontext_t *tmp_port = NULL;
	context_struct_t *tmp_con = NULL;
	int tmp_proto;

	int low = sepol_port_get_low(data);
	int high = sepol_port_get_high(data);
	int proto = sepol_port_get_proto(data);

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

	/* Process protocol */
	tmp_proto = sepol2ipproto(handle, proto);
	if (tmp_proto < 0)
		goto err;
	tmp_port->u.port.protocol = tmp_proto;

	/* Port range */
	tmp_port->u.port.low_port = low;
	tmp_port->u.port.high_port = high;
	if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) {
		ERR(handle, "low port %d exceeds high port %d",
		    tmp_port->u.port.low_port, tmp_port->u.port.high_port);
		goto err;
	}

	/* Context */
	if (context_from_record(handle, policydb, &tmp_con,
				sepol_port_get_con(data)) < 0)
		goto err;
	context_cpy(&tmp_port->context[0], tmp_con);
	context_destroy(tmp_con);
	free(tmp_con);
	tmp_con = NULL;

	*port = tmp_port;
	return STATUS_SUCCESS;

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

      err:
	if (tmp_port != NULL) {
		context_destroy(&tmp_port->context[0]);
		free(tmp_port);
	}
	context_destroy(tmp_con);
	free(tmp_con);
	ERR(handle, "could not create port structure for range %u:%u (%s)",
	    low, high, sepol_port_get_proto_str(proto));
	return STATUS_ERR;
}

static int port_to_record(sepol_handle_t * handle,
			  const policydb_t * policydb,
			  ocontext_t * port, sepol_port_t ** record)
{

	int proto = port->u.port.protocol;
	int low = port->u.port.low_port;
	int high = port->u.port.high_port;
	context_struct_t *con = &port->context[0];
	int rec_proto = -1;

	sepol_context_t *tmp_con = NULL;
	sepol_port_t *tmp_record = NULL;

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

	rec_proto = ipproto2sepol(handle, proto);
	if (rec_proto < 0)
		goto err;

	sepol_port_set_proto(tmp_record, rec_proto);
	sepol_port_set_range(tmp_record, low, high);

	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
		goto err;

	if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0)
		goto err;

	sepol_context_free(tmp_con);
	*record = tmp_record;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not convert port range %u - %u (%s) "
	    "to record", low, high, sepol_port_get_proto_str(rec_proto));
	sepol_context_free(tmp_con);
	sepol_port_free(tmp_record);
	return STATUS_ERR;
}

/* Return the number of ports */
extern int sepol_port_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_PORT];
	for (c = head; c != NULL; c = c->next)
		count++;

	*response = count;

	handle = NULL;
	return STATUS_SUCCESS;
}

/* Check if a port exists */
int sepol_port_exists(sepol_handle_t * handle,
		      const sepol_policydb_t * p,
		      const sepol_port_key_t * key, int *response)
{

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

	int low, high, proto;
	const char *proto_str;
	sepol_port_key_unpack(key, &low, &high, &proto);
	proto_str = sepol_port_get_proto_str(proto);
	proto = sepol2ipproto(handle, proto);
	if (proto < 0)
		goto err;

	head = policydb->ocontexts[OCON_PORT];
	for (c = head; c; c = c->next) {
		int proto2 = c->u.port.protocol;
		int low2 = c->u.port.low_port;
		int high2 = c->u.port.high_port;

		if (proto == proto2 && low2 == low && high2 == high) {
			*response = 1;
			return STATUS_SUCCESS;
		}
	}

	*response = 0;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not check if port range %u - %u (%s) exists",
	    low, high, proto_str);
	return STATUS_ERR;
}

/* Query a port */
int sepol_port_query(sepol_handle_t * handle,
		     const sepol_policydb_t * p,
		     const sepol_port_key_t * key, sepol_port_t ** response)
{

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

	int low, high, proto;
	const char *proto_str;
	sepol_port_key_unpack(key, &low, &high, &proto);
	proto_str = sepol_port_get_proto_str(proto);
	proto = sepol2ipproto(handle, proto);
	if (proto < 0)
		goto err;

	head = policydb->ocontexts[OCON_PORT];
	for (c = head; c; c = c->next) {
		int proto2 = c->u.port.protocol;
		int low2 = c->u.port.low_port;
		int high2 = c->u.port.high_port;

		if (proto == proto2 && low2 == low && high2 == high) {
			if (port_to_record(handle, policydb, c, response) < 0)
				goto err;
			return STATUS_SUCCESS;
		}
	}

	*response = NULL;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not query port range %u - %u (%s)",
	    low, high, proto_str);
	return STATUS_ERR;

}

/* Load a port into policy */
int sepol_port_modify(sepol_handle_t * handle,
		      sepol_policydb_t * p,
		      const sepol_port_key_t * key, const sepol_port_t * data)
{

	policydb_t *policydb = &p->p;
	ocontext_t *port = NULL;

	int low, high, proto;
	const char *proto_str;

	sepol_port_key_unpack(key, &low, &high, &proto);
	proto_str = sepol_port_get_proto_str(proto);
	proto = sepol2ipproto(handle, proto);
	if (proto < 0)
		goto err;

	if (port_from_record(handle, policydb, &port, data) < 0)
		goto err;

	/* Attach to context list */
	port->next = policydb->ocontexts[OCON_PORT];
	policydb->ocontexts[OCON_PORT] = port;

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not load port range %u - %u (%s)",
	    low, high, proto_str);
	if (port != NULL) {
		context_destroy(&port->context[0]);
		free(port);
	}
	return STATUS_ERR;
}

int sepol_port_iterate(sepol_handle_t * handle,
		       const sepol_policydb_t * p,
		       int (*fn) (const sepol_port_t * port,
				  void *fn_arg), void *arg)
{

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

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

		if (port_to_record(handle, policydb, c, &port) < 0)
			goto err;

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

		sepol_port_free(port);
		port = NULL;

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

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not iterate over ports");
	sepol_port_free(port);
	return STATUS_ERR;
}
