1255e72915d4cbddceb435e13d81601755714e9fSE Android#include <netinet/in.h>
2255e72915d4cbddceb435e13d81601755714e9fSE Android#include <arpa/inet.h>
3255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
4255e72915d4cbddceb435e13d81601755714e9fSE Android
5255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
6255e72915d4cbddceb435e13d81601755714e9fSE Android#include "context.h"
7255e72915d4cbddceb435e13d81601755714e9fSE Android#include "handle.h"
8255e72915d4cbddceb435e13d81601755714e9fSE Android
9255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h>
10255e72915d4cbddceb435e13d81601755714e9fSE Android#include "node_internal.h"
11255e72915d4cbddceb435e13d81601755714e9fSE Android
12255e72915d4cbddceb435e13d81601755714e9fSE Android/* Create a low level node structure from
13255e72915d4cbddceb435e13d81601755714e9fSE Android * a high level representation */
14255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int node_from_record(sepol_handle_t * handle,
15255e72915d4cbddceb435e13d81601755714e9fSE Android			    const policydb_t * policydb,
16255e72915d4cbddceb435e13d81601755714e9fSE Android			    ocontext_t ** node, const sepol_node_t * data)
17255e72915d4cbddceb435e13d81601755714e9fSE Android{
18255e72915d4cbddceb435e13d81601755714e9fSE Android
19255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *tmp_node = NULL;
20255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *tmp_con = NULL;
21255e72915d4cbddceb435e13d81601755714e9fSE Android	char *addr_buf = NULL, *mask_buf = NULL;
22255e72915d4cbddceb435e13d81601755714e9fSE Android
23255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
24255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tmp_node)
25255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
26255e72915d4cbddceb435e13d81601755714e9fSE Android
27255e72915d4cbddceb435e13d81601755714e9fSE Android	size_t addr_bsize, mask_bsize;
28255e72915d4cbddceb435e13d81601755714e9fSE Android
29255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Address and netmask */
30255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
31255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
32255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
33255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
34255e72915d4cbddceb435e13d81601755714e9fSE Android
35255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto = sepol_node_get_proto(data);
36255e72915d4cbddceb435e13d81601755714e9fSE Android
37255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
38255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP4:
39255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
40255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
41255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
42255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP6:
43255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
44255e72915d4cbddceb435e13d81601755714e9fSE Android		memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
45255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
46255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
47255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
48255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
49255e72915d4cbddceb435e13d81601755714e9fSE Android	}
50255e72915d4cbddceb435e13d81601755714e9fSE Android	free(addr_buf);
51255e72915d4cbddceb435e13d81601755714e9fSE Android	free(mask_buf);
52255e72915d4cbddceb435e13d81601755714e9fSE Android	addr_buf = NULL;
53255e72915d4cbddceb435e13d81601755714e9fSE Android	mask_buf = NULL;
54255e72915d4cbddceb435e13d81601755714e9fSE Android
55255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Context */
56255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_from_record(handle, policydb, &tmp_con,
57255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_node_get_con(data)) < 0)
58255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
59255e72915d4cbddceb435e13d81601755714e9fSE Android	context_cpy(&tmp_node->context[0], tmp_con);
60255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(tmp_con);
61255e72915d4cbddceb435e13d81601755714e9fSE Android	free(tmp_con);
62255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_con = NULL;
63255e72915d4cbddceb435e13d81601755714e9fSE Android
64255e72915d4cbddceb435e13d81601755714e9fSE Android	*node = tmp_node;
65255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
66255e72915d4cbddceb435e13d81601755714e9fSE Android
67255e72915d4cbddceb435e13d81601755714e9fSE Android      omem:
68255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "out of memory");
69255e72915d4cbddceb435e13d81601755714e9fSE Android
70255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
71255e72915d4cbddceb435e13d81601755714e9fSE Android	if (tmp_node != NULL) {
72255e72915d4cbddceb435e13d81601755714e9fSE Android		context_destroy(&tmp_node->context[0]);
73255e72915d4cbddceb435e13d81601755714e9fSE Android		free(tmp_node);
74255e72915d4cbddceb435e13d81601755714e9fSE Android	}
75255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(tmp_con);
76255e72915d4cbddceb435e13d81601755714e9fSE Android	free(tmp_con);
77255e72915d4cbddceb435e13d81601755714e9fSE Android	free(addr_buf);
78255e72915d4cbddceb435e13d81601755714e9fSE Android	free(mask_buf);
79255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not create node structure");
80255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
81255e72915d4cbddceb435e13d81601755714e9fSE Android}
82255e72915d4cbddceb435e13d81601755714e9fSE Android
83255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int node_to_record(sepol_handle_t * handle,
84255e72915d4cbddceb435e13d81601755714e9fSE Android			  const policydb_t * policydb,
85255e72915d4cbddceb435e13d81601755714e9fSE Android			  ocontext_t * node, int proto, sepol_node_t ** record)
86255e72915d4cbddceb435e13d81601755714e9fSE Android{
87255e72915d4cbddceb435e13d81601755714e9fSE Android
88255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *con = &node->context[0];
89255e72915d4cbddceb435e13d81601755714e9fSE Android
90255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_t *tmp_con = NULL;
91255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_t *tmp_record = NULL;
92255e72915d4cbddceb435e13d81601755714e9fSE Android
93255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_node_create(handle, &tmp_record) < 0)
94255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
95255e72915d4cbddceb435e13d81601755714e9fSE Android
96255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_set_proto(tmp_record, proto);
97255e72915d4cbddceb435e13d81601755714e9fSE Android
98255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
99255e72915d4cbddceb435e13d81601755714e9fSE Android
100255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP4:
101255e72915d4cbddceb435e13d81601755714e9fSE Android		if (sepol_node_set_addr_bytes(handle, tmp_record,
102255e72915d4cbddceb435e13d81601755714e9fSE Android					      (const char *)&node->u.node.addr,
103255e72915d4cbddceb435e13d81601755714e9fSE Android					      4) < 0)
104255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
105255e72915d4cbddceb435e13d81601755714e9fSE Android
106255e72915d4cbddceb435e13d81601755714e9fSE Android		if (sepol_node_set_mask_bytes(handle, tmp_record,
107255e72915d4cbddceb435e13d81601755714e9fSE Android					      (const char *)&node->u.node.mask,
108255e72915d4cbddceb435e13d81601755714e9fSE Android					      4) < 0)
109255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
110255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
111255e72915d4cbddceb435e13d81601755714e9fSE Android
112255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP6:
113255e72915d4cbddceb435e13d81601755714e9fSE Android		if (sepol_node_set_addr_bytes(handle, tmp_record,
114255e72915d4cbddceb435e13d81601755714e9fSE Android					      (const char *)&node->u.node6.addr,
115255e72915d4cbddceb435e13d81601755714e9fSE Android					      16) < 0)
116255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
117255e72915d4cbddceb435e13d81601755714e9fSE Android
118255e72915d4cbddceb435e13d81601755714e9fSE Android		if (sepol_node_set_mask_bytes(handle, tmp_record,
119255e72915d4cbddceb435e13d81601755714e9fSE Android					      (const char *)&node->u.node6.mask,
120255e72915d4cbddceb435e13d81601755714e9fSE Android					      16) < 0)
121255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
122255e72915d4cbddceb435e13d81601755714e9fSE Android		break;
123255e72915d4cbddceb435e13d81601755714e9fSE Android
124255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
125255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
126255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
127255e72915d4cbddceb435e13d81601755714e9fSE Android	}
128255e72915d4cbddceb435e13d81601755714e9fSE Android
129255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
130255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
131255e72915d4cbddceb435e13d81601755714e9fSE Android
132255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0)
133255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
134255e72915d4cbddceb435e13d81601755714e9fSE Android
135255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_free(tmp_con);
136255e72915d4cbddceb435e13d81601755714e9fSE Android	*record = tmp_record;
137255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
138255e72915d4cbddceb435e13d81601755714e9fSE Android
139255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
140255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not convert node to record");
141255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_free(tmp_con);
142255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_free(tmp_record);
143255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
144255e72915d4cbddceb435e13d81601755714e9fSE Android}
145255e72915d4cbddceb435e13d81601755714e9fSE Android
146255e72915d4cbddceb435e13d81601755714e9fSE Android/* Return the number of nodes */
147255e72915d4cbddceb435e13d81601755714e9fSE Androidextern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)),
148255e72915d4cbddceb435e13d81601755714e9fSE Android			    const sepol_policydb_t * p, unsigned int *response)
149255e72915d4cbddceb435e13d81601755714e9fSE Android{
150255e72915d4cbddceb435e13d81601755714e9fSE Android
151255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int count = 0;
152255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
153255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
154255e72915d4cbddceb435e13d81601755714e9fSE Android
155255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_NODE];
156255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c != NULL; c = c->next)
157255e72915d4cbddceb435e13d81601755714e9fSE Android		count++;
158255e72915d4cbddceb435e13d81601755714e9fSE Android
159255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_NODE6];
160255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c != NULL; c = c->next)
161255e72915d4cbddceb435e13d81601755714e9fSE Android		count++;
162255e72915d4cbddceb435e13d81601755714e9fSE Android
163255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = count;
164255e72915d4cbddceb435e13d81601755714e9fSE Android
165255e72915d4cbddceb435e13d81601755714e9fSE Android	handle = NULL;
166255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
167255e72915d4cbddceb435e13d81601755714e9fSE Android}
168255e72915d4cbddceb435e13d81601755714e9fSE Android
169255e72915d4cbddceb435e13d81601755714e9fSE Android/* Check if a node exists */
170255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_node_exists(sepol_handle_t * handle,
171255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_policydb_t * p,
172255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_node_key_t * key, int *response)
173255e72915d4cbddceb435e13d81601755714e9fSE Android{
174255e72915d4cbddceb435e13d81601755714e9fSE Android
175255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
176255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
177255e72915d4cbddceb435e13d81601755714e9fSE Android
178255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto;
179255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *addr, *mask;
180255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_key_unpack(key, &addr, &mask, &proto);
181255e72915d4cbddceb435e13d81601755714e9fSE Android
182255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
183255e72915d4cbddceb435e13d81601755714e9fSE Android
184255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP4:
185255e72915d4cbddceb435e13d81601755714e9fSE Android		{
186255e72915d4cbddceb435e13d81601755714e9fSE Android			head = policydb->ocontexts[OCON_NODE];
187255e72915d4cbddceb435e13d81601755714e9fSE Android			for (c = head; c; c = c->next) {
188255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *addr2 = &c->u.node.addr;
189255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *mask2 = &c->u.node.mask;
190255e72915d4cbddceb435e13d81601755714e9fSE Android
191255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!memcmp(addr, addr2, 4) &&
192255e72915d4cbddceb435e13d81601755714e9fSE Android				    !memcmp(mask, mask2, 4)) {
193255e72915d4cbddceb435e13d81601755714e9fSE Android
194255e72915d4cbddceb435e13d81601755714e9fSE Android					*response = 1;
195255e72915d4cbddceb435e13d81601755714e9fSE Android					return STATUS_SUCCESS;
196255e72915d4cbddceb435e13d81601755714e9fSE Android				}
197255e72915d4cbddceb435e13d81601755714e9fSE Android			}
198255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
199255e72915d4cbddceb435e13d81601755714e9fSE Android		}
200255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP6:
201255e72915d4cbddceb435e13d81601755714e9fSE Android		{
202255e72915d4cbddceb435e13d81601755714e9fSE Android			head = policydb->ocontexts[OCON_NODE6];
203255e72915d4cbddceb435e13d81601755714e9fSE Android			for (c = head; c; c = c->next) {
204255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *addr2 = c->u.node6.addr;
205255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *mask2 = c->u.node6.mask;
206255e72915d4cbddceb435e13d81601755714e9fSE Android
207255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!memcmp(addr, addr2, 16) &&
208255e72915d4cbddceb435e13d81601755714e9fSE Android				    !memcmp(mask, mask2, 16)) {
209255e72915d4cbddceb435e13d81601755714e9fSE Android					*response = 1;
210255e72915d4cbddceb435e13d81601755714e9fSE Android					return STATUS_SUCCESS;
211255e72915d4cbddceb435e13d81601755714e9fSE Android				}
212255e72915d4cbddceb435e13d81601755714e9fSE Android			}
213255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
214255e72915d4cbddceb435e13d81601755714e9fSE Android		}
215255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
216255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
217255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
218255e72915d4cbddceb435e13d81601755714e9fSE Android	}
219255e72915d4cbddceb435e13d81601755714e9fSE Android
220255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = 0;
221255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
222255e72915d4cbddceb435e13d81601755714e9fSE Android
223255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
224255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not check if node %s/%s (%s) exists",
225255e72915d4cbddceb435e13d81601755714e9fSE Android	    addr, mask, sepol_node_get_proto_str(proto));
226255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
227255e72915d4cbddceb435e13d81601755714e9fSE Android}
228255e72915d4cbddceb435e13d81601755714e9fSE Android
229255e72915d4cbddceb435e13d81601755714e9fSE Android/* Query a node */
230255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_node_query(sepol_handle_t * handle,
231255e72915d4cbddceb435e13d81601755714e9fSE Android		     const sepol_policydb_t * p,
232255e72915d4cbddceb435e13d81601755714e9fSE Android		     const sepol_node_key_t * key, sepol_node_t ** response)
233255e72915d4cbddceb435e13d81601755714e9fSE Android{
234255e72915d4cbddceb435e13d81601755714e9fSE Android
235255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
236255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
237255e72915d4cbddceb435e13d81601755714e9fSE Android
238255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto;
239255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *addr, *mask;
240255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_key_unpack(key, &addr, &mask, &proto);
241255e72915d4cbddceb435e13d81601755714e9fSE Android
242255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
243255e72915d4cbddceb435e13d81601755714e9fSE Android
244255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP4:
245255e72915d4cbddceb435e13d81601755714e9fSE Android		{
246255e72915d4cbddceb435e13d81601755714e9fSE Android			head = policydb->ocontexts[OCON_NODE];
247255e72915d4cbddceb435e13d81601755714e9fSE Android			for (c = head; c; c = c->next) {
248255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *addr2 = &c->u.node.addr;
249255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *mask2 = &c->u.node.mask;
250255e72915d4cbddceb435e13d81601755714e9fSE Android
251255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!memcmp(addr, addr2, 4) &&
252255e72915d4cbddceb435e13d81601755714e9fSE Android				    !memcmp(mask, mask2, 4)) {
253255e72915d4cbddceb435e13d81601755714e9fSE Android
254255e72915d4cbddceb435e13d81601755714e9fSE Android					if (node_to_record(handle, policydb,
255255e72915d4cbddceb435e13d81601755714e9fSE Android							   c, SEPOL_PROTO_IP4,
256255e72915d4cbddceb435e13d81601755714e9fSE Android							   response) < 0)
257255e72915d4cbddceb435e13d81601755714e9fSE Android						goto err;
258255e72915d4cbddceb435e13d81601755714e9fSE Android					return STATUS_SUCCESS;
259255e72915d4cbddceb435e13d81601755714e9fSE Android				}
260255e72915d4cbddceb435e13d81601755714e9fSE Android			}
261255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
262255e72915d4cbddceb435e13d81601755714e9fSE Android		}
263255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP6:
264255e72915d4cbddceb435e13d81601755714e9fSE Android		{
265255e72915d4cbddceb435e13d81601755714e9fSE Android			head = policydb->ocontexts[OCON_NODE6];
266255e72915d4cbddceb435e13d81601755714e9fSE Android			for (c = head; c; c = c->next) {
267255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *addr2 = c->u.node6.addr;
268255e72915d4cbddceb435e13d81601755714e9fSE Android				unsigned int *mask2 = c->u.node6.mask;
269255e72915d4cbddceb435e13d81601755714e9fSE Android
270255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!memcmp(addr, addr2, 16) &&
271255e72915d4cbddceb435e13d81601755714e9fSE Android				    !memcmp(mask, mask2, 16)) {
272255e72915d4cbddceb435e13d81601755714e9fSE Android
273255e72915d4cbddceb435e13d81601755714e9fSE Android					if (node_to_record(handle, policydb,
274255e72915d4cbddceb435e13d81601755714e9fSE Android							   c, SEPOL_PROTO_IP6,
275255e72915d4cbddceb435e13d81601755714e9fSE Android							   response) < 0)
276255e72915d4cbddceb435e13d81601755714e9fSE Android						goto err;
277255e72915d4cbddceb435e13d81601755714e9fSE Android				}
278255e72915d4cbddceb435e13d81601755714e9fSE Android			}
279255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
280255e72915d4cbddceb435e13d81601755714e9fSE Android		}
281255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
282255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
283255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
284255e72915d4cbddceb435e13d81601755714e9fSE Android	}
285255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = NULL;
286255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
287255e72915d4cbddceb435e13d81601755714e9fSE Android
288255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
289255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not query node %s/%s (%s)",
290255e72915d4cbddceb435e13d81601755714e9fSE Android	    addr, mask, sepol_node_get_proto_str(proto));
291255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
292255e72915d4cbddceb435e13d81601755714e9fSE Android
293255e72915d4cbddceb435e13d81601755714e9fSE Android}
294255e72915d4cbddceb435e13d81601755714e9fSE Android
295255e72915d4cbddceb435e13d81601755714e9fSE Android/* Load a node into policy */
296255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_node_modify(sepol_handle_t * handle,
297255e72915d4cbddceb435e13d81601755714e9fSE Android		      sepol_policydb_t * p,
298255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_node_key_t * key, const sepol_node_t * data)
299255e72915d4cbddceb435e13d81601755714e9fSE Android{
300255e72915d4cbddceb435e13d81601755714e9fSE Android
301255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *policydb = &p->p;
302255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *node = NULL;
303255e72915d4cbddceb435e13d81601755714e9fSE Android
304255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto;
305255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *addr, *mask;
306255e72915d4cbddceb435e13d81601755714e9fSE Android
307255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_key_unpack(key, &addr, &mask, &proto);
308255e72915d4cbddceb435e13d81601755714e9fSE Android
309255e72915d4cbddceb435e13d81601755714e9fSE Android	if (node_from_record(handle, policydb, &node, data) < 0)
310255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
311255e72915d4cbddceb435e13d81601755714e9fSE Android
312255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
313255e72915d4cbddceb435e13d81601755714e9fSE Android
314255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP4:
315255e72915d4cbddceb435e13d81601755714e9fSE Android		{
316255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Attach to context list */
317255e72915d4cbddceb435e13d81601755714e9fSE Android			node->next = policydb->ocontexts[OCON_NODE];
318255e72915d4cbddceb435e13d81601755714e9fSE Android			policydb->ocontexts[OCON_NODE] = node;
319255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
320255e72915d4cbddceb435e13d81601755714e9fSE Android		}
321255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_IP6:
322255e72915d4cbddceb435e13d81601755714e9fSE Android		{
323255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Attach to context list */
324255e72915d4cbddceb435e13d81601755714e9fSE Android			node->next = policydb->ocontexts[OCON_NODE6];
325255e72915d4cbddceb435e13d81601755714e9fSE Android			policydb->ocontexts[OCON_NODE6] = node;
326255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
327255e72915d4cbddceb435e13d81601755714e9fSE Android		}
328255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
329255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
330255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
331255e72915d4cbddceb435e13d81601755714e9fSE Android	}
332255e72915d4cbddceb435e13d81601755714e9fSE Android
333255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
334255e72915d4cbddceb435e13d81601755714e9fSE Android
335255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
336255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not load node %s/%s (%s)",
337255e72915d4cbddceb435e13d81601755714e9fSE Android	    addr, mask, sepol_node_get_proto_str(proto));
338255e72915d4cbddceb435e13d81601755714e9fSE Android	if (node != NULL) {
339255e72915d4cbddceb435e13d81601755714e9fSE Android		context_destroy(&node->context[0]);
340255e72915d4cbddceb435e13d81601755714e9fSE Android		free(node);
341255e72915d4cbddceb435e13d81601755714e9fSE Android	}
342255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
343255e72915d4cbddceb435e13d81601755714e9fSE Android}
344255e72915d4cbddceb435e13d81601755714e9fSE Android
345255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_node_iterate(sepol_handle_t * handle,
346255e72915d4cbddceb435e13d81601755714e9fSE Android		       const sepol_policydb_t * p,
347255e72915d4cbddceb435e13d81601755714e9fSE Android		       int (*fn) (const sepol_node_t * node,
348255e72915d4cbddceb435e13d81601755714e9fSE Android				  void *fn_arg), void *arg)
349255e72915d4cbddceb435e13d81601755714e9fSE Android{
350255e72915d4cbddceb435e13d81601755714e9fSE Android
351255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
352255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
353255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_t *node = NULL;
354255e72915d4cbddceb435e13d81601755714e9fSE Android	int status;
355255e72915d4cbddceb435e13d81601755714e9fSE Android
356255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_NODE];
357255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c; c = c->next) {
358255e72915d4cbddceb435e13d81601755714e9fSE Android		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
359255e72915d4cbddceb435e13d81601755714e9fSE Android		    < 0)
360255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
361255e72915d4cbddceb435e13d81601755714e9fSE Android
362255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Invoke handler */
363255e72915d4cbddceb435e13d81601755714e9fSE Android		status = fn(node, arg);
364255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status < 0)
365255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
366255e72915d4cbddceb435e13d81601755714e9fSE Android
367255e72915d4cbddceb435e13d81601755714e9fSE Android		sepol_node_free(node);
368255e72915d4cbddceb435e13d81601755714e9fSE Android		node = NULL;
369255e72915d4cbddceb435e13d81601755714e9fSE Android
370255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Handler requested exit */
371255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status > 0)
372255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
373255e72915d4cbddceb435e13d81601755714e9fSE Android	}
374255e72915d4cbddceb435e13d81601755714e9fSE Android
375255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_NODE6];
376255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c; c = c->next) {
377255e72915d4cbddceb435e13d81601755714e9fSE Android		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
378255e72915d4cbddceb435e13d81601755714e9fSE Android		    < 0)
379255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
380255e72915d4cbddceb435e13d81601755714e9fSE Android
381255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Invoke handler */
382255e72915d4cbddceb435e13d81601755714e9fSE Android		status = fn(node, arg);
383255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status < 0)
384255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
385255e72915d4cbddceb435e13d81601755714e9fSE Android
386255e72915d4cbddceb435e13d81601755714e9fSE Android		sepol_node_free(node);
387255e72915d4cbddceb435e13d81601755714e9fSE Android		node = NULL;
388255e72915d4cbddceb435e13d81601755714e9fSE Android
389255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Handler requested exit */
390255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status > 0)
391255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
392255e72915d4cbddceb435e13d81601755714e9fSE Android	}
393255e72915d4cbddceb435e13d81601755714e9fSE Android
394255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
395255e72915d4cbddceb435e13d81601755714e9fSE Android
396255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
397255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not iterate over nodes");
398255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_node_free(node);
399255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
400255e72915d4cbddceb435e13d81601755714e9fSE Android}
401