#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include "node_internal.h"
#include "context_internal.h"
#include "debug.h"

struct sepol_node {

	/* Network address and mask */
	char *addr;
	size_t addr_sz;

	char *mask;
	size_t mask_sz;

	/* Protocol */
	int proto;

	/* Context */
	sepol_context_t *con;
};

struct sepol_node_key {

	/* Network address and mask */
	char *addr;
	size_t addr_sz;

	char *mask;
	size_t mask_sz;

	/* Protocol */
	int proto;
};

/* Converts a string represtation (addr_str)
 * to a numeric representation (addr_bytes) */

static int node_parse_addr(sepol_handle_t * handle,
			   const char *addr_str, int proto, char *addr_bytes)
{

	switch (proto) {

	case SEPOL_PROTO_IP4:
		{
			struct in_addr in_addr;

			if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
				ERR(handle, "could not parse IPv4 address "
				    "%s: %s", addr_str, strerror(errno));
				return STATUS_ERR;
			}

			memcpy(addr_bytes, &in_addr.s_addr, 4);
			break;
		}
	case SEPOL_PROTO_IP6:
		{
			struct in6_addr in_addr;

			if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
				ERR(handle, "could not parse IPv6 address "
				    "%s: %s", addr_str, strerror(errno));
				return STATUS_ERR;
			}

			memcpy(addr_bytes, in_addr.s6_addr32, 16);
			break;
		}
	default:
		ERR(handle, "unsupported protocol %u, could not "
		    "parse address", proto);
		return STATUS_ERR;
	}

	return STATUS_SUCCESS;
}

/* Allocates a sufficiently large buffer (addr, addr_sz)
 * according the the protocol */

static int node_alloc_addr(sepol_handle_t * handle,
			   int proto, char **addr, size_t * addr_sz)
{

	char *tmp_addr = NULL;
	size_t tmp_addr_sz;

	switch (proto) {

	case SEPOL_PROTO_IP4:
		tmp_addr_sz = 4;
		tmp_addr = malloc(4);
		if (!tmp_addr)
			goto omem;
		break;

	case SEPOL_PROTO_IP6:
		tmp_addr_sz = 16;
		tmp_addr = malloc(16);
		if (!tmp_addr)
			goto omem;
		break;

	default:
		ERR(handle, "unsupported protocol %u", proto);
		goto err;
	}

	*addr = tmp_addr;
	*addr_sz = tmp_addr_sz;
	return STATUS_SUCCESS;

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

      err:
	free(tmp_addr);
	ERR(handle, "could not allocate address of protocol %s",
	    sepol_node_get_proto_str(proto));
	return STATUS_ERR;
}

/* Converts a numeric representation (addr_bytes)
 * to a string representation (addr_str), according to 
 * the protocol */

static int node_expand_addr(sepol_handle_t * handle,
			    char *addr_bytes, int proto, char *addr_str)
{

	switch (proto) {

	case SEPOL_PROTO_IP4:
		{
			struct in_addr addr;
			memset(&addr, 0, sizeof(struct in_addr));
			memcpy(&addr.s_addr, addr_bytes, 4);

			if (inet_ntop(AF_INET, &addr, addr_str,
				      INET_ADDRSTRLEN) == NULL) {

				ERR(handle,
				    "could not expand IPv4 address to string: %s",
				    strerror(errno));
				return STATUS_ERR;
			}
			break;
		}

	case SEPOL_PROTO_IP6:
		{
			struct in6_addr addr;
			memset(&addr, 0, sizeof(struct in6_addr));
			memcpy(&addr.s6_addr32[0], addr_bytes, 16);

			if (inet_ntop(AF_INET6, &addr, addr_str,
				      INET6_ADDRSTRLEN) == NULL) {

				ERR(handle,
				    "could not expand IPv6 address to string: %s",
				    strerror(errno));
				return STATUS_ERR;
			}
			break;
		}

	default:
		ERR(handle, "unsupported protocol %u, could not"
		    " expand address to string", proto);
		return STATUS_ERR;
	}

	return STATUS_SUCCESS;
}

/* Allocates a sufficiently large address string (addr)
 * according to the protocol */

static int node_alloc_addr_string(sepol_handle_t * handle,
				  int proto, char **addr)
{

	char *tmp_addr = NULL;

	switch (proto) {

	case SEPOL_PROTO_IP4:
		tmp_addr = malloc(INET_ADDRSTRLEN);
		if (!tmp_addr)
			goto omem;
		break;

	case SEPOL_PROTO_IP6:
		tmp_addr = malloc(INET6_ADDRSTRLEN);
		if (!tmp_addr)
			goto omem;
		break;

	default:
		ERR(handle, "unsupported protocol %u", proto);
		goto err;
	}

	*addr = tmp_addr;
	return STATUS_SUCCESS;

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

      err:
	free(tmp_addr);
	ERR(handle, "could not allocate string buffer for "
	    "address of protocol %s", sepol_node_get_proto_str(proto));
	return STATUS_ERR;
}

/* Key */
int sepol_node_key_create(sepol_handle_t * handle,
			  const char *addr,
			  const char *mask,
			  int proto, sepol_node_key_t ** key_ptr)
{

	sepol_node_key_t *tmp_key =
	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
	if (!tmp_key)
		goto omem;

	if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) <
	    0)
		goto err;
	if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0)
		goto err;

	if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) <
	    0)
		goto err;
	if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0)
		goto err;

	tmp_key->proto = proto;

	*key_ptr = tmp_key;
	return STATUS_SUCCESS;

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

      err:
	sepol_node_key_free(tmp_key);
	ERR(handle, "could not create node key for (%s, %s, %s)",
	    addr, mask, sepol_node_get_proto_str(proto));
	return STATUS_ERR;
}

hidden_def(sepol_node_key_create)

void sepol_node_key_unpack(const sepol_node_key_t * key,
			   const char **addr, const char **mask, int *proto)
{

	*addr = key->addr;
	*mask = key->mask;
	*proto = key->proto;
}

hidden_def(sepol_node_key_unpack)

int sepol_node_key_extract(sepol_handle_t * handle,
			   const sepol_node_t * node,
			   sepol_node_key_t ** key_ptr)
{

	sepol_node_key_t *tmp_key =
	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
	if (!tmp_key)
		goto omem;

	tmp_key->addr = malloc(node->addr_sz);
	tmp_key->mask = malloc(node->mask_sz);

	if (!tmp_key->addr || !tmp_key->mask)
		goto omem;

	memcpy(tmp_key->addr, node->addr, node->addr_sz);
	memcpy(tmp_key->mask, node->mask, node->mask_sz);
	tmp_key->addr_sz = node->addr_sz;
	tmp_key->mask_sz = node->mask_sz;
	tmp_key->proto = node->proto;

	*key_ptr = tmp_key;
	return STATUS_SUCCESS;

      omem:
	sepol_node_key_free(tmp_key);
	ERR(handle, "out of memory, could not extract node key");
	return STATUS_ERR;
}

void sepol_node_key_free(sepol_node_key_t * key)
{

	if (!key)
		return;

	free(key->addr);
	free(key->mask);
	free(key);
}

hidden_def(sepol_node_key_free)

int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key)
{

	int rc1, rc2;

	if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz))
		return -1;

	else if ((node->addr_sz > key->addr_sz) ||
		 (node->mask_sz > key->mask_sz))
		return 1;

	rc1 = memcmp(node->addr, key->addr, node->addr_sz);
	rc2 = memcmp(node->mask, key->mask, node->mask_sz);

	return (rc2 != 0) ? rc2 : rc1;
}

int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2)
{

	int rc1, rc2;

	if ((node->addr_sz < node2->addr_sz) ||
	    (node->mask_sz < node2->mask_sz))
		return -1;

	else if ((node->addr_sz > node2->addr_sz) ||
		 (node->mask_sz > node2->mask_sz))
		return 1;

	rc1 = memcmp(node->addr, node2->addr, node->addr_sz);
	rc2 = memcmp(node->mask, node2->mask, node->mask_sz);

	return (rc2 != 0) ? rc2 : rc1;
}

/* Addr */
int sepol_node_get_addr(sepol_handle_t * handle,
			const sepol_node_t * node, char **addr)
{

	char *tmp_addr = NULL;

	if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0)
		goto err;

	if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0)
		goto err;

	*addr = tmp_addr;
	return STATUS_SUCCESS;

      err:
	free(tmp_addr);
	ERR(handle, "could not get node address");
	return STATUS_ERR;
}

hidden_def(sepol_node_get_addr)

int sepol_node_get_addr_bytes(sepol_handle_t * handle,
			      const sepol_node_t * node,
			      char **buffer, size_t * bsize)
{

	char *tmp_buf = malloc(node->addr_sz);
	if (!tmp_buf) {
		ERR(handle, "out of memory, could not get address bytes");
		return STATUS_ERR;
	}

	memcpy(tmp_buf, node->addr, node->addr_sz);
	*buffer = tmp_buf;
	*bsize = node->addr_sz;
	return STATUS_SUCCESS;
}

hidden_def(sepol_node_get_addr_bytes)

int sepol_node_set_addr(sepol_handle_t * handle,
			sepol_node_t * node, int proto, const char *addr)
{

	char *tmp_addr = NULL;
	size_t tmp_addr_sz;

	if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0)
		goto err;

	if (node_parse_addr(handle, addr, proto, tmp_addr) < 0)
		goto err;

	free(node->addr);
	node->addr = tmp_addr;
	node->addr_sz = tmp_addr_sz;
	return STATUS_SUCCESS;

      err:
	free(tmp_addr);
	ERR(handle, "could not set node address to %s", addr);
	return STATUS_ERR;
}

hidden_def(sepol_node_set_addr)

int sepol_node_set_addr_bytes(sepol_handle_t * handle,
			      sepol_node_t * node,
			      const char *addr, size_t addr_sz)
{

	char *tmp_addr = malloc(addr_sz);
	if (!tmp_addr) {
		ERR(handle, "out of memory, could not " "set node address");
		return STATUS_ERR;
	}

	memcpy(tmp_addr, addr, addr_sz);
	free(node->addr);
	node->addr = tmp_addr;
	node->addr_sz = addr_sz;
	return STATUS_SUCCESS;
}

hidden_def(sepol_node_set_addr_bytes)

/* Mask */
int sepol_node_get_mask(sepol_handle_t * handle,
			const sepol_node_t * node, char **mask)
{

	char *tmp_mask = NULL;

	if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0)
		goto err;

	if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0)
		goto err;

	*mask = tmp_mask;
	return STATUS_SUCCESS;

      err:
	free(tmp_mask);
	ERR(handle, "could not get node netmask");
	return STATUS_ERR;
}

hidden_def(sepol_node_get_mask)

int sepol_node_get_mask_bytes(sepol_handle_t * handle,
			      const sepol_node_t * node,
			      char **buffer, size_t * bsize)
{

	char *tmp_buf = malloc(node->mask_sz);
	if (!tmp_buf) {
		ERR(handle, "out of memory, could not get netmask bytes");
		return STATUS_ERR;
	}

	memcpy(tmp_buf, node->mask, node->mask_sz);
	*buffer = tmp_buf;
	*bsize = node->mask_sz;
	return STATUS_SUCCESS;
}

hidden_def(sepol_node_get_mask_bytes)

int sepol_node_set_mask(sepol_handle_t * handle,
			sepol_node_t * node, int proto, const char *mask)
{

	char *tmp_mask = NULL;
	size_t tmp_mask_sz;

	if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0)
		goto err;

	if (node_parse_addr(handle, mask, proto, tmp_mask) < 0)
		goto err;

	free(node->mask);
	node->mask = tmp_mask;
	node->mask_sz = tmp_mask_sz;
	return STATUS_SUCCESS;

      err:
	free(tmp_mask);
	ERR(handle, "could not set node netmask to %s", mask);
	return STATUS_ERR;
}

hidden_def(sepol_node_set_mask)

int sepol_node_set_mask_bytes(sepol_handle_t * handle,
			      sepol_node_t * node,
			      const char *mask, size_t mask_sz)
{

	char *tmp_mask = malloc(mask_sz);
	if (!tmp_mask) {
		ERR(handle, "out of memory, could not " "set node netmask");
		return STATUS_ERR;
	}
	memcpy(tmp_mask, mask, mask_sz);
	free(node->mask);
	node->mask = tmp_mask;
	node->mask_sz = mask_sz;
	return STATUS_SUCCESS;
}

hidden_def(sepol_node_set_mask_bytes)

/* Protocol */
int sepol_node_get_proto(const sepol_node_t * node)
{

	return node->proto;
}

hidden_def(sepol_node_get_proto)

void sepol_node_set_proto(sepol_node_t * node, int proto)
{

	node->proto = proto;
}

hidden_def(sepol_node_set_proto)

const char *sepol_node_get_proto_str(int proto)
{

	switch (proto) {
	case SEPOL_PROTO_IP4:
		return "ipv4";
	case SEPOL_PROTO_IP6:
		return "ipv6";
	default:
		return "???";
	}
}

hidden_def(sepol_node_get_proto_str)

/* Create */
int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
{

	sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t));

	if (!tmp_node) {
		ERR(handle, "out of memory, could not create " "node record");
		return STATUS_ERR;
	}

	tmp_node->addr = NULL;
	tmp_node->addr_sz = 0;
	tmp_node->mask = NULL;
	tmp_node->mask_sz = 0;
	tmp_node->proto = SEPOL_PROTO_IP4;
	tmp_node->con = NULL;
	*node = tmp_node;

	return STATUS_SUCCESS;
}

hidden_def(sepol_node_create)

/* Deep copy clone */
int sepol_node_clone(sepol_handle_t * handle,
		     const sepol_node_t * node, sepol_node_t ** node_ptr)
{

	sepol_node_t *new_node = NULL;
	if (sepol_node_create(handle, &new_node) < 0)
		goto err;

	/* Copy address, mask, protocol */
	new_node->addr = malloc(node->addr_sz);
	new_node->mask = malloc(node->mask_sz);
	if (!new_node->addr || !new_node->mask)
		goto omem;

	memcpy(new_node->addr, node->addr, node->addr_sz);
	memcpy(new_node->mask, node->mask, node->mask_sz);
	new_node->addr_sz = node->addr_sz;
	new_node->mask_sz = node->mask_sz;
	new_node->proto = node->proto;

	/* Copy context */
	if (node->con &&
	    (sepol_context_clone(handle, node->con, &new_node->con) < 0))
		goto err;

	*node_ptr = new_node;
	return STATUS_SUCCESS;

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

      err:
	ERR(handle, "could not clone node record");
	sepol_node_free(new_node);
	return STATUS_ERR;
}

/* Destroy */
void sepol_node_free(sepol_node_t * node)
{

	if (!node)
		return;

	sepol_context_free(node->con);
	free(node->addr);
	free(node->mask);
	free(node);
}

hidden_def(sepol_node_free)

/* Context */
sepol_context_t *sepol_node_get_con(const sepol_node_t * node)
{

	return node->con;
}

hidden_def(sepol_node_get_con)

int sepol_node_set_con(sepol_handle_t * handle,
		       sepol_node_t * node, sepol_context_t * con)
{

	sepol_context_t *newcon;

	if (sepol_context_clone(handle, con, &newcon) < 0) {
		ERR(handle, "out of memory, could not set node context");
		return STATUS_ERR;
	}

	sepol_context_free(node->con);
	node->con = newcon;
	return STATUS_SUCCESS;
}

hidden_def(sepol_node_set_con)
