#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include "sepol/policydb/policydb.h"
#include "ibendport_internal.h"
#include "context_internal.h"
#include "debug.h"
struct sepol_ibendport {
/* Device Name */
char *ibdev_name;
/* Port number */
int port;
/* Context */
sepol_context_t *con;
};
struct sepol_ibendport_key {
/* Device Name */
char *ibdev_name;
/* Port number */
int port;
};
/* Allocates a sufficiently large string (ibdev_name) */
int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle,
char **ibdev_name)
{
*ibdev_name = calloc(1, IB_DEVICE_NAME_MAX);
if (!*ibdev_name)
goto omem;
return STATUS_SUCCESS;
omem:
ERR(handle, "out of memory");
ERR(handle, "could not allocate string buffer for ibdev_name");
return STATUS_ERR;
}
/* Key */
int sepol_ibendport_key_create(sepol_handle_t *handle,
const char *ibdev_name,
int port,
sepol_ibendport_key_t **key_ptr)
{
sepol_ibendport_key_t *tmp_key =
(sepol_ibendport_key_t *)malloc(sizeof(sepol_ibendport_key_t));
if (!tmp_key) {
ERR(handle, "out of memory, could not create ibendport key");
goto omem;
}
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0)
goto err;
strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX);
tmp_key->port = port;
*key_ptr = tmp_key;
return STATUS_SUCCESS;
omem:
ERR(handle, "out of memory");
err:
sepol_ibendport_key_free(tmp_key);
ERR(handle, "could not create ibendport key for IB device %s, port %u",
ibdev_name, port);
return STATUS_ERR;
}
hidden_def(sepol_ibendport_key_create)
void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key,
const char **ibdev_name, int *port)
{
*ibdev_name = key->ibdev_name;
*port = key->port;
}
hidden_def(sepol_ibendport_key_unpack)
int sepol_ibendport_key_extract(sepol_handle_t *handle,
const sepol_ibendport_t *ibendport,
sepol_ibendport_key_t **key_ptr)
{
if (sepol_ibendport_key_create
(handle, ibendport->ibdev_name, ibendport->port, key_ptr) < 0) {
ERR(handle, "could not extract key from ibendport device %s port %d",
ibendport->ibdev_name,
ibendport->port);
return STATUS_ERR;
}
return STATUS_SUCCESS;
}
void sepol_ibendport_key_free(sepol_ibendport_key_t *key)
{
if (!key)
return;
free(key->ibdev_name);
free(key);
}
int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key)
{
int rc;
rc = strcmp(ibendport->ibdev_name, key->ibdev_name);
if ((ibendport->port == key->port) && !rc)
return 0;
if (ibendport->port < key->port)
return -1;
else if (key->port < ibendport->port)
return 1;
else
return rc;
}
int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2)
{
int rc;
rc = strcmp(ibendport->ibdev_name, ibendport2->ibdev_name);
if ((ibendport->port == ibendport2->port) && !rc)
return 0;
if (ibendport->port < ibendport2->port)
return -1;
else if (ibendport2->port < ibendport->port)
return 1;
else
return rc;
}
int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport)
{
return ibendport->port;
}
hidden_def(sepol_ibendport_get_port)
void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port)
{
ibendport->port = port;
}
hidden_def(sepol_ibendport_set_port)
int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle,
const sepol_ibendport_t *ibendport,
char **ibdev_name)
{
char *tmp_ibdev_name = NULL;
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0)
goto err;
strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
*ibdev_name = tmp_ibdev_name;
return STATUS_SUCCESS;
err:
free(tmp_ibdev_name);
ERR(handle, "could not get ibendport ibdev_name");
return STATUS_ERR;
}
hidden_def(sepol_ibendport_get_ibdev_name)
int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle,
sepol_ibendport_t *ibendport,
const char *ibdev_name)
{
char *tmp = NULL;
if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0)
goto err;
strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
free(ibendport->ibdev_name);
ibendport->ibdev_name = tmp;
return STATUS_SUCCESS;
err:
free(tmp);
ERR(handle, "could not set ibendport subnet prefix to %s", ibdev_name);
return STATUS_ERR;
}
hidden_def(sepol_ibendport_set_ibdev_name)
/* Create */
int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport)
{
sepol_ibendport_t *tmp_ibendport = (sepol_ibendport_t *)malloc(sizeof(sepol_ibendport_t));
if (!tmp_ibendport) {
ERR(handle, "out of memory, could not create ibendport record");
return STATUS_ERR;
}
tmp_ibendport->ibdev_name = NULL;
tmp_ibendport->port = 0;
tmp_ibendport->con = NULL;
*ibendport = tmp_ibendport;
return STATUS_SUCCESS;
}
hidden_def(sepol_ibendport_create)
/* Deep copy clone */
int sepol_ibendport_clone(sepol_handle_t *handle,
const sepol_ibendport_t *ibendport,
sepol_ibendport_t **ibendport_ptr)
{
sepol_ibendport_t *new_ibendport = NULL;
if (sepol_ibendport_create(handle, &new_ibendport) < 0)
goto err;
if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0)
goto omem;
strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
new_ibendport->port = ibendport->port;
if (ibendport->con &&
(sepol_context_clone(handle, ibendport->con, &new_ibendport->con) < 0))
goto err;
*ibendport_ptr = new_ibendport;
return STATUS_SUCCESS;
omem:
ERR(handle, "out of memory");
err:
ERR(handle, "could not clone ibendport record");
sepol_ibendport_free(new_ibendport);
return STATUS_ERR;
}
/* Destroy */
void sepol_ibendport_free(sepol_ibendport_t *ibendport)
{
if (!ibendport)
return;
free(ibendport->ibdev_name);
sepol_context_free(ibendport->con);
free(ibendport);
}
hidden_def(sepol_ibendport_free)
/* Context */
sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport)
{
return ibendport->con;
}
hidden_def(sepol_ibendport_get_con)
int sepol_ibendport_set_con(sepol_handle_t *handle,
sepol_ibendport_t *ibendport, sepol_context_t *con)
{
sepol_context_t *newcon;
if (sepol_context_clone(handle, con, &newcon) < 0) {
ERR(handle, "out of memory, could not set ibendport context");
return STATUS_ERR;
}
sepol_context_free(ibendport->con);
ibendport->con = newcon;
return STATUS_SUCCESS;
}
hidden_def(sepol_ibendport_set_con)