semanage: Update semanage to allow runtime labeling of ibendports

Update libsepol and libsemanage to work with ibendport records. Add local
storage for new and modified ibendport records in ibendports.local.
Update semanage to parse the ibendport command options to add, modify,
and delete them.

Signed-off-by: Daniel Jurgens <[email protected]>
diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
index cae1a08..65842df 100644
--- a/libsemanage/src/direct_api.c
+++ b/libsemanage/src/direct_api.c
@@ -41,6 +41,7 @@
 #include "seuser_internal.h"
 #include "port_internal.h"
 #include "ibpkey_internal.h"
+#include "ibendport_internal.h"
 #include "iface_internal.h"
 #include "boolean_internal.h"
 #include "fcontext_internal.h"
@@ -233,6 +234,14 @@
 				   semanage_ibpkey_dbase_local(sh)) < 0)
 		goto err;
 
+	if (ibendport_file_dbase_init(sh,
+				      semanage_path(SEMANAGE_ACTIVE,
+						    SEMANAGE_IBENDPORTS_LOCAL),
+				      semanage_path(SEMANAGE_TMP,
+						    SEMANAGE_IBENDPORTS_LOCAL),
+				      semanage_ibendport_dbase_local(sh)) < 0)
+		goto err;
+
 	/* Object databases: local modifications + policy */
 	if (user_base_policydb_dbase_init(sh,
 					  semanage_user_base_dbase_policy(sh)) <
@@ -260,6 +269,9 @@
 	if (ibpkey_policydb_dbase_init(sh, semanage_ibpkey_dbase_policy(sh)) < 0)
 		goto err;
 
+	if (ibendport_policydb_dbase_init(sh, semanage_ibendport_dbase_policy(sh)) < 0)
+		goto err;
+
 	if (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0)
 		goto err;
 
@@ -333,6 +345,7 @@
 	user_join_dbase_release(semanage_user_dbase_local(sh));
 	port_file_dbase_release(semanage_port_dbase_local(sh));
 	ibpkey_file_dbase_release(semanage_ibpkey_dbase_local(sh));
+	ibendport_file_dbase_release(semanage_ibendport_dbase_local(sh));
 	iface_file_dbase_release(semanage_iface_dbase_local(sh));
 	bool_file_dbase_release(semanage_bool_dbase_local(sh));
 	fcontext_file_dbase_release(semanage_fcontext_dbase_local(sh));
@@ -345,6 +358,7 @@
 	user_join_dbase_release(semanage_user_dbase_policy(sh));
 	port_policydb_dbase_release(semanage_port_dbase_policy(sh));
 	ibpkey_policydb_dbase_release(semanage_ibpkey_dbase_policy(sh));
+	ibendport_policydb_dbase_release(semanage_ibendport_dbase_policy(sh));
 	iface_policydb_dbase_release(semanage_iface_dbase_policy(sh));
 	bool_policydb_dbase_release(semanage_bool_dbase_policy(sh));
 	fcontext_file_dbase_release(semanage_fcontext_dbase_policy(sh));
@@ -1158,7 +1172,8 @@
 
 	int do_rebuild, do_write_kernel, do_install;
 	int fcontexts_modified, ports_modified, seusers_modified,
-		disable_dontaudit, preserve_tunables, ibpkeys_modified;
+		disable_dontaudit, preserve_tunables, ibpkeys_modified,
+		ibendports_modified;
 	dbase_config_t *users = semanage_user_dbase_local(sh);
 	dbase_config_t *users_base = semanage_user_base_dbase_local(sh);
 	dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh);
@@ -1167,6 +1182,8 @@
 	dbase_config_t *pports = semanage_port_dbase_policy(sh);
 	dbase_config_t *ibpkeys = semanage_ibpkey_dbase_local(sh);
 	dbase_config_t *pibpkeys = semanage_ibpkey_dbase_policy(sh);
+	dbase_config_t *ibendports = semanage_ibendport_dbase_local(sh);
+	dbase_config_t *pibendports = semanage_ibendport_dbase_policy(sh);
 	dbase_config_t *bools = semanage_bool_dbase_local(sh);
 	dbase_config_t *pbools = semanage_bool_dbase_policy(sh);
 	dbase_config_t *ifaces = semanage_iface_dbase_local(sh);
@@ -1181,6 +1198,7 @@
 	/* Modified flags that we need to use more than once. */
 	ports_modified = ports->dtable->is_modified(ports->dbase);
 	ibpkeys_modified = ibpkeys->dtable->is_modified(ibpkeys->dbase);
+	ibendports_modified = ibendports->dtable->is_modified(ibendports->dbase);
 	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
 	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
 
@@ -1303,6 +1321,7 @@
 	 * will be modified.
 	 */
 	do_write_kernel = do_rebuild | ports_modified | ibpkeys_modified |
+		ibendports_modified |
 		bools->dtable->is_modified(bools->dbase) |
 		ifaces->dtable->is_modified(ifaces->dbase) |
 		nodes->dtable->is_modified(nodes->dbase) |
@@ -1449,6 +1468,7 @@
 	dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pibpkeys->dbase, out);
+	dbase_policydb_attach((dbase_policydb_t *) pibendports->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out);
 	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out);
@@ -1503,6 +1523,13 @@
 		if (retval < 0)
 			goto cleanup;
 	}
+
+	/* Validate local ibendports */
+	if (do_rebuild || ibendports_modified) {
+		retval = semanage_ibendport_validate_local(sh);
+		if (retval < 0)
+			goto cleanup;
+	}
 	/* ================== Write non-policydb components ========= */
 
 	/* Commit changes to components */
@@ -1583,6 +1610,7 @@
 	dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pports->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pibpkeys->dbase);
+	dbase_policydb_detach((dbase_policydb_t *) pibendports->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pifaces->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase);
 	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
diff --git a/libsemanage/src/handle.h b/libsemanage/src/handle.h
index 306727a..889871d 100644
--- a/libsemanage/src/handle.h
+++ b/libsemanage/src/handle.h
@@ -79,7 +79,7 @@
 	struct semanage_policy_table *funcs;
 
 	/* Object databases */
-#define DBASE_COUNT      21
+#define DBASE_COUNT      23
 
 /* Local modifications */
 #define DBASE_LOCAL_USERS_BASE  0
@@ -92,21 +92,23 @@
 #define DBASE_LOCAL_SEUSERS     7
 #define DBASE_LOCAL_NODES       8
 #define DBASE_LOCAL_IBPKEYS     9
+#define DBASE_LOCAL_IBENDPORTS  10
 
 /* Policy + Local modifications */
-#define DBASE_POLICY_USERS_BASE  10
-#define DBASE_POLICY_USERS_EXTRA 11
-#define DBASE_POLICY_USERS       12
-#define DBASE_POLICY_PORTS       13
-#define DBASE_POLICY_INTERFACES  14
-#define DBASE_POLICY_BOOLEANS    15
-#define DBASE_POLICY_FCONTEXTS   16
-#define DBASE_POLICY_SEUSERS     17
-#define DBASE_POLICY_NODES       18
-#define DBASE_POLICY_IBPKEYS     19
+#define DBASE_POLICY_USERS_BASE  11
+#define DBASE_POLICY_USERS_EXTRA 12
+#define DBASE_POLICY_USERS       13
+#define DBASE_POLICY_PORTS       14
+#define DBASE_POLICY_INTERFACES  15
+#define DBASE_POLICY_BOOLEANS    16
+#define DBASE_POLICY_FCONTEXTS   17
+#define DBASE_POLICY_SEUSERS     18
+#define DBASE_POLICY_NODES       19
+#define DBASE_POLICY_IBPKEYS     20
+#define DBASE_POLICY_IBENDPORTS  21
 
 /* Active kernel policy */
-#define DBASE_ACTIVE_BOOLEANS    20
+#define DBASE_ACTIVE_BOOLEANS    22
 	dbase_config_t dbase[DBASE_COUNT];
 };
 
@@ -142,6 +144,12 @@
 }
 
 static inline
+    dbase_config_t * semanage_ibendport_dbase_local(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_LOCAL_IBENDPORTS];
+}
+
+static inline
     dbase_config_t * semanage_iface_dbase_local(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_LOCAL_INTERFACES];
@@ -204,6 +212,12 @@
 }
 
 static inline
+    dbase_config_t * semanage_ibendport_dbase_policy(semanage_handle_t * handle)
+{
+	return &handle->dbase[DBASE_POLICY_IBENDPORTS];
+}
+
+static inline
     dbase_config_t * semanage_iface_dbase_policy(semanage_handle_t * handle)
 {
 	return &handle->dbase[DBASE_POLICY_INTERFACES];
diff --git a/libsemanage/src/ibendport_internal.h b/libsemanage/src/ibendport_internal.h
new file mode 100644
index 0000000..970fbdb
--- /dev/null
+++ b/libsemanage/src/ibendport_internal.h
@@ -0,0 +1,48 @@
+#ifndef _SEMANAGE_IBENDPORT_INTERNAL_H_
+#define _SEMANAGE_IBENDPORT_INTERNAL_H_
+
+#include <semanage/ibendport_record.h>
+#include <semanage/ibendports_local.h>
+#include <semanage/ibendports_policy.h>
+#include "database.h"
+#include "handle.h"
+#include "dso.h"
+
+hidden_proto(semanage_ibendport_create)
+hidden_proto(semanage_ibendport_compare)
+hidden_proto(semanage_ibendport_compare2)
+hidden_proto(semanage_ibendport_clone)
+hidden_proto(semanage_ibendport_free)
+hidden_proto(semanage_ibendport_key_extract)
+hidden_proto(semanage_ibendport_key_free)
+hidden_proto(semanage_ibendport_get_port)
+hidden_proto(semanage_ibendport_set_port)
+hidden_proto(semanage_ibendport_get_con)
+hidden_proto(semanage_ibendport_set_con)
+hidden_proto(semanage_ibendport_list_local)
+hidden_proto(semanage_ibendport_get_ibdev_name)
+hidden_proto(semanage_ibendport_set_ibdev_name)
+
+/* IBENDPORT RECORD: method table */
+extern record_table_t SEMANAGE_IBENDPORT_RTABLE;
+
+extern int ibendport_file_dbase_init(semanage_handle_t *handle,
+				     const char *path_ro,
+				     const char *path_rw,
+				     dbase_config_t *dconfig);
+
+extern void ibendport_file_dbase_release(dbase_config_t *dconfig);
+
+extern int ibendport_policydb_dbase_init(semanage_handle_t *handle,
+					 dbase_config_t *dconfig);
+
+extern void ibendport_policydb_dbase_release(dbase_config_t *dconfig);
+
+extern int hidden semanage_ibendport_validate_local(semanage_handle_t *handle);
+
+/* ==== Internal (to ibendports) API === */
+
+hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+					     const semanage_ibendport_t **ibendport2);
+
+#endif
diff --git a/libsemanage/src/ibendport_record.c b/libsemanage/src/ibendport_record.c
new file mode 100644
index 0000000..955067e
--- /dev/null
+++ b/libsemanage/src/ibendport_record.c
@@ -0,0 +1,154 @@
+/*Copyright (C) 2005 Red Hat, Inc. */
+
+/*Object: semanage_ibendport_t (Infiniband Pkey)
+ *Object: semanage_ibendport_key_t (Infiniband Pkey Key)
+ *Implements: record_t (Database Record)
+ *Implements: record_key_t (Database Record Key)
+ */
+
+#include <sepol/context_record.h>
+#include <sepol/ibendport_record.h>
+
+typedef sepol_context_t semanage_context_t;
+typedef sepol_ibendport_t semanage_ibendport_t;
+typedef sepol_ibendport_key_t semanage_ibendport_key_t;
+#define _SEMANAGE_IBENDPORT_DEFINED_
+#define _SEMANAGE_CONTEXT_DEFINED_
+
+typedef semanage_ibendport_t record_t;
+typedef semanage_ibendport_key_t record_key_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibendport_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_compare(const semanage_ibendport_t *ibendport,
+			       const semanage_ibendport_key_t *key)
+{
+	return sepol_ibendport_compare(ibendport, key);
+}
+
+hidden_def(semanage_ibendport_compare)
+
+int semanage_ibendport_compare2(const semanage_ibendport_t *ibendport,
+				const semanage_ibendport_t *ibendport2)
+{
+	return sepol_ibendport_compare2(ibendport, ibendport2);
+}
+
+hidden_def(semanage_ibendport_compare2)
+
+hidden int semanage_ibendport_compare2_qsort(const semanage_ibendport_t **ibendport,
+					     const semanage_ibendport_t **ibendport2)
+{
+	return sepol_ibendport_compare2(*ibendport, *ibendport2);
+}
+
+int semanage_ibendport_key_create(semanage_handle_t *handle,
+				  const char *ibdev_name,
+				  int port,
+				  semanage_ibendport_key_t **key_ptr)
+{
+	return sepol_ibendport_key_create(handle->sepolh, ibdev_name, port, key_ptr);
+}
+
+int semanage_ibendport_key_extract(semanage_handle_t *handle,
+				   const semanage_ibendport_t *ibendport,
+				   semanage_ibendport_key_t **key_ptr)
+{
+	return sepol_ibendport_key_extract(handle->sepolh, ibendport, key_ptr);
+}
+
+hidden_def(semanage_ibendport_key_extract)
+
+void semanage_ibendport_key_free(semanage_ibendport_key_t *key)
+{
+	sepol_ibendport_key_free(key);
+}
+
+hidden_def(semanage_ibendport_key_free)
+
+int semanage_ibendport_get_ibdev_name(semanage_handle_t *handle,
+				      const semanage_ibendport_t *ibendport,
+				      char **ibdev_name_ptr)
+{
+	return sepol_ibendport_get_ibdev_name(handle->sepolh, ibendport, ibdev_name_ptr);
+}
+
+hidden_def(semanage_ibendport_get_ibdev_name)
+
+int semanage_ibendport_set_ibdev_name(semanage_handle_t *handle,
+				      semanage_ibendport_t *ibendport,
+				      const char *ibdev_name)
+{
+	return sepol_ibendport_set_ibdev_name(handle->sepolh, ibendport, ibdev_name);
+}
+
+hidden_def(semanage_ibendport_set_ibdev_name)
+
+int semanage_ibendport_get_port(const semanage_ibendport_t *ibendport)
+{
+	return sepol_ibendport_get_port(ibendport);
+}
+
+hidden_def(semanage_ibendport_get_port)
+
+void semanage_ibendport_set_port(semanage_ibendport_t *ibendport, int port)
+{
+	sepol_ibendport_set_port(ibendport, port);
+}
+
+hidden_def(semanage_ibendport_set_port)
+
+semanage_context_t *semanage_ibendport_get_con(const semanage_ibendport_t *ibendport)
+{
+	return sepol_ibendport_get_con(ibendport);
+}
+
+hidden_def(semanage_ibendport_get_con)
+
+int semanage_ibendport_set_con(semanage_handle_t *handle,
+			       semanage_ibendport_t *ibendport,
+			       semanage_context_t *con)
+{
+	return sepol_ibendport_set_con(handle->sepolh, ibendport, con);
+}
+
+hidden_def(semanage_ibendport_set_con)
+
+int semanage_ibendport_create(semanage_handle_t *handle,
+			      semanage_ibendport_t **ibendport_ptr)
+{
+	return sepol_ibendport_create(handle->sepolh, ibendport_ptr);
+}
+
+hidden_def(semanage_ibendport_create)
+
+int semanage_ibendport_clone(semanage_handle_t *handle,
+			     const semanage_ibendport_t *ibendport,
+			     semanage_ibendport_t **ibendport_ptr)
+{
+	return sepol_ibendport_clone(handle->sepolh, ibendport, ibendport_ptr);
+}
+
+hidden_def(semanage_ibendport_clone)
+
+void semanage_ibendport_free(semanage_ibendport_t *ibendport)
+{
+	sepol_ibendport_free(ibendport);
+}
+
+hidden_def(semanage_ibendport_free)
+
+/*key base functions */
+record_table_t SEMANAGE_IBENDPORT_RTABLE = {
+	.create = semanage_ibendport_create,
+	.key_extract = semanage_ibendport_key_extract,
+	.key_free = semanage_ibendport_key_free,
+	.clone = semanage_ibendport_clone,
+	.compare = semanage_ibendport_compare,
+	.compare2 = semanage_ibendport_compare2,
+	.compare2_qsort = semanage_ibendport_compare2_qsort,
+	.free = semanage_ibendport_free,
+};
diff --git a/libsemanage/src/ibendports_file.c b/libsemanage/src/ibendports_file.c
new file mode 100644
index 0000000..402c7a5
--- /dev/null
+++ b/libsemanage/src/ibendports_file.c
@@ -0,0 +1,157 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc. */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport record_t;
+typedef struct semanage_ibendport_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_file;
+typedef struct dbase_file dbase_t;
+#define DBASE_DEFINED
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <semanage/handle.h>
+#include "ibendport_internal.h"
+#include "context_internal.h"
+#include "database_file.h"
+#include "parse_utils.h"
+#include "debug.h"
+
+static int ibendport_print(semanage_handle_t *handle,
+			   semanage_ibendport_t *ibendport,
+			   FILE *str)
+{
+	char *con_str = NULL;
+	char *ibdev_name_str = NULL;
+	int port = semanage_ibendport_get_port(ibendport);
+
+	if (semanage_ibendport_get_ibdev_name(handle, ibendport, &ibdev_name_str) != 0)
+		goto err;
+
+	semanage_context_t *con = semanage_ibendport_get_con(ibendport);
+
+	if (fprintf(str, "ibendportcon %s ", ibdev_name_str) < 0)
+		goto err;
+
+	if (fprintf(str, "%d ", port) < 0)
+		goto err;
+
+	if (semanage_context_to_string(handle, con, &con_str) < 0)
+		goto err;
+	if (fprintf(str, "%s\n", con_str) < 0)
+		goto err;
+
+	free(ibdev_name_str);
+	free(con_str);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not print ibendport (%s) %u to stream",
+	    ibdev_name_str, port);
+	free(ibdev_name_str);
+	free(con_str);
+	return STATUS_ERR;
+}
+
+static int ibendport_parse(semanage_handle_t *handle,
+			   parse_info_t *info,
+			   semanage_ibendport_t *ibendport)
+{
+	int port;
+	char *str = NULL;
+	semanage_context_t *con = NULL;
+
+	if (parse_skip_space(handle, info) < 0)
+		goto err;
+	if (!info->ptr)
+		goto last;
+
+	/* Header */
+	if (parse_assert_str(handle, info, "ibendportcon") < 0)
+		goto err;
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	/* IB Device Name */
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_ibendport_set_ibdev_name(handle, ibendport, str) < 0)
+		goto err;
+	free(str);
+	str = NULL;
+
+	/* Port */
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+	if (parse_fetch_int(handle, info, &port, ' ') < 0)
+		goto err;
+	semanage_ibendport_set_port(ibendport, port);
+
+	/* context */
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+	if (parse_fetch_string(handle, info, &str, ' ') < 0)
+		goto err;
+	if (semanage_context_from_string(handle, str, &con) < 0) {
+		ERR(handle, "invalid security context \"%s\" (%s: %u)\n%s",
+		    str, info->filename, info->lineno, info->orig_line);
+		goto err;
+	}
+	if (!con) {
+		ERR(handle, "<<none>> context is not valid for ibendport (%s: %u):\n%s",
+		    info->filename, info->lineno, info->orig_line);
+		goto err;
+	}
+	free(str);
+	str = NULL;
+
+	if (semanage_ibendport_set_con(handle, ibendport, con) < 0)
+		goto err;
+
+	if (parse_assert_space(handle, info) < 0)
+		goto err;
+
+	semanage_context_free(con);
+	return STATUS_SUCCESS;
+
+last:
+	parse_dispose_line(info);
+	return STATUS_NODATA;
+
+err:
+	ERR(handle, "could not parse ibendport record");
+	free(str);
+	semanage_context_free(con);
+	parse_dispose_line(info);
+	return STATUS_ERR;
+}
+
+/* IBENDPORT RECORD: FILE extension: method table */
+record_file_table_t SEMANAGE_IBENDPORT_FILE_RTABLE = {
+	.parse = ibendport_parse,
+	.print = ibendport_print,
+};
+
+int ibendport_file_dbase_init(semanage_handle_t *handle,
+			      const char *path_ro,
+			      const char *path_rw,
+			      dbase_config_t *dconfig)
+{
+	if (dbase_file_init(handle,
+			    path_ro,
+			    path_rw,
+			    &SEMANAGE_IBENDPORT_RTABLE,
+			    &SEMANAGE_IBENDPORT_FILE_RTABLE, &dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
+	return STATUS_SUCCESS;
+}
+
+void ibendport_file_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_file_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/ibendports_local.c b/libsemanage/src/ibendports_local.c
new file mode 100644
index 0000000..8b5567d
--- /dev/null
+++ b/libsemanage/src/ibendports_local.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport_key record_key_t;
+typedef struct semanage_ibendport record_t;
+#define DBASE_RECORD_DEFINED
+
+#include <stdlib.h>
+#include <string.h>
+#include <sepol/policydb.h>
+#include "ibendport_internal.h"
+#include "debug.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_modify_local(semanage_handle_t *handle,
+				    const semanage_ibendport_key_t *key,
+				    const semanage_ibendport_t *data)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_modify(handle, dconfig, key, data);
+}
+
+int semanage_ibendport_del_local(semanage_handle_t *handle,
+				 const semanage_ibendport_key_t *key)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_del(handle, dconfig, key);
+}
+
+int semanage_ibendport_query_local(semanage_handle_t *handle,
+				   const semanage_ibendport_key_t *key,
+				   semanage_ibendport_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_exists_local(semanage_handle_t *handle,
+				    const semanage_ibendport_key_t *key,
+				    int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_count_local(semanage_handle_t *handle,
+				   unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibendport_iterate_local(semanage_handle_t *handle,
+				     int (*handler)(const semanage_ibendport_t *record,
+						    void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibendport_list_local(semanage_handle_t *handle,
+				  semanage_ibendport_t ***records,
+				  unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_local(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
+
+hidden_def(semanage_ibendport_list_local)
+
+int hidden semanage_ibendport_validate_local(semanage_handle_t *handle)
+{
+	semanage_ibendport_t **ibendports = NULL;
+	unsigned int nibendports = 0;
+	unsigned int i = 0, j = 0;
+	char *ibdev_name;
+	char *ibdev_name2;
+	int port;
+	int port2;
+
+	/* List and sort the ibendports */
+	if (semanage_ibendport_list_local(handle, &ibendports, &nibendports) < 0)
+		goto err;
+
+	qsort(ibendports, nibendports, sizeof(semanage_ibendport_t *),
+	      (int (*)(const void *, const void *))
+	      &semanage_ibendport_compare2_qsort);
+
+	/* Test each ibendport */
+	while (i < nibendports) {
+		int stop = 0;
+
+		if (STATUS_SUCCESS !=
+				semanage_ibendport_get_ibdev_name(handle,
+								  ibendports[i],
+								  &ibdev_name)) {
+			ERR(handle, "Couldn't get IB device name");
+			goto err;
+		}
+
+		port = semanage_ibendport_get_port(ibendports[i]);
+
+		/* Find the first ibendport with matching
+		 * ibdev_name to compare against
+		 */
+		do {
+			if (j == nibendports - 1)
+				goto next;
+			j++;
+			if (STATUS_SUCCESS !=
+				semanage_ibendport_get_ibdev_name(handle,
+								  ibendports[j],
+								  &ibdev_name2)) {
+				ERR(handle, "Couldn't get IB device name.");
+				goto err;
+			}
+			port2 = semanage_ibendport_get_port(ibendports[j]);
+
+			stop = !strcmp(ibdev_name, ibdev_name2);
+		} while (!stop);
+
+		if (port == port2) {
+			ERR(handle, "ibendport %s/%u already exists.",
+			    ibdev_name2, port2);
+			goto invalid;
+		}
+next:
+		i++;
+		j = i;
+	}
+
+	for (i = 0; i < nibendports; i++)
+		semanage_ibendport_free(ibendports[i]);
+	free(ibendports);
+	return STATUS_SUCCESS;
+
+err:
+	ERR(handle, "could not complete ibendports validity check");
+
+invalid:
+	for (i = 0; i < nibendports; i++)
+		semanage_ibendport_free(ibendports[i]);
+	free(ibendports);
+	return STATUS_ERR;
+}
diff --git a/libsemanage/src/ibendports_policy.c b/libsemanage/src/ibendports_policy.c
new file mode 100644
index 0000000..1347b67
--- /dev/null
+++ b/libsemanage/src/ibendports_policy.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2017 Mellanox Technologies Inc */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport_key record_key_t;
+typedef struct semanage_ibendport record_t;
+#define DBASE_RECORD_DEFINED
+
+#include "ibendport_internal.h"
+#include "handle.h"
+#include "database.h"
+
+int semanage_ibendport_query(semanage_handle_t *handle,
+			     const semanage_ibendport_key_t *key,
+			     semanage_ibendport_t **response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_query(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_exists(semanage_handle_t *handle,
+			      const semanage_ibendport_key_t *key,
+			      int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_exists(handle, dconfig, key, response);
+}
+
+int semanage_ibendport_count(semanage_handle_t *handle,
+			     unsigned int *response)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_count(handle, dconfig, response);
+}
+
+int semanage_ibendport_iterate(semanage_handle_t *handle,
+			       int (*handler)(const semanage_ibendport_t *record,
+					      void *varg), void *handler_arg)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_iterate(handle, dconfig, handler, handler_arg);
+}
+
+int semanage_ibendport_list(semanage_handle_t *handle,
+			    semanage_ibendport_t ***records,
+			    unsigned int *count)
+{
+	dbase_config_t *dconfig = semanage_ibendport_dbase_policy(handle);
+
+	return dbase_list(handle, dconfig, records, count);
+}
diff --git a/libsemanage/src/ibendports_policydb.c b/libsemanage/src/ibendports_policydb.c
new file mode 100644
index 0000000..1029810
--- /dev/null
+++ b/libsemanage/src/ibendports_policydb.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Mellanox Technologies Inc
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ */
+
+struct semanage_ibendport;
+struct semanage_ibendport_key;
+typedef struct semanage_ibendport record_t;
+typedef struct semanage_ibendport_key record_key_t;
+#define DBASE_RECORD_DEFINED
+
+struct dbase_policydb;
+typedef struct dbase_policydb dbase_t;
+#define DBASE_DEFINED
+
+#include <sepol/ibendports.h>
+#include <semanage/handle.h>
+#include "ibendport_internal.h"
+#include "debug.h"
+#include "database_policydb.h"
+#include "semanage_store.h"
+
+/* IBENDPORT RECORD (SEPOL): POLICYDB extension : method table */
+record_policydb_table_t SEMANAGE_IBENDPORT_POLICYDB_RTABLE = {
+	.add = NULL,
+	.modify = (record_policydb_table_modify_t)sepol_ibendport_modify,
+	.set = NULL,
+	.query = (record_policydb_table_query_t)sepol_ibendport_query,
+	.count = (record_policydb_table_count_t)sepol_ibendport_count,
+	.exists = (record_policydb_table_exists_t)sepol_ibendport_exists,
+	.iterate = (record_policydb_table_iterate_t)sepol_ibendport_iterate,
+};
+
+int ibendport_policydb_dbase_init(semanage_handle_t *handle,
+				  dbase_config_t *dconfig)
+{
+	if (dbase_policydb_init(handle,
+				semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
+				semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
+				&SEMANAGE_IBENDPORT_RTABLE,
+				&SEMANAGE_IBENDPORT_POLICYDB_RTABLE,
+				&dconfig->dbase) < 0)
+		return STATUS_ERR;
+
+	dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE;
+
+	return STATUS_SUCCESS;
+}
+
+void ibendport_policydb_dbase_release(dbase_config_t *dconfig)
+{
+	dbase_policydb_release(dconfig->dbase);
+}
diff --git a/libsemanage/src/libsemanage.map b/libsemanage/src/libsemanage.map
index 041b1ce..0203669 100644
--- a/libsemanage/src/libsemanage.map
+++ b/libsemanage/src/libsemanage.map
@@ -19,6 +19,7 @@
 	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
 	  semanage_iface_*; semanage_port_*; semanage_context_*;
 	  semanage_ibpkey_*;
+	  semanage_ibendport_*;
 	  semanage_node_*;
 	  semanage_fcontext_*; semanage_access_check; semanage_set_create_store;
 	  semanage_is_connected; semanage_get_disable_dontaudit; semanage_set_disable_dontaudit;
diff --git a/libsemanage/src/policy_components.c b/libsemanage/src/policy_components.c
index 136c5a7..896ac51 100644
--- a/libsemanage/src/policy_components.c
+++ b/libsemanage/src/policy_components.c
@@ -140,6 +140,9 @@
 
 		{semanage_ibpkey_dbase_local(handle),
 		 semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},
+
+		{semanage_ibendport_dbase_local(handle),
+		 semanage_ibendport_dbase_policy(handle), MODE_MODIFY},
 	};
 	const unsigned int CCOUNT = sizeof(components) / sizeof(components[0]);
 
@@ -221,6 +224,7 @@
 		semanage_bool_dbase_active(handle),
 		semanage_node_dbase_local(handle),
 		semanage_ibpkey_dbase_local(handle),
+		semanage_ibendport_dbase_local(handle),
 	};
 	const int CCOUNT = sizeof(components) / sizeof(components[0]);
 
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
index f61f3b2..5642772 100644
--- a/libsemanage/src/semanage_store.c
+++ b/libsemanage/src/semanage_store.c
@@ -100,6 +100,7 @@
 	"/file_contexts.template",
 	"/commit_num",
 	"/pkeys.local",
+	"/ibendports.local",
 	"/ports.local",
 	"/interfaces.local",
 	"/nodes.local",
diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
index c7bcf44..fcaa505 100644
--- a/libsemanage/src/semanage_store.h
+++ b/libsemanage/src/semanage_store.h
@@ -45,6 +45,7 @@
 	SEMANAGE_FC_TMPL,
 	SEMANAGE_COMMIT_NUM_FILE,
 	SEMANAGE_IBPKEYS_LOCAL,
+	SEMANAGE_IBENDPORTS_LOCAL,
 	SEMANAGE_PORTS_LOCAL,
 	SEMANAGE_INTERFACES_LOCAL,
 	SEMANAGE_NODES_LOCAL,
diff --git a/libsemanage/src/semanageswig.i b/libsemanage/src/semanageswig.i
index d3ca795..ebf39cf 100644
--- a/libsemanage/src/semanageswig.i
+++ b/libsemanage/src/semanageswig.i
@@ -42,6 +42,9 @@
 %include "../include/semanage/ibpkey_record.h"
 %include "../include/semanage/ibpkeys_local.h"
 %include "../include/semanage/ibpkeys_policy.h"
+%include "../include/semanage/ibendport_record.h"
+%include "../include/semanage/ibendports_local.h"
+%include "../include/semanage/ibendports_policy.h"
 %include "../include/semanage/fcontext_record.h"
 %include "../include/semanage/fcontexts_local.h"
 %include "../include/semanage/fcontexts_policy.h"
diff --git a/libsemanage/src/semanageswig_python.i b/libsemanage/src/semanageswig_python.i
index 40932d8..8604b8a 100644
--- a/libsemanage/src/semanageswig_python.i
+++ b/libsemanage/src/semanageswig_python.i
@@ -480,6 +480,49 @@
 	$1 = &temp;
 }
 
+/** ibendport typemaps **/
+
+/* the wrapper will setup this parameter for passing... the resulting python functions
+   will not take the semanage_ibendport_t *** parameter */
+%typemap(in, numinputs=0) semanage_ibendport_t ***(semanage_ibendport_t **temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) (
+	semanage_handle_t* handle,
+	semanage_ibendport_t*** records,
+	unsigned int* count) {
+
+	if ($result) {
+		int value;
+		SWIG_AsVal_int($result, &value);
+		if (value >= 0) {
+			PyObject* plist = NULL;
+			if (semanage_array2plist($1, (void**) *$2, *$3, SWIGTYPE_p_semanage_ibendport,
+				(void (*) (void*)) &semanage_ibendport_free, &plist) < 0)
+				$result = SWIG_From_int(STATUS_ERR);
+			else
+				$result = SWIG_Python_AppendOutput($result, plist);
+		}
+	}
+}
+
+%typemap(in, numinputs=0) semanage_ibendport_t **(semanage_ibendport_t *temp=NULL) {
+	$1 = &temp;
+}
+
+%typemap(argout) semanage_ibendport_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(argout) semanage_ibendport_key_t ** {
+	$result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+
+%typemap(in, numinputs=0) semanage_ibendport_key_t **(semanage_ibendport_key_t *temp=NULL) {
+	$1 = &temp;
+}
+
 /** node typemaps **/
 
 /* the wrapper will setup this parameter for passing... the resulting python functions