xref: /aosp_15_r20/external/selinux/libsepol/src/nodes.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker #include <netinet/in.h>
2*2d543d20SAndroid Build Coastguard Worker #include <arpa/inet.h>
3*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
4*2d543d20SAndroid Build Coastguard Worker 
5*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
6*2d543d20SAndroid Build Coastguard Worker #include "context.h"
7*2d543d20SAndroid Build Coastguard Worker #include "handle.h"
8*2d543d20SAndroid Build Coastguard Worker 
9*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
10*2d543d20SAndroid Build Coastguard Worker #include "node_internal.h"
11*2d543d20SAndroid Build Coastguard Worker 
12*2d543d20SAndroid Build Coastguard Worker /* Create a low level node structure from
13*2d543d20SAndroid Build Coastguard Worker  * a high level representation */
node_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** node,const sepol_node_t * data)14*2d543d20SAndroid Build Coastguard Worker static int node_from_record(sepol_handle_t * handle,
15*2d543d20SAndroid Build Coastguard Worker 			    const policydb_t * policydb,
16*2d543d20SAndroid Build Coastguard Worker 			    ocontext_t ** node, const sepol_node_t * data)
17*2d543d20SAndroid Build Coastguard Worker {
18*2d543d20SAndroid Build Coastguard Worker 
19*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *tmp_node = NULL;
20*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *tmp_con = NULL;
21*2d543d20SAndroid Build Coastguard Worker 	char *addr_buf = NULL, *mask_buf = NULL;
22*2d543d20SAndroid Build Coastguard Worker 	size_t addr_bsize, mask_bsize;
23*2d543d20SAndroid Build Coastguard Worker 	int proto;
24*2d543d20SAndroid Build Coastguard Worker 
25*2d543d20SAndroid Build Coastguard Worker 	tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
26*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_node)
27*2d543d20SAndroid Build Coastguard Worker 		goto omem;
28*2d543d20SAndroid Build Coastguard Worker 
29*2d543d20SAndroid Build Coastguard Worker 	/* Address and netmask */
30*2d543d20SAndroid Build Coastguard Worker 	if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
31*2d543d20SAndroid Build Coastguard Worker 		goto err;
32*2d543d20SAndroid Build Coastguard Worker 	if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
33*2d543d20SAndroid Build Coastguard Worker 		goto err;
34*2d543d20SAndroid Build Coastguard Worker 
35*2d543d20SAndroid Build Coastguard Worker 	proto = sepol_node_get_proto(data);
36*2d543d20SAndroid Build Coastguard Worker 
37*2d543d20SAndroid Build Coastguard Worker 	switch (proto) {
38*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP4:
39*2d543d20SAndroid Build Coastguard Worker 		memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
40*2d543d20SAndroid Build Coastguard Worker 		memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
41*2d543d20SAndroid Build Coastguard Worker 		break;
42*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP6:
43*2d543d20SAndroid Build Coastguard Worker 		memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
44*2d543d20SAndroid Build Coastguard Worker 		memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
45*2d543d20SAndroid Build Coastguard Worker 		break;
46*2d543d20SAndroid Build Coastguard Worker 	default:
47*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unsupported protocol %u", proto);
48*2d543d20SAndroid Build Coastguard Worker 		goto err;
49*2d543d20SAndroid Build Coastguard Worker 	}
50*2d543d20SAndroid Build Coastguard Worker 	free(addr_buf);
51*2d543d20SAndroid Build Coastguard Worker 	free(mask_buf);
52*2d543d20SAndroid Build Coastguard Worker 	addr_buf = NULL;
53*2d543d20SAndroid Build Coastguard Worker 	mask_buf = NULL;
54*2d543d20SAndroid Build Coastguard Worker 
55*2d543d20SAndroid Build Coastguard Worker 	/* Context */
56*2d543d20SAndroid Build Coastguard Worker 	if (context_from_record(handle, policydb, &tmp_con,
57*2d543d20SAndroid Build Coastguard Worker 				sepol_node_get_con(data)) < 0)
58*2d543d20SAndroid Build Coastguard Worker 		goto err;
59*2d543d20SAndroid Build Coastguard Worker 	context_cpy(&tmp_node->context[0], tmp_con);
60*2d543d20SAndroid Build Coastguard Worker 	context_destroy(tmp_con);
61*2d543d20SAndroid Build Coastguard Worker 	free(tmp_con);
62*2d543d20SAndroid Build Coastguard Worker 	tmp_con = NULL;
63*2d543d20SAndroid Build Coastguard Worker 
64*2d543d20SAndroid Build Coastguard Worker 	*node = tmp_node;
65*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
66*2d543d20SAndroid Build Coastguard Worker 
67*2d543d20SAndroid Build Coastguard Worker       omem:
68*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "out of memory");
69*2d543d20SAndroid Build Coastguard Worker 
70*2d543d20SAndroid Build Coastguard Worker       err:
71*2d543d20SAndroid Build Coastguard Worker 	if (tmp_node != NULL) {
72*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&tmp_node->context[0]);
73*2d543d20SAndroid Build Coastguard Worker 		free(tmp_node);
74*2d543d20SAndroid Build Coastguard Worker 	}
75*2d543d20SAndroid Build Coastguard Worker 	context_destroy(tmp_con);
76*2d543d20SAndroid Build Coastguard Worker 	free(tmp_con);
77*2d543d20SAndroid Build Coastguard Worker 	free(addr_buf);
78*2d543d20SAndroid Build Coastguard Worker 	free(mask_buf);
79*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not create node structure");
80*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
81*2d543d20SAndroid Build Coastguard Worker }
82*2d543d20SAndroid Build Coastguard Worker 
node_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * node,int proto,sepol_node_t ** record)83*2d543d20SAndroid Build Coastguard Worker static int node_to_record(sepol_handle_t * handle,
84*2d543d20SAndroid Build Coastguard Worker 			  const policydb_t * policydb,
85*2d543d20SAndroid Build Coastguard Worker 			  ocontext_t * node, int proto, sepol_node_t ** record)
86*2d543d20SAndroid Build Coastguard Worker {
87*2d543d20SAndroid Build Coastguard Worker 
88*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *con = &node->context[0];
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker 	sepol_context_t *tmp_con = NULL;
91*2d543d20SAndroid Build Coastguard Worker 	sepol_node_t *tmp_record = NULL;
92*2d543d20SAndroid Build Coastguard Worker 
93*2d543d20SAndroid Build Coastguard Worker 	if (sepol_node_create(handle, &tmp_record) < 0)
94*2d543d20SAndroid Build Coastguard Worker 		goto err;
95*2d543d20SAndroid Build Coastguard Worker 
96*2d543d20SAndroid Build Coastguard Worker 	sepol_node_set_proto(tmp_record, proto);
97*2d543d20SAndroid Build Coastguard Worker 
98*2d543d20SAndroid Build Coastguard Worker 	switch (proto) {
99*2d543d20SAndroid Build Coastguard Worker 
100*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP4:
101*2d543d20SAndroid Build Coastguard Worker 		if (sepol_node_set_addr_bytes(handle, tmp_record,
102*2d543d20SAndroid Build Coastguard Worker 					      (const char *)&node->u.node.addr,
103*2d543d20SAndroid Build Coastguard Worker 					      4) < 0)
104*2d543d20SAndroid Build Coastguard Worker 			goto err;
105*2d543d20SAndroid Build Coastguard Worker 
106*2d543d20SAndroid Build Coastguard Worker 		if (sepol_node_set_mask_bytes(handle, tmp_record,
107*2d543d20SAndroid Build Coastguard Worker 					      (const char *)&node->u.node.mask,
108*2d543d20SAndroid Build Coastguard Worker 					      4) < 0)
109*2d543d20SAndroid Build Coastguard Worker 			goto err;
110*2d543d20SAndroid Build Coastguard Worker 		break;
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP6:
113*2d543d20SAndroid Build Coastguard Worker 		if (sepol_node_set_addr_bytes(handle, tmp_record,
114*2d543d20SAndroid Build Coastguard Worker 					      (const char *)&node->u.node6.addr,
115*2d543d20SAndroid Build Coastguard Worker 					      16) < 0)
116*2d543d20SAndroid Build Coastguard Worker 			goto err;
117*2d543d20SAndroid Build Coastguard Worker 
118*2d543d20SAndroid Build Coastguard Worker 		if (sepol_node_set_mask_bytes(handle, tmp_record,
119*2d543d20SAndroid Build Coastguard Worker 					      (const char *)&node->u.node6.mask,
120*2d543d20SAndroid Build Coastguard Worker 					      16) < 0)
121*2d543d20SAndroid Build Coastguard Worker 			goto err;
122*2d543d20SAndroid Build Coastguard Worker 		break;
123*2d543d20SAndroid Build Coastguard Worker 
124*2d543d20SAndroid Build Coastguard Worker 	default:
125*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unsupported protocol %u", proto);
126*2d543d20SAndroid Build Coastguard Worker 		goto err;
127*2d543d20SAndroid Build Coastguard Worker 	}
128*2d543d20SAndroid Build Coastguard Worker 
129*2d543d20SAndroid Build Coastguard Worker 	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
130*2d543d20SAndroid Build Coastguard Worker 		goto err;
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 	if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0)
133*2d543d20SAndroid Build Coastguard Worker 		goto err;
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker 	sepol_context_free(tmp_con);
136*2d543d20SAndroid Build Coastguard Worker 	*record = tmp_record;
137*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
138*2d543d20SAndroid Build Coastguard Worker 
139*2d543d20SAndroid Build Coastguard Worker       err:
140*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not convert node to record");
141*2d543d20SAndroid Build Coastguard Worker 	sepol_context_free(tmp_con);
142*2d543d20SAndroid Build Coastguard Worker 	sepol_node_free(tmp_record);
143*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
144*2d543d20SAndroid Build Coastguard Worker }
145*2d543d20SAndroid Build Coastguard Worker 
146*2d543d20SAndroid Build Coastguard Worker /* Return the number of nodes */
sepol_node_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)147*2d543d20SAndroid Build Coastguard Worker extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)),
148*2d543d20SAndroid Build Coastguard Worker 			    const sepol_policydb_t * p, unsigned int *response)
149*2d543d20SAndroid Build Coastguard Worker {
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 	unsigned int count = 0;
152*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
153*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
154*2d543d20SAndroid Build Coastguard Worker 
155*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NODE];
156*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c != NULL; c = c->next)
157*2d543d20SAndroid Build Coastguard Worker 		count++;
158*2d543d20SAndroid Build Coastguard Worker 
159*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NODE6];
160*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c != NULL; c = c->next)
161*2d543d20SAndroid Build Coastguard Worker 		count++;
162*2d543d20SAndroid Build Coastguard Worker 
163*2d543d20SAndroid Build Coastguard Worker 	*response = count;
164*2d543d20SAndroid Build Coastguard Worker 
165*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
166*2d543d20SAndroid Build Coastguard Worker }
167*2d543d20SAndroid Build Coastguard Worker 
168*2d543d20SAndroid Build Coastguard Worker /* Check if a node exists */
sepol_node_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_node_key_t * key,int * response)169*2d543d20SAndroid Build Coastguard Worker int sepol_node_exists(sepol_handle_t * handle,
170*2d543d20SAndroid Build Coastguard Worker 		      const sepol_policydb_t * p,
171*2d543d20SAndroid Build Coastguard Worker 		      const sepol_node_key_t * key, int *response)
172*2d543d20SAndroid Build Coastguard Worker {
173*2d543d20SAndroid Build Coastguard Worker 
174*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
175*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
176*2d543d20SAndroid Build Coastguard Worker 
177*2d543d20SAndroid Build Coastguard Worker 	int proto;
178*2d543d20SAndroid Build Coastguard Worker 	const char *addr, *mask;
179*2d543d20SAndroid Build Coastguard Worker 	sepol_node_key_unpack(key, &addr, &mask, &proto);
180*2d543d20SAndroid Build Coastguard Worker 
181*2d543d20SAndroid Build Coastguard Worker 	switch (proto) {
182*2d543d20SAndroid Build Coastguard Worker 
183*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP4:
184*2d543d20SAndroid Build Coastguard Worker 		{
185*2d543d20SAndroid Build Coastguard Worker 			head = policydb->ocontexts[OCON_NODE];
186*2d543d20SAndroid Build Coastguard Worker 			for (c = head; c; c = c->next) {
187*2d543d20SAndroid Build Coastguard Worker 				unsigned int *addr2 = &c->u.node.addr;
188*2d543d20SAndroid Build Coastguard Worker 				unsigned int *mask2 = &c->u.node.mask;
189*2d543d20SAndroid Build Coastguard Worker 
190*2d543d20SAndroid Build Coastguard Worker 				if (!memcmp(addr, addr2, 4) &&
191*2d543d20SAndroid Build Coastguard Worker 				    !memcmp(mask, mask2, 4)) {
192*2d543d20SAndroid Build Coastguard Worker 
193*2d543d20SAndroid Build Coastguard Worker 					*response = 1;
194*2d543d20SAndroid Build Coastguard Worker 					return STATUS_SUCCESS;
195*2d543d20SAndroid Build Coastguard Worker 				}
196*2d543d20SAndroid Build Coastguard Worker 			}
197*2d543d20SAndroid Build Coastguard Worker 			break;
198*2d543d20SAndroid Build Coastguard Worker 		}
199*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP6:
200*2d543d20SAndroid Build Coastguard Worker 		{
201*2d543d20SAndroid Build Coastguard Worker 			head = policydb->ocontexts[OCON_NODE6];
202*2d543d20SAndroid Build Coastguard Worker 			for (c = head; c; c = c->next) {
203*2d543d20SAndroid Build Coastguard Worker 				unsigned int *addr2 = c->u.node6.addr;
204*2d543d20SAndroid Build Coastguard Worker 				unsigned int *mask2 = c->u.node6.mask;
205*2d543d20SAndroid Build Coastguard Worker 
206*2d543d20SAndroid Build Coastguard Worker 				if (!memcmp(addr, addr2, 16) &&
207*2d543d20SAndroid Build Coastguard Worker 				    !memcmp(mask, mask2, 16)) {
208*2d543d20SAndroid Build Coastguard Worker 					*response = 1;
209*2d543d20SAndroid Build Coastguard Worker 					return STATUS_SUCCESS;
210*2d543d20SAndroid Build Coastguard Worker 				}
211*2d543d20SAndroid Build Coastguard Worker 			}
212*2d543d20SAndroid Build Coastguard Worker 			break;
213*2d543d20SAndroid Build Coastguard Worker 		}
214*2d543d20SAndroid Build Coastguard Worker 	default:
215*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unsupported protocol %u", proto);
216*2d543d20SAndroid Build Coastguard Worker 		goto err;
217*2d543d20SAndroid Build Coastguard Worker 	}
218*2d543d20SAndroid Build Coastguard Worker 
219*2d543d20SAndroid Build Coastguard Worker 	*response = 0;
220*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker       err:
223*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not check if node %s/%s (%s) exists",
224*2d543d20SAndroid Build Coastguard Worker 	    addr, mask, sepol_node_get_proto_str(proto));
225*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
226*2d543d20SAndroid Build Coastguard Worker }
227*2d543d20SAndroid Build Coastguard Worker 
228*2d543d20SAndroid Build Coastguard Worker /* Query a node */
sepol_node_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_node_key_t * key,sepol_node_t ** response)229*2d543d20SAndroid Build Coastguard Worker int sepol_node_query(sepol_handle_t * handle,
230*2d543d20SAndroid Build Coastguard Worker 		     const sepol_policydb_t * p,
231*2d543d20SAndroid Build Coastguard Worker 		     const sepol_node_key_t * key, sepol_node_t ** response)
232*2d543d20SAndroid Build Coastguard Worker {
233*2d543d20SAndroid Build Coastguard Worker 
234*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
235*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
236*2d543d20SAndroid Build Coastguard Worker 
237*2d543d20SAndroid Build Coastguard Worker 	int proto;
238*2d543d20SAndroid Build Coastguard Worker 	const char *addr, *mask;
239*2d543d20SAndroid Build Coastguard Worker 	sepol_node_key_unpack(key, &addr, &mask, &proto);
240*2d543d20SAndroid Build Coastguard Worker 
241*2d543d20SAndroid Build Coastguard Worker 	switch (proto) {
242*2d543d20SAndroid Build Coastguard Worker 
243*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP4:
244*2d543d20SAndroid Build Coastguard Worker 		{
245*2d543d20SAndroid Build Coastguard Worker 			head = policydb->ocontexts[OCON_NODE];
246*2d543d20SAndroid Build Coastguard Worker 			for (c = head; c; c = c->next) {
247*2d543d20SAndroid Build Coastguard Worker 				unsigned int *addr2 = &c->u.node.addr;
248*2d543d20SAndroid Build Coastguard Worker 				unsigned int *mask2 = &c->u.node.mask;
249*2d543d20SAndroid Build Coastguard Worker 
250*2d543d20SAndroid Build Coastguard Worker 				if (!memcmp(addr, addr2, 4) &&
251*2d543d20SAndroid Build Coastguard Worker 				    !memcmp(mask, mask2, 4)) {
252*2d543d20SAndroid Build Coastguard Worker 
253*2d543d20SAndroid Build Coastguard Worker 					if (node_to_record(handle, policydb,
254*2d543d20SAndroid Build Coastguard Worker 							   c, SEPOL_PROTO_IP4,
255*2d543d20SAndroid Build Coastguard Worker 							   response) < 0)
256*2d543d20SAndroid Build Coastguard Worker 						goto err;
257*2d543d20SAndroid Build Coastguard Worker 					return STATUS_SUCCESS;
258*2d543d20SAndroid Build Coastguard Worker 				}
259*2d543d20SAndroid Build Coastguard Worker 			}
260*2d543d20SAndroid Build Coastguard Worker 			break;
261*2d543d20SAndroid Build Coastguard Worker 		}
262*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP6:
263*2d543d20SAndroid Build Coastguard Worker 		{
264*2d543d20SAndroid Build Coastguard Worker 			head = policydb->ocontexts[OCON_NODE6];
265*2d543d20SAndroid Build Coastguard Worker 			for (c = head; c; c = c->next) {
266*2d543d20SAndroid Build Coastguard Worker 				unsigned int *addr2 = c->u.node6.addr;
267*2d543d20SAndroid Build Coastguard Worker 				unsigned int *mask2 = c->u.node6.mask;
268*2d543d20SAndroid Build Coastguard Worker 
269*2d543d20SAndroid Build Coastguard Worker 				if (!memcmp(addr, addr2, 16) &&
270*2d543d20SAndroid Build Coastguard Worker 				    !memcmp(mask, mask2, 16)) {
271*2d543d20SAndroid Build Coastguard Worker 
272*2d543d20SAndroid Build Coastguard Worker 					if (node_to_record(handle, policydb,
273*2d543d20SAndroid Build Coastguard Worker 							   c, SEPOL_PROTO_IP6,
274*2d543d20SAndroid Build Coastguard Worker 							   response) < 0)
275*2d543d20SAndroid Build Coastguard Worker 						goto err;
276*2d543d20SAndroid Build Coastguard Worker 					return STATUS_SUCCESS;
277*2d543d20SAndroid Build Coastguard Worker 				}
278*2d543d20SAndroid Build Coastguard Worker 			}
279*2d543d20SAndroid Build Coastguard Worker 			break;
280*2d543d20SAndroid Build Coastguard Worker 		}
281*2d543d20SAndroid Build Coastguard Worker 	default:
282*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unsupported protocol %u", proto);
283*2d543d20SAndroid Build Coastguard Worker 		goto err;
284*2d543d20SAndroid Build Coastguard Worker 	}
285*2d543d20SAndroid Build Coastguard Worker 	*response = NULL;
286*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
287*2d543d20SAndroid Build Coastguard Worker 
288*2d543d20SAndroid Build Coastguard Worker       err:
289*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not query node %s/%s (%s)",
290*2d543d20SAndroid Build Coastguard Worker 	    addr, mask, sepol_node_get_proto_str(proto));
291*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
292*2d543d20SAndroid Build Coastguard Worker 
293*2d543d20SAndroid Build Coastguard Worker }
294*2d543d20SAndroid Build Coastguard Worker 
295*2d543d20SAndroid Build Coastguard Worker /* Load a node into policy */
sepol_node_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_node_key_t * key,const sepol_node_t * data)296*2d543d20SAndroid Build Coastguard Worker int sepol_node_modify(sepol_handle_t * handle,
297*2d543d20SAndroid Build Coastguard Worker 		      sepol_policydb_t * p,
298*2d543d20SAndroid Build Coastguard Worker 		      const sepol_node_key_t * key, const sepol_node_t * data)
299*2d543d20SAndroid Build Coastguard Worker {
300*2d543d20SAndroid Build Coastguard Worker 
301*2d543d20SAndroid Build Coastguard Worker 	policydb_t *policydb = &p->p;
302*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *node = NULL;
303*2d543d20SAndroid Build Coastguard Worker 
304*2d543d20SAndroid Build Coastguard Worker 	int proto;
305*2d543d20SAndroid Build Coastguard Worker 	const char *addr, *mask;
306*2d543d20SAndroid Build Coastguard Worker 
307*2d543d20SAndroid Build Coastguard Worker 	sepol_node_key_unpack(key, &addr, &mask, &proto);
308*2d543d20SAndroid Build Coastguard Worker 
309*2d543d20SAndroid Build Coastguard Worker 	if (node_from_record(handle, policydb, &node, data) < 0)
310*2d543d20SAndroid Build Coastguard Worker 		goto err;
311*2d543d20SAndroid Build Coastguard Worker 
312*2d543d20SAndroid Build Coastguard Worker 	switch (proto) {
313*2d543d20SAndroid Build Coastguard Worker 
314*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP4:
315*2d543d20SAndroid Build Coastguard Worker 		{
316*2d543d20SAndroid Build Coastguard Worker 			/* Attach to context list */
317*2d543d20SAndroid Build Coastguard Worker 			node->next = policydb->ocontexts[OCON_NODE];
318*2d543d20SAndroid Build Coastguard Worker 			policydb->ocontexts[OCON_NODE] = node;
319*2d543d20SAndroid Build Coastguard Worker 			break;
320*2d543d20SAndroid Build Coastguard Worker 		}
321*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_PROTO_IP6:
322*2d543d20SAndroid Build Coastguard Worker 		{
323*2d543d20SAndroid Build Coastguard Worker 			/* Attach to context list */
324*2d543d20SAndroid Build Coastguard Worker 			node->next = policydb->ocontexts[OCON_NODE6];
325*2d543d20SAndroid Build Coastguard Worker 			policydb->ocontexts[OCON_NODE6] = node;
326*2d543d20SAndroid Build Coastguard Worker 			break;
327*2d543d20SAndroid Build Coastguard Worker 		}
328*2d543d20SAndroid Build Coastguard Worker 	default:
329*2d543d20SAndroid Build Coastguard Worker 		ERR(handle, "unsupported protocol %u", proto);
330*2d543d20SAndroid Build Coastguard Worker 		goto err;
331*2d543d20SAndroid Build Coastguard Worker 	}
332*2d543d20SAndroid Build Coastguard Worker 
333*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
334*2d543d20SAndroid Build Coastguard Worker 
335*2d543d20SAndroid Build Coastguard Worker       err:
336*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not load node %s/%s (%s)",
337*2d543d20SAndroid Build Coastguard Worker 	    addr, mask, sepol_node_get_proto_str(proto));
338*2d543d20SAndroid Build Coastguard Worker 	if (node != NULL) {
339*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&node->context[0]);
340*2d543d20SAndroid Build Coastguard Worker 		free(node);
341*2d543d20SAndroid Build Coastguard Worker 	}
342*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
343*2d543d20SAndroid Build Coastguard Worker }
344*2d543d20SAndroid Build Coastguard Worker 
sepol_node_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_node_t * node,void * fn_arg),void * arg)345*2d543d20SAndroid Build Coastguard Worker int sepol_node_iterate(sepol_handle_t * handle,
346*2d543d20SAndroid Build Coastguard Worker 		       const sepol_policydb_t * p,
347*2d543d20SAndroid Build Coastguard Worker 		       int (*fn) (const sepol_node_t * node,
348*2d543d20SAndroid Build Coastguard Worker 				  void *fn_arg), void *arg)
349*2d543d20SAndroid Build Coastguard Worker {
350*2d543d20SAndroid Build Coastguard Worker 
351*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
352*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
353*2d543d20SAndroid Build Coastguard Worker 	sepol_node_t *node = NULL;
354*2d543d20SAndroid Build Coastguard Worker 	int status;
355*2d543d20SAndroid Build Coastguard Worker 
356*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NODE];
357*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
358*2d543d20SAndroid Build Coastguard Worker 		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
359*2d543d20SAndroid Build Coastguard Worker 		    < 0)
360*2d543d20SAndroid Build Coastguard Worker 			goto err;
361*2d543d20SAndroid Build Coastguard Worker 
362*2d543d20SAndroid Build Coastguard Worker 		/* Invoke handler */
363*2d543d20SAndroid Build Coastguard Worker 		status = fn(node, arg);
364*2d543d20SAndroid Build Coastguard Worker 		if (status < 0)
365*2d543d20SAndroid Build Coastguard Worker 			goto err;
366*2d543d20SAndroid Build Coastguard Worker 
367*2d543d20SAndroid Build Coastguard Worker 		sepol_node_free(node);
368*2d543d20SAndroid Build Coastguard Worker 		node = NULL;
369*2d543d20SAndroid Build Coastguard Worker 
370*2d543d20SAndroid Build Coastguard Worker 		/* Handler requested exit */
371*2d543d20SAndroid Build Coastguard Worker 		if (status > 0)
372*2d543d20SAndroid Build Coastguard Worker 			break;
373*2d543d20SAndroid Build Coastguard Worker 	}
374*2d543d20SAndroid Build Coastguard Worker 
375*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NODE6];
376*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
377*2d543d20SAndroid Build Coastguard Worker 		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
378*2d543d20SAndroid Build Coastguard Worker 		    < 0)
379*2d543d20SAndroid Build Coastguard Worker 			goto err;
380*2d543d20SAndroid Build Coastguard Worker 
381*2d543d20SAndroid Build Coastguard Worker 		/* Invoke handler */
382*2d543d20SAndroid Build Coastguard Worker 		status = fn(node, arg);
383*2d543d20SAndroid Build Coastguard Worker 		if (status < 0)
384*2d543d20SAndroid Build Coastguard Worker 			goto err;
385*2d543d20SAndroid Build Coastguard Worker 
386*2d543d20SAndroid Build Coastguard Worker 		sepol_node_free(node);
387*2d543d20SAndroid Build Coastguard Worker 		node = NULL;
388*2d543d20SAndroid Build Coastguard Worker 
389*2d543d20SAndroid Build Coastguard Worker 		/* Handler requested exit */
390*2d543d20SAndroid Build Coastguard Worker 		if (status > 0)
391*2d543d20SAndroid Build Coastguard Worker 			break;
392*2d543d20SAndroid Build Coastguard Worker 	}
393*2d543d20SAndroid Build Coastguard Worker 
394*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
395*2d543d20SAndroid Build Coastguard Worker 
396*2d543d20SAndroid Build Coastguard Worker       err:
397*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not iterate over nodes");
398*2d543d20SAndroid Build Coastguard Worker 	sepol_node_free(node);
399*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
400*2d543d20SAndroid Build Coastguard Worker }
401