node_record.c revision b1db49d77789525ac1f4e73e978e35694f21ea1a
1e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <stdlib.h>
2e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <stddef.h>
3e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <string.h>
4e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <netinet/in.h>
5e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <arpa/inet.h>
6e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include <errno.h>
7e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
8e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "node_internal.h"
9e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "context_internal.h"
10e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#include "debug.h"
11e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
12e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct sepol_node {
13e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
14e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	/* Network address and mask */
15e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *addr;
16e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	size_t addr_sz;
17e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
18e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *mask;
19e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	size_t mask_sz;
20e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
21e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	/* Protocol */
22e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int proto;
23e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
24e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	/* Context */
25e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	sepol_context_t *con;
26e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
27e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
28e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstruct sepol_node_key {
29e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
30e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	/* Network address and mask */
31e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *addr;
32e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	size_t addr_sz;
33e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
34e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *mask;
35e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	size_t mask_sz;
36e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
37e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	/* Protocol */
38e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int proto;
39e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project};
40e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
41e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Converts a string represtation (addr_str)
42e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * to a numeric representation (addr_bytes) */
43e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
44e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int node_parse_addr(sepol_handle_t * handle,
45e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			   const char *addr_str, int proto, char *addr_bytes)
46e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
47e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
48e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (proto) {
49e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
50e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP4:
51e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
52e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			struct in_addr in_addr;
53e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
54e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
55e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				ERR(handle, "could not parse IPv4 address "
56e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    "%s: %s", addr_str, strerror(errno));
57e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				return STATUS_ERR;
58e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
59e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
60e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(addr_bytes, &in_addr.s_addr, 4);
61e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			break;
62e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
63e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP6:
64e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
65e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			struct in6_addr in_addr;
66e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
67e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
68e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				ERR(handle, "could not parse IPv6 address "
69e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    "%s: %s", addr_str, strerror(errno));
70e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				return STATUS_ERR;
71e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
72e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
73e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#ifdef DARWIN
74e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(addr_bytes, in_addr.s6_addr, 16);
75e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#else
76e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(addr_bytes, in_addr.s6_addr32, 16);
77e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#endif
78e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			break;
79e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
80e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	default:
81e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ERR(handle, "unsupported protocol %u, could not "
82e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		    "parse address", proto);
83e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return STATUS_ERR;
84e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
85e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
86e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
87e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
88e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
89e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Allocates a sufficiently large buffer (addr, addr_sz)
90e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * according the the protocol */
91e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
92e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int node_alloc_addr(sepol_handle_t * handle,
93e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			   int proto, char **addr, size_t * addr_sz)
94e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
95e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
96e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *tmp_addr = NULL;
97e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	size_t tmp_addr_sz;
98e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
99e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (proto) {
100e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
101e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP4:
102e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr_sz = 4;
103e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr = malloc(4);
104e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!tmp_addr)
105e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			goto omem;
106e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		break;
107e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
108e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP6:
109e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr_sz = 16;
110e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr = malloc(16);
111e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!tmp_addr)
112e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			goto omem;
113e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		break;
114e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
115e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	default:
116e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ERR(handle, "unsupported protocol %u", proto);
117e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
118e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
119e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
120e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*addr = tmp_addr;
121e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*addr_sz = tmp_addr_sz;
122e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
123e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
124e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      omem:
125e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "out of memory");
126e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
127e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      err:
128e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(tmp_addr);
129e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "could not allocate address of protocol %s",
130e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    sepol_node_get_proto_str(proto));
131e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_ERR;
132e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
133e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
134e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Converts a numeric representation (addr_bytes)
135e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * to a string representation (addr_str), according to
136e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * the protocol */
137e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
138e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int node_expand_addr(sepol_handle_t * handle,
139e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			    char *addr_bytes, int proto, char *addr_str)
140e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
141e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
142e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (proto) {
143e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
144e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP4:
145e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
146e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			struct in_addr addr;
147e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memset(&addr, 0, sizeof(struct in_addr));
148e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(&addr.s_addr, addr_bytes, 4);
149e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
150e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (inet_ntop(AF_INET, &addr, addr_str,
151e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				      INET_ADDRSTRLEN) == NULL) {
152e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
153e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				ERR(handle,
154e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    "could not expand IPv4 address to string: %s",
155e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    strerror(errno));
156e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				return STATUS_ERR;
157e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
158e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			break;
159e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
160e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
161e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP6:
162e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		{
163e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			struct in6_addr addr;
164e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memset(&addr, 0, sizeof(struct in6_addr));
165e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#ifdef DARWIN
166e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(&addr.s6_addr[0], addr_bytes, 16);
167e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#else
168e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			memcpy(&addr.s6_addr32[0], addr_bytes, 16);
169e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project#endif
170e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			if (inet_ntop(AF_INET6, &addr, addr_str,
171e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				      INET6_ADDRSTRLEN) == NULL) {
172e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
173e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				ERR(handle,
174e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    "could not expand IPv6 address to string: %s",
175e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				    strerror(errno));
176e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				return STATUS_ERR;
177e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			}
178e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			break;
179e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		}
180e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
181e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	default:
182e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ERR(handle, "unsupported protocol %u, could not"
183e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		    " expand address to string", proto);
184e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return STATUS_ERR;
185e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
186e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
187e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
188e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
189e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
190e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Allocates a sufficiently large address string (addr)
191e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project * according to the protocol */
192e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
193e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectstatic int node_alloc_addr_string(sepol_handle_t * handle,
194e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project				  int proto, char **addr)
195e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
196e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
197e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *tmp_addr = NULL;
198e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
199e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	switch (proto) {
200e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
201e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP4:
202e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr = malloc(INET_ADDRSTRLEN);
203e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!tmp_addr)
204e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			goto omem;
205e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		break;
206e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
207e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	case SEPOL_PROTO_IP6:
208e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		tmp_addr = malloc(INET6_ADDRSTRLEN);
209e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		if (!tmp_addr)
210e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			goto omem;
211e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		break;
212e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
213e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	default:
214e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		ERR(handle, "unsupported protocol %u", proto);
215e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
216e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	}
217e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
218e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*addr = tmp_addr;
219e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
220e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
221e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      omem:
222e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "out of memory");
223e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
224e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      err:
225e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(tmp_addr);
226e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "could not allocate string buffer for "
227e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    "address of protocol %s", sepol_node_get_proto_str(proto));
228e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_ERR;
229e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
230e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
231e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Key */
232e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_key_create(sepol_handle_t * handle,
233e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			  const char *addr,
234e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			  const char *mask,
235e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			  int proto, sepol_node_key_t ** key_ptr)
236e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
237e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
238e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	sepol_node_key_t *tmp_key =
239e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
240e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!tmp_key)
241e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto omem;
242e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
243e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) <
244e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    0)
245e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
246e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0)
247e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
248e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
249e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) <
250e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    0)
251e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
252e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0)
253e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
254e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
255e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->proto = proto;
256e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
257e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*key_ptr = tmp_key;
258e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
259e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
260e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      omem:
261e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "out of memory");
262e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
263e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      err:
264e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	sepol_node_key_free(tmp_key);
265e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "could not create node key for (%s, %s, %s)",
266e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    addr, mask, sepol_node_get_proto_str(proto));
267e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_ERR;
268e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
269e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
270e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projecthidden_def(sepol_node_key_create)
271e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
272e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectvoid sepol_node_key_unpack(const sepol_node_key_t * key,
273e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			   const char **addr, const char **mask, int *proto)
274e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
275e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
276e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*addr = key->addr;
277e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*mask = key->mask;
278e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*proto = key->proto;
279e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
280e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
281e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projecthidden_def(sepol_node_key_unpack)
282e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
283e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_key_extract(sepol_handle_t * handle,
284e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			   const sepol_node_t * node,
285e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			   sepol_node_key_t ** key_ptr)
286e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
287e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
288e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	sepol_node_key_t *tmp_key =
289e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
290e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!tmp_key)
291e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto omem;
292e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
293e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->addr = malloc(node->addr_sz);
294e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->mask = malloc(node->mask_sz);
295e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
296e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!tmp_key->addr || !tmp_key->mask)
297e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto omem;
298e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
299e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	memcpy(tmp_key->addr, node->addr, node->addr_sz);
300e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	memcpy(tmp_key->mask, node->mask, node->mask_sz);
301e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->addr_sz = node->addr_sz;
302e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->mask_sz = node->mask_sz;
303e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	tmp_key->proto = node->proto;
304e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
305e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*key_ptr = tmp_key;
306e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
307e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
308e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      omem:
309e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	sepol_node_key_free(tmp_key);
310e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "out of memory, could not extract node key");
311e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_ERR;
312e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
313e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
314e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectvoid sepol_node_key_free(sepol_node_key_t * key)
315e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
316e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
317e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (!key)
318e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return;
319e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
320e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(key->addr);
321e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(key->mask);
322e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(key);
323e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
324e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
325e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projecthidden_def(sepol_node_key_free)
326e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
327e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key)
328e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
329e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
330e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int rc1, rc2;
331e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
332e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz))
333e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return -1;
334e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
335e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	else if ((node->addr_sz > key->addr_sz) ||
336e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 (node->mask_sz > key->mask_sz))
337e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return 1;
338e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
339e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	rc1 = memcmp(node->addr, key->addr, node->addr_sz);
340e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	rc2 = memcmp(node->mask, key->mask, node->mask_sz);
341e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
342e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return (rc2 != 0) ? rc2 : rc1;
343e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
344e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
345e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2)
346e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
347e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
348e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	int rc1, rc2;
349e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
350e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if ((node->addr_sz < node2->addr_sz) ||
351e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	    (node->mask_sz < node2->mask_sz))
352e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return -1;
353e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
354e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	else if ((node->addr_sz > node2->addr_sz) ||
355e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		 (node->mask_sz > node2->mask_sz))
356e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		return 1;
357e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
358e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	rc1 = memcmp(node->addr, node2->addr, node->addr_sz);
359e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	rc2 = memcmp(node->mask, node2->mask, node->mask_sz);
360e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
361e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return (rc2 != 0) ? rc2 : rc1;
362e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
363e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
364e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project/* Addr */
365e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_get_addr(sepol_handle_t * handle,
366e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			const sepol_node_t * node, char **addr)
367e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
368e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
369e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *tmp_addr = NULL;
370e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
371e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0)
372e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
373e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
374e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0)
375e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project		goto err;
376e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
377e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	*addr = tmp_addr;
378e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_SUCCESS;
379e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
380e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project      err:
381e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	free(tmp_addr);
382e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	ERR(handle, "could not get node address");
383e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	return STATUS_ERR;
384e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project}
385e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
386e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projecthidden_def(sepol_node_get_addr)
387e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
388e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Projectint sepol_node_get_addr_bytes(sepol_handle_t * handle,
389e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			      const sepol_node_t * node,
390e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project			      char **buffer, size_t * bsize)
391e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project{
392e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project
393e9df6ba5a8fcccf306a80b1670b423be8fe7746The Android Open Source Project	char *tmp_buf = malloc(node->addr_sz);
394	if (!tmp_buf) {
395		ERR(handle, "out of memory, could not get address bytes");
396		return STATUS_ERR;
397	}
398
399	memcpy(tmp_buf, node->addr, node->addr_sz);
400	*buffer = tmp_buf;
401	*bsize = node->addr_sz;
402	return STATUS_SUCCESS;
403}
404
405hidden_def(sepol_node_get_addr_bytes)
406
407int sepol_node_set_addr(sepol_handle_t * handle,
408			sepol_node_t * node, int proto, const char *addr)
409{
410
411	char *tmp_addr = NULL;
412	size_t tmp_addr_sz;
413
414	if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0)
415		goto err;
416
417	if (node_parse_addr(handle, addr, proto, tmp_addr) < 0)
418		goto err;
419
420	free(node->addr);
421	node->addr = tmp_addr;
422	node->addr_sz = tmp_addr_sz;
423	return STATUS_SUCCESS;
424
425      err:
426	free(tmp_addr);
427	ERR(handle, "could not set node address to %s", addr);
428	return STATUS_ERR;
429}
430
431hidden_def(sepol_node_set_addr)
432
433int sepol_node_set_addr_bytes(sepol_handle_t * handle,
434			      sepol_node_t * node,
435			      const char *addr, size_t addr_sz)
436{
437
438	char *tmp_addr = malloc(addr_sz);
439	if (!tmp_addr) {
440		ERR(handle, "out of memory, could not " "set node address");
441		return STATUS_ERR;
442	}
443
444	memcpy(tmp_addr, addr, addr_sz);
445	free(node->addr);
446	node->addr = tmp_addr;
447	node->addr_sz = addr_sz;
448	return STATUS_SUCCESS;
449}
450
451hidden_def(sepol_node_set_addr_bytes)
452
453/* Mask */
454int sepol_node_get_mask(sepol_handle_t * handle,
455			const sepol_node_t * node, char **mask)
456{
457
458	char *tmp_mask = NULL;
459
460	if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0)
461		goto err;
462
463	if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0)
464		goto err;
465
466	*mask = tmp_mask;
467	return STATUS_SUCCESS;
468
469      err:
470	free(tmp_mask);
471	ERR(handle, "could not get node netmask");
472	return STATUS_ERR;
473}
474
475hidden_def(sepol_node_get_mask)
476
477int sepol_node_get_mask_bytes(sepol_handle_t * handle,
478			      const sepol_node_t * node,
479			      char **buffer, size_t * bsize)
480{
481
482	char *tmp_buf = malloc(node->mask_sz);
483	if (!tmp_buf) {
484		ERR(handle, "out of memory, could not get netmask bytes");
485		return STATUS_ERR;
486	}
487
488	memcpy(tmp_buf, node->mask, node->mask_sz);
489	*buffer = tmp_buf;
490	*bsize = node->mask_sz;
491	return STATUS_SUCCESS;
492}
493
494hidden_def(sepol_node_get_mask_bytes)
495
496int sepol_node_set_mask(sepol_handle_t * handle,
497			sepol_node_t * node, int proto, const char *mask)
498{
499
500	char *tmp_mask = NULL;
501	size_t tmp_mask_sz;
502
503	if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0)
504		goto err;
505
506	if (node_parse_addr(handle, mask, proto, tmp_mask) < 0)
507		goto err;
508
509	free(node->mask);
510	node->mask = tmp_mask;
511	node->mask_sz = tmp_mask_sz;
512	return STATUS_SUCCESS;
513
514      err:
515	free(tmp_mask);
516	ERR(handle, "could not set node netmask to %s", mask);
517	return STATUS_ERR;
518}
519
520hidden_def(sepol_node_set_mask)
521
522int sepol_node_set_mask_bytes(sepol_handle_t * handle,
523			      sepol_node_t * node,
524			      const char *mask, size_t mask_sz)
525{
526
527	char *tmp_mask = malloc(mask_sz);
528	if (!tmp_mask) {
529		ERR(handle, "out of memory, could not " "set node netmask");
530		return STATUS_ERR;
531	}
532	memcpy(tmp_mask, mask, mask_sz);
533	free(node->mask);
534	node->mask = tmp_mask;
535	node->mask_sz = mask_sz;
536	return STATUS_SUCCESS;
537}
538
539hidden_def(sepol_node_set_mask_bytes)
540
541/* Protocol */
542int sepol_node_get_proto(const sepol_node_t * node)
543{
544
545	return node->proto;
546}
547
548hidden_def(sepol_node_get_proto)
549
550void sepol_node_set_proto(sepol_node_t * node, int proto)
551{
552
553	node->proto = proto;
554}
555
556hidden_def(sepol_node_set_proto)
557
558const char *sepol_node_get_proto_str(int proto)
559{
560
561	switch (proto) {
562	case SEPOL_PROTO_IP4:
563		return "ipv4";
564	case SEPOL_PROTO_IP6:
565		return "ipv6";
566	default:
567		return "???";
568	}
569}
570
571hidden_def(sepol_node_get_proto_str)
572
573/* Create */
574int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
575{
576
577	sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t));
578
579	if (!tmp_node) {
580		ERR(handle, "out of memory, could not create " "node record");
581		return STATUS_ERR;
582	}
583
584	tmp_node->addr = NULL;
585	tmp_node->addr_sz = 0;
586	tmp_node->mask = NULL;
587	tmp_node->mask_sz = 0;
588	tmp_node->proto = SEPOL_PROTO_IP4;
589	tmp_node->con = NULL;
590	*node = tmp_node;
591
592	return STATUS_SUCCESS;
593}
594
595hidden_def(sepol_node_create)
596
597/* Deep copy clone */
598int sepol_node_clone(sepol_handle_t * handle,
599		     const sepol_node_t * node, sepol_node_t ** node_ptr)
600{
601
602	sepol_node_t *new_node = NULL;
603	if (sepol_node_create(handle, &new_node) < 0)
604		goto err;
605
606	/* Copy address, mask, protocol */
607	new_node->addr = malloc(node->addr_sz);
608	new_node->mask = malloc(node->mask_sz);
609	if (!new_node->addr || !new_node->mask)
610		goto omem;
611
612	memcpy(new_node->addr, node->addr, node->addr_sz);
613	memcpy(new_node->mask, node->mask, node->mask_sz);
614	new_node->addr_sz = node->addr_sz;
615	new_node->mask_sz = node->mask_sz;
616	new_node->proto = node->proto;
617
618	/* Copy context */
619	if (node->con &&
620	    (sepol_context_clone(handle, node->con, &new_node->con) < 0))
621		goto err;
622
623	*node_ptr = new_node;
624	return STATUS_SUCCESS;
625
626      omem:
627	ERR(handle, "out of memory");
628
629      err:
630	ERR(handle, "could not clone node record");
631	sepol_node_free(new_node);
632	return STATUS_ERR;
633}
634
635/* Destroy */
636void sepol_node_free(sepol_node_t * node)
637{
638
639	if (!node)
640		return;
641
642	sepol_context_free(node->con);
643	free(node->addr);
644	free(node->mask);
645	free(node);
646}
647
648hidden_def(sepol_node_free)
649
650/* Context */
651sepol_context_t *sepol_node_get_con(const sepol_node_t * node)
652{
653
654	return node->con;
655}
656
657hidden_def(sepol_node_get_con)
658
659int sepol_node_set_con(sepol_handle_t * handle,
660		       sepol_node_t * node, sepol_context_t * con)
661{
662
663	sepol_context_t *newcon;
664
665	if (sepol_context_clone(handle, con, &newcon) < 0) {
666		ERR(handle, "out of memory, could not set node context");
667		return STATUS_ERR;
668	}
669
670	sepol_context_free(node->con);
671	node->con = newcon;
672	return STATUS_SUCCESS;
673}
674
675hidden_def(sepol_node_set_con)
676