16cd6a6acSopenharmony_ci#include <netinet/in.h>
26cd6a6acSopenharmony_ci#include <stdlib.h>
36cd6a6acSopenharmony_ci
46cd6a6acSopenharmony_ci#include "debug.h"
56cd6a6acSopenharmony_ci#include "context.h"
66cd6a6acSopenharmony_ci#include "handle.h"
76cd6a6acSopenharmony_ci
86cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
96cd6a6acSopenharmony_ci#include "ibendport_internal.h"
106cd6a6acSopenharmony_ci
116cd6a6acSopenharmony_ci/* Create a low level ibendport structure from
126cd6a6acSopenharmony_ci * a high level representation
136cd6a6acSopenharmony_ci */
146cd6a6acSopenharmony_cistatic int ibendport_from_record(sepol_handle_t *handle,
156cd6a6acSopenharmony_ci				 const policydb_t *policydb,
166cd6a6acSopenharmony_ci				 ocontext_t **ibendport,
176cd6a6acSopenharmony_ci				 const sepol_ibendport_t *data)
186cd6a6acSopenharmony_ci{
196cd6a6acSopenharmony_ci	ocontext_t *tmp_ibendport = NULL;
206cd6a6acSopenharmony_ci	context_struct_t *tmp_con = NULL;
216cd6a6acSopenharmony_ci	char *ibdev_name = NULL;
226cd6a6acSopenharmony_ci	int port = sepol_ibendport_get_port(data);
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_ci	tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t));
256cd6a6acSopenharmony_ci	if (!tmp_ibendport)
266cd6a6acSopenharmony_ci		goto omem;
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	if (sepol_ibendport_alloc_ibdev_name(handle,
296cd6a6acSopenharmony_ci					     &tmp_ibendport->u.ibendport.dev_name) < 0)
306cd6a6acSopenharmony_ci		goto omem;
316cd6a6acSopenharmony_ci
326cd6a6acSopenharmony_ci	if (sepol_ibendport_get_ibdev_name(handle,
336cd6a6acSopenharmony_ci					   data,
346cd6a6acSopenharmony_ci					   &ibdev_name) < 0)
356cd6a6acSopenharmony_ci		goto err;
366cd6a6acSopenharmony_ci
376cd6a6acSopenharmony_ci	strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1);
386cd6a6acSopenharmony_ci
396cd6a6acSopenharmony_ci	free(ibdev_name);
406cd6a6acSopenharmony_ci	ibdev_name = NULL;
416cd6a6acSopenharmony_ci
426cd6a6acSopenharmony_ci	tmp_ibendport->u.ibendport.port = port;
436cd6a6acSopenharmony_ci
446cd6a6acSopenharmony_ci	/* Context */
456cd6a6acSopenharmony_ci	if (context_from_record(handle, policydb, &tmp_con,
466cd6a6acSopenharmony_ci				sepol_ibendport_get_con(data)) < 0)
476cd6a6acSopenharmony_ci		goto err;
486cd6a6acSopenharmony_ci	context_cpy(&tmp_ibendport->context[0], tmp_con);
496cd6a6acSopenharmony_ci	context_destroy(tmp_con);
506cd6a6acSopenharmony_ci	free(tmp_con);
516cd6a6acSopenharmony_ci	tmp_con = NULL;
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ci	*ibendport = tmp_ibendport;
546cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_ciomem:
576cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
586cd6a6acSopenharmony_ci
596cd6a6acSopenharmony_cierr:
606cd6a6acSopenharmony_ci	if (tmp_ibendport) {
616cd6a6acSopenharmony_ci		context_destroy(&tmp_ibendport->context[0]);
626cd6a6acSopenharmony_ci		free(tmp_ibendport);
636cd6a6acSopenharmony_ci	}
646cd6a6acSopenharmony_ci	context_destroy(tmp_con);
656cd6a6acSopenharmony_ci	free(tmp_con);
666cd6a6acSopenharmony_ci	free(ibdev_name);
676cd6a6acSopenharmony_ci	ERR(handle, "could not create ibendport structure");
686cd6a6acSopenharmony_ci	return STATUS_ERR;
696cd6a6acSopenharmony_ci}
706cd6a6acSopenharmony_ci
716cd6a6acSopenharmony_cistatic int ibendport_to_record(sepol_handle_t *handle,
726cd6a6acSopenharmony_ci			       const policydb_t *policydb,
736cd6a6acSopenharmony_ci			       ocontext_t *ibendport,
746cd6a6acSopenharmony_ci			       sepol_ibendport_t **record)
756cd6a6acSopenharmony_ci{
766cd6a6acSopenharmony_ci	int port = ibendport->u.ibendport.port;
776cd6a6acSopenharmony_ci	context_struct_t *con = &ibendport->context[0];
786cd6a6acSopenharmony_ci
796cd6a6acSopenharmony_ci	sepol_context_t *tmp_con = NULL;
806cd6a6acSopenharmony_ci	sepol_ibendport_t *tmp_record = NULL;
816cd6a6acSopenharmony_ci
826cd6a6acSopenharmony_ci	if (sepol_ibendport_create(handle, &tmp_record) < 0)
836cd6a6acSopenharmony_ci		goto err;
846cd6a6acSopenharmony_ci
856cd6a6acSopenharmony_ci	if (sepol_ibendport_set_ibdev_name(handle, tmp_record,
866cd6a6acSopenharmony_ci					   ibendport->u.ibendport.dev_name) < 0)
876cd6a6acSopenharmony_ci		goto err;
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ci	sepol_ibendport_set_port(tmp_record, port);
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_ci	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
926cd6a6acSopenharmony_ci		goto err;
936cd6a6acSopenharmony_ci
946cd6a6acSopenharmony_ci	if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0)
956cd6a6acSopenharmony_ci		goto err;
966cd6a6acSopenharmony_ci
976cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
986cd6a6acSopenharmony_ci	*record = tmp_record;
996cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1006cd6a6acSopenharmony_ci
1016cd6a6acSopenharmony_cierr:
1026cd6a6acSopenharmony_ci	ERR(handle, "could not convert ibendport to record");
1036cd6a6acSopenharmony_ci	sepol_context_free(tmp_con);
1046cd6a6acSopenharmony_ci	sepol_ibendport_free(tmp_record);
1056cd6a6acSopenharmony_ci	return STATUS_ERR;
1066cd6a6acSopenharmony_ci}
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_ci/* Return the number of ibendports */
1096cd6a6acSopenharmony_ciextern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)),
1106cd6a6acSopenharmony_ci				 const sepol_policydb_t *p, unsigned int *response)
1116cd6a6acSopenharmony_ci{
1126cd6a6acSopenharmony_ci	unsigned int count = 0;
1136cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1146cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1156cd6a6acSopenharmony_ci
1166cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBENDPORT];
1176cd6a6acSopenharmony_ci	for (c = head; c; c = c->next)
1186cd6a6acSopenharmony_ci		count++;
1196cd6a6acSopenharmony_ci
1206cd6a6acSopenharmony_ci	*response = count;
1216cd6a6acSopenharmony_ci
1226cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1236cd6a6acSopenharmony_ci}
1246cd6a6acSopenharmony_ci
1256cd6a6acSopenharmony_ci/* Check if a ibendport exists */
1266cd6a6acSopenharmony_ciint sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)),
1276cd6a6acSopenharmony_ci			   const sepol_policydb_t *p,
1286cd6a6acSopenharmony_ci			   const sepol_ibendport_key_t *key, int *response)
1296cd6a6acSopenharmony_ci{
1306cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1316cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1326cd6a6acSopenharmony_ci	int port;
1336cd6a6acSopenharmony_ci	const char *ibdev_name;
1346cd6a6acSopenharmony_ci
1356cd6a6acSopenharmony_ci	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
1366cd6a6acSopenharmony_ci
1376cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBENDPORT];
1386cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1396cd6a6acSopenharmony_ci		const char *ibdev_name2 = c->u.ibendport.dev_name;
1406cd6a6acSopenharmony_ci		int port2 = c->u.ibendport.port;
1416cd6a6acSopenharmony_ci
1426cd6a6acSopenharmony_ci		if (port2 == port &&
1436cd6a6acSopenharmony_ci		    (!strcmp(ibdev_name, ibdev_name2))) {
1446cd6a6acSopenharmony_ci			*response = 1;
1456cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1466cd6a6acSopenharmony_ci		}
1476cd6a6acSopenharmony_ci	}
1486cd6a6acSopenharmony_ci
1496cd6a6acSopenharmony_ci	*response = 0;
1506cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1516cd6a6acSopenharmony_ci}
1526cd6a6acSopenharmony_ci
1536cd6a6acSopenharmony_ciint sepol_ibendport_query(sepol_handle_t *handle,
1546cd6a6acSopenharmony_ci			  const sepol_policydb_t *p,
1556cd6a6acSopenharmony_ci			  const sepol_ibendport_key_t *key,
1566cd6a6acSopenharmony_ci			  sepol_ibendport_t **response)
1576cd6a6acSopenharmony_ci{
1586cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
1596cd6a6acSopenharmony_ci	ocontext_t *c, *head;
1606cd6a6acSopenharmony_ci	int port;
1616cd6a6acSopenharmony_ci	const char *ibdev_name;
1626cd6a6acSopenharmony_ci
1636cd6a6acSopenharmony_ci	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
1646cd6a6acSopenharmony_ci
1656cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBENDPORT];
1666cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
1676cd6a6acSopenharmony_ci		const char *ibdev_name2 = c->u.ibendport.dev_name;
1686cd6a6acSopenharmony_ci		int port2 = c->u.ibendport.port;
1696cd6a6acSopenharmony_ci
1706cd6a6acSopenharmony_ci		if (port2 == port &&
1716cd6a6acSopenharmony_ci		    (!strcmp(ibdev_name, ibdev_name2))) {
1726cd6a6acSopenharmony_ci			if (ibendport_to_record(handle, policydb, c, response) < 0)
1736cd6a6acSopenharmony_ci				goto err;
1746cd6a6acSopenharmony_ci			return STATUS_SUCCESS;
1756cd6a6acSopenharmony_ci		}
1766cd6a6acSopenharmony_ci	}
1776cd6a6acSopenharmony_ci
1786cd6a6acSopenharmony_ci	*response = NULL;
1796cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
1806cd6a6acSopenharmony_ci
1816cd6a6acSopenharmony_cierr:
1826cd6a6acSopenharmony_ci	ERR(handle, "could not query ibendport, IB device: %s port %u",
1836cd6a6acSopenharmony_ci	    ibdev_name, port);
1846cd6a6acSopenharmony_ci	return STATUS_ERR;
1856cd6a6acSopenharmony_ci}
1866cd6a6acSopenharmony_ci
1876cd6a6acSopenharmony_ci/* Load a ibendport into policy */
1886cd6a6acSopenharmony_ciint sepol_ibendport_modify(sepol_handle_t *handle,
1896cd6a6acSopenharmony_ci			   sepol_policydb_t *p,
1906cd6a6acSopenharmony_ci			   const sepol_ibendport_key_t *key,
1916cd6a6acSopenharmony_ci			   const sepol_ibendport_t *data)
1926cd6a6acSopenharmony_ci{
1936cd6a6acSopenharmony_ci	policydb_t *policydb = &p->p;
1946cd6a6acSopenharmony_ci	ocontext_t *ibendport = NULL;
1956cd6a6acSopenharmony_ci	int port;
1966cd6a6acSopenharmony_ci	const char *ibdev_name;
1976cd6a6acSopenharmony_ci
1986cd6a6acSopenharmony_ci	sepol_ibendport_key_unpack(key, &ibdev_name, &port);
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci	if (ibendport_from_record(handle, policydb, &ibendport, data) < 0)
2016cd6a6acSopenharmony_ci		goto err;
2026cd6a6acSopenharmony_ci
2036cd6a6acSopenharmony_ci	/* Attach to context list */
2046cd6a6acSopenharmony_ci	ibendport->next = policydb->ocontexts[OCON_IBENDPORT];
2056cd6a6acSopenharmony_ci	policydb->ocontexts[OCON_IBENDPORT] = ibendport;
2066cd6a6acSopenharmony_ci
2076cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2086cd6a6acSopenharmony_ci
2096cd6a6acSopenharmony_cierr:
2106cd6a6acSopenharmony_ci	ERR(handle, "could not load ibendport %s/%d",
2116cd6a6acSopenharmony_ci	    ibdev_name, port);
2126cd6a6acSopenharmony_ci	if (ibendport) {
2136cd6a6acSopenharmony_ci		context_destroy(&ibendport->context[0]);
2146cd6a6acSopenharmony_ci		free(ibendport);
2156cd6a6acSopenharmony_ci	}
2166cd6a6acSopenharmony_ci	return STATUS_ERR;
2176cd6a6acSopenharmony_ci}
2186cd6a6acSopenharmony_ci
2196cd6a6acSopenharmony_ciint sepol_ibendport_iterate(sepol_handle_t *handle,
2206cd6a6acSopenharmony_ci			    const sepol_policydb_t *p,
2216cd6a6acSopenharmony_ci			    int (*fn)(const sepol_ibendport_t *ibendport,
2226cd6a6acSopenharmony_ci				      void *fn_arg), void *arg)
2236cd6a6acSopenharmony_ci{
2246cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
2256cd6a6acSopenharmony_ci	ocontext_t *c, *head;
2266cd6a6acSopenharmony_ci	sepol_ibendport_t *ibendport = NULL;
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_ci	head = policydb->ocontexts[OCON_IBENDPORT];
2296cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
2306cd6a6acSopenharmony_ci		int status;
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_ci		if (ibendport_to_record(handle, policydb, c, &ibendport) < 0)
2336cd6a6acSopenharmony_ci			goto err;
2346cd6a6acSopenharmony_ci
2356cd6a6acSopenharmony_ci		/* Invoke handler */
2366cd6a6acSopenharmony_ci		status = fn(ibendport, arg);
2376cd6a6acSopenharmony_ci		if (status < 0)
2386cd6a6acSopenharmony_ci			goto err;
2396cd6a6acSopenharmony_ci
2406cd6a6acSopenharmony_ci		sepol_ibendport_free(ibendport);
2416cd6a6acSopenharmony_ci		ibendport = NULL;
2426cd6a6acSopenharmony_ci
2436cd6a6acSopenharmony_ci		/* Handler requested exit */
2446cd6a6acSopenharmony_ci		if (status > 0)
2456cd6a6acSopenharmony_ci			break;
2466cd6a6acSopenharmony_ci	}
2476cd6a6acSopenharmony_ci
2486cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2496cd6a6acSopenharmony_ci
2506cd6a6acSopenharmony_cierr:
2516cd6a6acSopenharmony_ci	ERR(handle, "could not iterate over ibendports");
2526cd6a6acSopenharmony_ci	sepol_ibendport_free(ibendport);
2536cd6a6acSopenharmony_ci	return STATUS_ERR;
2546cd6a6acSopenharmony_ci}
255