#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)