Re: [PATCH 7/9] semanage: Update semanage to allow runtime labeling of Infiniband Pkeys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2017-05-09 at 23:50 +0300, Dan Jurgens wrote:
> From: Daniel Jurgens <danielj@xxxxxxxxxxxx>
> 
> Update libsepol and libsemanage to work with pkey records. Add local
> storage for new and modified pkey records in pkeys.local. Update
> semanage
> to parse the pkey command options to add, modify, and delete pkeys.
> 
> Signed-off-by: Daniel Jurgens <danielj@xxxxxxxxxxxx>
> ---
>  libsemanage/include/semanage/ibpkey_record.h  |   76 ++++
>  libsemanage/include/semanage/ibpkeys_local.h  |   36 ++
>  libsemanage/include/semanage/ibpkeys_policy.h |   28 ++
>  libsemanage/include/semanage/semanage.h       |    3 +
>  libsemanage/src/direct_api.c                  |   29 ++-
>  libsemanage/src/handle.h                      |   36 ++-
>  libsemanage/src/ibpkey_internal.h             |   52 +++
>  libsemanage/src/ibpkey_record.c               |  187 ++++++++++
>  libsemanage/src/ibpkeys_file.c                |  181 ++++++++++
>  libsemanage/src/ibpkeys_local.c               |  182 ++++++++++
>  libsemanage/src/ibpkeys_policy.c              |   52 +++
>  libsemanage/src/ibpkeys_policydb.c            |   62 ++++
>  libsemanage/src/libsemanage.map               |    1 +
>  libsemanage/src/policy_components.c           |    5 +-
>  libsemanage/src/semanage_store.c              |    1 +
>  libsemanage/src/semanage_store.h              |    1 +
>  libsemanage/src/semanageswig.i                |    3 +
>  libsemanage/src/semanageswig_python.i         |   43 +++
>  libsemanage/utils/semanage_migrate_store      |    3 +-
>  libsepol/VERSION                              |    2 +-
>  libsepol/include/sepol/ibpkey_record.h        |   75 ++++
>  libsepol/include/sepol/ibpkeys.h              |   44 +++
>  libsepol/include/sepol/sepol.h                |    2 +
>  libsepol/src/ibpkey_internal.h                |   21 ++
>  libsepol/src/ibpkey_record.c                  |  474
> +++++++++++++++++++++++++
>  libsepol/src/ibpkeys.c                        |  264 ++++++++++++++
>  python/semanage/semanage                      |   60 +++-
>  python/semanage/seobject.py                   |  253 +++++++++++++
>  28 files changed, 2159 insertions(+), 17 deletions(-)

That's a lot of code.  Did you look at whether you could generalize the
port record stuff at all to see if we could factor out common helpers
or anything?  I guess this is consistent with the current code, but it
seems like a lot of very similar code being duplicated and then
slightly tweaked.

>  create mode 100644 libsemanage/include/semanage/ibpkey_record.h
>  create mode 100644 libsemanage/include/semanage/ibpkeys_local.h
>  create mode 100644 libsemanage/include/semanage/ibpkeys_policy.h
>  create mode 100644 libsemanage/src/ibpkey_internal.h
>  create mode 100644 libsemanage/src/ibpkey_record.c
>  create mode 100644 libsemanage/src/ibpkeys_file.c
>  create mode 100644 libsemanage/src/ibpkeys_local.c
>  create mode 100644 libsemanage/src/ibpkeys_policy.c
>  create mode 100644 libsemanage/src/ibpkeys_policydb.c
>  create mode 100644 libsepol/include/sepol/ibpkey_record.h
>  create mode 100644 libsepol/include/sepol/ibpkeys.h
>  create mode 100644 libsepol/src/ibpkey_internal.h
>  create mode 100644 libsepol/src/ibpkey_record.c
>  create mode 100644 libsepol/src/ibpkeys.c
> 
> diff --git a/libsemanage/include/semanage/ibpkey_record.h
> b/libsemanage/include/semanage/ibpkey_record.h
> new file mode 100644
> index 0000000..45fe59e
> --- /dev/null
> +++ b/libsemanage/include/semanage/ibpkey_record.h
> @@ -0,0 +1,76 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc */
> +
> +#ifndef _SEMANAGE_IBPKEY_RECORD_H_
> +#define _SEMANAGE_IBPKEY_RECORD_H_
> +
> +#include <semanage/context_record.h>
> +#include <semanage/handle.h>
> +#include <stddef.h>
> +
> +#ifndef _SEMANAGE_IBPKEY_DEFINED_
> +struct semanage_ibpkey;
> +struct semanage_ibpkey_key;
> +typedef struct semanage_ibpkey semanage_ibpkey_t;
> +typedef struct semanage_ibpkey_key semanage_ibpkey_key_t;
> +#define _SEMANAGE_IBPKEY_DEFINED_
> +#endif
> +
> +extern int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
> +				   const semanage_ibpkey_key_t
> *key);
> +
> +extern int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
> +				    const semanage_ibpkey_t
> *ibpkey2);
> +
> +extern int semanage_ibpkey_key_create(semanage_handle_t *handle,
> +				      const char *subnet_prefix,
> +				      int low, int high,
> +				      semanage_ibpkey_key_t
> **key_ptr);
> +
> +extern int semanage_ibpkey_key_extract(semanage_handle_t *handle,
> +				       const semanage_ibpkey_t
> *ibpkey,
> +				       semanage_ibpkey_key_t
> **key_ptr);
> +
> +extern void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key);
> +
> +extern int semanage_ibpkey_get_subnet_prefix(semanage_handle_t
> *handle,
> +					     const semanage_ibpkey_t
> *ibpkey,
> +					     char
> **subnet_prefix_ptr);
> +
> +extern int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +						   const
> semanage_ibpkey_t *ibpkey,
> +						   char
> **subnet_prefix,
> +						   size_t
> *subnet_prefix_sz);
> +
> +extern int semanage_ibpkey_set_subnet_prefix(semanage_handle_t
> *handle,
> +					     semanage_ibpkey_t
> *ibpkey,
> +					     const char
> *subnet_prefix);
> +
> +extern int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +						   semanage_ibpkey_t
> *ibpkey,
> +						   const char
> *subnet_prefix,
> +						   size_t
> subnet_prefix_sz);
> +
> +extern int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey);
> +
> +extern int semanage_ibpkey_get_high(const semanage_ibpkey_t
> *ibpkey);
> +
> +extern void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int
> pkey_num);
> +
> +extern void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int
> low, int high);
> +
> +extern semanage_context_t *semanage_ibpkey_get_con(const
> semanage_ibpkey_t *ibpkey);
> +
> +extern int semanage_ibpkey_set_con(semanage_handle_t *handle,
> +				   semanage_ibpkey_t *ibpkey,
> +				   semanage_context_t *con);
> +
> +extern int semanage_ibpkey_create(semanage_handle_t *handle,
> +				  semanage_ibpkey_t **ibpkey_ptr);
> +
> +extern int semanage_ibpkey_clone(semanage_handle_t *handle,
> +				 const semanage_ibpkey_t *ibpkey,
> +				 semanage_ibpkey_t **ibpkey_ptr);
> +
> +extern void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey);
> +
> +#endif
> diff --git a/libsemanage/include/semanage/ibpkeys_local.h
> b/libsemanage/include/semanage/ibpkeys_local.h
> new file mode 100644
> index 0000000..079a642
> --- /dev/null
> +++ b/libsemanage/include/semanage/ibpkeys_local.h
> @@ -0,0 +1,36 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc */
> +
> +#ifndef _SEMANAGE_IBPKEYS_LOCAL_H_
> +#define _SEMANAGE_IBPKEYS_LOCAL_H_
> +
> +#include <semanage/ibpkey_record.h>
> +#include <semanage/handle.h>
> +
> +extern int semanage_ibpkey_modify_local(semanage_handle_t *handle,
> +					const semanage_ibpkey_key_t
> *key,
> +					const semanage_ibpkey_t
> *data);
> +
> +extern int semanage_ibpkey_del_local(semanage_handle_t *handle,
> +				     const semanage_ibpkey_key_t
> *key);
> +
> +extern int semanage_ibpkey_query_local(semanage_handle_t *handle,
> +				       const semanage_ibpkey_key_t
> *key,
> +				       semanage_ibpkey_t
> **response);
> +
> +extern int semanage_ibpkey_exists_local(semanage_handle_t *handle,
> +					const semanage_ibpkey_key_t
> *key,
> +					int *response);
> +
> +extern int semanage_ibpkey_count_local(semanage_handle_t *handle,
> +				       unsigned int *response);
> +
> +extern int semanage_ibpkey_iterate_local(semanage_handle_t *handle,
> +					 int (*handler)(const
> semanage_ibpkey_t *
> +							record, void
> *varg),
> +					 void *handler_arg);
> +
> +extern int semanage_ibpkey_list_local(semanage_handle_t *handle,
> +				      semanage_ibpkey_t ***records,
> +				      unsigned int *count);
> +
> +#endif
> diff --git a/libsemanage/include/semanage/ibpkeys_policy.h
> b/libsemanage/include/semanage/ibpkeys_policy.h
> new file mode 100644
> index 0000000..c287ac0
> --- /dev/null
> +++ b/libsemanage/include/semanage/ibpkeys_policy.h
> @@ -0,0 +1,28 @@
> +/* Copyright (C) 2017 Mellanox Technolgies Inc. */
> +
> +#ifndef _SEMANAGE_IBPKEYS_POLICY_H_
> +#define _SEMANAGE_IBPKEYS_POLICY_H_
> +
> +#include <semanage/handle.h>
> +#include <semanage/ibpkey_record.h>
> +
> +extern int semanage_ibpkey_query(semanage_handle_t *handle,
> +				 const semanage_ibpkey_key_t *key,
> +				 semanage_ibpkey_t **response);
> +
> +extern int semanage_ibpkey_exists(semanage_handle_t *handle,
> +				  const semanage_ibpkey_key_t *key,
> int *response);
> +
> +extern int semanage_ibpkey_count(semanage_handle_t *handle,
> +				 unsigned int *response);
> +
> +extern int semanage_ibpkey_iterate(semanage_handle_t *handle,
> +				   int (*handler)(const
> semanage_ibpkey_t *record,
> +						  void *varg),
> +				   void *handler_arg);
> +
> +extern int semanage_ibpkey_list(semanage_handle_t *handle,
> +				semanage_ibpkey_t ***records,
> +				unsigned int *count);
> +
> +#endif
> diff --git a/libsemanage/include/semanage/semanage.h
> b/libsemanage/include/semanage/semanage.h
> index f417ce4..cebf3f4 100644
> --- a/libsemanage/include/semanage/semanage.h
> +++ b/libsemanage/include/semanage/semanage.h
> @@ -33,6 +33,7 @@
>  #include <semanage/context_record.h>
>  #include <semanage/iface_record.h>
>  #include <semanage/port_record.h>
> +#include <semanage/ibpkey_record.h>
>  #include <semanage/node_record.h>
>  
>  /* Dbase */
> @@ -47,6 +48,8 @@
>  #include <semanage/seusers_policy.h>
>  #include <semanage/ports_local.h>
>  #include <semanage/ports_policy.h>
> +#include <semanage/ibpkeys_local.h>
> +#include <semanage/ibpkeys_policy.h>
>  #include <semanage/interfaces_local.h>
>  #include <semanage/interfaces_policy.h>
>  #include <semanage/nodes_local.h>
> diff --git a/libsemanage/src/direct_api.c
> b/libsemanage/src/direct_api.c
> index f4b0416..f190b0c 100644
> --- a/libsemanage/src/direct_api.c
> +++ b/libsemanage/src/direct_api.c
> @@ -40,6 +40,7 @@
>  #include "user_internal.h"
>  #include "seuser_internal.h"
>  #include "port_internal.h"
> +#include "ibpkey_internal.h"
>  #include "iface_internal.h"
>  #include "boolean_internal.h"
>  #include "fcontext_internal.h"
> @@ -224,6 +225,14 @@ int semanage_direct_connect(semanage_handle_t *
> sh)
>  				 semanage_node_dbase_local(sh)) < 0)
>  		goto err;
>  
> +	if (ibpkey_file_dbase_init(sh,
> +				 semanage_path(SEMANAGE_ACTIVE,
> +					       SEMANAGE_IBPKEYS_LOCA
> L),
> +				 semanage_path(SEMANAGE_TMP,
> +					       SEMANAGE_IBPKEYS_LOCA
> L),
> +				 semanage_ibpkey_dbase_local(sh)) <
> 0)
> +		goto err;
> +
>  	/* Object databases: local modifications + policy */
>  	if (user_base_policydb_dbase_init(sh,
>  					  semanage_user_base_dbase_p
> olicy(sh)) <
> @@ -248,6 +257,9 @@ int semanage_direct_connect(semanage_handle_t *
> sh)
>  	if (port_policydb_dbase_init(sh,
> semanage_port_dbase_policy(sh)) < 0)
>  		goto err;
>  
> +	if (ibpkey_policydb_dbase_init(sh,
> semanage_ibpkey_dbase_policy(sh)) < 0)
> +		goto err;
> +
>  	if (iface_policydb_dbase_init(sh,
> semanage_iface_dbase_policy(sh)) < 0)
>  		goto err;
>  
> @@ -320,6 +332,7 @@ static int
> semanage_direct_disconnect(semanage_handle_t * sh)
>  	user_extra_file_dbase_release(semanage_user_extra_dbase_loca
> l(sh));
>  	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));
>  	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
> ));
> @@ -331,6 +344,7 @@ static int
> semanage_direct_disconnect(semanage_handle_t * sh)
>  	user_extra_file_dbase_release(semanage_user_extra_dbase_poli
> cy(sh));
>  	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(s
> h));
>  	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(s
> h));
> @@ -1144,13 +1158,15 @@ static int
> semanage_direct_commit(semanage_handle_t * sh)
>  
>  	int do_rebuild, do_write_kernel, do_install;
>  	int fcontexts_modified, ports_modified, seusers_modified,
> -		disable_dontaudit, preserve_tunables;
> +		disable_dontaudit, preserve_tunables,
> ibpkeys_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);
>  	dbase_config_t *pusers_extra =
> semanage_user_extra_dbase_policy(sh);
>  	dbase_config_t *ports = semanage_port_dbase_local(sh);
>  	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 *bools = semanage_bool_dbase_local(sh);
>  	dbase_config_t *pbools = semanage_bool_dbase_policy(sh);
>  	dbase_config_t *ifaces = semanage_iface_dbase_local(sh);
> @@ -1164,6 +1180,7 @@ static int
> semanage_direct_commit(semanage_handle_t * sh)
>  
>  	/* 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);
>  	seusers_modified = seusers->dtable->is_modified(seusers-
> >dbase);
>  	fcontexts_modified = fcontexts->dtable-
> >is_modified(fcontexts->dbase);
>  
> @@ -1285,7 +1302,7 @@ rebuild:
>  	 * that live under /etc/selinux (kernel policy, seusers,
> file contexts)
>  	 * will be modified.
>  	 */
> -	do_write_kernel = do_rebuild | ports_modified |
> +	do_write_kernel = do_rebuild | ports_modified |
> ibpkeys_modified
>  		bools->dtable->is_modified(bools->dbase) |
>  		ifaces->dtable->is_modified(ifaces->dbase) |
>  		nodes->dtable->is_modified(nodes->dbase) |
> @@ -1431,6 +1448,7 @@ rebuild:
>  	/* Attach our databases to the policydb we just created or
> loaded. */
>  	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 *) pifaces->dbase,
> out);
>  	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase,
> out);
>  	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase,
> out);
> @@ -1479,6 +1497,12 @@ rebuild:
>  			goto cleanup;
>  	}
>  
> +	/* Validate local ibpkeys for overlap */
> +	if (do_rebuild || ibpkeys_modified) {
> +		retval = semanage_ibpkey_validate_local(sh);
> +		if (retval < 0)
> +			goto cleanup;
> +	}
>  	/* ================== Write non-policydb components
> ========= */
>  
>  	/* Commit changes to components */
> @@ -1558,6 +1582,7 @@ cleanup:
>  	/* Detach from policydb, so it can be freed */
>  	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 *) 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 64175c4..306727a 100644
> --- a/libsemanage/src/handle.h
> +++ b/libsemanage/src/handle.h
> @@ -79,7 +79,7 @@ struct semanage_handle {
>  	struct semanage_policy_table *funcs;
>  
>  	/* Object databases */
> -#define DBASE_COUNT      19
> +#define DBASE_COUNT      21
>  
>  /* Local modifications */
>  #define DBASE_LOCAL_USERS_BASE  0
> @@ -91,20 +91,22 @@ struct semanage_handle {
>  #define DBASE_LOCAL_FCONTEXTS	6
>  #define DBASE_LOCAL_SEUSERS     7
>  #define DBASE_LOCAL_NODES       8
> +#define DBASE_LOCAL_IBPKEYS     9
>  
>  /* Policy + Local modifications */
> -#define DBASE_POLICY_USERS_BASE  9
> -#define DBASE_POLICY_USERS_EXTRA 10
> -#define DBASE_POLICY_USERS       11
> -#define DBASE_POLICY_PORTS       12
> -#define DBASE_POLICY_INTERFACES  13
> -#define DBASE_POLICY_BOOLEANS    14
> -#define DBASE_POLICY_FCONTEXTS   15
> -#define DBASE_POLICY_SEUSERS     16
> -#define DBASE_POLICY_NODES       17
> +#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
>  
>  /* Active kernel policy */
> -#define DBASE_ACTIVE_BOOLEANS    18
> +#define DBASE_ACTIVE_BOOLEANS    20
>  	dbase_config_t dbase[DBASE_COUNT];
>  };
>  
> @@ -134,6 +136,12 @@ static inline
>  }
>  
>  static inline
> +    dbase_config_t * semanage_ibpkey_dbase_local(semanage_handle_t *
> handle)
> +{
> +	return &handle->dbase[DBASE_LOCAL_IBPKEYS];
> +}
> +
> +static inline
>      dbase_config_t * semanage_iface_dbase_local(semanage_handle_t *
> handle)
>  {
>  	return &handle->dbase[DBASE_LOCAL_INTERFACES];
> @@ -190,6 +198,12 @@ static inline
>  }
>  
>  static inline
> +    dbase_config_t * semanage_ibpkey_dbase_policy(semanage_handle_t
> * handle)
> +{
> +	return &handle->dbase[DBASE_POLICY_IBPKEYS];
> +}
> +
> +static inline
>      dbase_config_t * semanage_iface_dbase_policy(semanage_handle_t *
> handle)
>  {
>  	return &handle->dbase[DBASE_POLICY_INTERFACES];
> diff --git a/libsemanage/src/ibpkey_internal.h
> b/libsemanage/src/ibpkey_internal.h
> new file mode 100644
> index 0000000..9465bb8
> --- /dev/null
> +++ b/libsemanage/src/ibpkey_internal.h
> @@ -0,0 +1,52 @@
> +#ifndef _SEMANAGE_IBPKEY_INTERNAL_H_
> +#define _SEMANAGE_IBPKEY_INTERNAL_H_
> +
> +#include <semanage/ibpkey_record.h>
> +#include <semanage/ibpkeys_local.h>
> +#include <semanage/ibpkeys_policy.h>
> +#include "database.h"
> +#include "handle.h"
> +#include "dso.h"
> +
> +hidden_proto(semanage_ibpkey_create)
> +hidden_proto(semanage_ibpkey_compare)
> +hidden_proto(semanage_ibpkey_compare2)
> +hidden_proto(semanage_ibpkey_clone)
> +hidden_proto(semanage_ibpkey_free)
> +hidden_proto(semanage_ibpkey_key_extract)
> +hidden_proto(semanage_ibpkey_key_free)
> +hidden_proto(semanage_ibpkey_get_high)
> +hidden_proto(semanage_ibpkey_get_low)
> +hidden_proto(semanage_ibpkey_set_pkey)
> +hidden_proto(semanage_ibpkey_set_range)
> +hidden_proto(semanage_ibpkey_get_con)
> +hidden_proto(semanage_ibpkey_set_con)
> +hidden_proto(semanage_ibpkey_list_local)
> +hidden_proto(semanage_ibpkey_get_subnet_prefix)
> +hidden_proto(semanage_ibpkey_get_subnet_prefix_bytes)
> +hidden_proto(semanage_ibpkey_set_subnet_prefix)
> +hidden_proto(semanage_ibpkey_set_subnet_prefix_bytes)
> +
> +/* PKEY RECORD: method table */
> +extern record_table_t SEMANAGE_IBPKEY_RTABLE;
> +
> +extern int ibpkey_file_dbase_init(semanage_handle_t *handle,
> +				  const char *path_ro,
> +				  const char *path_rw,
> +				  dbase_config_t *dconfig);
> +
> +extern void ibpkey_file_dbase_release(dbase_config_t *dconfig);
> +
> +extern int ibpkey_policydb_dbase_init(semanage_handle_t *handle,
> +				      dbase_config_t *dconfig);
> +
> +extern void ibpkey_policydb_dbase_release(dbase_config_t *dconfig);
> +
> +extern int hidden semanage_ibpkey_validate_local(semanage_handle_t
> *handle);
> +
> +/* ==== Internal (to ibpkeys) API === */
> +
> +hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t
> **ibpkey,
> +					  const semanage_ibpkey_t
> **ibpkey2);
> +
> +#endif
> diff --git a/libsemanage/src/ibpkey_record.c
> b/libsemanage/src/ibpkey_record.c
> new file mode 100644
> index 0000000..d170c40
> --- /dev/null
> +++ b/libsemanage/src/ibpkey_record.c
> @@ -0,0 +1,187 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc. */
> +
> +/* Object: semanage_ibpkey_t (Infiniband Pkey)
> + * Object: semanage_ibpkey_key_t (Infiniband Pkey Key)
> + * Implements: record_t (Database Record)
> + * Implements: record_key_t (Database Record Key)
> + */
> +
> +#include <sepol/context_record.h>
> +#include <sepol/ibpkey_record.h>
> +
> +typedef sepol_context_t semanage_context_t;
> +typedef sepol_ibpkey_t semanage_ibpkey_t;
> +typedef sepol_ibpkey_key_t semanage_ibpkey_key_t;
> +#define _SEMANAGE_IBPKEY_DEFINED_
> +#define _SEMANAGE_CONTEXT_DEFINED_
> +
> +typedef semanage_ibpkey_t record_t;
> +typedef semanage_ibpkey_key_t record_key_t;
> +#define DBASE_RECORD_DEFINED
> +
> +#include "ibpkey_internal.h"
> +#include "handle.h"
> +#include "database.h"
> +
> +int semanage_ibpkey_compare(const semanage_ibpkey_t *ibpkey,
> +			    const semanage_ibpkey_key_t *key)
> +{
> +	return sepol_ibpkey_compare(ibpkey, key);
> +}
> +
> +hidden_def(semanage_ibpkey_compare)
> +
> +int semanage_ibpkey_compare2(const semanage_ibpkey_t *ibpkey,
> +			     const semanage_ibpkey_t *ibpkey2)
> +{
> +	return sepol_ibpkey_compare2(ibpkey, ibpkey2);
> +}
> +
> +hidden_def(semanage_ibpkey_compare2)
> +
> +hidden int semanage_ibpkey_compare2_qsort(const semanage_ibpkey_t
> **ibpkey,
> +					  const semanage_ibpkey_t
> **ibpkey2)
> +{
> +	return sepol_ibpkey_compare2(*ibpkey, *ibpkey2);
> +}
> +
> +int semanage_ibpkey_key_create(semanage_handle_t *handle,
> +			       const char *subnet_prefix,
> +			       int low, int high,
> +			       semanage_ibpkey_key_t **key_ptr)
> +{
> +	return sepol_ibpkey_key_create(handle->sepolh,
> subnet_prefix, low, high, key_ptr);
> +}
> +
> +int semanage_ibpkey_key_extract(semanage_handle_t *handle,
> +				const semanage_ibpkey_t *ibpkey,
> +				semanage_ibpkey_key_t **key_ptr)
> +{
> +	return sepol_ibpkey_key_extract(handle->sepolh, ibpkey,
> key_ptr);
> +}
> +
> +hidden_def(semanage_ibpkey_key_extract)
> +
> +void semanage_ibpkey_key_free(semanage_ibpkey_key_t *key)
> +{
> +	sepol_ibpkey_key_free(key);
> +}
> +
> +hidden_def(semanage_ibpkey_key_free)
> +
> +int semanage_ibpkey_get_subnet_prefix(semanage_handle_t *handle,
> +				      const semanage_ibpkey_t
> *ibpkey,
> +				      char **subnet_prefix_ptr)
> +{
> +	return sepol_ibpkey_get_subnet_prefix(handle->sepolh,
> ibpkey, subnet_prefix_ptr);
> +}
> +
> +hidden_def(semanage_ibpkey_get_subnet_prefix)
> +
> +int semanage_ibpkey_get_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +					    const semanage_ibpkey_t
> *ibpkey,
> +					    char **subnet_prefix,
> +					    size_t
> *subnet_prefix_sz)
> +{
> +	return sepol_ibpkey_get_subnet_prefix_bytes(handle->sepolh,
> ibpkey, subnet_prefix, subnet_prefix_sz);
> +}
> +
> +hidden_def(semanage_ibpkey_get_subnet_prefix_bytes)
> +
> +int semanage_ibpkey_set_subnet_prefix(semanage_handle_t *handle,
> +				      semanage_ibpkey_t *ibpkey,
> +				      const char *subnet_prefix)
> +{
> +	return sepol_ibpkey_set_subnet_prefix(handle->sepolh,
> ibpkey, subnet_prefix);
> +}
> +
> +hidden_def(semanage_ibpkey_set_subnet_prefix)
> +
> +int semanage_ibpkey_set_subnet_prefix_bytes(semanage_handle_t
> *handle,
> +					    semanage_ibpkey_t
> *ibpkey,
> +					    const char
> *subnet_prefix,
> +					    size_t subnet_prefix_sz)
> +{
> +	return sepol_ibpkey_set_subnet_prefix_bytes(handle->sepolh,
> ibpkey, subnet_prefix, subnet_prefix_sz);
> +}
> +
> +hidden_def(semanage_ibpkey_set_subnet_prefix_bytes)
> +
> +int semanage_ibpkey_get_low(const semanage_ibpkey_t *ibpkey)
> +{
> +	return sepol_ibpkey_get_low(ibpkey);
> +}
> +
> +hidden_def(semanage_ibpkey_get_low)
> +
> +int semanage_ibpkey_get_high(const semanage_ibpkey_t *ibpkey)
> +{
> +	return sepol_ibpkey_get_high(ibpkey);
> +}
> +
> +hidden_def(semanage_ibpkey_get_high)
> +
> +void semanage_ibpkey_set_pkey(semanage_ibpkey_t *ibpkey, int
> ibpkey_num)
> +{
> +	sepol_ibpkey_set_pkey(ibpkey, ibpkey_num);
> +}
> +
> +hidden_def(semanage_ibpkey_set_pkey)
> +
> +void semanage_ibpkey_set_range(semanage_ibpkey_t *ibpkey, int low,
> int high)
> +{
> +	sepol_ibpkey_set_range(ibpkey, low, high);
> +}
> +
> +hidden_def(semanage_ibpkey_set_range)
> +
> +semanage_context_t *semanage_ibpkey_get_con(const semanage_ibpkey_t
> *ibpkey)
> +{
> +	return sepol_ibpkey_get_con(ibpkey);
> +}
> +
> +hidden_def(semanage_ibpkey_get_con)
> +
> +int semanage_ibpkey_set_con(semanage_handle_t *handle,
> +			    semanage_ibpkey_t *ibpkey,
> semanage_context_t *con)
> +{
> +	return sepol_ibpkey_set_con(handle->sepolh, ibpkey, con);
> +}
> +
> +hidden_def(semanage_ibpkey_set_con)
> +
> +int semanage_ibpkey_create(semanage_handle_t *handle,
> +			   semanage_ibpkey_t **ibpkey_ptr)
> +{
> +	return sepol_ibpkey_create(handle->sepolh, ibpkey_ptr);
> +}
> +
> +hidden_def(semanage_ibpkey_create)
> +
> +int semanage_ibpkey_clone(semanage_handle_t *handle,
> +			  const semanage_ibpkey_t *ibpkey,
> +			  semanage_ibpkey_t **ibpkey_ptr)
> +{
> +	return sepol_ibpkey_clone(handle->sepolh, ibpkey,
> ibpkey_ptr);
> +}
> +
> +hidden_def(semanage_ibpkey_clone)
> +
> +void semanage_ibpkey_free(semanage_ibpkey_t *ibpkey)
> +{
> +	sepol_ibpkey_free(ibpkey);
> +}
> +
> +hidden_def(semanage_ibpkey_free)
> +
> +/* key base functions */
> +record_table_t SEMANAGE_IBPKEY_RTABLE = {
> +	.create = semanage_ibpkey_create,
> +	.key_extract = semanage_ibpkey_key_extract,
> +	.key_free = semanage_ibpkey_key_free,
> +	.clone = semanage_ibpkey_clone,
> +	.compare = semanage_ibpkey_compare,
> +	.compare2 = semanage_ibpkey_compare2,
> +	.compare2_qsort = semanage_ibpkey_compare2_qsort,
> +	.free = semanage_ibpkey_free,
> +};
> diff --git a/libsemanage/src/ibpkeys_file.c
> b/libsemanage/src/ibpkeys_file.c
> new file mode 100644
> index 0000000..ceaea7a
> --- /dev/null
> +++ b/libsemanage/src/ibpkeys_file.c
> @@ -0,0 +1,181 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc. */
> +
> +struct semanage_ibpkey;
> +struct semanage_ibpkey_key;
> +typedef struct semanage_ibpkey record_t;
> +typedef struct semanage_ibpkey_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 "ibpkey_internal.h"
> +#include "context_internal.h"
> +#include "database_file.h"
> +#include "parse_utils.h"
> +#include "debug.h"
> +
> +static int ibpkey_print(semanage_handle_t *handle,
> +			semanage_ibpkey_t *ibpkey, FILE *str)
> +{
> +	char *con_str = NULL;
> +	char *subnet_prefix_str = NULL;
> +
> +	int low = semanage_ibpkey_get_low(ibpkey);
> +	int high = semanage_ibpkey_get_high(ibpkey);
> +
> +	if (semanage_ibpkey_get_subnet_prefix(handle, ibpkey,
> &subnet_prefix_str) != 0)
> +		goto err;
> +
> +	semanage_context_t *con = semanage_ibpkey_get_con(ibpkey);
> +
> +	if (fprintf(str, "ibpkeycon %s ", subnet_prefix_str) < 0)
> +		goto err;
> +
> +	if (low == high) {
> +		if (fprintf(str, "%d ", low) < 0)
> +			goto err;
> +	} else {
> +		if (fprintf(str, "%d - %d ", low, high) < 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(subnet_prefix_str);
> +	free(con_str);
> +	return STATUS_SUCCESS;
> +
> +err:
> +	ERR(handle, "could not print ibpkey range (%s) %u - %u to
> stream",
> +	    subnet_prefix_str, low, high);
> +	free(subnet_prefix_str);
> +	free(con_str);
> +	return STATUS_ERR;
> +}
> +
> +static int ibpkey_parse(semanage_handle_t *handle,
> +			parse_info_t *info, semanage_ibpkey_t
> *ibpkey)
> +{
> +	int low, high;
> +	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, "ibpkeycon") < 0)
> +		goto err;
> +	if (parse_assert_space(handle, info) < 0)
> +		goto err;
> +
> +	/* Subnet Prefix */
> +	if (parse_fetch_string(handle, info, &str, ' ') < 0)
> +		goto err;
> +	if (semanage_ibpkey_set_subnet_prefix(handle, ibpkey, str) <
> 0)
> +		goto err;
> +	free(str);
> +	str = NULL;
> +
> +	/* Range/Pkey */
> +	if (parse_assert_space(handle, info) < 0)
> +		goto err;
> +	if (parse_fetch_int(handle, info, &low, '-') < 0)
> +		goto err;
> +
> +	/* If range (-) does not follow immediately, require a space
> +	 * In other words, the space here is optional, but only
> +	 * in the ranged case, not in the single ibpkey case,
> +	 * so do a custom test
> +	 */
> +	if (*info->ptr && *info->ptr != '-') {
> +		if (parse_assert_space(handle, info) < 0)
> +			goto err;
> +	}
> +
> +	if (parse_optional_ch(info, '-') != STATUS_NODATA) {
> +		if (parse_skip_space(handle, info) < 0)
> +			goto err;
> +		if (parse_fetch_int(handle, info, &high, ' ') < 0)
> +			goto err;
> +		if (parse_assert_space(handle, info) < 0)
> +			goto err;
> +		semanage_ibpkey_set_range(ibpkey, low, high);
> +	} else {
> +		semanage_ibpkey_set_pkey(ibpkey, low);
> +	}
> +	/* Pkey context */
> +	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
> ibpkeys (%s: %u):\n%s",
> +		    info->filename,
> +		    info->lineno, info->orig_line);
> +		goto err;
> +	}
> +	free(str);
> +	str = NULL;
> +
> +	if (semanage_ibpkey_set_con(handle, ibpkey, 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 ibpkey record");
> +	free(str);
> +	semanage_context_free(con);
> +	parse_dispose_line(info);
> +	return STATUS_ERR;
> +}
> +
> +/* IBPKEY RECORD: FILE extension: method table */
> +record_file_table_t SEMANAGE_IBPKEY_FILE_RTABLE = {
> +	.parse = ibpkey_parse,
> +	.print = ibpkey_print,
> +};
> +
> +int ibpkey_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_IBPKEY_RTABLE,
> +			    &SEMANAGE_IBPKEY_FILE_RTABLE, &dconfig-
> >dbase) < 0)
> +		return STATUS_ERR;
> +
> +	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
> +	return STATUS_SUCCESS;
> +}
> +
> +void ibpkey_file_dbase_release(dbase_config_t *dconfig)
> +{
> +	dbase_file_release(dconfig->dbase);
> +}
> diff --git a/libsemanage/src/ibpkeys_local.c
> b/libsemanage/src/ibpkeys_local.c
> new file mode 100644
> index 0000000..e016db0
> --- /dev/null
> +++ b/libsemanage/src/ibpkeys_local.c
> @@ -0,0 +1,182 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc. */
> +
> +struct semanage_ibpkey;
> +struct semanage_ibpkey_key;
> +typedef struct semanage_ibpkey_key record_key_t;
> +typedef struct semanage_ibpkey record_t;
> +#define DBASE_RECORD_DEFINED
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include "ibpkey_internal.h"
> +#include "debug.h"
> +#include "handle.h"
> +#include "database.h"
> +
> +int semanage_ibpkey_modify_local(semanage_handle_t *handle,
> +				 const semanage_ibpkey_key_t *key,
> +				 const semanage_ibpkey_t *data)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_modify(handle, dconfig, key, data);
> +}
> +
> +int semanage_ibpkey_del_local(semanage_handle_t *handle,
> +			      const semanage_ibpkey_key_t *key)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_del(handle, dconfig, key);
> +}
> +
> +int semanage_ibpkey_query_local(semanage_handle_t *handle,
> +				const semanage_ibpkey_key_t *key,
> +				semanage_ibpkey_t **response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_query(handle, dconfig, key, response);
> +}
> +
> +int semanage_ibpkey_exists_local(semanage_handle_t *handle,
> +				 const semanage_ibpkey_key_t *key,
> +				 int *response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_exists(handle, dconfig, key, response);
> +}
> +
> +int semanage_ibpkey_count_local(semanage_handle_t *handle,
> +				unsigned int *response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_count(handle, dconfig, response);
> +}
> +
> +int semanage_ibpkey_iterate_local(semanage_handle_t *handle,
> +				  int (*handler)(const
> semanage_ibpkey_t *record,
> +						 void *varg), void
> *handler_arg)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_iterate(handle, dconfig, handler, handler_arg);
> +}
> +
> +int semanage_ibpkey_list_local(semanage_handle_t *handle,
> +			       semanage_ibpkey_t ***records,
> unsigned int *count)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_local(handle);
> +
> +	return dbase_list(handle, dconfig, records, count);
> +}
> +
> +hidden_def(semanage_ibpkey_list_local)
> +
> +int hidden semanage_ibpkey_validate_local(semanage_handle_t *handle)
> +{
> +	semanage_ibpkey_t **ibpkeys = NULL;
> +	unsigned int nibpkeys = 0;
> +	unsigned int i = 0, j = 0;
> +	char *subnet_prefix;
> +	char *subnet_prefix2;
> +	char *subnet_prefix_str;
> +	char *subnet_prefix_str2;
> +	int low, high;
> +	int low2, high2;
> +	size_t subnet_prefix_sz, subnet_prefix2_sz;
> +
> +	/* List and sort the ibpkeys */
> +	if (semanage_ibpkey_list_local(handle, &ibpkeys, &nibpkeys)
> < 0)
> +		goto err;
> +
> +	qsort(ibpkeys, nibpkeys, sizeof(semanage_ibpkey_t *),
> +	      (int (*)(const void *, const void *))
> +	      &semanage_ibpkey_compare2_qsort);
> +
> +	/* Test each ibpkey for overlap */
> +	while (i < nibpkeys) {
> +		int stop = 0;
> +
> +		if (STATUS_SUCCESS !=
> +				semanage_ibpkey_get_subnet_prefix_by
> tes(handle,
> +								    
>   ibpkeys[i],
> +								    
>   &subnet_prefix,
> +								    
>   &subnet_prefix_sz)) {
> +			ERR(handle, "Couldn't get subnet prefix");
> +			goto err;
> +		}
> +		if (STATUS_SUCCESS !=
> semanage_ibpkey_get_subnet_prefix(handle,
> +								    
>   ibpkeys[i],
> +								    
>   &subnet_prefix_str)) {
> +			ERR(handle, "Couldn't get subnet prefix
> string");
> +			goto err;
> +		}
> +
> +		low = semanage_ibpkey_get_low(ibpkeys[i]);
> +		high = semanage_ibpkey_get_high(ibpkeys[i]);
> +
> +		/* Find the first ibpkey with matching
> +		 * subnet_prefix to compare against
> +		 */
> +		do {
> +			if (j == nibpkeys - 1)
> +				goto next;
> +			j++;
> +			if (STATUS_SUCCESS !=
> +				semanage_ibpkey_get_subnet_prefix_by
> tes(handle,
> +								    
>   ibpkeys[j],
> +								    
>   &subnet_prefix2,
> +								    
>   &subnet_prefix2_sz)) {
> +				ERR(handle, "Couldn't get subnet
> prefix");
> +				goto err;
> +			}
> +			if (STATUS_SUCCESS !=
> +				semanage_ibpkey_get_subnet_prefix(ha
> ndle,
> +								ibpk
> eys[j],
> +								&sub
> net_prefix_str2)) {
> +				ERR(handle, "Couldn't get subnet
> prefix string");
> +				goto err;
> +			}
> +			low2 = semanage_ibpkey_get_low(ibpkeys[j]);
> +			high2 =
> semanage_ibpkey_get_high(ibpkeys[j]);
> +
> +			if (subnet_prefix_sz == subnet_prefix2_sz)
> +				stop = !memcmp(subnet_prefix,
> subnet_prefix2, subnet_prefix_sz);
> +		} while (!stop);
> +
> +		/* Overlap detected */
> +		if (low2 <= high) {
> +			ERR(handle, "ibpkey overlap between ranges "
> +			    "(%s) %u - %u <--> (%s) %u - %u.",
> +			    subnet_prefix_str, low, high,
> +			    subnet_prefix_str2, low2, high2);
> +			goto invalid;
> +		}
> +
> +		/* If closest ibpkey of matching subnet prefix
> doesn't overlap
> +		 * with test ibpkey, neither do the rest of them,
> because that's
> +		 * how the sort function works on ibpkeys - lower
> bound
> +		 * ibpkeys come first
> +		 */
> +next:
> +		i++;
> +		j = i;
> +	}
> +
> +	for (i = 0; i < nibpkeys; i++)
> +		semanage_ibpkey_free(ibpkeys[i]);
> +	free(ibpkeys);
> +	return STATUS_SUCCESS;
> +
> +err:
> +	ERR(handle, "could not complete ibpkeys validity check");
> +
> +invalid:
> +	for (i = 0; i < nibpkeys; i++)
> +		semanage_ibpkey_free(ibpkeys[i]);
> +	free(ibpkeys);
> +	return STATUS_ERR;
> +}
> diff --git a/libsemanage/src/ibpkeys_policy.c
> b/libsemanage/src/ibpkeys_policy.c
> new file mode 100644
> index 0000000..0956230
> --- /dev/null
> +++ b/libsemanage/src/ibpkeys_policy.c
> @@ -0,0 +1,52 @@
> +/* Copyright (C) 2017 Mellanox Technologies Inc. */
> +
> +struct semanage_ibpkey;
> +struct semanage_ibpkey_key;
> +typedef struct semanage_ibpkey_key record_key_t;
> +typedef struct semanage_ibpkey record_t;
> +#define DBASE_RECORD_DEFINED
> +
> +#include "ibpkey_internal.h"
> +#include "handle.h"
> +#include "database.h"
> +
> +int semanage_ibpkey_query(semanage_handle_t *handle,
> +			  const semanage_ibpkey_key_t *key,
> +			  semanage_ibpkey_t **response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_policy(handle);
> +
> +	return dbase_query(handle, dconfig, key, response);
> +}
> +
> +int semanage_ibpkey_exists(semanage_handle_t *handle,
> +			   const semanage_ibpkey_key_t *key, int
> *response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_policy(handle);
> +
> +	return dbase_exists(handle, dconfig, key, response);
> +}
> +
> +int semanage_ibpkey_count(semanage_handle_t *handle, unsigned int
> *response)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_policy(handle);
> +
> +	return dbase_count(handle, dconfig, response);
> +}
> +
> +int semanage_ibpkey_iterate(semanage_handle_t *handle,
> +			    int (*handler)(const semanage_ibpkey_t
> *record,
> +					   void *varg), void
> *handler_arg)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_policy(handle);
> +
> +	return dbase_iterate(handle, dconfig, handler, handler_arg);
> +}
> +
> +int semanage_ibpkey_list(semanage_handle_t *handle,
> +			 semanage_ibpkey_t ***records, unsigned int
> *count)
> +{
> +	dbase_config_t *dconfig =
> semanage_ibpkey_dbase_policy(handle);
> +
> +	return dbase_list(handle, dconfig, records, count);
> +}
> diff --git a/libsemanage/src/ibpkeys_policydb.c
> b/libsemanage/src/ibpkeys_policydb.c
> new file mode 100644
> index 0000000..8d73cf6
> --- /dev/null
> +++ b/libsemanage/src/ibpkeys_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_ibpkey;
> +struct semanage_ibpkey_key;
> +typedef struct semanage_ibpkey record_t;
> +typedef struct semanage_ibpkey_key record_key_t;
> +#define DBASE_RECORD_DEFINED
> +
> +struct dbase_policydb;
> +typedef struct dbase_policydb dbase_t;
> +#define DBASE_DEFINED
> +
> +#include <sepol/ibpkeys.h>
> +#include <semanage/handle.h>
> +#include "ibpkey_internal.h"
> +#include "debug.h"
> +#include "database_policydb.h"
> +#include "semanage_store.h"
> +
> +/* PKEY RECORD (SEPOL): POLICYDB extension : method table */
> +record_policydb_table_t SEMANAGE_IBPKEY_POLICYDB_RTABLE = {
> +	.add = NULL,
> +	.modify =
> (record_policydb_table_modify_t)sepol_ibpkey_modify,
> +	.set = NULL,
> +	.query = (record_policydb_table_query_t)sepol_ibpkey_query,
> +	.count = (record_policydb_table_count_t)sepol_ibpkey_count,
> +	.exists =
> (record_policydb_table_exists_t)sepol_ibpkey_exists,
> +	.iterate =
> (record_policydb_table_iterate_t)sepol_ibpkey_iterate,
> +};
> +
> +int ibpkey_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_IBPKEY_RTABLE,
> +				&SEMANAGE_IBPKEY_POLICYDB_RTABLE,
> +				&dconfig->dbase) < 0)
> +		return STATUS_ERR;
> +
> +	dconfig->dtable = &SEMANAGE_POLICYDB_DTABLE;
> +
> +	return STATUS_SUCCESS;
> +}
> +
> +void ibpkey_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 9f8a754..041b1ce 100644
> --- a/libsemanage/src/libsemanage.map
> +++ b/libsemanage/src/libsemanage.map
> @@ -18,6 +18,7 @@ LIBSEMANAGE_1.0 {
>  	  semanage_root;
>  	  semanage_user_*; semanage_bool_*; semanage_seuser_*;
>  	  semanage_iface_*; semanage_port_*; semanage_context_*;
> +	  semanage_ibpkey_*;
>  	  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 d31bd48..136c5a7 100644
> --- a/libsemanage/src/policy_components.c
> +++ b/libsemanage/src/policy_components.c
> @@ -137,12 +137,14 @@ int
> semanage_base_merge_components(semanage_handle_t * handle)
>  
>  		{semanage_node_dbase_local(handle),
>  		 semanage_node_dbase_policy(handle), MODE_MODIFY |
> MODE_SORT},
> +
> +		{semanage_ibpkey_dbase_local(handle),
> +		 semanage_ibpkey_dbase_policy(handle), MODE_MODIFY},
>  	};
>  	const unsigned int CCOUNT = sizeof(components) /
> sizeof(components[0]);
>  
>  	/* Merge components into policy (and validate) */
>  	for (i = 0; i < CCOUNT; i++) {
> -
>  		record_t **records = NULL;
>  		unsigned int nrecords = 0;
>  
> @@ -218,6 +220,7 @@ int semanage_commit_components(semanage_handle_t
> * handle)
>  		semanage_seuser_dbase_policy(handle),
>  		semanage_bool_dbase_active(handle),
>  		semanage_node_dbase_local(handle),
> +		semanage_ibpkey_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 6b75002..f61f3b2 100644
> --- a/libsemanage/src/semanage_store.c
> +++ b/libsemanage/src/semanage_store.c
> @@ -99,6 +99,7 @@ static const char
> *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
>  	"/homedir_template",
>  	"/file_contexts.template",
>  	"/commit_num",
> +	"/pkeys.local",
>  	"/ports.local",
>  	"/interfaces.local",
>  	"/nodes.local",
> diff --git a/libsemanage/src/semanage_store.h
> b/libsemanage/src/semanage_store.h
> index 0b96fbe..c7bcf44 100644
> --- a/libsemanage/src/semanage_store.h
> +++ b/libsemanage/src/semanage_store.h
> @@ -44,6 +44,7 @@ enum semanage_sandbox_defs {
>  	SEMANAGE_HOMEDIR_TMPL,
>  	SEMANAGE_FC_TMPL,
>  	SEMANAGE_COMMIT_NUM_FILE,
> +	SEMANAGE_IBPKEYS_LOCAL,
>  	SEMANAGE_PORTS_LOCAL,
>  	SEMANAGE_INTERFACES_LOCAL,
>  	SEMANAGE_NODES_LOCAL,
> diff --git a/libsemanage/src/semanageswig.i
> b/libsemanage/src/semanageswig.i
> index 583b7d8..d3ca795 100644
> --- a/libsemanage/src/semanageswig.i
> +++ b/libsemanage/src/semanageswig.i
> @@ -39,6 +39,9 @@
>  %include "../include/semanage/port_record.h"
>  %include "../include/semanage/ports_local.h"
>  %include "../include/semanage/ports_policy.h"
> +%include "../include/semanage/ibpkey_record.h"
> +%include "../include/semanage/ibpkeys_local.h"
> +%include "../include/semanage/ibpkeys_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 1346b2e..40932d8 100644
> --- a/libsemanage/src/semanageswig_python.i
> +++ b/libsemanage/src/semanageswig_python.i
> @@ -437,6 +437,49 @@
>  	$1 = &temp;
>  }
>  
> +/** ibpkey typemaps **/
> +
> +/* the wrapper will setup this parameter for passing... the
> resulting python functions
> +   will not take the semanage_ibpkey_t *** parameter */
> +%typemap(in, numinputs=0) semanage_ibpkey_t ***(semanage_ibpkey_t
> **temp=NULL) {
> +	$1 = &temp;
> +}
> +
> +%typemap(argout) (
> +	semanage_handle_t* handle,
> +	semanage_ibpkey_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_ibpkey,
> +				(void (*) (void*))
> &semanage_ibpkey_free, &plist) < 0)
> +				$result = SWIG_From_int(STATUS_ERR);
> +			else
> +				$result =
> SWIG_Python_AppendOutput($result, plist);
> +		}
> +	}
> +}
> +
> +%typemap(in, numinputs=0) semanage_ibpkey_t **(semanage_ibpkey_t
> *temp=NULL) {
> +	$1 = &temp;
> +}
> +
> +%typemap(argout) semanage_ibpkey_t ** {
> +	$result = SWIG_Python_AppendOutput($result,
> SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
> +}
> +
> +%typemap(argout) semanage_ibpkey_key_t ** {
> +	$result = SWIG_Python_AppendOutput($result,
> SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
> +}
> +
> +%typemap(in, numinputs=0) semanage_ibpkey_key_t
> **(semanage_ibpkey_key_t *temp=NULL) {
> +	$1 = &temp;
> +}
> +
>  /** node typemaps **/
>  
>  /* the wrapper will setup this parameter for passing... the
> resulting python functions
> diff --git a/libsemanage/utils/semanage_migrate_store
> b/libsemanage/utils/semanage_migrate_store
> index 0ebd285..325de47 100755
> --- a/libsemanage/utils/semanage_migrate_store
> +++ b/libsemanage/utils/semanage_migrate_store
> @@ -253,7 +253,8 @@ if __name__ == "__main__":
>  		"preserve_tunables",
>  		"policy.kern",
>  		"file_contexts",
> -		"homedir_template"]
> +		"homedir_template",
> +                "pkeys.local"]
>  
>  
>  	create_dir(newroot_path(), 0o755)
> diff --git a/libsepol/VERSION b/libsepol/VERSION
> index 5154b3f..e70b452 100644
> --- a/libsepol/VERSION
> +++ b/libsepol/VERSION
> @@ -1 +1 @@
> -2.6
> +2.6.0

Extraneous change?

> diff --git a/libsepol/include/sepol/ibpkey_record.h
> b/libsepol/include/sepol/ibpkey_record.h
> new file mode 100644
> index 0000000..815582b
> --- /dev/null
> +++ b/libsepol/include/sepol/ibpkey_record.h
> @@ -0,0 +1,75 @@
> +#ifndef _SEPOL_IBPKEY_RECORD_H_
> +#define _SEPOL_IBPKEY_RECORD_H_
> +
> +#include <stddef.h>
> +#include <sepol/context_record.h>
> +#include <sepol/handle.h>
> +#include <sys/cdefs.h>
> +
> +__BEGIN_DECLS
> +
> +struct sepol_ibpkey;
> +struct sepol_ibpkey_key;
> +typedef struct sepol_ibpkey sepol_ibpkey_t;
> +typedef struct sepol_ibpkey_key sepol_ibpkey_key_t;
> +
> +extern int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey,
> +			      const sepol_ibpkey_key_t *key);
> +
> +extern int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey,
> +			       const sepol_ibpkey_t *ibpkey2);
> +
> +extern int sepol_ibpkey_key_create(sepol_handle_t *handle,
> +				 const char *subnet_prefix,
> +				 int low, int high,
> +				 sepol_ibpkey_key_t **key_ptr);
> +
> +extern void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
> +				  const char **subnet_prefix,
> +				  int *low, int *high);
> +
> +extern int sepol_ibpkey_key_extract(sepol_handle_t *handle,
> +				  const sepol_ibpkey_t *ibpkey,
> +				  sepol_ibpkey_key_t **key_ptr);
> +
> +extern void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key);
> +
> +extern int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey);
> +
> +extern int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey);
> +
> +extern void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int
> pkey_num);
> +
> +extern void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low,
> int high);
> +
> +extern int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
> +					const sepol_ibpkey_t
> *ibpkey,
> +					char **subnet_prefix);
> +
> +extern int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t
> *handle,
> +					      const sepol_ibpkey_t
> *ibpkey,
> +					      char **buffer, size_t
> *bsize);
> +
> +extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
> +			sepol_ibpkey_t *ibpkey, const char
> *subnet_prefix);
> +
> +extern int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t
> *handle,
> +					      sepol_ibpkey_t
> *ibpkey,
> +					      const char
> *subnet_prefix,
> +					      size_t
> subnet_prefix_sz);
> +
> +extern sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t
> *ibpkey);
> +
> +extern int sepol_ibpkey_set_con(sepol_handle_t *handle,
> +			      sepol_ibpkey_t *ibpkey,
> sepol_context_t *con);
> +
> +extern int sepol_ibpkey_create(sepol_handle_t *handle,
> sepol_ibpkey_t **ibpkey_ptr);
> +
> +extern int sepol_ibpkey_clone(sepol_handle_t *handle,
> +			    const sepol_ibpkey_t *ibpkey,
> +			    sepol_ibpkey_t **ibpkey_ptr);
> +
> +extern void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey);
> +
> +__END_DECLS
> +#endif
> diff --git a/libsepol/include/sepol/ibpkeys.h
> b/libsepol/include/sepol/ibpkeys.h
> new file mode 100644
> index 0000000..4ab0a8a
> --- /dev/null
> +++ b/libsepol/include/sepol/ibpkeys.h
> @@ -0,0 +1,44 @@
> +#ifndef _SEPOL_IBPKEYS_H_
> +#define _SEPOL_IBPKEYS_H_
> +
> +#include <sepol/handle.h>
> +#include <sepol/policydb.h>
> +#include <sepol/ibpkey_record.h>
> +#include <sys/cdefs.h>
> +
> +__BEGIN_DECLS
> +
> +/* Return the number of ibpkeys */
> +extern int sepol_ibpkey_count(sepol_handle_t *handle,
> +			      const sepol_policydb_t *p, unsigned
> int *response);
> +
> +/* Check if a ibpkey exists */
> +extern int sepol_ibpkey_exists(sepol_handle_t *handle,
> +			       const sepol_policydb_t *policydb,
> +			       const sepol_ibpkey_key_t *key, int
> *response);
> +
> +/* Query a ibpkey - returns the ibpkey, or NULL if not found */
> +extern int sepol_ibpkey_query(sepol_handle_t *handle,
> +			      const sepol_policydb_t *policydb,
> +			      const sepol_ibpkey_key_t *key,
> +			      sepol_ibpkey_t **response);
> +
> +/* Modify a ibpkey, or add it, if the key is not found */
> +extern int sepol_ibpkey_modify(sepol_handle_t *handle,
> +			       sepol_policydb_t *policydb,
> +			       const sepol_ibpkey_key_t *key,
> +			       const sepol_ibpkey_t *data);
> +
> +/* Iterate the ibpkeys
> + * The handler may return:
> + * -1 to signal an error condition,
> + * 1 to signal successful exit
> + * 0 to signal continue
> + */
> +extern int sepol_ibpkey_iterate(sepol_handle_t *handle,
> +				const sepol_policydb_t *policydb,
> +				int (*fn)(const sepol_ibpkey_t
> *ibpkey,
> +					  void *fn_arg), void *arg);
> +
> +__END_DECLS
> +#endif
> diff --git a/libsepol/include/sepol/sepol.h
> b/libsepol/include/sepol/sepol.h
> index 513f77d..540f01d 100644
> --- a/libsepol/include/sepol/sepol.h
> +++ b/libsepol/include/sepol/sepol.h
> @@ -11,12 +11,14 @@ extern "C" {
>  #include <sepol/user_record.h>
>  #include <sepol/context_record.h>
>  #include <sepol/iface_record.h>
> +#include <sepol/ibpkey_record.h>
>  #include <sepol/port_record.h>
>  #include <sepol/boolean_record.h>
>  #include <sepol/node_record.h>
>  
>  #include <sepol/booleans.h>
>  #include <sepol/interfaces.h>
> +#include <sepol/ibpkeys.h>
>  #include <sepol/ports.h>
>  #include <sepol/nodes.h>
>  #include <sepol/users.h>
> diff --git a/libsepol/src/ibpkey_internal.h
> b/libsepol/src/ibpkey_internal.h
> new file mode 100644
> index 0000000..addf80a
> --- /dev/null
> +++ b/libsepol/src/ibpkey_internal.h
> @@ -0,0 +1,21 @@
> +#ifndef _SEPOL_IBPKEY_INTERNAL_H_
> +#define _SEPOL_IBPKEY_INTERNAL_H_
> +
> +#include <sepol/ibpkey_record.h>
> +#include <sepol/ibpkeys.h>
> +#include "dso.h"
> +
> +hidden_proto(sepol_ibpkey_create)
> +hidden_proto(sepol_ibpkey_free)
> +hidden_proto(sepol_ibpkey_get_con)
> +hidden_proto(sepol_ibpkey_get_high)
> +hidden_proto(sepol_ibpkey_get_low)
> +hidden_proto(sepol_ibpkey_key_create)
> +hidden_proto(sepol_ibpkey_key_unpack)
> +hidden_proto(sepol_ibpkey_set_con)
> +hidden_proto(sepol_ibpkey_set_range)
> +hidden_proto(sepol_ibpkey_get_subnet_prefix)
> +hidden_proto(sepol_ibpkey_get_subnet_prefix_bytes)
> +hidden_proto(sepol_ibpkey_set_subnet_prefix)
> +hidden_proto(sepol_ibpkey_set_subnet_prefix_bytes)
> +#endif
> diff --git a/libsepol/src/ibpkey_record.c
> b/libsepol/src/ibpkey_record.c
> new file mode 100644
> index 0000000..6fd9116
> --- /dev/null
> +++ b/libsepol/src/ibpkey_record.c
> @@ -0,0 +1,474 @@
> +#include <stdlib.h>
> +#include <string.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <errno.h>
> +#include <sepol/ibpkey_record.h>
> +
> +#include "ibpkey_internal.h"
> +#include "context_internal.h"
> +#include "debug.h"
> +
> +struct sepol_ibpkey {
> +	/* Subnet prefix */
> +	char *subnet_prefix;
> +	size_t subnet_prefix_sz;

Do we need support for variable-length subnet prefix?  Can it change?

> +
> +	/* Low - High range. Same for single ibpkeys. */
> +	int low, high;
> +
> +	/* Context */
> +	sepol_context_t *con;
> +};
> +
> +struct sepol_ibpkey_key {
> +	/* Subnet prefix */
> +	char *subnet_prefix;
> +	size_t subnet_prefix_sz;
> +
> +	/* Low - High range. Same for single ibpkeys. */
> +	int low, high;
> +};
> +
> +/* Converts a string represtation (subnet_prefix_str)
> + * to a numeric representation (subnet_prefix_bytes)
> + */
> +static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle,
> +				      const char *subnet_prefix_str,
> +				      char *subnet_prefix_bytes)
> +{
> +	struct in6_addr in_addr;
> +
> +	if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) {
> +		ERR(handle, "could not parse IPv6 address for ibpkey
> subnet prefix %s: %s",
> +		    subnet_prefix_str, strerror(errno));
> +		return STATUS_ERR;
> +	}
> +
> +#ifdef DARWIN
> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr, 16);
> +#else
> +	memcpy(subnet_prefix_bytes, in_addr.s6_addr32, 16);
> +#endif

Just reduce to always using s6_addr

> +
> +	return STATUS_SUCCESS;
> +}
> +
> +static int ibpkey_alloc_subnet_prefix(sepol_handle_t *handle,
> +				      char **subnet_prefix,
> +				      size_t *subnet_prefix_sz)
> +{
> +	char *tmp_subnet_prefix = malloc(16);
> +	size_t tmp_subnet_prefix_sz = 16;

No magic constants, and definitely not repeatedly used.

> +
> +	if (!tmp_subnet_prefix)
> +		goto omem;
> +
> +	*subnet_prefix = tmp_subnet_prefix;
> +	*subnet_prefix_sz = tmp_subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +	return STATUS_ERR;
> +}
> +
> +/* Converts a numeric representation (subnet_prefix_bytes)
> + * to a string representation (subnet_prefix_str)
> + */
> +
> +static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle,
> +				       char *subnet_prefix_bytes,
> +				       char *subnet_prefix_str)
> +{
> +	struct in6_addr addr;
> +
> +	memset(&addr, 0, sizeof(struct in6_addr));
> +#ifdef DARWIN
> +	memcpy(&addr.s6_addr[0], subnet_prefix_bytes, 16);
> +#else
> +	memcpy(&addr.s6_addr32[0], subnet_prefix_bytes, 16);
> +#endif
> +	if (inet_ntop(AF_INET6, &addr, subnet_prefix_str,
> +		      INET6_ADDRSTRLEN) == NULL) {
> +		ERR(handle,
> +		    "could not expand IPv6 address to string: %s",
> +		    strerror(errno));
> +		return STATUS_ERR;
> +	}
> +
> +	return STATUS_SUCCESS;
> +}
> +
> +/* Allocates a sufficiently large string (subnet_prefix)
> + * for an IPV6 address for the subnet prefix
> + */
> +static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle,
> +					     char **subnet_prefix)
> +{
> +	char *tmp_subnet_prefix = NULL;
> +
> +	tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN);
> +
> +	if (!tmp_subnet_prefix)
> +		goto omem;
> +
> +	*subnet_prefix = tmp_subnet_prefix;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +
> +	ERR(handle, "could not allocate string buffer for
> subnet_prefix");
> +	return STATUS_ERR;
> +}
> +
> +/* Key */
> +int sepol_ibpkey_key_create(sepol_handle_t *handle,
> +			    const char *subnet_prefix,
> +			    int low, int high,
> +			    sepol_ibpkey_key_t **key_ptr)
> +{
> +	sepol_ibpkey_key_t *tmp_key =
> +	    (sepol_ibpkey_key_t
> *)malloc(sizeof(sepol_ibpkey_key_t));
> +
> +	if (!tmp_key) {
> +		ERR(handle, "out of memory, could not create ibpkey
> key");
> +		goto omem;
> +	}
> +
> +	if (ibpkey_alloc_subnet_prefix(handle, &tmp_key-
> >subnet_prefix, &tmp_key->subnet_prefix_sz) < 0)
> +		goto err;
> +	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix,
> tmp_key->subnet_prefix) < 0)
> +		goto err;
> +
> +	tmp_key->low = low;
> +	tmp_key->high = high;
> +
> +	*key_ptr = tmp_key;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +
> +err:
> +	sepol_ibpkey_key_free(tmp_key);
> +	ERR(handle, "could not create ibpkey key for subnet
> prefix%s, range %u, %u",
> +	    subnet_prefix, low, high);
> +	return STATUS_ERR;
> +}
> +
> +hidden_def(sepol_ibpkey_key_create)
> +
> +void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key,
> +			     const char **subnet_prefix, int *low,
> int *high)
> +{
> +	*subnet_prefix = key->subnet_prefix;
> +	*low = key->low;
> +	*high = key->high;
> +}
> +
> +hidden_def(sepol_ibpkey_key_unpack)
> +
> +int sepol_ibpkey_key_extract(sepol_handle_t *handle,
> +			     const sepol_ibpkey_t *ibpkey,
> +			     sepol_ibpkey_key_t **key_ptr)
> +{
> +	char subnet_prefix_str[INET6_ADDRSTRLEN];
> +
> +	ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix,
> subnet_prefix_str);
> +
> +	if (sepol_ibpkey_key_create
> +	    (handle, subnet_prefix_str, ibpkey->low, ibpkey->high,
> key_ptr) < 0) {
> +		ERR(handle, "could not extract key from ibpkey %s
> %d:%d",
> +		    subnet_prefix_str,
> +		    ibpkey->low, ibpkey->high);
> +
> +		return STATUS_ERR;
> +	}
> +
> +	return STATUS_SUCCESS;
> +}
> +
> +void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key)
> +{
> +	if (!key)
> +		return;
> +	free(key->subnet_prefix);
> +	free(key);
> +}
> +
> +int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const
> sepol_ibpkey_key_t *key)
> +{
> +	int rc;
> +
> +	if (ibpkey->subnet_prefix_sz < key->subnet_prefix_sz)
> +		return -1;
> +	else if (ibpkey->subnet_prefix_sz > key->subnet_prefix_sz)
> +		return 1;
> +
> +	rc = memcmp(ibpkey->subnet_prefix, key->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +
> +	if (ibpkey->low == key->low &&
> +	    ibpkey->high == key->high &&
> +	    !rc)
> +		return 0;
> +
> +	if (ibpkey->low < key->low)
> +		return -1;
> +
> +	else if (key->low < ibpkey->low)
> +		return 1;
> +
> +	else if (ibpkey->high < key->high)
> +		return -1;
> +
> +	else if (key->high < ibpkey->high)
> +		return 1;
> +	else
> +		return rc;
> +}
> +
> +int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const
> sepol_ibpkey_t *ibpkey2)
> +{
> +	int rc;
> +
> +	if (ibpkey->subnet_prefix_sz < ibpkey2->subnet_prefix_sz)
> +		return -1;
> +	else if (ibpkey->subnet_prefix_sz > ibpkey2-
> >subnet_prefix_sz)
> +		return 1;
> +
> +	rc = memcmp(ibpkey->subnet_prefix, ibpkey2->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +
> +	if (ibpkey->low == ibpkey2->low &&
> +	    ibpkey->high == ibpkey2->high &&
> +	    !rc)
> +		return 0;
> +
> +	if (ibpkey->low < ibpkey2->low)
> +		return -1;
> +
> +	else if (ibpkey2->low < ibpkey->low)
> +		return 1;
> +
> +	else if (ibpkey->high < ibpkey2->high)
> +		return -1;
> +
> +	else if (ibpkey2->high < ibpkey->high)
> +		return 1;
> +	else
> +		return rc;
> +}
> +
> +/* Pkey */
> +int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey)
> +{
> +	return ibpkey->low;
> +}
> +
> +hidden_def(sepol_ibpkey_get_low)
> +
> +int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey)
> +{
> +	return ibpkey->high;
> +}
> +
> +hidden_def(sepol_ibpkey_get_high)
> +
> +void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num)
> +{
> +	ibpkey->low = pkey_num;
> +	ibpkey->high = pkey_num;
> +}
> +
> +void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int
> high)
> +{
> +	ibpkey->low = low;
> +	ibpkey->high = high;
> +}
> +
> +hidden_def(sepol_ibpkey_set_range)
> +
> +int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle,
> +				   const sepol_ibpkey_t *ibpkey,
> +				   char **subnet_prefix)
> +{
> +	char *tmp_subnet_prefix = NULL;
> +
> +	if (ibpkey_alloc_subnet_prefix_string(handle,
> &tmp_subnet_prefix) < 0)
> +		goto err;
> +
> +	if (ibpkey_expand_subnet_prefix(handle, ibpkey-
> >subnet_prefix, tmp_subnet_prefix) < 0)
> +		goto err;
> +
> +	*subnet_prefix = tmp_subnet_prefix;
> +	return STATUS_SUCCESS;
> +
> +err:
> +	free(tmp_subnet_prefix);
> +	ERR(handle, "could not get ibpkey subnet_prefix");
> +	return STATUS_ERR;
> +}
> +
> +hidden_def(sepol_ibpkey_get_subnet_prefix)
> +
> +/* Subnet prefix */
> +int sepol_ibpkey_get_subnet_prefix_bytes(sepol_handle_t *handle,
> +					 const sepol_ibpkey_t
> *ibpkey,
> +					 char **buffer, size_t
> *bsize)
> +{
> +	char *tmp_buf = malloc(ibpkey->subnet_prefix_sz);
> +
> +	if (!tmp_buf) {
> +		ERR(handle, "out of memory, could not get subnet
> prefix bytes");
> +		return STATUS_ERR;
> +	}
> +
> +	memcpy(tmp_buf, ibpkey->subnet_prefix, ibpkey-
> >subnet_prefix_sz);
> +	*buffer = tmp_buf;
> +	*bsize = ibpkey->subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +}
> +
> +hidden_def(sepol_ibpkey_get_subnet_prefix_bytes)
> +
> +int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle,
> +				   sepol_ibpkey_t *ibpkey,
> +				   const char *subnet_prefix)
> +{
> +	char *tmp = NULL;
> +	size_t tmp_sz;
> +
> +	if (ibpkey_alloc_subnet_prefix(handle, &tmp, &tmp_sz) < 0)
> +		goto err;
> +
> +	if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, tmp) <
> 0)
> +		goto err;
> +
> +	free(ibpkey->subnet_prefix);
> +	ibpkey->subnet_prefix = tmp;
> +	ibpkey->subnet_prefix_sz = tmp_sz;
> +	return STATUS_SUCCESS;
> +
> +err:
> +	free(tmp);
> +	ERR(handle, "could not set ibpkey subnet prefix to %s",
> subnet_prefix);
> +	return STATUS_ERR;
> +}
> +
> +hidden_def(sepol_ibpkey_set_subnet_prefix)
> +
> +int sepol_ibpkey_set_subnet_prefix_bytes(sepol_handle_t *handle,
> +					 sepol_ibpkey_t *ibpkey,
> +					 const char *subnet_prefix,
> +					 size_t subnet_prefix_sz)
> +{
> +	char *tmp_subnet_prefix = malloc(subnet_prefix_sz);
> +
> +	if (!tmp_subnet_prefix) {
> +		ERR(handle, "out of memory, could not set ibpkey
> subnet prefix");
> +		return STATUS_ERR;
> +	}
> +
> +	memcpy(tmp_subnet_prefix, subnet_prefix, subnet_prefix_sz);
> +	free(ibpkey->subnet_prefix);
> +	ibpkey->subnet_prefix = tmp_subnet_prefix;
> +	ibpkey->subnet_prefix_sz = subnet_prefix_sz;
> +	return STATUS_SUCCESS;
> +}
> +
> +hidden_def(sepol_ibpkey_set_subnet_prefix_bytes)
> +
> +/* Create */
> +int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t
> **ibpkey)
> +{
> +	sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t
> *)malloc(sizeof(sepol_ibpkey_t));
> +
> +	if (!tmp_ibpkey) {
> +		ERR(handle, "out of memory, could not create ibpkey
> record");
> +		return STATUS_ERR;
> +	}
> +
> +	tmp_ibpkey->subnet_prefix = NULL;
> +	tmp_ibpkey->subnet_prefix_sz = 0;
> +	tmp_ibpkey->low = 0;
> +	tmp_ibpkey->high = 0;
> +	tmp_ibpkey->con = NULL;
> +	*ibpkey = tmp_ibpkey;
> +
> +	return STATUS_SUCCESS;
> +}
> +
> +hidden_def(sepol_ibpkey_create)
> +
> +/* Deep copy clone */
> +int sepol_ibpkey_clone(sepol_handle_t *handle,
> +		       const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t
> **ibpkey_ptr)
> +{
> +	sepol_ibpkey_t *new_ibpkey = NULL;
> +
> +	if (sepol_ibpkey_create(handle, &new_ibpkey) < 0)
> +		goto err;
> +
> +	new_ibpkey->subnet_prefix = malloc(ibpkey-
> >subnet_prefix_sz);
> +	if (!new_ibpkey->subnet_prefix)
> +		goto omem;
> +
> +	memcpy(new_ibpkey->subnet_prefix, ibpkey->subnet_prefix,
> ibpkey->subnet_prefix_sz);
> +	new_ibpkey->subnet_prefix_sz = ibpkey->subnet_prefix_sz;
> +	new_ibpkey->low = ibpkey->low;
> +	new_ibpkey->high = ibpkey->high;
> +
> +	if (ibpkey->con &&
> +	    (sepol_context_clone(handle, ibpkey->con, &new_ibpkey-
> >con) < 0))
> +		goto err;
> +
> +	*ibpkey_ptr = new_ibpkey;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +
> +err:
> +	ERR(handle, "could not clone ibpkey record");
> +	sepol_ibpkey_free(new_ibpkey);
> +	return STATUS_ERR;
> +}
> +
> +/* Destroy */
> +void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey)
> +{
> +	if (!ibpkey)
> +		return;
> +
> +	free(ibpkey->subnet_prefix);
> +	sepol_context_free(ibpkey->con);
> +	free(ibpkey);
> +}
> +
> +hidden_def(sepol_ibpkey_free)
> +
> +/* Context */
> +sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey)
> +{
> +	return ibpkey->con;
> +}
> +
> +hidden_def(sepol_ibpkey_get_con)
> +
> +int sepol_ibpkey_set_con(sepol_handle_t *handle,
> +			 sepol_ibpkey_t *ibpkey, sepol_context_t
> *con)
> +{
> +	sepol_context_t *newcon;
> +
> +	if (sepol_context_clone(handle, con, &newcon) < 0) {
> +		ERR(handle, "out of memory, could not set ibpkey
> context");
> +		return STATUS_ERR;
> +	}
> +
> +	sepol_context_free(ibpkey->con);
> +	ibpkey->con = newcon;
> +	return STATUS_SUCCESS;
> +}
> +
> +hidden_def(sepol_ibpkey_set_con)
> diff --git a/libsepol/src/ibpkeys.c b/libsepol/src/ibpkeys.c
> new file mode 100644
> index 0000000..625ecfd
> --- /dev/null
> +++ b/libsepol/src/ibpkeys.c
> @@ -0,0 +1,264 @@
> +#include <netinet/in.h>
> +#include <stdlib.h>
> +
> +#include "debug.h"
> +#include "context.h"
> +#include "handle.h"
> +
> +#include <sepol/ibpkey_record.h>
> +#include <sepol/policydb/policydb.h>
> +#include "ibpkey_internal.h"
> +
> +/* Create a low level ibpkey structure from
> + * a high level representation
> + */
> +static int ibpkey_from_record(sepol_handle_t *handle,
> +			    const policydb_t *policydb,
> +			    ocontext_t **ibpkey, const
> sepol_ibpkey_t *data)
> +{
> +	ocontext_t *tmp_ibpkey = NULL;
> +	context_struct_t *tmp_con = NULL;
> +	char *subnet_prefix_buf = NULL;
> +	int low = sepol_ibpkey_get_low(data);
> +	int high = sepol_ibpkey_get_high(data);
> +	size_t subnet_prefix_bsize = 0;
> +
> +	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
> +	if (!tmp_ibpkey)
> +		goto omem;
> +
> +	if (sepol_ibpkey_get_subnet_prefix_bytes(handle,
> +					       data,
> +					       &subnet_prefix_buf,
> +					       &subnet_prefix_bsize)
> < 0)
> +		goto err;
> +
> +	memcpy(tmp_ibpkey->u.ibpkey.subnet_prefix,
> subnet_prefix_buf, subnet_prefix_bsize);
> +
> +	free(subnet_prefix_buf);
> +	subnet_prefix_buf = NULL;
> +
> +	/* Pkey range */
> +	tmp_ibpkey->u.ibpkey.low_pkey = low;
> +	tmp_ibpkey->u.ibpkey.high_pkey = high;
> +	if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey-
> >u.ibpkey.high_pkey) {
> +		ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
> +		    tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey-
> >u.ibpkey.high_pkey);
> +		goto err;
> +	}
> +
> +	/* Context */
> +	if (context_from_record(handle, policydb, &tmp_con,
> +				sepol_ibpkey_get_con(data)) < 0)
> +		goto err;
> +	context_cpy(&tmp_ibpkey->context[0], tmp_con);
> +	context_destroy(tmp_con);
> +	free(tmp_con);
> +	tmp_con = NULL;
> +
> +	*ibpkey = tmp_ibpkey;
> +	return STATUS_SUCCESS;
> +
> +omem:
> +	ERR(handle, "out of memory");
> +
> +err:
> +	if (tmp_ibpkey) {
> +		context_destroy(&tmp_ibpkey->context[0]);
> +		free(tmp_ibpkey);
> +	}
> +	context_destroy(tmp_con);
> +	free(tmp_con);
> +	free(subnet_prefix_buf);
> +	ERR(handle, "could not create ibpkey structure");
> +	return STATUS_ERR;
> +}
> +
> +static int ibpkey_to_record(sepol_handle_t *handle,
> +			  const policydb_t *policydb,
> +			  ocontext_t *ibpkey, sepol_ibpkey_t
> **record)
> +{
> +	int low = ibpkey->u.ibpkey.low_pkey;
> +	int high = ibpkey->u.ibpkey.high_pkey;
> +	context_struct_t *con = &ibpkey->context[0];
> +
> +	sepol_context_t *tmp_con = NULL;
> +	sepol_ibpkey_t *tmp_record = NULL;
> +
> +	if (sepol_ibpkey_create(handle, &tmp_record) < 0)
> +		goto err;
> +
> +	if (sepol_ibpkey_set_subnet_prefix_bytes(handle, tmp_record,
> +					       (const char
> *)&ibpkey->u.ibpkey.subnet_prefix, 16) < 0)
> +		goto err;
> +
> +	sepol_ibpkey_set_range(tmp_record, low, high);
> +
> +	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
> +		goto err;
> +
> +	if (sepol_ibpkey_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 ibpkey to record");
> +	sepol_context_free(tmp_con);
> +	sepol_ibpkey_free(tmp_record);
> +	return STATUS_ERR;
> +}
> +
> +/* Return the number of ibpkeys */
> +extern int sepol_ibpkey_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_IBPKEY];
> +	for (c = head; c; c = c->next)
> +		count++;
> +
> +	*response = count;
> +
> +	handle = NULL;
> +	return STATUS_SUCCESS;
> +}
> +
> +/* Check if a ibpkey exists */
> +int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__
> ((unused)),
> +		      const sepol_policydb_t *p,
> +		      const sepol_ibpkey_key_t *key, int *response)
> +{
> +	const policydb_t *policydb = &p->p;
> +	ocontext_t *c, *head;
> +	int low, high;
> +	const char *subnet_prefix;
> +
> +	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
> +
> +	head = policydb->ocontexts[OCON_IBPKEY];
> +	for (c = head; c; c = c->next) {
> +		unsigned int *subnet_prefix2 = c-
> >u.ibpkey.subnet_prefix;
> +		uint16_t low2 = c->u.ibpkey.low_pkey;
> +		uint16_t high2 = c->u.ibpkey.high_pkey;
> +
> +		if (low2 == low &&
> +		    high2 == high &&
> +		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
> +			*response = 1;
> +			return STATUS_SUCCESS;
> +		}
> +	}
> +
> +	*response = 0;
> +	return STATUS_SUCCESS;
> +}
> +
> +/* Query a ibpkey */
> +int sepol_ibpkey_query(sepol_handle_t *handle,
> +		     const sepol_policydb_t *p,
> +		     const sepol_ibpkey_key_t *key, sepol_ibpkey_t
> **response)
> +{
> +	const policydb_t *policydb = &p->p;
> +	ocontext_t *c, *head;
> +	int low, high;
> +	const char *subnet_prefix;
> +
> +	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
> +
> +	head = policydb->ocontexts[OCON_IBPKEY];
> +	for (c = head; c; c = c->next) {
> +		unsigned int *subnet_prefix2 = c-
> >u.ibpkey.subnet_prefix;
> +		int low2 = c->u.ibpkey.low_pkey;
> +		int high2 = c->u.ibpkey.high_pkey;
> +
> +		if (low2 == low &&
> +		    high2 == high &&
> +		    (!memcmp(subnet_prefix, subnet_prefix2, 16))) {
> +			if (ibpkey_to_record(handle, policydb, c,
> response) < 0)
> +				goto err;
> +			return STATUS_SUCCESS;
> +		}
> +	}
> +
> +	*response = NULL;
> +	return STATUS_SUCCESS;
> +
> +err:
> +	ERR(handle, "could not query ibpkey subnet prefix: %s range
> %u - %u exists",
> +	    subnet_prefix, low, high);
> +	return STATUS_ERR;
> +}
> +
> +/* Load a ibpkey into policy */
> +int sepol_ibpkey_modify(sepol_handle_t *handle,
> +		      sepol_policydb_t *p,
> +		      const sepol_ibpkey_key_t *key, const
> sepol_ibpkey_t *data)
> +{
> +	policydb_t *policydb = &p->p;
> +	ocontext_t *ibpkey = NULL;
> +	int low, high;
> +	const char *subnet_prefix;
> +
> +	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
> +
> +	if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
> +		goto err;
> +
> +	/* Attach to context list */
> +	ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
> +	policydb->ocontexts[OCON_IBPKEY] = ibpkey;
> +
> +	return STATUS_SUCCESS;
> +
> +err:
> +	ERR(handle, "could not load ibpkey subnet prefix: %s range
> %u - %u exists",
> +	    subnet_prefix, low, high);
> +	if (ibpkey) {
> +		context_destroy(&ibpkey->context[0]);
> +		free(ibpkey);
> +	}
> +	return STATUS_ERR;
> +}
> +
> +int sepol_ibpkey_iterate(sepol_handle_t *handle,
> +		       const sepol_policydb_t *p,
> +		       int (*fn)(const sepol_ibpkey_t *ibpkey,
> +				 void *fn_arg), void *arg)
> +{
> +	const policydb_t *policydb = &p->p;
> +	ocontext_t *c, *head;
> +	sepol_ibpkey_t *ibpkey = NULL;
> +
> +	head = policydb->ocontexts[OCON_IBPKEY];
> +	for (c = head; c; c = c->next) {
> +		int status;
> +
> +		if (ibpkey_to_record(handle, policydb, c, &ibpkey) <
> 0)
> +			goto err;
> +
> +		/* Invoke handler */
> +		status = fn(ibpkey, arg);
> +		if (status < 0)
> +			goto err;
> +
> +		sepol_ibpkey_free(ibpkey);
> +		ibpkey = NULL;
> +
> +		/* Handler requested exit */
> +		if (status > 0)
> +			break;
> +	}
> +
> +	return STATUS_SUCCESS;
> +
> +err:
> +	ERR(handle, "could not iterate over ibpkeys");
> +	sepol_ibpkey_free(ibpkey);
> +	return STATUS_ERR;
> +}
> diff --git a/python/semanage/semanage b/python/semanage/semanage
> index 9659aac..11b56e2 100644
> --- a/python/semanage/semanage
> +++ b/python/semanage/semanage
> @@ -58,6 +58,9 @@ usage_user_dict = {' --add': ('(', '-L LEVEL', '-R
> ROLES', '-r RANGE', '-s SEUSE
>  usage_port = "semanage port [-h] [-n] [-N] [-S STORE] ["
>  usage_port_dict = {' --add': ('-t TYPE', '-p PROTOCOL', '-r RANGE',
> '(', 'port_name', '|', 'port_range', ')'), ' --modify': ('-t TYPE',
> '-p PROTOCOL', '-r RANGE', '(', 'port_name', '|', 'port_range', ')'),
> ' --delete': ('-p PROTOCOL', '(', 'port_name', '|', 'port_range',
> ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)}
>  
> +usage_ibpkey = "semanage ibpkey [-h] [-n] [-N] [-s STORE] ["
> +usage_ibpkey_dict = {' --add': ('-t TYPE', '-x SUBNET_PREFIX', '-r
> RANGE', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --modify': ('-
> t TYPE', '-x SUBNET_PREFIX', '-r RANGE', '(', 'ibpkey_name', '|',
> 'pkey_range', ')'), ' --delete': ('-x SUBNET_PREFIX', '(',
> 'ibpkey_name', '|', 'pkey_range', ')'), ' --list': ('-C',), ' --
> extract': ('',), ' --deleteall': ('',)}
> +
>  usage_node = "semanage node [-h] [-n] [-N] [-S STORE] ["
>  usage_node_dict = {' --add': ('-M NETMASK', '-p PROTOCOL', '-t
> TYPE', '-r RANGE', 'node'), ' --modify': ('-M NETMASK', '-p
> PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --delete': ('-M
> NETMASK', '-p PROTOCOL', 'node'), ' --list': ('-C',), ' --extract':
> ('',), ' --deleteall': ('',)}
>  
> @@ -145,6 +148,9 @@ def port_ini():
>      OBJECT = seobject.portRecords(store)
>      return OBJECT
>  
> +def ibpkey_ini():
> +    OBJECT = seobject.ibpkeyRecords(store)
> +    return OBJECT
>  
>  def module_ini():
>      OBJECT = seobject.moduleRecords(store)
> @@ -181,7 +187,7 @@ def dontaudit_ini():
>      return OBJECT
>  
>  # define dictonary for seobject OBEJCTS
> -object_dict = {'login': login_ini, 'user': user_ini, 'port':
> port_ini, 'module': module_ini, 'interface': interface_ini, 'node':
> node_ini, 'fcontext': fcontext_ini, 'boolean': boolean_ini,
> 'permissive': permissive_ini, 'dontaudit': dontaudit_ini}
> +object_dict = {'login': login_ini, 'user': user_ini, 'port':
> port_ini, 'module': module_ini, 'interface': interface_ini, 'node':
> node_ini, 'fcontext': fcontext_ini, 'boolean': boolean_ini,
> 'permissive': permissive_ini, 'dontaudit': dontaudit_ini, 'ibpkey':
> ibpkey_ini}
>  
>  
>  def generate_custom_usage(usage_text, usage_dict):
> @@ -292,6 +298,11 @@ def parser_add_proto(parser, name):
>      version for the specified node (ipv4|ipv6).
>  '''))
>  
> +def parser_add_subnet_prefix(parser, name):
> +    parser.add_argument('-x', '--subnet_prefix', help=_('''
> +    Subnet prefix for  the specified infiniband ibpkey.
> +'''))
> +
>  
>  def parser_add_modify(parser, name):
>      parser.add_argument('-m', '--modify', dest='action',
> action='store_const', const='modify', help=_("Modify a record of the
> %s object type") % name)
> @@ -511,6 +522,52 @@ def setupPortParser(subparsers):
>      portParser.set_defaults(func=handlePort)
>  
>  
> +
> +def handlePkey(args):
> +    ibpkey_args = {'list': [('ibpkey', 'type', 'subnet_prefix'),
> ('')], 'add': [('locallist'), ('type', 'ibpkey', 'subnet_prefix')],
> 'modify': [('localist'), ('ibpkey', 'subnet_prefix')], 'delete':
> [('locallist'), ('ibpkey', 'subnet_prefix')], 'extract':
> [('locallist', 'ibpkey', 'type', 'subnet prefix'), ('')],
> 'deleteall': [('locallist'), ('')]}
> +
> +    handle_opts(args, ibpkey_args, args.action)
> +
> +    OBJECT = object_dict['ibpkey']()
> +    OBJECT.set_reload(args.noreload)
> +
> +    if args.action is "add":
> +        OBJECT.add(args.ibpkey, args.subnet_prefix, args.range,
> args.type)
> +    if args.action is "modify":
> +        OBJECT.modify(args.ibpkey, args.subnet_prefix, args.range,
> args.type)
> +    if args.action is "delete":
> +        OBJECT.delete(args.ibpkey, args.subnet_prefix)
> +    if args.action is "list":
> +        OBJECT.list(args.noheading, args.locallist)
> +    if args.action is "deleteall":
> +        OBJECT.deleteall()
> +    if args.action is "extract":
> +        for i in OBJECT.customized():
> +            print("ibpkey %s" % str(i))
> +
> +
> +def setupPkeyParser(subparsers):
> +    generated_usage = generate_custom_usage(usage_ibpkey,
> usage_ibpkey_dict)
> +    ibpkeyParser = subparsers.add_parser('ibpkey',
> usage=generated_usage, help=_('Manage infiniband ibpkey type
> definitions'))
> +    parser_add_locallist(ibpkeyParser, "ibpkey")
> +    parser_add_noheading(ibpkeyParser, "ibpkey")
> +    parser_add_noreload(ibpkeyParser, "ibpkey")
> +    parser_add_store(ibpkeyParser, "ibpkey")
> +
> +    ibpkey_action =
> ibpkeyParser.add_mutually_exclusive_group(required=True)
> +    parser_add_add(ibpkey_action, "ibpkey")
> +    parser_add_delete(ibpkey_action, "ibpkey")
> +    parser_add_modify(ibpkey_action, "ibpkey")
> +    parser_add_list(ibpkey_action, "ibpkey")
> +    parser_add_extract(ibpkey_action, "ibpkey")
> +    parser_add_deleteall(ibpkey_action, "ibpkey")
> +    parser_add_type(ibpkeyParser, "ibpkey")
> +    parser_add_range(ibpkeyParser, "ibpkey")
> +    parser_add_subnet_prefix(ibpkeyParser, "ibpkey")
> +    ibpkeyParser.add_argument('ibpkey', nargs='?', default=None,
> help=_('pkey | pkey_range'))
> +    ibpkeyParser.set_defaults(func=handlePkey)
> +
> +
>  def handleInterface(args):
>      interface_args = {'list': [('interface'), ('')], 'add':
> [('locallist'), ('type', 'interface')], 'modify': [('locallist'),
> ('type', 'interface')], 'delete': [('locallist'), ('interface')],
> 'extract': [('locallist', 'interface', 'type'), ('')], 'deleteall':
> [('locallist'), ('')]}
>  
> @@ -849,6 +906,7 @@ def createCommandParser():
>      setupLoginParser(subparsers)
>      setupUserParser(subparsers)
>      setupPortParser(subparsers)
> +    setupPkeyParser(subparsers)
>      setupInterfaceParser(subparsers)
>      setupModuleParser(subparsers)
>      setupNodeParser(subparsers)
> diff --git a/python/semanage/seobject.py
> b/python/semanage/seobject.py
> index 7a54373..02ad9f3 100644
> --- a/python/semanage/seobject.py
> +++ b/python/semanage/seobject.py
> @@ -1309,6 +1309,259 @@ class portRecords(semanageRecords):
>                  rec += ", %s" % p
>              print(rec)
>  
> +class ibpkeyRecords(semanageRecords):
> +    try:
> +        valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE,
> "ibpkey_type"))[0]["types"])
> +    except RuntimeError:
> +        valid_types = []
> +
> +    def __init__(self, store=""):
> +        semanageRecords.__init__(self, store)
> +
> +    def __genkey(self, pkey, subnet_prefix):
> +	if subnet_prefix == "":
> +            raise ValueError(_("Subnet Prefix is required"))
> +
> +	pkeys = pkey.split("-")
> +        if len(pkeys) == 1:
> +            high = low = int(pkeys[0], 0)
> +        else:
> +            low = int(pkeys[0], 0)
> +            high = int(pkeys[1], 0)
> +
> +        if high > 65535:
> +            raise ValueError(_("Invalid Pkey"))
> +
> +        (rc, k) = semanage_ibpkey_key_create(self.sh, subnet_prefix,
> low, high)
> +        if rc < 0:
> +            raise ValueError(_("Could not create a key for %s/%s") %
> (subnet_prefix, pkey))
> +        return (k, subnet_prefix, low, high)
> +
> +    def __add(self, pkey, subnet_prefix, serange, type):
> +        if is_mls_enabled == 1:
> +            if serange == "":
> +                serange = "s0"
> +            else:
> +                serange = untranslate(serange)
> +
> +        if type == "":
> +            raise ValueError(_("Type is required"))
> +
> +        if type not in self.valid_types:
> +            raise ValueError(_("Type %s is invalid, must be a ibpkey
> type") % type)
> +
> +        (k, subnet_prefix, low, high) = self.__genkey(pkey,
> subnet_prefix)
> +
> +        (rc, exists) = semanage_ibpkey_exists(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not check if ibpkey %s/%s is
> defined") % (subnet_prefix, pkey))
> +        if exists:
> +            raise ValueError(_("ibpkey %s/%s already defined") %
> (subnet_prefix, pkey))
> +
> +        (rc, p) = semanage_ibpkey_create(self.sh)
> +        if rc < 0:
> +            raise ValueError(_("Could not create ibpkey for %s/%s")
> % (subnet_prefix, pkey))
> +
> +        semanage_ibpkey_set_subnet_prefix(self.sh, p, subnet_prefix)
> +        semanage_ibpkey_set_range(p, low, high)
> +        (rc, con) = semanage_context_create(self.sh)
> +        if rc < 0:
> +            raise ValueError(_("Could not create context for %s/%s")
> % (subnet_prefix, pkey))
> +
> +        rc = semanage_context_set_user(self.sh, con, "system_u")
> +        if rc < 0:
> +            raise ValueError(_("Could not set user in ibpkey context
> for %s/%s") % (subnet_prefix, pkey))
> +
> +        rc = semanage_context_set_role(self.sh, con, "object_r")
> +        if rc < 0:
> +            raise ValueError(_("Could not set role in ibpkey context
> for %s/%s") % (subnet_prefix, pkey))
> +
> +        rc = semanage_context_set_type(self.sh, con, type)
> +        if rc < 0:
> +            raise ValueError(_("Could not set type in ibpkey context
> for %s/%s") % (subnet_prefix, pkey))
> +
> +        if (is_mls_enabled == 1) and (serange != ""):
> +            rc = semanage_context_set_mls(self.sh, con, serange)
> +            if rc < 0:
> +                raise ValueError(_("Could not set mls fields in
> ibpkey context for %s/%s") % (subnet_prefix, pkey))
> +
> +        rc = semanage_ibpkey_set_con(self.sh, p, con)
> +        if rc < 0:
> +            raise ValueError(_("Could not set ibpkey context for
> %s/%s") % (subnet_prefix, pkey))
> +
> +        rc = semanage_ibpkey_modify_local(self.sh, k, p)
> +        if rc < 0:
> +            raise ValueError(_("Could not add ibpkey %s/%s") %
> (subnet_prefix, pkey))
> +
> +        semanage_context_free(con)
> +        semanage_ibpkey_key_free(k)
> +        semanage_ibpkey_free(p)
> +
> +    def add(self, pkey, subnet_prefix, serange, type):
> +        self.begin()
> +        self.__add(pkey, subnet_prefix, serange, type)
> +        self.commit()
> +
> +    def __modify(self, pkey, subnet_prefix, serange, setype):
> +        if serange == "" and setype == "":
> +            if is_mls_enabled == 1:
> +                raise ValueError(_("Requires setype or serange"))
> +            else:
> +                raise ValueError(_("Requires setype"))
> +
> +        if setype and setype not in self.valid_types:
> +            raise ValueError(_("Type %s is invalid, must be a ibpkey
> type") % setype)
> +
> +        (k, subnet_prefix, low, high) = self.__genkey(pkey,
> subnet_prefix)
> +
> +        (rc, exists) = semanage_ibpkey_exists(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not check if ibpkey %s/%s is
> defined") % (subnet_prefix, pkey))
> +        if not exists:
> +            raise ValueError(_("ibpkey %s/%s is not defined") %
> (subnet_prefix, pkey))
> +
> +        (rc, p) = semanage_ibpkey_query(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not query ibpkey %s/%s") %
> (subnet_prefix, pkey))
> +
> +        con = semanage_ibpkey_get_con(p)
> +
> +        if (is_mls_enabled == 1) and (serange != ""):
> +            semanage_context_set_mls(self.sh, con,
> untranslate(serange))
> +        if setype != "":
> +            semanage_context_set_type(self.sh, con, setype)
> +
> +        rc = semanage_ibpkey_modify_local(self.sh, k, p)
> +        if rc < 0:
> +            raise ValueError(_("Could not modify ibpkey %s/%s") %
> (subnet_prefix, pkey))
> +
> +        semanage_ibpkey_key_free(k)
> +        semanage_ibpkey_free(p)
> +
> +    def modify(self, pkey, subnet_prefix, serange, setype):
> +        self.begin()
> +        self.__modify(pkey, subnet_prefix, serange, setype)
> +        self.commit()
> +
> +    def deleteall(self):
> +        (rc, plist) = semanage_ibpkey_list_local(self.sh)
> +        if rc < 0:
> +            raise ValueError(_("Could not list the ibpkeys"))
> +
> +        self.begin()
> +
> +        for ibpkey in plist:
> +            (rc, subnet_prefix) =
> semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
> +            low = semanage_ibpkey_get_low(ibpkey)
> +            high = semanage_ibpkey_get_high(ibpkey)
> +            pkey_str = "%s-%s" % (low, high)
> +            (k, subnet_prefix, low, high) = self.__genkey(pkey_str,
> subnet_prefix)
> +            if rc < 0:
> +                raise ValueError(_("Could not create a key for %s")
> % pkey_str)
> +
> +            rc = semanage_ibpkey_del_local(self.sh, k)
> +            if rc < 0:
> +                raise ValueError(_("Could not delete the ibpkey %s")
> % pkey_str)
> +            semanage_ibpkey_key_free(k)
> +
> +        self.commit()
> +
> +    def __delete(self, pkey, subnet_prefix):
> +        (k, subnet_prefix, low, high) = self.__genkey(pkey,
> subnet_prefix)
> +        (rc, exists) = semanage_pkey_exists(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not check if ibpkey %s/%s is
> defined") % (subnet_prefix, pkey))
> +        if not exists:
> +            raise ValueError(_("ibpkey %s/%s is not defined") %
> (subnet_prefix, pkey))
> +
> +        (rc, exists) = semanage_ibpkey_exists_local(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not check if ibpkey %s/%s is
> defined") % (subnet_prefix, pkey))
> +        if not exists:
> +            raise ValueError(_("ibpkey %s/%s is defined in policy,
> cannot be deleted") % (subnet_prefix, pkey))
> +
> +        rc = semanage_ibpkey_del_local(self.sh, k)
> +        if rc < 0:
> +            raise ValueError(_("Could not delete ibpkey %s/%s") %
> (subnet_prefix, pkey))
> +
> +        semanage_ibpkey_key_free(k)
> +
> +    def delete(self, pkey, subnet_prefix):
> +        self.begin()
> +        self.__delete(pkey, subnet_prefix)
> +        self.commit()
> +
> +    def get_all(self, locallist=0):
> +        ddict = {}
> +        if locallist:
> +            (rc, self.plist) = semanage_ibpkey_list_local(self.sh)
> +        else:
> +            (rc, self.plist) = semanage_ibpkey_list(self.sh)
> +        if rc < 0:
> +            raise ValueError(_("Could not list ibpkeys"))
> +
> +        for ibpkey in self.plist:
> +            con = semanage_ibpkey_get_con(ibpkey)
> +            ctype = semanage_context_get_type(con)
> +            if ctype == "reserved_ibpkey_t":
> +                continue
> +            level = semanage_context_get_mls(con)
> +            (rc, subnet_prefix) =
> semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
> +            low = semanage_ibpkey_get_low(ibpkey)
> +            high = semanage_ibpkey_get_high(ibpkey)
> +            ddict[(low, high, subnet_prefix)] = (ctype, level)
> +        return ddict
> +
> +    def get_all_by_type(self, locallist=0):
> +        ddict = {}
> +        if locallist:
> +            (rc, self.plist) = semanage_ibpkey_list_local(self.sh)
> +        else:
> +            (rc, self.plist) = semanage_ibpkey_list(self.sh)
> +        if rc < 0:
> +            raise ValueError(_("Could not list ibpkeys"))
> +
> +        for ibpkey in self.plist:
> +            con = semanage_ibpkey_get_con(ibpkey)
> +            ctype = semanage_context_get_type(con)
> +            (rc, subnet_prefix) =
> semanage_ibpkey_get_subnet_prefix(self.sh, ibpkey)
> +            low = semanage_ibpkey_get_low(ibpkey)
> +            high = semanage_ibpkey_get_high(ibpkey)
> +            if (ctype, subnet_prefix) not in ddict.keys():
> +                ddict[(ctype, subnet_prefix)] = []
> +            if low == high:
> +                ddict[(ctype, subnet_prefix)].append("0x%x" % low)
> +            else:
> +                ddict[(ctype, subnet_prefix)].append("0x%x-0x%x" %
> (low, high))
> +        return ddict
> +
> +    def customized(self):
> +        l = []
> +        ddict = self.get_all(True)
> +        keys = ddict.keys()
> +        keys.sort()
> +        for k in keys:
> +            if k[0] == k[1]:
> +                l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2],
> k[0]))
> +            else:
> +                l.append("-a -t %s -x %s %s-%s" % (ddict[k][0],
> k[2], k[0], k[1]))
> +        return l
> +
> +    def list(self, heading=1, locallist=0):
> +        ddict = self.get_all_by_type(locallist)
> +        keys = ddict.keys()
> +        if len(keys) == 0:
> +            return
> +        keys.sort()
> +
> +        if heading:
> +            print "%-30s %-18s %s\n" % (_("SELinux IB Pkey Type"),
> _("Subnet_Prefix"), _("Pkey Number"))
> +        for i in keys:
> +            rec = "%-30s %-18s " % i
> +            rec += "%s" % ddict[i][0]
> +            for p in ddict[i][1:]:
> +                rec += ", %s" % p
> +            print rec
>  
>  class nodeRecords(semanageRecords):
>      try:




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux