113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <netinet/in.h>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <arpa/inet.h>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "debug.h"
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "context.h"
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "handle.h"
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb/policydb.h>
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "node_internal.h"
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Create a low level node structure from
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * a high level representation */
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int node_from_record(sepol_handle_t * handle,
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    const policydb_t * policydb,
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    ocontext_t ** node, const sepol_node_t * data)
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *tmp_node = NULL;
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_struct_t *tmp_con = NULL;
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *addr_buf = NULL, *mask_buf = NULL;
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!tmp_node)
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto omem;
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t addr_bsize, mask_bsize;
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Address and netmask */
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int proto = sepol_node_get_proto(data);
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (proto) {
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP4:
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP6:
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "unsupported protocol %u", proto);
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(addr_buf);
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mask_buf);
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	addr_buf = NULL;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	mask_buf = NULL;
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Context */
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (context_from_record(handle, policydb, &tmp_con,
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				sepol_node_get_con(data)) < 0)
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_cpy(&tmp_node->context[0], tmp_con);
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_destroy(tmp_con);
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(tmp_con);
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	tmp_con = NULL;
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*node = tmp_node;
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      omem:
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "out of memory");
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (tmp_node != NULL) {
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		context_destroy(&tmp_node->context[0]);
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(tmp_node);
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_destroy(tmp_con);
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(tmp_con);
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(addr_buf);
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(mask_buf);
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not create node structure");
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int node_to_record(sepol_handle_t * handle,
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  const policydb_t * policydb,
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  ocontext_t * node, int proto, sepol_node_t ** record)
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	context_struct_t *con = &node->context[0];
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_context_t *tmp_con = NULL;
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_t *tmp_record = NULL;
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_node_create(handle, &tmp_record) < 0)
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_set_proto(tmp_record, proto);
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (proto) {
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP4:
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (sepol_node_set_addr_bytes(handle, tmp_record,
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      (const char *)&node->u.node.addr,
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      4) < 0)
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (sepol_node_set_mask_bytes(handle, tmp_record,
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      (const char *)&node->u.node.mask,
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      4) < 0)
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP6:
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (sepol_node_set_addr_bytes(handle, tmp_record,
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      (const char *)&node->u.node6.addr,
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      16) < 0)
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (sepol_node_set_mask_bytes(handle, tmp_record,
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      (const char *)&node->u.node6.mask,
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					      16) < 0)
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		break;
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "unsupported protocol %u", proto);
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0)
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_context_free(tmp_con);
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*record = tmp_record;
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not convert node to record");
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_context_free(tmp_con);
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_free(tmp_record);
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Return the number of nodes */
147033959726bf32ab59a52201e0696f269c0810609Justin P. Mattockextern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)),
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    const sepol_policydb_t * p, unsigned int *response)
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int count = 0;
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *head;
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const policydb_t *policydb = &p->p;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	head = policydb->ocontexts[OCON_NODE];
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (c = head; c != NULL; c = c->next)
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		count++;
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	head = policydb->ocontexts[OCON_NODE6];
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (c = head; c != NULL; c = c->next)
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		count++;
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*response = count;
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Check if a node exists */
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_node_exists(sepol_handle_t * handle,
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		      const sepol_policydb_t * p,
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		      const sepol_node_key_t * key, int *response)
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const policydb_t *policydb = &p->p;
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *head;
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int proto;
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *addr, *mask;
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_key_unpack(key, &addr, &mask, &proto);
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (proto) {
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP4:
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			head = policydb->ocontexts[OCON_NODE];
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (c = head; c; c = c->next) {
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *addr2 = &c->u.node.addr;
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *mask2 = &c->u.node.mask;
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!memcmp(addr, addr2, 4) &&
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    !memcmp(mask, mask2, 4)) {
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					*response = 1;
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return STATUS_SUCCESS;
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP6:
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			head = policydb->ocontexts[OCON_NODE6];
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (c = head; c; c = c->next) {
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *addr2 = c->u.node6.addr;
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *mask2 = c->u.node6.mask;
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!memcmp(addr, addr2, 16) &&
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    !memcmp(mask, mask2, 16)) {
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					*response = 1;
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return STATUS_SUCCESS;
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "unsupported protocol %u", proto);
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*response = 0;
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not check if node %s/%s (%s) exists",
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    addr, mask, sepol_node_get_proto_str(proto));
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Query a node */
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_node_query(sepol_handle_t * handle,
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     const sepol_policydb_t * p,
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     const sepol_node_key_t * key, sepol_node_t ** response)
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const policydb_t *policydb = &p->p;
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *head;
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int proto;
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *addr, *mask;
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_key_unpack(key, &addr, &mask, &proto);
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (proto) {
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP4:
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			head = policydb->ocontexts[OCON_NODE];
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (c = head; c; c = c->next) {
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *addr2 = &c->u.node.addr;
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *mask2 = &c->u.node.mask;
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!memcmp(addr, addr2, 4) &&
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    !memcmp(mask, mask2, 4)) {
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (node_to_record(handle, policydb,
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   c, SEPOL_PROTO_IP4,
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   response) < 0)
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto err;
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					return STATUS_SUCCESS;
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP6:
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			head = policydb->ocontexts[OCON_NODE6];
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			for (c = head; c; c = c->next) {
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *addr2 = c->u.node6.addr;
26713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				unsigned int *mask2 = c->u.node6.mask;
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (!memcmp(addr, addr2, 16) &&
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    !memcmp(mask, mask2, 16)) {
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					if (node_to_record(handle, policydb,
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   c, SEPOL_PROTO_IP6,
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle							   response) < 0)
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						goto err;
276747a440fdd5b32c16739ecbd76367eb2a582fe82Petr Lautrbach					return STATUS_SUCCESS;
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
28013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "unsupported protocol %u", proto);
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
28413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*response = NULL;
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not query node %s/%s (%s)",
29013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    addr, mask, sepol_node_get_proto_str(proto));
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Load a node into policy */
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_node_modify(sepol_handle_t * handle,
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		      sepol_policydb_t * p,
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		      const sepol_node_key_t * key, const sepol_node_t * data)
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	policydb_t *policydb = &p->p;
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *node = NULL;
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int proto;
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const char *addr, *mask;
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_key_unpack(key, &addr, &mask, &proto);
30813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (node_from_record(handle, policydb, &node, data) < 0)
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	switch (proto) {
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP4:
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* Attach to context list */
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->next = policydb->ocontexts[OCON_NODE];
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			policydb->ocontexts[OCON_NODE] = node;
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	case SEPOL_PROTO_IP6:
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		{
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			/* Attach to context list */
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			node->next = policydb->ocontexts[OCON_NODE6];
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			policydb->ocontexts[OCON_NODE6] = node;
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	default:
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ERR(handle, "unsupported protocol %u", proto);
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not load node %s/%s (%s)",
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    addr, mask, sepol_node_get_proto_str(proto));
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (node != NULL) {
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		context_destroy(&node->context[0]);
34013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(node);
34113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint sepol_node_iterate(sepol_handle_t * handle,
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       const sepol_policydb_t * p,
34713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		       int (*fn) (const sepol_node_t * node,
34813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				  void *fn_arg), void *arg)
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	const policydb_t *policydb = &p->p;
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ocontext_t *c, *head;
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_t *node = NULL;
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int status;
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	head = policydb->ocontexts[OCON_NODE];
35713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (c = head; c; c = c->next) {
35813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
35913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    < 0)
36013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
36113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Invoke handler */
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		status = fn(node, arg);
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (status < 0)
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		sepol_node_free(node);
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = NULL;
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Handler requested exit */
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (status > 0)
37213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	head = policydb->ocontexts[OCON_NODE6];
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (c = head; c; c = c->next) {
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    < 0)
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Invoke handler */
38213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		status = fn(node, arg);
38313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (status < 0)
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto err;
38513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		sepol_node_free(node);
38713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		node = NULL;
38813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
38913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Handler requested exit */
39013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (status > 0)
39113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
39213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
39313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_SUCCESS;
39513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
39613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
39713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ERR(handle, "could not iterate over nodes");
39813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_node_free(node);
39913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return STATUS_ERR;
40013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
401