/* Copyright (C) 2005 Red Hat, Inc. */

struct semanage_port;
struct semanage_port_key;
typedef struct semanage_port_key record_key_t;
typedef struct semanage_port record_t;
#define DBASE_RECORD_DEFINED

#include <stdlib.h>
#include "port_internal.h"
#include "debug.h"
#include "handle.h"
#include "database.h"

int semanage_port_modify_local(semanage_handle_t * handle,
			       const semanage_port_key_t * key,
			       const semanage_port_t * data)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_modify(handle, dconfig, key, data);
}

int semanage_port_del_local(semanage_handle_t * handle,
			    const semanage_port_key_t * key)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_del(handle, dconfig, key);
}

int semanage_port_query_local(semanage_handle_t * handle,
			      const semanage_port_key_t * key,
			      semanage_port_t ** response)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_query(handle, dconfig, key, response);
}

int semanage_port_exists_local(semanage_handle_t * handle,
			       const semanage_port_key_t * key, int *response)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_exists(handle, dconfig, key, response);
}

int semanage_port_count_local(semanage_handle_t * handle,
			      unsigned int *response)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_count(handle, dconfig, response);
}

int semanage_port_iterate_local(semanage_handle_t * handle,
				int (*handler) (const semanage_port_t * record,
						void *varg), void *handler_arg)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_iterate(handle, dconfig, handler, handler_arg);
}

int semanage_port_list_local(semanage_handle_t * handle,
			     semanage_port_t *** records, unsigned int *count)
{

	dbase_config_t *dconfig = semanage_port_dbase_local(handle);
	return dbase_list(handle, dconfig, records, count);
}


int semanage_port_validate_local(semanage_handle_t * handle)
{

	semanage_port_t **ports = NULL;
	unsigned int nports = 0;
	unsigned int i = 0, j = 0;

	/* List and sort the ports */
	if (semanage_port_list_local(handle, &ports, &nports) < 0)
		goto err;
	qsort(ports, nports, sizeof(semanage_port_t *),
	      (int (*)(const void *, const void *))
	      &semanage_port_compare2_qsort);

	/* Test each port for overlap */
	while (i < nports) {

		int proto = semanage_port_get_proto(ports[i]);
		int low = semanage_port_get_low(ports[i]);
		int high = semanage_port_get_high(ports[i]);
		const char *proto_str = semanage_port_get_proto_str(proto);

		const char *proto_str2;
		int proto2, low2, high2;

		/* Find the first port with matching 
		   protocol to compare against */
		do {
			if (j == nports - 1)
				goto next;
			j++;
			proto2 = semanage_port_get_proto(ports[j]);
			low2 = semanage_port_get_low(ports[j]);
			high2 = semanage_port_get_high(ports[j]);
			proto_str2 = semanage_port_get_proto_str(proto2);

		} while (proto != proto2);

		/* Overlap detected */
		if (low2 <= high) {
			ERR(handle, "port overlap between ranges "
			    "%u - %u (%s) <--> %u - %u (%s).",
			    low, high, proto_str, low2, high2, proto_str2);
			goto invalid;
		}

		/* If closest port of matching protocol doesn't overlap with
		 * test port, neither do the rest of them, because that's 
		 * how the sort function works on ports - lower bound 
		 * ports come first */
	      next:
		i++;
		j = i;
	}

	for (i = 0; i < nports; i++)
		semanage_port_free(ports[i]);
	free(ports);
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not complete ports validity check");

      invalid:
	for (i = 0; i < nports; i++)
		semanage_port_free(ports[i]);
	free(ports);
	return STATUS_ERR;
}
