1#include <netinet/in.h>
2#include <stdlib.h>
3
4#include "debug.h"
5#include "context.h"
6#include "handle.h"
7
8#include <sepol/policydb/policydb.h>
9#include "ibendport_internal.h"
10
11/* Create a low level ibendport structure from
12 * a high level representation
13 */
14static int ibendport_from_record(sepol_handle_t *handle,
15				 const policydb_t *policydb,
16				 ocontext_t **ibendport,
17				 const sepol_ibendport_t *data)
18{
19	ocontext_t *tmp_ibendport = NULL;
20	context_struct_t *tmp_con = NULL;
21	char *ibdev_name = NULL;
22	int port = sepol_ibendport_get_port(data);
23
24	tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t));
25	if (!tmp_ibendport)
26		goto omem;
27
28	if (sepol_ibendport_alloc_ibdev_name(handle,
29					     &tmp_ibendport->u.ibendport.dev_name) < 0)
30		goto omem;
31
32	if (sepol_ibendport_get_ibdev_name(handle,
33					   data,
34					   &ibdev_name) < 0)
35		goto err;
36
37	strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
38
39	free(ibdev_name);
40	ibdev_name = NULL;
41
42	tmp_ibendport->u.ibendport.port = port;
43
44	/* Context */
45	if (context_from_record(handle, policydb, &tmp_con,
46				sepol_ibendport_get_con(data)) < 0)
47		goto err;
48	context_cpy(&tmp_ibendport->context[0], tmp_con);
49	context_destroy(tmp_con);
50	free(tmp_con);
51	tmp_con = NULL;
52
53	*ibendport = tmp_ibendport;
54	return STATUS_SUCCESS;
55
56omem:
57	ERR(handle, "out of memory");
58
59err:
60	if (tmp_ibendport) {
61		context_destroy(&tmp_ibendport->context[0]);
62		free(tmp_ibendport);
63	}
64	context_destroy(tmp_con);
65	free(tmp_con);
66	free(ibdev_name);
67	ERR(handle, "could not create ibendport structure");
68	return STATUS_ERR;
69}
70
71static int ibendport_to_record(sepol_handle_t *handle,
72			       const policydb_t *policydb,
73			       ocontext_t *ibendport,
74			       sepol_ibendport_t **record)
75{
76	int port = ibendport->u.ibendport.port;
77	context_struct_t *con = &ibendport->context[0];
78
79	sepol_context_t *tmp_con = NULL;
80	sepol_ibendport_t *tmp_record = NULL;
81
82	if (sepol_ibendport_create(handle, &tmp_record) < 0)
83		goto err;
84
85	if (sepol_ibendport_set_ibdev_name(handle, tmp_record,
86					   ibendport->u.ibendport.dev_name) < 0)
87		goto err;
88
89	sepol_ibendport_set_port(tmp_record, port);
90
91	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
92		goto err;
93
94	if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0)
95		goto err;
96
97	sepol_context_free(tmp_con);
98	*record = tmp_record;
99	return STATUS_SUCCESS;
100
101err:
102	ERR(handle, "could not convert ibendport to record");
103	sepol_context_free(tmp_con);
104	sepol_ibendport_free(tmp_record);
105	return STATUS_ERR;
106}
107
108/* Return the number of ibendports */
109extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)),
110				 const sepol_policydb_t *p, unsigned int *response)
111{
112	unsigned int count = 0;
113	ocontext_t *c, *head;
114	const policydb_t *policydb = &p->p;
115
116	head = policydb->ocontexts[OCON_IBENDPORT];
117	for (c = head; c; c = c->next)
118		count++;
119
120	*response = count;
121
122	return STATUS_SUCCESS;
123}
124
125/* Check if a ibendport exists */
126int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)),
127			   const sepol_policydb_t *p,
128			   const sepol_ibendport_key_t *key, int *response)
129{
130	const policydb_t *policydb = &p->p;
131	ocontext_t *c, *head;
132	int port;
133	const char *ibdev_name;
134
135	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
136
137	head = policydb->ocontexts[OCON_IBENDPORT];
138	for (c = head; c; c = c->next) {
139		const char *ibdev_name2 = c->u.ibendport.dev_name;
140		int port2 = c->u.ibendport.port;
141
142		if (port2 == port &&
143		    (!strcmp(ibdev_name, ibdev_name2))) {
144			*response = 1;
145			return STATUS_SUCCESS;
146		}
147	}
148
149	*response = 0;
150	return STATUS_SUCCESS;
151}
152
153int sepol_ibendport_query(sepol_handle_t *handle,
154			  const sepol_policydb_t *p,
155			  const sepol_ibendport_key_t *key,
156			  sepol_ibendport_t **response)
157{
158	const policydb_t *policydb = &p->p;
159	ocontext_t *c, *head;
160	int port;
161	const char *ibdev_name;
162
163	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
164
165	head = policydb->ocontexts[OCON_IBENDPORT];
166	for (c = head; c; c = c->next) {
167		const char *ibdev_name2 = c->u.ibendport.dev_name;
168		int port2 = c->u.ibendport.port;
169
170		if (port2 == port &&
171		    (!strcmp(ibdev_name, ibdev_name2))) {
172			if (ibendport_to_record(handle, policydb, c, response) < 0)
173				goto err;
174			return STATUS_SUCCESS;
175		}
176	}
177
178	*response = NULL;
179	return STATUS_SUCCESS;
180
181err:
182	ERR(handle, "could not query ibendport, IB device: %s port %u",
183	    ibdev_name, port);
184	return STATUS_ERR;
185}
186
187/* Load a ibendport into policy */
188int sepol_ibendport_modify(sepol_handle_t *handle,
189			   sepol_policydb_t *p,
190			   const sepol_ibendport_key_t *key,
191			   const sepol_ibendport_t *data)
192{
193	policydb_t *policydb = &p->p;
194	ocontext_t *ibendport = NULL;
195	int port;
196	const char *ibdev_name;
197
198	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
199
200	if (ibendport_from_record(handle, policydb, &ibendport, data) < 0)
201		goto err;
202
203	/* Attach to context list */
204	ibendport->next = policydb->ocontexts[OCON_IBENDPORT];
205	policydb->ocontexts[OCON_IBENDPORT] = ibendport;
206
207	return STATUS_SUCCESS;
208
209err:
210	ERR(handle, "could not load ibendport %s/%d",
211	    ibdev_name, port);
212	if (ibendport) {
213		context_destroy(&ibendport->context[0]);
214		free(ibendport);
215	}
216	return STATUS_ERR;
217}
218
219int sepol_ibendport_iterate(sepol_handle_t *handle,
220			    const sepol_policydb_t *p,
221			    int (*fn)(const sepol_ibendport_t *ibendport,
222				      void *fn_arg), void *arg)
223{
224	const policydb_t *policydb = &p->p;
225	ocontext_t *c, *head;
226	sepol_ibendport_t *ibendport = NULL;
227
228	head = policydb->ocontexts[OCON_IBENDPORT];
229	for (c = head; c; c = c->next) {
230		int status;
231
232		if (ibendport_to_record(handle, policydb, c, &ibendport) < 0)
233			goto err;
234
235		/* Invoke handler */
236		status = fn(ibendport, arg);
237		if (status < 0)
238			goto err;
239
240		sepol_ibendport_free(ibendport);
241		ibendport = NULL;
242
243		/* Handler requested exit */
244		if (status > 0)
245			break;
246	}
247
248	return STATUS_SUCCESS;
249
250err:
251	ERR(handle, "could not iterate over ibendports");
252	sepol_ibendport_free(ibendport);
253	return STATUS_ERR;
254}
255