16cd6a6acSopenharmony_ci#include <stdlib.h>
26cd6a6acSopenharmony_ci#include <stddef.h>
36cd6a6acSopenharmony_ci#include <string.h>
46cd6a6acSopenharmony_ci#include <netinet/in.h>
56cd6a6acSopenharmony_ci#include <arpa/inet.h>
66cd6a6acSopenharmony_ci#include <errno.h>
76cd6a6acSopenharmony_ci
86cd6a6acSopenharmony_ci#include "node_internal.h"
96cd6a6acSopenharmony_ci#include "context_internal.h"
106cd6a6acSopenharmony_ci#include "debug.h"
116cd6a6acSopenharmony_ci
126cd6a6acSopenharmony_cistruct sepol_node {
136cd6a6acSopenharmony_ci
146cd6a6acSopenharmony_ci	/* Network address and mask */
156cd6a6acSopenharmony_ci	char *addr;
166cd6a6acSopenharmony_ci	size_t addr_sz;
176cd6a6acSopenharmony_ci
186cd6a6acSopenharmony_ci	char *mask;
196cd6a6acSopenharmony_ci	size_t mask_sz;
206cd6a6acSopenharmony_ci
216cd6a6acSopenharmony_ci	/* Protocol */
226cd6a6acSopenharmony_ci	int proto;
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_ci	/* Context */
256cd6a6acSopenharmony_ci	sepol_context_t *con;
266cd6a6acSopenharmony_ci};
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_cistruct sepol_node_key {
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci	/* Network address and mask */
316cd6a6acSopenharmony_ci	char *addr;
326cd6a6acSopenharmony_ci	size_t addr_sz;
336cd6a6acSopenharmony_ci
346cd6a6acSopenharmony_ci	char *mask;
356cd6a6acSopenharmony_ci	size_t mask_sz;
366cd6a6acSopenharmony_ci
376cd6a6acSopenharmony_ci	/* Protocol */
386cd6a6acSopenharmony_ci	int proto;
396cd6a6acSopenharmony_ci};
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_ci/* Converts a string represtation (addr_str)
426cd6a6acSopenharmony_ci * to a numeric representation (addr_bytes) */
436cd6a6acSopenharmony_ci
446cd6a6acSopenharmony_cistatic int node_parse_addr(sepol_handle_t * handle,
456cd6a6acSopenharmony_ci			   const char *addr_str, int proto, char *addr_bytes)
466cd6a6acSopenharmony_ci{
476cd6a6acSopenharmony_ci
486cd6a6acSopenharmony_ci	switch (proto) {
496cd6a6acSopenharmony_ci
506cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP4:
516cd6a6acSopenharmony_ci		{
526cd6a6acSopenharmony_ci			struct in_addr in_addr;
536cd6a6acSopenharmony_ci
546cd6a6acSopenharmony_ci			if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
556cd6a6acSopenharmony_ci				ERR(handle, "could not parse IPv4 address "
566cd6a6acSopenharmony_ci				    "%s: %m", addr_str);
576cd6a6acSopenharmony_ci				return STATUS_ERR;
586cd6a6acSopenharmony_ci			}
596cd6a6acSopenharmony_ci
606cd6a6acSopenharmony_ci			memcpy(addr_bytes, &in_addr.s_addr, 4);
616cd6a6acSopenharmony_ci			break;
626cd6a6acSopenharmony_ci		}
636cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP6:
646cd6a6acSopenharmony_ci		{
656cd6a6acSopenharmony_ci			struct in6_addr in_addr;
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_ci			if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
686cd6a6acSopenharmony_ci				ERR(handle, "could not parse IPv6 address "
696cd6a6acSopenharmony_ci				    "%s: %m", addr_str);
706cd6a6acSopenharmony_ci				return STATUS_ERR;
716cd6a6acSopenharmony_ci			}
726cd6a6acSopenharmony_ci
736cd6a6acSopenharmony_ci			memcpy(addr_bytes, in_addr.s6_addr, 16);
746cd6a6acSopenharmony_ci			break;
756cd6a6acSopenharmony_ci		}
766cd6a6acSopenharmony_ci	default:
776cd6a6acSopenharmony_ci		ERR(handle, "unsupported protocol %u, could not "
786cd6a6acSopenharmony_ci		    "parse address", proto);
796cd6a6acSopenharmony_ci		return STATUS_ERR;
806cd6a6acSopenharmony_ci	}
816cd6a6acSopenharmony_ci
826cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
836cd6a6acSopenharmony_ci}
846cd6a6acSopenharmony_ci
856cd6a6acSopenharmony_ci/* Allocates a sufficiently large buffer (addr, addr_sz)
866cd6a6acSopenharmony_ci * according to the protocol */
876cd6a6acSopenharmony_ci
886cd6a6acSopenharmony_cistatic int node_alloc_addr(sepol_handle_t * handle,
896cd6a6acSopenharmony_ci			   int proto, char **addr, size_t * addr_sz)
906cd6a6acSopenharmony_ci{
916cd6a6acSopenharmony_ci
926cd6a6acSopenharmony_ci	char *tmp_addr = NULL;
936cd6a6acSopenharmony_ci	size_t tmp_addr_sz;
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_ci	switch (proto) {
966cd6a6acSopenharmony_ci
976cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP4:
986cd6a6acSopenharmony_ci		tmp_addr_sz = 4;
996cd6a6acSopenharmony_ci		tmp_addr = malloc(4);
1006cd6a6acSopenharmony_ci		if (!tmp_addr)
1016cd6a6acSopenharmony_ci			goto omem;
1026cd6a6acSopenharmony_ci		break;
1036cd6a6acSopenharmony_ci
1046cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP6:
1056cd6a6acSopenharmony_ci		tmp_addr_sz = 16;
1066cd6a6acSopenharmony_ci		tmp_addr = malloc(16);
1076cd6a6acSopenharmony_ci		if (!tmp_addr)
1086cd6a6acSopenharmony_ci			goto omem;
1096cd6a6acSopenharmony_ci		break;
1106cd6a6acSopenharmony_ci
1116cd6a6acSopenharmony_ci	default:
1126cd6a6acSopenharmony_ci		ERR(handle, "unsupported protocol %u", proto);
1136cd6a6acSopenharmony_ci		goto err;
1146cd6a6acSopenharmony_ci	}
1156cd6a6acSopenharmony_ci
1166cd6a6acSopenharmony_ci	*addr = tmp_addr;
1176cd6a6acSopenharmony_ci	*addr_sz = tmp_addr_sz;
1186cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1196cd6a6acSopenharmony_ci
1206cd6a6acSopenharmony_ci      omem:
1216cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
1226cd6a6acSopenharmony_ci
1236cd6a6acSopenharmony_ci      err:
1246cd6a6acSopenharmony_ci	free(tmp_addr);
1256cd6a6acSopenharmony_ci	ERR(handle, "could not allocate address of protocol %s",
1266cd6a6acSopenharmony_ci	    sepol_node_get_proto_str(proto));
1276cd6a6acSopenharmony_ci	return STATUS_ERR;
1286cd6a6acSopenharmony_ci}
1296cd6a6acSopenharmony_ci
1306cd6a6acSopenharmony_ci/* Converts a numeric representation (addr_bytes)
1316cd6a6acSopenharmony_ci * to a string representation (addr_str), according to
1326cd6a6acSopenharmony_ci * the protocol */
1336cd6a6acSopenharmony_ci
1346cd6a6acSopenharmony_cistatic int node_expand_addr(sepol_handle_t * handle,
1356cd6a6acSopenharmony_ci			    char *addr_bytes, int proto, char *addr_str)
1366cd6a6acSopenharmony_ci{
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_ci	switch (proto) {
1396cd6a6acSopenharmony_ci
1406cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP4:
1416cd6a6acSopenharmony_ci		{
1426cd6a6acSopenharmony_ci			struct in_addr addr;
1436cd6a6acSopenharmony_ci			memset(&addr, 0, sizeof(struct in_addr));
1446cd6a6acSopenharmony_ci			memcpy(&addr.s_addr, addr_bytes, 4);
1456cd6a6acSopenharmony_ci
1466cd6a6acSopenharmony_ci			if (inet_ntop(AF_INET, &addr, addr_str,
1476cd6a6acSopenharmony_ci				      INET_ADDRSTRLEN) == NULL) {
1486cd6a6acSopenharmony_ci
1496cd6a6acSopenharmony_ci				ERR(handle,
1506cd6a6acSopenharmony_ci				    "could not expand IPv4 address to string: %m");
1516cd6a6acSopenharmony_ci				return STATUS_ERR;
1526cd6a6acSopenharmony_ci			}
1536cd6a6acSopenharmony_ci			break;
1546cd6a6acSopenharmony_ci		}
1556cd6a6acSopenharmony_ci
1566cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP6:
1576cd6a6acSopenharmony_ci		{
1586cd6a6acSopenharmony_ci			struct in6_addr addr;
1596cd6a6acSopenharmony_ci			memset(&addr, 0, sizeof(struct in6_addr));
1606cd6a6acSopenharmony_ci			memcpy(&addr.s6_addr[0], addr_bytes, 16);
1616cd6a6acSopenharmony_ci			if (inet_ntop(AF_INET6, &addr, addr_str,
1626cd6a6acSopenharmony_ci				      INET6_ADDRSTRLEN) == NULL) {
1636cd6a6acSopenharmony_ci
1646cd6a6acSopenharmony_ci				ERR(handle,
1656cd6a6acSopenharmony_ci				    "could not expand IPv6 address to string: %m");
1666cd6a6acSopenharmony_ci				return STATUS_ERR;
1676cd6a6acSopenharmony_ci			}
1686cd6a6acSopenharmony_ci			break;
1696cd6a6acSopenharmony_ci		}
1706cd6a6acSopenharmony_ci
1716cd6a6acSopenharmony_ci	default:
1726cd6a6acSopenharmony_ci		ERR(handle, "unsupported protocol %u, could not"
1736cd6a6acSopenharmony_ci		    " expand address to string", proto);
1746cd6a6acSopenharmony_ci		return STATUS_ERR;
1756cd6a6acSopenharmony_ci	}
1766cd6a6acSopenharmony_ci
1776cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1786cd6a6acSopenharmony_ci}
1796cd6a6acSopenharmony_ci
1806cd6a6acSopenharmony_ci/* Allocates a sufficiently large address string (addr)
1816cd6a6acSopenharmony_ci * according to the protocol */
1826cd6a6acSopenharmony_ci
1836cd6a6acSopenharmony_cistatic int node_alloc_addr_string(sepol_handle_t * handle,
1846cd6a6acSopenharmony_ci				  int proto, char **addr)
1856cd6a6acSopenharmony_ci{
1866cd6a6acSopenharmony_ci
1876cd6a6acSopenharmony_ci	char *tmp_addr = NULL;
1886cd6a6acSopenharmony_ci
1896cd6a6acSopenharmony_ci	switch (proto) {
1906cd6a6acSopenharmony_ci
1916cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP4:
1926cd6a6acSopenharmony_ci		tmp_addr = malloc(INET_ADDRSTRLEN);
1936cd6a6acSopenharmony_ci		if (!tmp_addr)
1946cd6a6acSopenharmony_ci			goto omem;
1956cd6a6acSopenharmony_ci		break;
1966cd6a6acSopenharmony_ci
1976cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP6:
1986cd6a6acSopenharmony_ci		tmp_addr = malloc(INET6_ADDRSTRLEN);
1996cd6a6acSopenharmony_ci		if (!tmp_addr)
2006cd6a6acSopenharmony_ci			goto omem;
2016cd6a6acSopenharmony_ci		break;
2026cd6a6acSopenharmony_ci
2036cd6a6acSopenharmony_ci	default:
2046cd6a6acSopenharmony_ci		ERR(handle, "unsupported protocol %u", proto);
2056cd6a6acSopenharmony_ci		goto err;
2066cd6a6acSopenharmony_ci	}
2076cd6a6acSopenharmony_ci
2086cd6a6acSopenharmony_ci	*addr = tmp_addr;
2096cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2106cd6a6acSopenharmony_ci
2116cd6a6acSopenharmony_ci      omem:
2126cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
2136cd6a6acSopenharmony_ci
2146cd6a6acSopenharmony_ci      err:
2156cd6a6acSopenharmony_ci	free(tmp_addr);
2166cd6a6acSopenharmony_ci	ERR(handle, "could not allocate string buffer for "
2176cd6a6acSopenharmony_ci	    "address of protocol %s", sepol_node_get_proto_str(proto));
2186cd6a6acSopenharmony_ci	return STATUS_ERR;
2196cd6a6acSopenharmony_ci}
2206cd6a6acSopenharmony_ci
2216cd6a6acSopenharmony_ci/* Key */
2226cd6a6acSopenharmony_ciint sepol_node_key_create(sepol_handle_t * handle,
2236cd6a6acSopenharmony_ci			  const char *addr,
2246cd6a6acSopenharmony_ci			  const char *mask,
2256cd6a6acSopenharmony_ci			  int proto, sepol_node_key_t ** key_ptr)
2266cd6a6acSopenharmony_ci{
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_ci	sepol_node_key_t *tmp_key =
2296cd6a6acSopenharmony_ci	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
2306cd6a6acSopenharmony_ci	if (!tmp_key)
2316cd6a6acSopenharmony_ci		goto omem;
2326cd6a6acSopenharmony_ci
2336cd6a6acSopenharmony_ci	if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) <
2346cd6a6acSopenharmony_ci	    0)
2356cd6a6acSopenharmony_ci		goto err;
2366cd6a6acSopenharmony_ci	if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0)
2376cd6a6acSopenharmony_ci		goto err;
2386cd6a6acSopenharmony_ci
2396cd6a6acSopenharmony_ci	if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) <
2406cd6a6acSopenharmony_ci	    0)
2416cd6a6acSopenharmony_ci		goto err;
2426cd6a6acSopenharmony_ci	if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0)
2436cd6a6acSopenharmony_ci		goto err;
2446cd6a6acSopenharmony_ci
2456cd6a6acSopenharmony_ci	tmp_key->proto = proto;
2466cd6a6acSopenharmony_ci
2476cd6a6acSopenharmony_ci	*key_ptr = tmp_key;
2486cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2496cd6a6acSopenharmony_ci
2506cd6a6acSopenharmony_ci      omem:
2516cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
2526cd6a6acSopenharmony_ci
2536cd6a6acSopenharmony_ci      err:
2546cd6a6acSopenharmony_ci	sepol_node_key_free(tmp_key);
2556cd6a6acSopenharmony_ci	ERR(handle, "could not create node key for (%s, %s, %s)",
2566cd6a6acSopenharmony_ci	    addr, mask, sepol_node_get_proto_str(proto));
2576cd6a6acSopenharmony_ci	return STATUS_ERR;
2586cd6a6acSopenharmony_ci}
2596cd6a6acSopenharmony_ci
2606cd6a6acSopenharmony_ci
2616cd6a6acSopenharmony_civoid sepol_node_key_unpack(const sepol_node_key_t * key,
2626cd6a6acSopenharmony_ci			   const char **addr, const char **mask, int *proto)
2636cd6a6acSopenharmony_ci{
2646cd6a6acSopenharmony_ci
2656cd6a6acSopenharmony_ci	*addr = key->addr;
2666cd6a6acSopenharmony_ci	*mask = key->mask;
2676cd6a6acSopenharmony_ci	*proto = key->proto;
2686cd6a6acSopenharmony_ci}
2696cd6a6acSopenharmony_ci
2706cd6a6acSopenharmony_ci
2716cd6a6acSopenharmony_ciint sepol_node_key_extract(sepol_handle_t * handle,
2726cd6a6acSopenharmony_ci			   const sepol_node_t * node,
2736cd6a6acSopenharmony_ci			   sepol_node_key_t ** key_ptr)
2746cd6a6acSopenharmony_ci{
2756cd6a6acSopenharmony_ci
2766cd6a6acSopenharmony_ci	sepol_node_key_t *tmp_key =
2776cd6a6acSopenharmony_ci	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
2786cd6a6acSopenharmony_ci	if (!tmp_key)
2796cd6a6acSopenharmony_ci		goto omem;
2806cd6a6acSopenharmony_ci
2816cd6a6acSopenharmony_ci	tmp_key->addr = malloc(node->addr_sz);
2826cd6a6acSopenharmony_ci	tmp_key->mask = malloc(node->mask_sz);
2836cd6a6acSopenharmony_ci
2846cd6a6acSopenharmony_ci	if (!tmp_key->addr || !tmp_key->mask)
2856cd6a6acSopenharmony_ci		goto omem;
2866cd6a6acSopenharmony_ci
2876cd6a6acSopenharmony_ci	memcpy(tmp_key->addr, node->addr, node->addr_sz);
2886cd6a6acSopenharmony_ci	memcpy(tmp_key->mask, node->mask, node->mask_sz);
2896cd6a6acSopenharmony_ci	tmp_key->addr_sz = node->addr_sz;
2906cd6a6acSopenharmony_ci	tmp_key->mask_sz = node->mask_sz;
2916cd6a6acSopenharmony_ci	tmp_key->proto = node->proto;
2926cd6a6acSopenharmony_ci
2936cd6a6acSopenharmony_ci	*key_ptr = tmp_key;
2946cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2956cd6a6acSopenharmony_ci
2966cd6a6acSopenharmony_ci      omem:
2976cd6a6acSopenharmony_ci	sepol_node_key_free(tmp_key);
2986cd6a6acSopenharmony_ci	ERR(handle, "out of memory, could not extract node key");
2996cd6a6acSopenharmony_ci	return STATUS_ERR;
3006cd6a6acSopenharmony_ci}
3016cd6a6acSopenharmony_ci
3026cd6a6acSopenharmony_civoid sepol_node_key_free(sepol_node_key_t * key)
3036cd6a6acSopenharmony_ci{
3046cd6a6acSopenharmony_ci
3056cd6a6acSopenharmony_ci	if (!key)
3066cd6a6acSopenharmony_ci		return;
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_ci	free(key->addr);
3096cd6a6acSopenharmony_ci	free(key->mask);
3106cd6a6acSopenharmony_ci	free(key);
3116cd6a6acSopenharmony_ci}
3126cd6a6acSopenharmony_ci
3136cd6a6acSopenharmony_ci
3146cd6a6acSopenharmony_ciint sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key)
3156cd6a6acSopenharmony_ci{
3166cd6a6acSopenharmony_ci
3176cd6a6acSopenharmony_ci	int rc1, rc2;
3186cd6a6acSopenharmony_ci
3196cd6a6acSopenharmony_ci	if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz))
3206cd6a6acSopenharmony_ci		return -1;
3216cd6a6acSopenharmony_ci
3226cd6a6acSopenharmony_ci	else if ((node->addr_sz > key->addr_sz) ||
3236cd6a6acSopenharmony_ci		 (node->mask_sz > key->mask_sz))
3246cd6a6acSopenharmony_ci		return 1;
3256cd6a6acSopenharmony_ci
3266cd6a6acSopenharmony_ci	rc1 = memcmp(node->addr, key->addr, node->addr_sz);
3276cd6a6acSopenharmony_ci	rc2 = memcmp(node->mask, key->mask, node->mask_sz);
3286cd6a6acSopenharmony_ci
3296cd6a6acSopenharmony_ci	return (rc2 != 0) ? rc2 : rc1;
3306cd6a6acSopenharmony_ci}
3316cd6a6acSopenharmony_ci
3326cd6a6acSopenharmony_ciint sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2)
3336cd6a6acSopenharmony_ci{
3346cd6a6acSopenharmony_ci
3356cd6a6acSopenharmony_ci	int rc1, rc2;
3366cd6a6acSopenharmony_ci
3376cd6a6acSopenharmony_ci	if ((node->addr_sz < node2->addr_sz) ||
3386cd6a6acSopenharmony_ci	    (node->mask_sz < node2->mask_sz))
3396cd6a6acSopenharmony_ci		return -1;
3406cd6a6acSopenharmony_ci
3416cd6a6acSopenharmony_ci	else if ((node->addr_sz > node2->addr_sz) ||
3426cd6a6acSopenharmony_ci		 (node->mask_sz > node2->mask_sz))
3436cd6a6acSopenharmony_ci		return 1;
3446cd6a6acSopenharmony_ci
3456cd6a6acSopenharmony_ci	rc1 = memcmp(node->addr, node2->addr, node->addr_sz);
3466cd6a6acSopenharmony_ci	rc2 = memcmp(node->mask, node2->mask, node->mask_sz);
3476cd6a6acSopenharmony_ci
3486cd6a6acSopenharmony_ci	return (rc2 != 0) ? rc2 : rc1;
3496cd6a6acSopenharmony_ci}
3506cd6a6acSopenharmony_ci
3516cd6a6acSopenharmony_ci/* Addr */
3526cd6a6acSopenharmony_ciint sepol_node_get_addr(sepol_handle_t * handle,
3536cd6a6acSopenharmony_ci			const sepol_node_t * node, char **addr)
3546cd6a6acSopenharmony_ci{
3556cd6a6acSopenharmony_ci
3566cd6a6acSopenharmony_ci	char *tmp_addr = NULL;
3576cd6a6acSopenharmony_ci
3586cd6a6acSopenharmony_ci	if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0)
3596cd6a6acSopenharmony_ci		goto err;
3606cd6a6acSopenharmony_ci
3616cd6a6acSopenharmony_ci	if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0)
3626cd6a6acSopenharmony_ci		goto err;
3636cd6a6acSopenharmony_ci
3646cd6a6acSopenharmony_ci	*addr = tmp_addr;
3656cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3666cd6a6acSopenharmony_ci
3676cd6a6acSopenharmony_ci      err:
3686cd6a6acSopenharmony_ci	free(tmp_addr);
3696cd6a6acSopenharmony_ci	ERR(handle, "could not get node address");
3706cd6a6acSopenharmony_ci	return STATUS_ERR;
3716cd6a6acSopenharmony_ci}
3726cd6a6acSopenharmony_ci
3736cd6a6acSopenharmony_ci
3746cd6a6acSopenharmony_ciint sepol_node_get_addr_bytes(sepol_handle_t * handle,
3756cd6a6acSopenharmony_ci			      const sepol_node_t * node,
3766cd6a6acSopenharmony_ci			      char **buffer, size_t * bsize)
3776cd6a6acSopenharmony_ci{
3786cd6a6acSopenharmony_ci
3796cd6a6acSopenharmony_ci	char *tmp_buf = malloc(node->addr_sz);
3806cd6a6acSopenharmony_ci	if (!tmp_buf) {
3816cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not get address bytes");
3826cd6a6acSopenharmony_ci		return STATUS_ERR;
3836cd6a6acSopenharmony_ci	}
3846cd6a6acSopenharmony_ci
3856cd6a6acSopenharmony_ci	memcpy(tmp_buf, node->addr, node->addr_sz);
3866cd6a6acSopenharmony_ci	*buffer = tmp_buf;
3876cd6a6acSopenharmony_ci	*bsize = node->addr_sz;
3886cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3896cd6a6acSopenharmony_ci}
3906cd6a6acSopenharmony_ci
3916cd6a6acSopenharmony_ci
3926cd6a6acSopenharmony_ciint sepol_node_set_addr(sepol_handle_t * handle,
3936cd6a6acSopenharmony_ci			sepol_node_t * node, int proto, const char *addr)
3946cd6a6acSopenharmony_ci{
3956cd6a6acSopenharmony_ci
3966cd6a6acSopenharmony_ci	char *tmp_addr = NULL;
3976cd6a6acSopenharmony_ci	size_t tmp_addr_sz;
3986cd6a6acSopenharmony_ci
3996cd6a6acSopenharmony_ci	if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0)
4006cd6a6acSopenharmony_ci		goto err;
4016cd6a6acSopenharmony_ci
4026cd6a6acSopenharmony_ci	if (node_parse_addr(handle, addr, proto, tmp_addr) < 0)
4036cd6a6acSopenharmony_ci		goto err;
4046cd6a6acSopenharmony_ci
4056cd6a6acSopenharmony_ci	free(node->addr);
4066cd6a6acSopenharmony_ci	node->addr = tmp_addr;
4076cd6a6acSopenharmony_ci	node->addr_sz = tmp_addr_sz;
4086cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
4096cd6a6acSopenharmony_ci
4106cd6a6acSopenharmony_ci      err:
4116cd6a6acSopenharmony_ci	free(tmp_addr);
4126cd6a6acSopenharmony_ci	ERR(handle, "could not set node address to %s", addr);
4136cd6a6acSopenharmony_ci	return STATUS_ERR;
4146cd6a6acSopenharmony_ci}
4156cd6a6acSopenharmony_ci
4166cd6a6acSopenharmony_ci
4176cd6a6acSopenharmony_ciint sepol_node_set_addr_bytes(sepol_handle_t * handle,
4186cd6a6acSopenharmony_ci			      sepol_node_t * node,
4196cd6a6acSopenharmony_ci			      const char *addr, size_t addr_sz)
4206cd6a6acSopenharmony_ci{
4216cd6a6acSopenharmony_ci
4226cd6a6acSopenharmony_ci	char *tmp_addr = malloc(addr_sz);
4236cd6a6acSopenharmony_ci	if (!tmp_addr) {
4246cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not " "set node address");
4256cd6a6acSopenharmony_ci		return STATUS_ERR;
4266cd6a6acSopenharmony_ci	}
4276cd6a6acSopenharmony_ci
4286cd6a6acSopenharmony_ci	memcpy(tmp_addr, addr, addr_sz);
4296cd6a6acSopenharmony_ci	free(node->addr);
4306cd6a6acSopenharmony_ci	node->addr = tmp_addr;
4316cd6a6acSopenharmony_ci	node->addr_sz = addr_sz;
4326cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
4336cd6a6acSopenharmony_ci}
4346cd6a6acSopenharmony_ci
4356cd6a6acSopenharmony_ci
4366cd6a6acSopenharmony_ci/* Mask */
4376cd6a6acSopenharmony_ciint sepol_node_get_mask(sepol_handle_t * handle,
4386cd6a6acSopenharmony_ci			const sepol_node_t * node, char **mask)
4396cd6a6acSopenharmony_ci{
4406cd6a6acSopenharmony_ci
4416cd6a6acSopenharmony_ci	char *tmp_mask = NULL;
4426cd6a6acSopenharmony_ci
4436cd6a6acSopenharmony_ci	if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0)
4446cd6a6acSopenharmony_ci		goto err;
4456cd6a6acSopenharmony_ci
4466cd6a6acSopenharmony_ci	if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0)
4476cd6a6acSopenharmony_ci		goto err;
4486cd6a6acSopenharmony_ci
4496cd6a6acSopenharmony_ci	*mask = tmp_mask;
4506cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
4516cd6a6acSopenharmony_ci
4526cd6a6acSopenharmony_ci      err:
4536cd6a6acSopenharmony_ci	free(tmp_mask);
4546cd6a6acSopenharmony_ci	ERR(handle, "could not get node netmask");
4556cd6a6acSopenharmony_ci	return STATUS_ERR;
4566cd6a6acSopenharmony_ci}
4576cd6a6acSopenharmony_ci
4586cd6a6acSopenharmony_ci
4596cd6a6acSopenharmony_ciint sepol_node_get_mask_bytes(sepol_handle_t * handle,
4606cd6a6acSopenharmony_ci			      const sepol_node_t * node,
4616cd6a6acSopenharmony_ci			      char **buffer, size_t * bsize)
4626cd6a6acSopenharmony_ci{
4636cd6a6acSopenharmony_ci
4646cd6a6acSopenharmony_ci	char *tmp_buf = malloc(node->mask_sz);
4656cd6a6acSopenharmony_ci	if (!tmp_buf) {
4666cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not get netmask bytes");
4676cd6a6acSopenharmony_ci		return STATUS_ERR;
4686cd6a6acSopenharmony_ci	}
4696cd6a6acSopenharmony_ci
4706cd6a6acSopenharmony_ci	memcpy(tmp_buf, node->mask, node->mask_sz);
4716cd6a6acSopenharmony_ci	*buffer = tmp_buf;
4726cd6a6acSopenharmony_ci	*bsize = node->mask_sz;
4736cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
4746cd6a6acSopenharmony_ci}
4756cd6a6acSopenharmony_ci
4766cd6a6acSopenharmony_ci
4776cd6a6acSopenharmony_ciint sepol_node_set_mask(sepol_handle_t * handle,
4786cd6a6acSopenharmony_ci			sepol_node_t * node, int proto, const char *mask)
4796cd6a6acSopenharmony_ci{
4806cd6a6acSopenharmony_ci
4816cd6a6acSopenharmony_ci	char *tmp_mask = NULL;
4826cd6a6acSopenharmony_ci	size_t tmp_mask_sz;
4836cd6a6acSopenharmony_ci
4846cd6a6acSopenharmony_ci	if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0)
4856cd6a6acSopenharmony_ci		goto err;
4866cd6a6acSopenharmony_ci
4876cd6a6acSopenharmony_ci	if (node_parse_addr(handle, mask, proto, tmp_mask) < 0)
4886cd6a6acSopenharmony_ci		goto err;
4896cd6a6acSopenharmony_ci
4906cd6a6acSopenharmony_ci	free(node->mask);
4916cd6a6acSopenharmony_ci	node->mask = tmp_mask;
4926cd6a6acSopenharmony_ci	node->mask_sz = tmp_mask_sz;
4936cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
4946cd6a6acSopenharmony_ci
4956cd6a6acSopenharmony_ci      err:
4966cd6a6acSopenharmony_ci	free(tmp_mask);
4976cd6a6acSopenharmony_ci	ERR(handle, "could not set node netmask to %s", mask);
4986cd6a6acSopenharmony_ci	return STATUS_ERR;
4996cd6a6acSopenharmony_ci}
5006cd6a6acSopenharmony_ci
5016cd6a6acSopenharmony_ci
5026cd6a6acSopenharmony_ciint sepol_node_set_mask_bytes(sepol_handle_t * handle,
5036cd6a6acSopenharmony_ci			      sepol_node_t * node,
5046cd6a6acSopenharmony_ci			      const char *mask, size_t mask_sz)
5056cd6a6acSopenharmony_ci{
5066cd6a6acSopenharmony_ci
5076cd6a6acSopenharmony_ci	char *tmp_mask = malloc(mask_sz);
5086cd6a6acSopenharmony_ci	if (!tmp_mask) {
5096cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not " "set node netmask");
5106cd6a6acSopenharmony_ci		return STATUS_ERR;
5116cd6a6acSopenharmony_ci	}
5126cd6a6acSopenharmony_ci	memcpy(tmp_mask, mask, mask_sz);
5136cd6a6acSopenharmony_ci	free(node->mask);
5146cd6a6acSopenharmony_ci	node->mask = tmp_mask;
5156cd6a6acSopenharmony_ci	node->mask_sz = mask_sz;
5166cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
5176cd6a6acSopenharmony_ci}
5186cd6a6acSopenharmony_ci
5196cd6a6acSopenharmony_ci
5206cd6a6acSopenharmony_ci/* Protocol */
5216cd6a6acSopenharmony_ciint sepol_node_get_proto(const sepol_node_t * node)
5226cd6a6acSopenharmony_ci{
5236cd6a6acSopenharmony_ci
5246cd6a6acSopenharmony_ci	return node->proto;
5256cd6a6acSopenharmony_ci}
5266cd6a6acSopenharmony_ci
5276cd6a6acSopenharmony_ci
5286cd6a6acSopenharmony_civoid sepol_node_set_proto(sepol_node_t * node, int proto)
5296cd6a6acSopenharmony_ci{
5306cd6a6acSopenharmony_ci
5316cd6a6acSopenharmony_ci	node->proto = proto;
5326cd6a6acSopenharmony_ci}
5336cd6a6acSopenharmony_ci
5346cd6a6acSopenharmony_ci
5356cd6a6acSopenharmony_ciconst char *sepol_node_get_proto_str(int proto)
5366cd6a6acSopenharmony_ci{
5376cd6a6acSopenharmony_ci
5386cd6a6acSopenharmony_ci	switch (proto) {
5396cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP4:
5406cd6a6acSopenharmony_ci		return "ipv4";
5416cd6a6acSopenharmony_ci	case SEPOL_PROTO_IP6:
5426cd6a6acSopenharmony_ci		return "ipv6";
5436cd6a6acSopenharmony_ci	default:
5446cd6a6acSopenharmony_ci		return "???";
5456cd6a6acSopenharmony_ci	}
5466cd6a6acSopenharmony_ci}
5476cd6a6acSopenharmony_ci
5486cd6a6acSopenharmony_ci
5496cd6a6acSopenharmony_ci/* Create */
5506cd6a6acSopenharmony_ciint sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
5516cd6a6acSopenharmony_ci{
5526cd6a6acSopenharmony_ci
5536cd6a6acSopenharmony_ci	sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t));
5546cd6a6acSopenharmony_ci
5556cd6a6acSopenharmony_ci	if (!tmp_node) {
5566cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not create " "node record");
5576cd6a6acSopenharmony_ci		return STATUS_ERR;
5586cd6a6acSopenharmony_ci	}
5596cd6a6acSopenharmony_ci
5606cd6a6acSopenharmony_ci	tmp_node->addr = NULL;
5616cd6a6acSopenharmony_ci	tmp_node->addr_sz = 0;
5626cd6a6acSopenharmony_ci	tmp_node->mask = NULL;
5636cd6a6acSopenharmony_ci	tmp_node->mask_sz = 0;
5646cd6a6acSopenharmony_ci	tmp_node->proto = SEPOL_PROTO_IP4;
5656cd6a6acSopenharmony_ci	tmp_node->con = NULL;
5666cd6a6acSopenharmony_ci	*node = tmp_node;
5676cd6a6acSopenharmony_ci
5686cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
5696cd6a6acSopenharmony_ci}
5706cd6a6acSopenharmony_ci
5716cd6a6acSopenharmony_ci
5726cd6a6acSopenharmony_ci/* Deep copy clone */
5736cd6a6acSopenharmony_ciint sepol_node_clone(sepol_handle_t * handle,
5746cd6a6acSopenharmony_ci		     const sepol_node_t * node, sepol_node_t ** node_ptr)
5756cd6a6acSopenharmony_ci{
5766cd6a6acSopenharmony_ci
5776cd6a6acSopenharmony_ci	sepol_node_t *new_node = NULL;
5786cd6a6acSopenharmony_ci	if (sepol_node_create(handle, &new_node) < 0)
5796cd6a6acSopenharmony_ci		goto err;
5806cd6a6acSopenharmony_ci
5816cd6a6acSopenharmony_ci	/* Copy address, mask, protocol */
5826cd6a6acSopenharmony_ci	new_node->addr = malloc(node->addr_sz);
5836cd6a6acSopenharmony_ci	new_node->mask = malloc(node->mask_sz);
5846cd6a6acSopenharmony_ci	if (!new_node->addr || !new_node->mask)
5856cd6a6acSopenharmony_ci		goto omem;
5866cd6a6acSopenharmony_ci
5876cd6a6acSopenharmony_ci	memcpy(new_node->addr, node->addr, node->addr_sz);
5886cd6a6acSopenharmony_ci	memcpy(new_node->mask, node->mask, node->mask_sz);
5896cd6a6acSopenharmony_ci	new_node->addr_sz = node->addr_sz;
5906cd6a6acSopenharmony_ci	new_node->mask_sz = node->mask_sz;
5916cd6a6acSopenharmony_ci	new_node->proto = node->proto;
5926cd6a6acSopenharmony_ci
5936cd6a6acSopenharmony_ci	/* Copy context */
5946cd6a6acSopenharmony_ci	if (node->con &&
5956cd6a6acSopenharmony_ci	    (sepol_context_clone(handle, node->con, &new_node->con) < 0))
5966cd6a6acSopenharmony_ci		goto err;
5976cd6a6acSopenharmony_ci
5986cd6a6acSopenharmony_ci	*node_ptr = new_node;
5996cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
6006cd6a6acSopenharmony_ci
6016cd6a6acSopenharmony_ci      omem:
6026cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
6036cd6a6acSopenharmony_ci
6046cd6a6acSopenharmony_ci      err:
6056cd6a6acSopenharmony_ci	ERR(handle, "could not clone node record");
6066cd6a6acSopenharmony_ci	sepol_node_free(new_node);
6076cd6a6acSopenharmony_ci	return STATUS_ERR;
6086cd6a6acSopenharmony_ci}
6096cd6a6acSopenharmony_ci
6106cd6a6acSopenharmony_ci/* Destroy */
6116cd6a6acSopenharmony_civoid sepol_node_free(sepol_node_t * node)
6126cd6a6acSopenharmony_ci{
6136cd6a6acSopenharmony_ci
6146cd6a6acSopenharmony_ci	if (!node)
6156cd6a6acSopenharmony_ci		return;
6166cd6a6acSopenharmony_ci
6176cd6a6acSopenharmony_ci	sepol_context_free(node->con);
6186cd6a6acSopenharmony_ci	free(node->addr);
6196cd6a6acSopenharmony_ci	free(node->mask);
6206cd6a6acSopenharmony_ci	free(node);
6216cd6a6acSopenharmony_ci}
6226cd6a6acSopenharmony_ci
6236cd6a6acSopenharmony_ci
6246cd6a6acSopenharmony_ci/* Context */
6256cd6a6acSopenharmony_cisepol_context_t *sepol_node_get_con(const sepol_node_t * node)
6266cd6a6acSopenharmony_ci{
6276cd6a6acSopenharmony_ci
6286cd6a6acSopenharmony_ci	return node->con;
6296cd6a6acSopenharmony_ci}
6306cd6a6acSopenharmony_ci
6316cd6a6acSopenharmony_ci
6326cd6a6acSopenharmony_ciint sepol_node_set_con(sepol_handle_t * handle,
6336cd6a6acSopenharmony_ci		       sepol_node_t * node, sepol_context_t * con)
6346cd6a6acSopenharmony_ci{
6356cd6a6acSopenharmony_ci
6366cd6a6acSopenharmony_ci	sepol_context_t *newcon;
6376cd6a6acSopenharmony_ci
6386cd6a6acSopenharmony_ci	if (sepol_context_clone(handle, con, &newcon) < 0) {
6396cd6a6acSopenharmony_ci		ERR(handle, "out of memory, could not set node context");
6406cd6a6acSopenharmony_ci		return STATUS_ERR;
6416cd6a6acSopenharmony_ci	}
6426cd6a6acSopenharmony_ci
6436cd6a6acSopenharmony_ci	sepol_context_free(node->con);
6446cd6a6acSopenharmony_ci	node->con = newcon;
6456cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
6466cd6a6acSopenharmony_ci}
6476cd6a6acSopenharmony_ci
648