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