#include <netinet/in.h>
#include <stdlib.h>
#include "debug.h"
#include "context.h"
#include "handle.h"
#include <sepol/policydb/policydb.h>
#include "ibendport_internal.h"
/* Create a low level ibendport structure from
* a high level representation
*/
static int ibendport_from_record(sepol_handle_t *handle,
const policydb_t *policydb,
ocontext_t **ibendport,
const sepol_ibendport_t *data)
{
ocontext_t *tmp_ibendport = NULL;
context_struct_t *tmp_con = NULL;
char *ibdev_name = NULL;
int port = sepol_ibendport_get_port(data);
tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t));
if (!tmp_ibendport)
goto omem;
if (sepol_ibendport_alloc_ibdev_name(handle,
&tmp_ibendport->u.ibendport.dev_name) < 0)
goto omem;
if (sepol_ibendport_get_ibdev_name(handle,
data,
&ibdev_name) < 0)
goto err;
strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX);
free(ibdev_name);
ibdev_name = NULL;
tmp_ibendport->u.ibendport.port = port;
/* Context */
if (context_from_record(handle, policydb, &tmp_con,
sepol_ibendport_get_con(data)) < 0)
goto err;
context_cpy(&tmp_ibendport->context[0], tmp_con);
context_destroy(tmp_con);
free(tmp_con);
tmp_con = NULL;
*ibendport = tmp_ibendport;
return STATUS_SUCCESS;
omem:
ERR(handle, "out of memory");
err:
if (tmp_ibendport) {
context_destroy(&tmp_ibendport->context[0]);
free(tmp_ibendport);
}
context_destroy(tmp_con);
free(tmp_con);
free(ibdev_name);
ERR(handle, "could not create ibendport structure");
return STATUS_ERR;
}
static int ibendport_to_record(sepol_handle_t *handle,
const policydb_t *policydb,
ocontext_t *ibendport,
sepol_ibendport_t **record)
{
int port = ibendport->u.ibendport.port;
context_struct_t *con = &ibendport->context[0];
sepol_context_t *tmp_con = NULL;
sepol_ibendport_t *tmp_record = NULL;
if (sepol_ibendport_create(handle, &tmp_record) < 0)
goto err;
if (sepol_ibendport_set_ibdev_name(handle, tmp_record,
ibendport->u.ibendport.dev_name) < 0)
goto err;
sepol_ibendport_set_port(tmp_record, port);
if (context_to_record(handle, policydb, con, &tmp_con) < 0)
goto err;
if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0)
goto err;
sepol_context_free(tmp_con);
*record = tmp_record;
return STATUS_SUCCESS;
err:
ERR(handle, "could not convert ibendport to record");
sepol_context_free(tmp_con);
sepol_ibendport_free(tmp_record);
return STATUS_ERR;
}
/* Return the number of ibendports */
extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)),
const sepol_policydb_t *p, unsigned int *response)
{
unsigned int count = 0;
ocontext_t *c, *head;
const policydb_t *policydb = &p->p;
head = policydb->ocontexts[OCON_IBENDPORT];
for (c = head; c; c = c->next)
count++;
*response = count;
return STATUS_SUCCESS;
}
/* Check if a ibendport exists */
int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)),
const sepol_policydb_t *p,
const sepol_ibendport_key_t *key, int *response)
{
const policydb_t *policydb = &p->p;
ocontext_t *c, *head;
int port;
const char *ibdev_name;
sepol_ibendport_key_unpack(key, &ibdev_name, &port);
head = policydb->ocontexts[OCON_IBENDPORT];
for (c = head; c; c = c->next) {
const char *ibdev_name2 = c->u.ibendport.dev_name;
int port2 = c->u.ibendport.port;
if (port2 == port &&
(!strcmp(ibdev_name, ibdev_name2))) {
*response = 1;
return STATUS_SUCCESS;
}
}
*response = 0;
return STATUS_SUCCESS;
}
int sepol_ibendport_query(sepol_handle_t *handle,
const sepol_policydb_t *p,
const sepol_ibendport_key_t *key,
sepol_ibendport_t **response)
{
const policydb_t *policydb = &p->p;
ocontext_t *c, *head;
int port;
const char *ibdev_name;
sepol_ibendport_key_unpack(key, &ibdev_name, &port);
head = policydb->ocontexts[OCON_IBENDPORT];
for (c = head; c; c = c->next) {
const char *ibdev_name2 = c->u.ibendport.dev_name;
int port2 = c->u.ibendport.port;
if (port2 == port &&
(!strcmp(ibdev_name, ibdev_name2))) {
if (ibendport_to_record(handle, policydb, c, response) < 0)
goto err;
return STATUS_SUCCESS;
}
}
*response = NULL;
return STATUS_SUCCESS;
err:
ERR(handle, "could not query ibendport, IB device: %s port %u",
ibdev_name, port);
return STATUS_ERR;
}
/* Load a ibendport into policy */
int sepol_ibendport_modify(sepol_handle_t *handle,
sepol_policydb_t *p,
const sepol_ibendport_key_t *key,
const sepol_ibendport_t *data)
{
policydb_t *policydb = &p->p;
ocontext_t *ibendport = NULL;
int port;
const char *ibdev_name;
sepol_ibendport_key_unpack(key, &ibdev_name, &port);
if (ibendport_from_record(handle, policydb, &ibendport, data) < 0)
goto err;
/* Attach to context list */
ibendport->next = policydb->ocontexts[OCON_IBENDPORT];
policydb->ocontexts[OCON_IBENDPORT] = ibendport;
return STATUS_SUCCESS;
err:
ERR(handle, "could not load ibendport %s/%d",
ibdev_name, port);
if (ibendport) {
context_destroy(&ibendport->context[0]);
free(ibendport);
}
return STATUS_ERR;
}
int sepol_ibendport_iterate(sepol_handle_t *handle,
const sepol_policydb_t *p,
int (*fn)(const sepol_ibendport_t *ibendport,
void *fn_arg), void *arg)
{
const policydb_t *policydb = &p->p;
ocontext_t *c, *head;
sepol_ibendport_t *ibendport = NULL;
head = policydb->ocontexts[OCON_IBENDPORT];
for (c = head; c; c = c->next) {
int status;
if (ibendport_to_record(handle, policydb, c, &ibendport) < 0)
goto err;
/* Invoke handler */
status = fn(ibendport, arg);
if (status < 0)
goto err;
sepol_ibendport_free(ibendport);
ibendport = NULL;
/* Handler requested exit */
if (status > 0)
break;
}
return STATUS_SUCCESS;
err:
ERR(handle, "could not iterate over ibendports");
sepol_ibendport_free(ibendport);
return STATUS_ERR;
}