Blame libnetlabel/mod_cipso.c

Packit 51d0f7
/** @file
Packit 51d0f7
 * CIPSO/IPv4 Module Functions
Packit 51d0f7
 *
Packit 51d0f7
 * Author: Paul Moore <paul@paul-moore.com>
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
Packit 51d0f7
 *
Packit 51d0f7
 * This program is free software: you can redistribute it and/or modify
Packit 51d0f7
 * it under the terms of version 2 of the GNU General Public License as
Packit 51d0f7
 * published by the Free Software Foundation.
Packit 51d0f7
 *
Packit 51d0f7
 * This program is distributed in the hope that it will be useful,
Packit 51d0f7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 51d0f7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 51d0f7
 * GNU General Public License for more details.
Packit 51d0f7
 *
Packit 51d0f7
 * You should have received a copy of the GNU General Public License
Packit 51d0f7
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
#include <stdlib.h>
Packit 51d0f7
#include <errno.h>
Packit 51d0f7
#include <sys/types.h>
Packit 51d0f7
#include <sys/socket.h>
Packit 51d0f7
#include <linux/types.h>
Packit 51d0f7
Packit 51d0f7
#include <libnetlabel.h>
Packit 51d0f7
Packit 51d0f7
#include "netlabel_internal.h"
Packit 51d0f7
Packit 51d0f7
/* Generic Netlink family ID */
Packit 51d0f7
static uint16_t nlbl_cipso_fid = 0;
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * Helper functions
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Create a new NetLabel CIPSO message
Packit 51d0f7
 * @param command the NetLabel management command
Packit 51d0f7
 * @param flags the message flags
Packit 51d0f7
 *
Packit 51d0f7
 * This function creates a new NetLabel CIPSO message using @command and
Packit 51d0f7
 * @flags.  Returns a pointer to the new message on success, or NULL on
Packit 51d0f7
 * failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static nlbl_msg *nlbl_cipso_msg_new(uint16_t command, int flags)
Packit 51d0f7
{
Packit 51d0f7
	nlbl_msg *msg;
Packit 51d0f7
	struct nlmsghdr *nl_hdr;
Packit 51d0f7
	struct genlmsghdr *genl_hdr;
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_msg_new();
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto msg_new_failure;
Packit 51d0f7
Packit 51d0f7
	/* setup the netlink header */
Packit 51d0f7
	nl_hdr = nlbl_msg_nlhdr(msg);
Packit 51d0f7
	if (nl_hdr == NULL)
Packit 51d0f7
		goto msg_new_failure;
Packit 51d0f7
	nl_hdr->nlmsg_type = nlbl_cipso_fid;
Packit 51d0f7
	nl_hdr->nlmsg_flags = flags;
Packit 51d0f7
Packit 51d0f7
	/* setup the generic netlink header */
Packit 51d0f7
	genl_hdr = nlbl_msg_genlhdr(msg);
Packit 51d0f7
	if (genl_hdr == NULL)
Packit 51d0f7
		goto msg_new_failure;
Packit 51d0f7
	genl_hdr->cmd = command;
Packit 51d0f7
Packit 51d0f7
	return msg;
Packit 51d0f7
Packit 51d0f7
msg_new_failure:
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	return NULL;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Read a NetLbel CIPSO message
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param msg the message
Packit 51d0f7
 *
Packit 51d0f7
 * Try to read a NetLabel CIPSO message and return the message in @msg.
Packit 51d0f7
 * Returns the number of bytes read on success, zero on EOF, and negative
Packit 51d0f7
 * values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int nlbl_cipso_recv(struct nlbl_handle *hndl, nlbl_msg **msg)
Packit 51d0f7
{
Packit 51d0f7
	int rc;
Packit 51d0f7
	struct nlmsghdr *nl_hdr;
Packit 51d0f7
Packit 51d0f7
	/* try to get a message from the handle */
Packit 51d0f7
	rc = nlbl_comm_recv(hndl, msg);
Packit 51d0f7
	if (rc <= 0)
Packit 51d0f7
		goto recv_failure;
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	nl_hdr = nlbl_msg_nlhdr(*msg);
Packit 51d0f7
	if (nl_hdr == NULL || (nl_hdr->nlmsg_type != nlbl_cipso_fid &&
Packit 51d0f7
			       nl_hdr->nlmsg_type != NLMSG_DONE &&
Packit 51d0f7
			       nl_hdr->nlmsg_type != NLMSG_ERROR)) {
Packit 51d0f7
		rc = -EBADMSG;
Packit 51d0f7
		goto recv_failure;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	return rc;
Packit 51d0f7
Packit 51d0f7
recv_failure:
Packit 51d0f7
	nlbl_msg_free(*msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Parse an ACK message
Packit 51d0f7
 * @param msg the message
Packit 51d0f7
 *
Packit 51d0f7
 * Parse the ACK message in @msg and return the error code specified in the
Packit 51d0f7
 * ACK.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int nlbl_cipso_parse_ack(nlbl_msg *msg)
Packit 51d0f7
{
Packit 51d0f7
	struct nlmsgerr *nl_err;
Packit 51d0f7
Packit 51d0f7
	nl_err = nlbl_msg_err(msg);
Packit 51d0f7
	if (nl_err == NULL)
Packit 51d0f7
		return -ENOMSG;
Packit 51d0f7
Packit 51d0f7
	return nl_err->error;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * Init functions
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Perform any setup needed
Packit 51d0f7
 *
Packit 51d0f7
 * Do any setup needed for the CIPSO component, including determining the
Packit 51d0f7
 * NetLabel CIPSO Generic Netlink family ID.  Returns zero on success,
Packit 51d0f7
 * negative values on error.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_init(void)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *hndl;
Packit 51d0f7
Packit 51d0f7
	/* get a netlabel handle */
Packit 51d0f7
	hndl = nlbl_comm_open();
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		goto init_return;
Packit 51d0f7
Packit 51d0f7
	/* resolve the family */
Packit 51d0f7
	rc = genl_ctrl_resolve(hndl->nl_sock, NETLBL_NLTYPE_CIPSOV4_NAME);
Packit 51d0f7
	if (rc < 0)
Packit 51d0f7
		goto init_return;
Packit 51d0f7
	nlbl_cipso_fid = rc;
Packit 51d0f7
Packit 51d0f7
	rc = 0;
Packit 51d0f7
Packit 51d0f7
init_return:
Packit 51d0f7
	nlbl_comm_close(hndl);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * NetLabel operations
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Add a translated CIPSO label mapping
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param doi the CIPSO DOI number
Packit 51d0f7
 * @param tags array of tags
Packit 51d0f7
 * @param lvls array of level mappings
Packit 51d0f7
 * @param cats array of category mappings, may be NULL
Packit 51d0f7
 *
Packit 51d0f7
 * Add the specified static CIPSO label mapping information to the NetLabel
Packit 51d0f7
 * system.  If @hndl is NULL then the function will handle opening and closing
Packit 51d0f7
 * it's own NetLabel handle.  Returns zero on success, negative values on
Packit 51d0f7
 * failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_add_trans(struct nlbl_handle *hndl,
Packit 51d0f7
			 nlbl_cip_doi doi,
Packit 51d0f7
			 struct nlbl_cip_tag_a *tags,
Packit 51d0f7
			 struct nlbl_cip_lvl_a *lvls,
Packit 51d0f7
			 struct nlbl_cip_cat_a *cats)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	nlbl_msg *nest_msg_a = NULL;
Packit 51d0f7
	nlbl_msg *nest_msg_b = NULL;
Packit 51d0f7
	nlbl_msg *ans_msg = NULL;
Packit 51d0f7
	uint32_t iter;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (doi == 0 ||
Packit 51d0f7
	    tags == NULL || tags->size == 0 ||
Packit 51d0f7
	    lvls == NULL || lvls->size == 0)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_ADD, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_DOI, doi);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_MTYPE, CIPSO_V4_MAP_TRANS);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
Packit 51d0f7
	nest_msg_a = nlmsg_inherit(NULL);
Packit 51d0f7
	if (nest_msg_a == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
	for (iter = 0; iter < tags->size; iter++) {
Packit 51d0f7
		rc = nla_put_u8(nest_msg_a,
Packit 51d0f7
				NLBL_CIPSOV4_A_TAG, tags->array[iter]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
	rc = nla_put_nested(msg, NLBL_CIPSOV4_A_TAGLST, nest_msg_a);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	nlbl_msg_free(nest_msg_a);
Packit 51d0f7
	nest_msg_a = NULL;
Packit 51d0f7
Packit 51d0f7
	nest_msg_a = nlmsg_inherit(NULL);
Packit 51d0f7
	if (nest_msg_a == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
	for (iter = 0; iter < lvls->size; iter++) {
Packit 51d0f7
		nest_msg_b = nlmsg_inherit(NULL);
Packit 51d0f7
		if (nest_msg_b == NULL) {
Packit 51d0f7
			rc = -ENOMEM;
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		}
Packit 51d0f7
		rc = nla_put_u32(nest_msg_b,
Packit 51d0f7
				 NLBL_CIPSOV4_A_MLSLVLLOC,
Packit 51d0f7
				 lvls->array[iter * 2]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		rc = nla_put_u32(nest_msg_b,
Packit 51d0f7
				 NLBL_CIPSOV4_A_MLSLVLREM,
Packit 51d0f7
				 lvls->array[iter * 2 + 1]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		rc = nla_put_nested(nest_msg_a, NLBL_CIPSOV4_A_MLSLVL,
Packit 51d0f7
				    nest_msg_b);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		nlbl_msg_free(nest_msg_b);
Packit 51d0f7
		nest_msg_b = NULL;
Packit 51d0f7
	}
Packit 51d0f7
	rc = nla_put_nested(msg, NLBL_CIPSOV4_A_MLSLVLLST, nest_msg_a);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	nlbl_msg_free(nest_msg_a);
Packit 51d0f7
	nest_msg_a = NULL;
Packit 51d0f7
Packit 51d0f7
	nest_msg_a = nlmsg_inherit(NULL);
Packit 51d0f7
	if (nest_msg_a == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
	for (iter = 0; iter < cats->size; iter++) {
Packit 51d0f7
		nest_msg_b = nlmsg_inherit(NULL);
Packit 51d0f7
		if (nest_msg_b == NULL) {
Packit 51d0f7
			rc = -ENOMEM;
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		}
Packit 51d0f7
		rc = nla_put_u32(nest_msg_b,
Packit 51d0f7
				 NLBL_CIPSOV4_A_MLSCATLOC,
Packit 51d0f7
				 cats->array[iter * 2]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		rc = nla_put_u32(nest_msg_b,
Packit 51d0f7
				 NLBL_CIPSOV4_A_MLSCATREM,
Packit 51d0f7
				 cats->array[iter * 2 + 1]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		rc = nla_put_nested(nest_msg_a, NLBL_CIPSOV4_A_MLSCAT,
Packit 51d0f7
				    nest_msg_b);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_std_return;
Packit 51d0f7
		nlbl_msg_free(nest_msg_b);
Packit 51d0f7
		nest_msg_b = NULL;
Packit 51d0f7
	}
Packit 51d0f7
	rc = nla_put_nested(msg, NLBL_CIPSOV4_A_MLSCATLST, nest_msg_a);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	nlbl_msg_free(nest_msg_a);
Packit 51d0f7
	nest_msg_a = NULL;
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_cipso_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_std_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_cipso_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
add_std_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	nlbl_msg_free(nest_msg_a);
Packit 51d0f7
	nlbl_msg_free(nest_msg_b);
Packit 51d0f7
	nlbl_msg_free(ans_msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Add a pass-through CIPSO label mapping
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param doi the CIPSO DOI number
Packit 51d0f7
 * @param tags array of tags
Packit 51d0f7
 *
Packit 51d0f7
 * Add the specified static CIPSO label mapping information to the NetLabel
Packit 51d0f7
 * system.  If @hndl is NULL then the function will handle opening and closing
Packit 51d0f7
 * it's own NetLabel handle.  Returns zero on success, negative values on
Packit 51d0f7
 * failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_add_pass(struct nlbl_handle *hndl,
Packit 51d0f7
			nlbl_cip_doi doi,
Packit 51d0f7
			struct nlbl_cip_tag_a *tags)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	nlbl_msg *nest_msg = NULL;
Packit 51d0f7
	nlbl_msg *ans_msg = NULL;
Packit 51d0f7
	uint32_t iter;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (doi == 0 ||
Packit 51d0f7
	    tags == NULL || tags->size == 0)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto add_pass_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_ADD, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_DOI, doi);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_MTYPE, CIPSO_V4_MAP_PASS);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
Packit 51d0f7
	nest_msg = nlmsg_inherit(NULL);
Packit 51d0f7
	if (nest_msg == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
	}
Packit 51d0f7
	for (iter = 0; iter < tags->size; iter++) {
Packit 51d0f7
		rc = nla_put_u8(nest_msg,
Packit 51d0f7
				NLBL_CIPSOV4_A_TAG, tags->array[iter]);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto add_pass_return;
Packit 51d0f7
	}
Packit 51d0f7
	rc = nla_put_nested(msg, NLBL_CIPSOV4_A_TAGLST, nest_msg);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_cipso_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_pass_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_cipso_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
add_pass_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	nlbl_msg_free(nest_msg);
Packit 51d0f7
	nlbl_msg_free(ans_msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Add a local CIPSO label mapping
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param doi the CIPSO DOI number
Packit 51d0f7
 *
Packit 51d0f7
 * Add the specified static CIPSO label mapping information to the NetLabel
Packit 51d0f7
 * system.  If @hndl is NULL then the function will handle opening and closing
Packit 51d0f7
 * it's own NetLabel handle.  Returns zero on success, negative values on
Packit 51d0f7
 * failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_add_local(struct nlbl_handle *hndl, nlbl_cip_doi doi)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	nlbl_msg *nest_msg = NULL;
Packit 51d0f7
	nlbl_msg *ans_msg = NULL;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (doi == 0)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto add_local_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_ADD, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_DOI, doi);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_MTYPE, CIPSO_V4_MAP_LOCAL);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
Packit 51d0f7
	nest_msg = nlmsg_inherit(NULL);
Packit 51d0f7
	if (nest_msg == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
	}
Packit 51d0f7
	rc = nla_put_u8(nest_msg, NLBL_CIPSOV4_A_TAG, 128);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
	rc = nla_put_nested(msg, NLBL_CIPSOV4_A_TAGLST, nest_msg);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_cipso_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto add_local_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_cipso_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
add_local_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	nlbl_msg_free(nest_msg);
Packit 51d0f7
	nlbl_msg_free(ans_msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Delete a CIPSO label mapping
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param doi the CIPSO DOI number
Packit 51d0f7
 *
Packit 51d0f7
 * Remove the CIPSO label mapping with the DOI value matching @doi.  If @hndl
Packit 51d0f7
 * is NULL then the function will handle opening and closing it's own NetLabel
Packit 51d0f7
 * handle.  Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_del(struct nlbl_handle *hndl, nlbl_cip_doi doi)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	nlbl_msg *ans_msg = NULL;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (doi == 0)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto del_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_REMOVE, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto del_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_DOI, doi);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto del_return;
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto del_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_cipso_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto del_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_cipso_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
del_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	nlbl_msg_free(ans_msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * List the details of a specific CIPSO label mapping
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param doi the CIPSO DOI number
Packit 51d0f7
 * @param mtype the DOI mapping type
Packit 51d0f7
 * @param tags array of tag numbers
Packit 51d0f7
 * @param lvls array of level mappings
Packit 51d0f7
 * @param cats array of category mappings
Packit 51d0f7
 *
Packit 51d0f7
 * Query the kernel for the specified CIPSO mapping specified by @doi and
Packit 51d0f7
 * return the details of the mapping to the caller.  If @hndl is NULL then the
Packit 51d0f7
 * function will handle opening and closing it's own NetLabel handle.  Returns
Packit 51d0f7
 * zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_list(struct nlbl_handle *hndl,
Packit 51d0f7
		    nlbl_cip_doi doi,
Packit 51d0f7
		    nlbl_cip_mtype *mtype,
Packit 51d0f7
		    struct nlbl_cip_tag_a *tags,
Packit 51d0f7
		    struct nlbl_cip_lvl_a *lvls,
Packit 51d0f7
		    struct nlbl_cip_cat_a *cats)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	nlbl_msg *ans_msg = NULL;
Packit 51d0f7
	struct genlmsghdr *genl_hdr;
Packit 51d0f7
	struct nlattr *nla_a;
Packit 51d0f7
	struct nlattr *nla_b;
Packit 51d0f7
	struct nlattr *nla_c;
Packit 51d0f7
	struct nlattr *nla_d;
Packit 51d0f7
	int nla_b_rem;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (doi == 0 ||
Packit 51d0f7
	    mtype == NULL || tags == NULL || lvls == NULL || cats == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto list_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_LIST, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	rc = nla_put_u32(msg, NLBL_CIPSOV4_A_DOI, doi);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_cipso_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* check the response */
Packit 51d0f7
	rc = nlbl_cipso_parse_ack(ans_msg);
Packit 51d0f7
	if (rc < 0 && rc != -ENOMSG)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	genl_hdr = nlbl_msg_genlhdr(ans_msg);
Packit 51d0f7
	if (genl_hdr == NULL || genl_hdr->cmd != NLBL_CIPSOV4_C_LIST) {
Packit 51d0f7
		rc = -EBADMSG;
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
Packit 51d0f7
	lvls->size = 0;
Packit 51d0f7
	lvls->array = NULL;
Packit 51d0f7
	cats->size = 0;
Packit 51d0f7
	cats->array = NULL;
Packit 51d0f7
Packit 51d0f7
	nla_a = nlbl_attr_find(ans_msg, NLBL_CIPSOV4_A_MTYPE);
Packit 51d0f7
	if (nla_a == NULL)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	*mtype = nla_get_u32(nla_a);
Packit 51d0f7
Packit 51d0f7
	nla_a = nlbl_attr_find(ans_msg, NLBL_CIPSOV4_A_TAGLST);
Packit 51d0f7
	if (nla_a == NULL)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	tags->size = 0;
Packit 51d0f7
	tags->array = NULL;
Packit 51d0f7
	nla_for_each_attr(nla_b, nla_data(nla_a), nla_len(nla_a), nla_b_rem)
Packit 51d0f7
	if (nla_b->nla_type == NLBL_CIPSOV4_A_TAG) {
Packit 51d0f7
		tags->array = realloc(tags->array, tags->size + 1);
Packit 51d0f7
		if (tags->array == NULL) {
Packit 51d0f7
			rc = -ENOMEM;
Packit 51d0f7
			goto list_return;
Packit 51d0f7
		}
Packit 51d0f7
		tags->array[tags->size++] = nla_get_u8(nla_b);
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	if (*mtype == CIPSO_V4_MAP_TRANS) {
Packit 51d0f7
		nla_a = nlbl_attr_find(ans_msg, NLBL_CIPSOV4_A_MLSLVLLST);
Packit 51d0f7
		if (nla_a == NULL)
Packit 51d0f7
			goto list_return;
Packit 51d0f7
		nla_for_each_attr(nla_b,
Packit 51d0f7
				  nla_data(nla_a), nla_len(nla_a), nla_b_rem)
Packit 51d0f7
		if (nla_b->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
Packit 51d0f7
			lvls->array = realloc(lvls->array,
Packit 51d0f7
					      ((lvls->size + 1) * 2) *
Packit 51d0f7
					      sizeof(nlbl_cip_lvl));
Packit 51d0f7
			if (lvls->array == NULL) {
Packit 51d0f7
				rc = -ENOMEM;
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			}
Packit 51d0f7
			nla_c = nla_find(nla_data(nla_b),
Packit 51d0f7
					 nla_len(nla_b),
Packit 51d0f7
					 NLBL_CIPSOV4_A_MLSLVLLOC);
Packit 51d0f7
			if (nla_c == NULL)
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			nla_d = nla_find(nla_data(nla_b),
Packit 51d0f7
					 nla_len(nla_b),
Packit 51d0f7
					 NLBL_CIPSOV4_A_MLSLVLREM);
Packit 51d0f7
			if (nla_d == NULL)
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			lvls->array[lvls->size * 2] = nla_get_u32(nla_c);
Packit 51d0f7
			lvls->array[lvls->size * 2 + 1] = nla_get_u32(nla_d);
Packit 51d0f7
			lvls->size++;
Packit 51d0f7
		}
Packit 51d0f7
Packit 51d0f7
		nla_a = nlbl_attr_find(ans_msg, NLBL_CIPSOV4_A_MLSCATLST);
Packit 51d0f7
		if (nla_a == NULL)
Packit 51d0f7
			goto list_return;
Packit 51d0f7
		nla_for_each_attr(nla_b,
Packit 51d0f7
				  nla_data(nla_a), nla_len(nla_a), nla_b_rem)
Packit 51d0f7
		if (nla_b->nla_type == NLBL_CIPSOV4_A_MLSCAT) {
Packit 51d0f7
			cats->array = realloc(cats->array,
Packit 51d0f7
					      ((cats->size + 1) * 2) *
Packit 51d0f7
					      sizeof(nlbl_cip_cat));
Packit 51d0f7
			if (cats->array == NULL) {
Packit 51d0f7
				rc = -ENOMEM;
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			}
Packit 51d0f7
			nla_c = nla_find(nla_data(nla_b),
Packit 51d0f7
					 nla_len(nla_b),
Packit 51d0f7
					 NLBL_CIPSOV4_A_MLSCATLOC);
Packit 51d0f7
			if (nla_c == NULL)
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			nla_d = nla_find(nla_data(nla_b),
Packit 51d0f7
					 nla_len(nla_b),
Packit 51d0f7
					 NLBL_CIPSOV4_A_MLSCATREM);
Packit 51d0f7
			if (nla_d == NULL)
Packit 51d0f7
				goto list_return;
Packit 51d0f7
			cats->array[cats->size * 2] = nla_get_u32(nla_c);
Packit 51d0f7
			cats->array[cats->size * 2 + 1] = nla_get_u32(nla_d);
Packit 51d0f7
			cats->size++;
Packit 51d0f7
		}
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	rc = 0;
Packit 51d0f7
Packit 51d0f7
list_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	nlbl_msg_free(ans_msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * List the CIPSO label mappings
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param dois an array of DOI values
Packit 51d0f7
 * @param mtypes an array of the mapping types
Packit 51d0f7
 *
Packit 51d0f7
 * Query the kernel for the configured CIPSO mappings and return two arrays;
Packit 51d0f7
 * @dois which contains the DOI values and @mtypes which contains the
Packit 51d0f7
 * type of mapping.  If @hndl is NULL then the function will handle opening
Packit 51d0f7
 * and closing it's own NetLabel handle.  Returns the number of mappings on
Packit 51d0f7
 * success, zero if no mappings exist, and negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_cipso_listall(struct nlbl_handle *hndl,
Packit 51d0f7
		       nlbl_cip_doi **dois,
Packit 51d0f7
		       nlbl_cip_mtype **mtypes)
Packit 51d0f7
{
Packit 51d0f7
	int rc = -ENOMEM;
Packit 51d0f7
	struct nlbl_handle *p_hndl = hndl;
Packit 51d0f7
	unsigned char *data = NULL;
Packit 51d0f7
	nlbl_msg *msg = NULL;
Packit 51d0f7
	struct nlmsghdr *nl_hdr;
Packit 51d0f7
	struct genlmsghdr *genl_hdr;
Packit 51d0f7
	struct nlattr *nla_head;
Packit 51d0f7
	struct nlattr *nla;
Packit 51d0f7
	int data_len;
Packit 51d0f7
	int data_attrlen;
Packit 51d0f7
	nlbl_cip_doi *doi_a = NULL, *doi_a_new;
Packit 51d0f7
	nlbl_cip_mtype *mtype_a = NULL, *mtype_a_new;
Packit 51d0f7
	uint32_t count = 0;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (dois == NULL || mtypes == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_cipso_fid == 0)
Packit 51d0f7
		return -ENOPROTOOPT;
Packit 51d0f7
Packit 51d0f7
	/* open a handle if we need one */
Packit 51d0f7
	if (p_hndl == NULL) {
Packit 51d0f7
		p_hndl = nlbl_comm_open();
Packit 51d0f7
		if (p_hndl == NULL)
Packit 51d0f7
			goto listall_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_cipso_msg_new(NLBL_CIPSOV4_C_LISTALL, NLM_F_DUMP);
Packit 51d0f7
	if (msg == NULL) {
Packit 51d0f7
		rc = -ENOMEM;
Packit 51d0f7
		goto listall_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* send the request */
Packit 51d0f7
	rc = nlbl_comm_send(p_hndl, msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto listall_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read all of the messages (multi-message response) */
Packit 51d0f7
	do {
Packit 51d0f7
		if (data) {
Packit 51d0f7
			free(data);
Packit 51d0f7
			data = NULL;
Packit 51d0f7
		}
Packit 51d0f7
Packit 51d0f7
		/* get the next set of messages */
Packit 51d0f7
		rc = nlbl_comm_recv_raw(p_hndl, &data);
Packit 51d0f7
		if (rc <= 0) {
Packit 51d0f7
			if (rc == 0)
Packit 51d0f7
				rc = -ENODATA;
Packit 51d0f7
			goto listall_return;
Packit 51d0f7
		}
Packit 51d0f7
		data_len = rc;
Packit 51d0f7
		nl_hdr = (struct nlmsghdr *)data;
Packit 51d0f7
Packit 51d0f7
		/* check to see if this is a netlink control message we don't
Packit 51d0f7
		 * care about */
Packit 51d0f7
		if (nl_hdr->nlmsg_type == NLMSG_NOOP ||
Packit 51d0f7
		    nl_hdr->nlmsg_type == NLMSG_ERROR ||
Packit 51d0f7
		    nl_hdr->nlmsg_type == NLMSG_OVERRUN) {
Packit 51d0f7
			rc = -EBADMSG;
Packit 51d0f7
			goto listall_return;
Packit 51d0f7
		}
Packit 51d0f7
Packit 51d0f7
		/* loop through the messages */
Packit 51d0f7
		while (nlmsg_ok(nl_hdr, data_len) &&
Packit 51d0f7
		       nl_hdr->nlmsg_type != NLMSG_DONE) {
Packit 51d0f7
			/* get the header pointers */
Packit 51d0f7
			genl_hdr = (struct genlmsghdr *)nlmsg_data(nl_hdr);
Packit 51d0f7
			if (genl_hdr == NULL ||
Packit 51d0f7
			    genl_hdr->cmd != NLBL_CIPSOV4_C_LISTALL) {
Packit 51d0f7
				rc = -EBADMSG;
Packit 51d0f7
				goto listall_return;
Packit 51d0f7
			}
Packit 51d0f7
			nla_head = (struct nlattr *)(&genl_hdr[1]);
Packit 51d0f7
			data_attrlen = genlmsg_attrlen(genl_hdr, 0);
Packit 51d0f7
Packit 51d0f7
			/* resize the arrays */
Packit 51d0f7
			doi_a_new = realloc(doi_a,
Packit 51d0f7
					    sizeof(nlbl_cip_doi) * (count + 1));
Packit 51d0f7
			if (doi_a_new == NULL)
Packit 51d0f7
				goto listall_return;
Packit 51d0f7
			doi_a = doi_a_new;
Packit 51d0f7
			mtype_a_new = realloc(mtype_a,
Packit 51d0f7
					      sizeof(nlbl_cip_mtype) * (count + 1));
Packit 51d0f7
			if (mtype_a_new == NULL)
Packit 51d0f7
				goto listall_return;
Packit 51d0f7
			mtype_a = mtype_a_new;
Packit 51d0f7
Packit 51d0f7
			/* get the attribute information */
Packit 51d0f7
			nla = nla_find(nla_head,
Packit 51d0f7
				       data_attrlen, NLBL_CIPSOV4_A_DOI);
Packit 51d0f7
			if (nla == NULL)
Packit 51d0f7
				goto listall_return;
Packit 51d0f7
			doi_a[count] = nla_get_u32(nla);
Packit 51d0f7
			nla = nla_find(nla_head,
Packit 51d0f7
				       data_attrlen, NLBL_CIPSOV4_A_MTYPE);
Packit 51d0f7
			if (nla == NULL)
Packit 51d0f7
				goto listall_return;
Packit 51d0f7
			mtype_a[count] = nla_get_u32(nla);
Packit 51d0f7
Packit 51d0f7
			count++;
Packit 51d0f7
Packit 51d0f7
			/* next message */
Packit 51d0f7
			nl_hdr = nlmsg_next(nl_hdr, &data_len);
Packit 51d0f7
		}
Packit 51d0f7
	} while (NL_MULTI_CONTINUE(nl_hdr));
Packit 51d0f7
Packit 51d0f7
	*dois = doi_a;
Packit 51d0f7
	*mtypes = mtype_a;
Packit 51d0f7
	rc = count;
Packit 51d0f7
Packit 51d0f7
listall_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	if (rc < 0) {
Packit 51d0f7
		if (doi_a != NULL)
Packit 51d0f7
			free(doi_a);
Packit 51d0f7
		if (mtype_a != NULL)
Packit 51d0f7
			free(mtype_a);
Packit 51d0f7
	}
Packit 51d0f7
	if (data != NULL)
Packit 51d0f7
		free(data);
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}