1255e72915d4cbddceb435e13d81601755714e9fSE Android#include <netinet/in.h>
2255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
3255e72915d4cbddceb435e13d81601755714e9fSE Android
4255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
5255e72915d4cbddceb435e13d81601755714e9fSE Android#include "context.h"
6255e72915d4cbddceb435e13d81601755714e9fSE Android#include "handle.h"
7255e72915d4cbddceb435e13d81601755714e9fSE Android
8255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h>
9255e72915d4cbddceb435e13d81601755714e9fSE Android#include "port_internal.h"
10255e72915d4cbddceb435e13d81601755714e9fSE Android
11255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int sepol2ipproto(sepol_handle_t * handle, int proto)
12255e72915d4cbddceb435e13d81601755714e9fSE Android{
13255e72915d4cbddceb435e13d81601755714e9fSE Android
14255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
15255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_TCP:
16255e72915d4cbddceb435e13d81601755714e9fSE Android		return IPPROTO_TCP;
17255e72915d4cbddceb435e13d81601755714e9fSE Android	case SEPOL_PROTO_UDP:
18255e72915d4cbddceb435e13d81601755714e9fSE Android		return IPPROTO_UDP;
19255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
20255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "unsupported protocol %u", proto);
21255e72915d4cbddceb435e13d81601755714e9fSE Android		return STATUS_ERR;
22255e72915d4cbddceb435e13d81601755714e9fSE Android	}
23255e72915d4cbddceb435e13d81601755714e9fSE Android}
24255e72915d4cbddceb435e13d81601755714e9fSE Android
25255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic inline int ipproto2sepol(sepol_handle_t * handle, int proto)
26255e72915d4cbddceb435e13d81601755714e9fSE Android{
27255e72915d4cbddceb435e13d81601755714e9fSE Android
28255e72915d4cbddceb435e13d81601755714e9fSE Android	switch (proto) {
29255e72915d4cbddceb435e13d81601755714e9fSE Android	case IPPROTO_TCP:
30255e72915d4cbddceb435e13d81601755714e9fSE Android		return SEPOL_PROTO_TCP;
31255e72915d4cbddceb435e13d81601755714e9fSE Android	case IPPROTO_UDP:
32255e72915d4cbddceb435e13d81601755714e9fSE Android		return SEPOL_PROTO_UDP;
33255e72915d4cbddceb435e13d81601755714e9fSE Android	default:
34255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "invalid protocol %u " "found in policy", proto);
35255e72915d4cbddceb435e13d81601755714e9fSE Android		return STATUS_ERR;
36255e72915d4cbddceb435e13d81601755714e9fSE Android	}
37255e72915d4cbddceb435e13d81601755714e9fSE Android}
38255e72915d4cbddceb435e13d81601755714e9fSE Android
39255e72915d4cbddceb435e13d81601755714e9fSE Android/* Create a low level port structure from
40255e72915d4cbddceb435e13d81601755714e9fSE Android * a high level representation */
41255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int port_from_record(sepol_handle_t * handle,
42255e72915d4cbddceb435e13d81601755714e9fSE Android			    const policydb_t * policydb,
43255e72915d4cbddceb435e13d81601755714e9fSE Android			    ocontext_t ** port, const sepol_port_t * data)
44255e72915d4cbddceb435e13d81601755714e9fSE Android{
45255e72915d4cbddceb435e13d81601755714e9fSE Android
46255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *tmp_port = NULL;
47255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *tmp_con = NULL;
48255e72915d4cbddceb435e13d81601755714e9fSE Android	int tmp_proto;
49255e72915d4cbddceb435e13d81601755714e9fSE Android
50255e72915d4cbddceb435e13d81601755714e9fSE Android	int low = sepol_port_get_low(data);
51255e72915d4cbddceb435e13d81601755714e9fSE Android	int high = sepol_port_get_high(data);
52255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto = sepol_port_get_proto(data);
53255e72915d4cbddceb435e13d81601755714e9fSE Android
54255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_port = (ocontext_t *) calloc(1, sizeof(ocontext_t));
55255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!tmp_port)
56255e72915d4cbddceb435e13d81601755714e9fSE Android		goto omem;
57255e72915d4cbddceb435e13d81601755714e9fSE Android
58255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Process protocol */
59255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_proto = sepol2ipproto(handle, proto);
60255e72915d4cbddceb435e13d81601755714e9fSE Android	if (tmp_proto < 0)
61255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
62255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_port->u.port.protocol = tmp_proto;
63255e72915d4cbddceb435e13d81601755714e9fSE Android
64255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Port range */
65255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_port->u.port.low_port = low;
66255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_port->u.port.high_port = high;
67255e72915d4cbddceb435e13d81601755714e9fSE Android	if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) {
68255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(handle, "low port %d exceeds high port %d",
69255e72915d4cbddceb435e13d81601755714e9fSE Android		    tmp_port->u.port.low_port, tmp_port->u.port.high_port);
70255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
71255e72915d4cbddceb435e13d81601755714e9fSE Android	}
72255e72915d4cbddceb435e13d81601755714e9fSE Android
73255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Context */
74255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_from_record(handle, policydb, &tmp_con,
75255e72915d4cbddceb435e13d81601755714e9fSE Android				sepol_port_get_con(data)) < 0)
76255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
77255e72915d4cbddceb435e13d81601755714e9fSE Android	context_cpy(&tmp_port->context[0], tmp_con);
78255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(tmp_con);
79255e72915d4cbddceb435e13d81601755714e9fSE Android	free(tmp_con);
80255e72915d4cbddceb435e13d81601755714e9fSE Android	tmp_con = NULL;
81255e72915d4cbddceb435e13d81601755714e9fSE Android
82255e72915d4cbddceb435e13d81601755714e9fSE Android	*port = tmp_port;
83255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
84255e72915d4cbddceb435e13d81601755714e9fSE Android
85255e72915d4cbddceb435e13d81601755714e9fSE Android      omem:
86255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "out of memory");
87255e72915d4cbddceb435e13d81601755714e9fSE Android
88255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
89255e72915d4cbddceb435e13d81601755714e9fSE Android	if (tmp_port != NULL) {
90255e72915d4cbddceb435e13d81601755714e9fSE Android		context_destroy(&tmp_port->context[0]);
91255e72915d4cbddceb435e13d81601755714e9fSE Android		free(tmp_port);
92255e72915d4cbddceb435e13d81601755714e9fSE Android	}
93255e72915d4cbddceb435e13d81601755714e9fSE Android	context_destroy(tmp_con);
94255e72915d4cbddceb435e13d81601755714e9fSE Android	free(tmp_con);
95255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not create port structure for range %u:%u (%s)",
96255e72915d4cbddceb435e13d81601755714e9fSE Android	    low, high, sepol_port_get_proto_str(proto));
97255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
98255e72915d4cbddceb435e13d81601755714e9fSE Android}
99255e72915d4cbddceb435e13d81601755714e9fSE Android
100255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int port_to_record(sepol_handle_t * handle,
101255e72915d4cbddceb435e13d81601755714e9fSE Android			  const policydb_t * policydb,
102255e72915d4cbddceb435e13d81601755714e9fSE Android			  ocontext_t * port, sepol_port_t ** record)
103255e72915d4cbddceb435e13d81601755714e9fSE Android{
104255e72915d4cbddceb435e13d81601755714e9fSE Android
105255e72915d4cbddceb435e13d81601755714e9fSE Android	int proto = port->u.port.protocol;
106255e72915d4cbddceb435e13d81601755714e9fSE Android	int low = port->u.port.low_port;
107255e72915d4cbddceb435e13d81601755714e9fSE Android	int high = port->u.port.high_port;
108255e72915d4cbddceb435e13d81601755714e9fSE Android	context_struct_t *con = &port->context[0];
109255e72915d4cbddceb435e13d81601755714e9fSE Android	int rec_proto = -1;
110255e72915d4cbddceb435e13d81601755714e9fSE Android
111255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_t *tmp_con = NULL;
112255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_t *tmp_record = NULL;
113255e72915d4cbddceb435e13d81601755714e9fSE Android
114255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_port_create(handle, &tmp_record) < 0)
115255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
116255e72915d4cbddceb435e13d81601755714e9fSE Android
117255e72915d4cbddceb435e13d81601755714e9fSE Android	rec_proto = ipproto2sepol(handle, proto);
118255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rec_proto < 0)
119255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
120255e72915d4cbddceb435e13d81601755714e9fSE Android
121255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_set_proto(tmp_record, rec_proto);
122255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_set_range(tmp_record, low, high);
123255e72915d4cbddceb435e13d81601755714e9fSE Android
124255e72915d4cbddceb435e13d81601755714e9fSE Android	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
125255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
126255e72915d4cbddceb435e13d81601755714e9fSE Android
127255e72915d4cbddceb435e13d81601755714e9fSE Android	if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0)
128255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
129255e72915d4cbddceb435e13d81601755714e9fSE Android
130255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_free(tmp_con);
131255e72915d4cbddceb435e13d81601755714e9fSE Android	*record = tmp_record;
132255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
133255e72915d4cbddceb435e13d81601755714e9fSE Android
134255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
135255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not convert port range %u - %u (%s) "
136255e72915d4cbddceb435e13d81601755714e9fSE Android	    "to record", low, high, sepol_port_get_proto_str(rec_proto));
137255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_context_free(tmp_con);
138255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_free(tmp_record);
139255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
140255e72915d4cbddceb435e13d81601755714e9fSE Android}
141255e72915d4cbddceb435e13d81601755714e9fSE Android
142255e72915d4cbddceb435e13d81601755714e9fSE Android/* Return the number of ports */
143255e72915d4cbddceb435e13d81601755714e9fSE Androidextern int sepol_port_count(sepol_handle_t * handle __attribute__ ((unused)),
144255e72915d4cbddceb435e13d81601755714e9fSE Android			    const sepol_policydb_t * p, unsigned int *response)
145255e72915d4cbddceb435e13d81601755714e9fSE Android{
146255e72915d4cbddceb435e13d81601755714e9fSE Android
147255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int count = 0;
148255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
149255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
150255e72915d4cbddceb435e13d81601755714e9fSE Android
151255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_PORT];
152255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c != NULL; c = c->next)
153255e72915d4cbddceb435e13d81601755714e9fSE Android		count++;
154255e72915d4cbddceb435e13d81601755714e9fSE Android
155255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = count;
156255e72915d4cbddceb435e13d81601755714e9fSE Android
157255e72915d4cbddceb435e13d81601755714e9fSE Android	handle = NULL;
158255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
159255e72915d4cbddceb435e13d81601755714e9fSE Android}
160255e72915d4cbddceb435e13d81601755714e9fSE Android
161255e72915d4cbddceb435e13d81601755714e9fSE Android/* Check if a port exists */
162255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_port_exists(sepol_handle_t * handle,
163255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_policydb_t * p,
164255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_port_key_t * key, int *response)
165255e72915d4cbddceb435e13d81601755714e9fSE Android{
166255e72915d4cbddceb435e13d81601755714e9fSE Android
167255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
168255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
169255e72915d4cbddceb435e13d81601755714e9fSE Android
170255e72915d4cbddceb435e13d81601755714e9fSE Android	int low, high, proto;
171255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *proto_str;
172255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_key_unpack(key, &low, &high, &proto);
173255e72915d4cbddceb435e13d81601755714e9fSE Android	proto_str = sepol_port_get_proto_str(proto);
174255e72915d4cbddceb435e13d81601755714e9fSE Android	proto = sepol2ipproto(handle, proto);
175255e72915d4cbddceb435e13d81601755714e9fSE Android	if (proto < 0)
176255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
177255e72915d4cbddceb435e13d81601755714e9fSE Android
178255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_PORT];
179255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c; c = c->next) {
180255e72915d4cbddceb435e13d81601755714e9fSE Android		int proto2 = c->u.port.protocol;
181255e72915d4cbddceb435e13d81601755714e9fSE Android		int low2 = c->u.port.low_port;
182255e72915d4cbddceb435e13d81601755714e9fSE Android		int high2 = c->u.port.high_port;
183255e72915d4cbddceb435e13d81601755714e9fSE Android
184255e72915d4cbddceb435e13d81601755714e9fSE Android		if (proto == proto2 && low2 == low && high2 == high) {
185255e72915d4cbddceb435e13d81601755714e9fSE Android			*response = 1;
186255e72915d4cbddceb435e13d81601755714e9fSE Android			return STATUS_SUCCESS;
187255e72915d4cbddceb435e13d81601755714e9fSE Android		}
188255e72915d4cbddceb435e13d81601755714e9fSE Android	}
189255e72915d4cbddceb435e13d81601755714e9fSE Android
190255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = 0;
191255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
192255e72915d4cbddceb435e13d81601755714e9fSE Android
193255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
194255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not check if port range %u - %u (%s) exists",
195255e72915d4cbddceb435e13d81601755714e9fSE Android	    low, high, proto_str);
196255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
197255e72915d4cbddceb435e13d81601755714e9fSE Android}
198255e72915d4cbddceb435e13d81601755714e9fSE Android
199255e72915d4cbddceb435e13d81601755714e9fSE Android/* Query a port */
200255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_port_query(sepol_handle_t * handle,
201255e72915d4cbddceb435e13d81601755714e9fSE Android		     const sepol_policydb_t * p,
202255e72915d4cbddceb435e13d81601755714e9fSE Android		     const sepol_port_key_t * key, sepol_port_t ** response)
203255e72915d4cbddceb435e13d81601755714e9fSE Android{
204255e72915d4cbddceb435e13d81601755714e9fSE Android
205255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
206255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
207255e72915d4cbddceb435e13d81601755714e9fSE Android
208255e72915d4cbddceb435e13d81601755714e9fSE Android	int low, high, proto;
209255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *proto_str;
210255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_key_unpack(key, &low, &high, &proto);
211255e72915d4cbddceb435e13d81601755714e9fSE Android	proto_str = sepol_port_get_proto_str(proto);
212255e72915d4cbddceb435e13d81601755714e9fSE Android	proto = sepol2ipproto(handle, proto);
213255e72915d4cbddceb435e13d81601755714e9fSE Android	if (proto < 0)
214255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
215255e72915d4cbddceb435e13d81601755714e9fSE Android
216255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_PORT];
217255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c; c = c->next) {
218255e72915d4cbddceb435e13d81601755714e9fSE Android		int proto2 = c->u.port.protocol;
219255e72915d4cbddceb435e13d81601755714e9fSE Android		int low2 = c->u.port.low_port;
220255e72915d4cbddceb435e13d81601755714e9fSE Android		int high2 = c->u.port.high_port;
221255e72915d4cbddceb435e13d81601755714e9fSE Android
222255e72915d4cbddceb435e13d81601755714e9fSE Android		if (proto == proto2 && low2 == low && high2 == high) {
223255e72915d4cbddceb435e13d81601755714e9fSE Android			if (port_to_record(handle, policydb, c, response) < 0)
224255e72915d4cbddceb435e13d81601755714e9fSE Android				goto err;
225255e72915d4cbddceb435e13d81601755714e9fSE Android			return STATUS_SUCCESS;
226255e72915d4cbddceb435e13d81601755714e9fSE Android		}
227255e72915d4cbddceb435e13d81601755714e9fSE Android	}
228255e72915d4cbddceb435e13d81601755714e9fSE Android
229255e72915d4cbddceb435e13d81601755714e9fSE Android	*response = NULL;
230255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
231255e72915d4cbddceb435e13d81601755714e9fSE Android
232255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
233255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not query port range %u - %u (%s)",
234255e72915d4cbddceb435e13d81601755714e9fSE Android	    low, high, proto_str);
235255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
236255e72915d4cbddceb435e13d81601755714e9fSE Android
237255e72915d4cbddceb435e13d81601755714e9fSE Android}
238255e72915d4cbddceb435e13d81601755714e9fSE Android
239255e72915d4cbddceb435e13d81601755714e9fSE Android/* Load a port into policy */
240255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_port_modify(sepol_handle_t * handle,
241255e72915d4cbddceb435e13d81601755714e9fSE Android		      sepol_policydb_t * p,
242255e72915d4cbddceb435e13d81601755714e9fSE Android		      const sepol_port_key_t * key, const sepol_port_t * data)
243255e72915d4cbddceb435e13d81601755714e9fSE Android{
244255e72915d4cbddceb435e13d81601755714e9fSE Android
245255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *policydb = &p->p;
246255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *port = NULL;
247255e72915d4cbddceb435e13d81601755714e9fSE Android
248255e72915d4cbddceb435e13d81601755714e9fSE Android	int low, high, proto;
249255e72915d4cbddceb435e13d81601755714e9fSE Android	const char *proto_str;
250255e72915d4cbddceb435e13d81601755714e9fSE Android
251255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_key_unpack(key, &low, &high, &proto);
252255e72915d4cbddceb435e13d81601755714e9fSE Android	proto_str = sepol_port_get_proto_str(proto);
253255e72915d4cbddceb435e13d81601755714e9fSE Android	proto = sepol2ipproto(handle, proto);
254255e72915d4cbddceb435e13d81601755714e9fSE Android	if (proto < 0)
255255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
256255e72915d4cbddceb435e13d81601755714e9fSE Android
257255e72915d4cbddceb435e13d81601755714e9fSE Android	if (port_from_record(handle, policydb, &port, data) < 0)
258255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
259255e72915d4cbddceb435e13d81601755714e9fSE Android
260255e72915d4cbddceb435e13d81601755714e9fSE Android	/* Attach to context list */
261255e72915d4cbddceb435e13d81601755714e9fSE Android	port->next = policydb->ocontexts[OCON_PORT];
262255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb->ocontexts[OCON_PORT] = port;
263255e72915d4cbddceb435e13d81601755714e9fSE Android
264255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
265255e72915d4cbddceb435e13d81601755714e9fSE Android
266255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
267255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not load port range %u - %u (%s)",
268255e72915d4cbddceb435e13d81601755714e9fSE Android	    low, high, proto_str);
269255e72915d4cbddceb435e13d81601755714e9fSE Android	if (port != NULL) {
270255e72915d4cbddceb435e13d81601755714e9fSE Android		context_destroy(&port->context[0]);
271255e72915d4cbddceb435e13d81601755714e9fSE Android		free(port);
272255e72915d4cbddceb435e13d81601755714e9fSE Android	}
273255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
274255e72915d4cbddceb435e13d81601755714e9fSE Android}
275255e72915d4cbddceb435e13d81601755714e9fSE Android
276255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_port_iterate(sepol_handle_t * handle,
277255e72915d4cbddceb435e13d81601755714e9fSE Android		       const sepol_policydb_t * p,
278255e72915d4cbddceb435e13d81601755714e9fSE Android		       int (*fn) (const sepol_port_t * port,
279255e72915d4cbddceb435e13d81601755714e9fSE Android				  void *fn_arg), void *arg)
280255e72915d4cbddceb435e13d81601755714e9fSE Android{
281255e72915d4cbddceb435e13d81601755714e9fSE Android
282255e72915d4cbddceb435e13d81601755714e9fSE Android	const policydb_t *policydb = &p->p;
283255e72915d4cbddceb435e13d81601755714e9fSE Android	ocontext_t *c, *head;
284255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_t *port = NULL;
285255e72915d4cbddceb435e13d81601755714e9fSE Android
286255e72915d4cbddceb435e13d81601755714e9fSE Android	head = policydb->ocontexts[OCON_PORT];
287255e72915d4cbddceb435e13d81601755714e9fSE Android	for (c = head; c; c = c->next) {
288255e72915d4cbddceb435e13d81601755714e9fSE Android		int status;
289255e72915d4cbddceb435e13d81601755714e9fSE Android
290255e72915d4cbddceb435e13d81601755714e9fSE Android		if (port_to_record(handle, policydb, c, &port) < 0)
291255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
292255e72915d4cbddceb435e13d81601755714e9fSE Android
293255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Invoke handler */
294255e72915d4cbddceb435e13d81601755714e9fSE Android		status = fn(port, arg);
295255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status < 0)
296255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
297255e72915d4cbddceb435e13d81601755714e9fSE Android
298255e72915d4cbddceb435e13d81601755714e9fSE Android		sepol_port_free(port);
299255e72915d4cbddceb435e13d81601755714e9fSE Android		port = NULL;
300255e72915d4cbddceb435e13d81601755714e9fSE Android
301255e72915d4cbddceb435e13d81601755714e9fSE Android		/* Handler requested exit */
302255e72915d4cbddceb435e13d81601755714e9fSE Android		if (status > 0)
303255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
304255e72915d4cbddceb435e13d81601755714e9fSE Android	}
305255e72915d4cbddceb435e13d81601755714e9fSE Android
306255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_SUCCESS;
307255e72915d4cbddceb435e13d81601755714e9fSE Android
308255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
309255e72915d4cbddceb435e13d81601755714e9fSE Android	ERR(handle, "could not iterate over ports");
310255e72915d4cbddceb435e13d81601755714e9fSE Android	sepol_port_free(port);
311255e72915d4cbddceb435e13d81601755714e9fSE Android	return STATUS_ERR;
312255e72915d4cbddceb435e13d81601755714e9fSE Android}
313