Blame libnetlabel/mod_unlabeled.c

Packit 51d0f7
/** @file
Packit 51d0f7
 * Unlabeled 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, 2007
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_unlbl_fid = 0;
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * Helper functions
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Create a new NetLabel unlbl message
Packit 51d0f7
 * @param command the NetLabel unlbl command
Packit 51d0f7
 * @param flags the message flags
Packit 51d0f7
 *
Packit 51d0f7
 * This function creates a new NetLabel unlbl 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_unlbl_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_unlbl_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 unlbl message
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param msg the message
Packit 51d0f7
 *
Packit 51d0f7
 * Try to read a NetLabel unlbl 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_unlbl_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_unlbl_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_unlbl_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 unlbl component, including determining the
Packit 51d0f7
 * NetLabel unlbl Generic Netlink family ID.  Returns zero on success,
Packit 51d0f7
 * negative values on error.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_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,
Packit 51d0f7
			       NETLBL_NLTYPE_UNLABELED_NAME);
Packit 51d0f7
	if (rc < 0)
Packit 51d0f7
		goto init_return;
Packit 51d0f7
	nlbl_unlbl_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
/*
Packit 51d0f7
 * NetLabel operations
Packit 51d0f7
 */
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Set the unlbl accept flag
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param allow_flag the desired accept flag setting
Packit 51d0f7
 *
Packit 51d0f7
 * Set the unlbl accept flag in the NetLabel system; if @allow_flag is
Packit 51d0f7
 * true then set the accept flag, otherwise clear the flag.  If @hndl is NULL
Packit 51d0f7
 * then the function will handle opening and closing it's own NetLabel handle.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_accept(struct nlbl_handle *hndl, uint8_t allow_flag)
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 (nlbl_unlbl_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 accept_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_ACCEPT, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto accept_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	if (allow_flag)
Packit 51d0f7
		rc = nla_put_u8(msg, NLBL_UNLABEL_A_ACPTFLG, 1);
Packit 51d0f7
	else
Packit 51d0f7
		rc = nla_put_u8(msg, NLBL_UNLABEL_A_ACPTFLG, 0);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto accept_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 accept_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_unlbl_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto accept_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_unlbl_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
accept_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
 * Query the unlbl accept flag
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param allow_flag the current accept flag setting
Packit 51d0f7
 *
Packit 51d0f7
 * Query the unlbl accept flag in the NetLabel system.  If @hndl is NULL then
Packit 51d0f7
 * the function will handle opening and closing it's own NetLabel handle.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_list(struct nlbl_handle *hndl, uint8_t *allow_flag)
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;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (allow_flag == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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_unlbl_msg_new(NLBL_UNLABEL_C_LIST, 0);
Packit 51d0f7
	if (msg == NULL)
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_unlbl_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_unlbl_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_UNLABEL_C_LIST) {
Packit 51d0f7
		rc = -EBADMSG;
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	nla = nlbl_attr_find(ans_msg, NLBL_UNLABEL_A_ACPTFLG);
Packit 51d0f7
	if (nla == NULL)
Packit 51d0f7
		goto list_return;
Packit 51d0f7
	*allow_flag = nla_get_u8(nla);
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
 * Add a static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param dev the network interface
Packit 51d0f7
 * @param addr the network IP address
Packit 51d0f7
 * @param label the security label
Packit 51d0f7
 *
Packit 51d0f7
 * Add a new static label configuration to the NetLabel system.  If @hndl is
Packit 51d0f7
 * 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_unlbl_staticadd(struct nlbl_handle *hndl,
Packit 51d0f7
			 nlbl_netdev dev,
Packit 51d0f7
			 struct nlbl_netaddr *addr,
Packit 51d0f7
			 nlbl_secctx label)
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 (dev == NULL || addr == NULL || label == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticadd_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICADD, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticadd_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	rc = nla_put_string(msg, NLBL_UNLABEL_A_IFACE, dev);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto staticadd_return;
Packit 51d0f7
	rc = nla_put_string(msg, NLBL_UNLABEL_A_SECCTX, label);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto staticadd_return;
Packit 51d0f7
	switch (addr->type) {
Packit 51d0f7
	case AF_INET:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4ADDR,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->addr.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadd_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4MASK,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->mask.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadd_return;
Packit 51d0f7
		break;
Packit 51d0f7
	case AF_INET6:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6ADDR,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->addr.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadd_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6MASK,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->mask.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadd_return;
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		rc = -EINVAL;
Packit 51d0f7
		goto staticadd_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 staticadd_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_unlbl_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto staticadd_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_unlbl_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
staticadd_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
 * Set the default static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param addr the network IP address
Packit 51d0f7
 * @param label the security label
Packit 51d0f7
 *
Packit 51d0f7
 * Set the default static label configuration to the NetLabel system.  If
Packit 51d0f7
 * @hndl is NULL then the function will handle opening and closing it's own
Packit 51d0f7
 * NetLabel handle.  Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_staticadddef(struct nlbl_handle *hndl,
Packit 51d0f7
			    struct nlbl_netaddr *addr,
Packit 51d0f7
			    nlbl_secctx label)
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 (addr == NULL || label == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticadddef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICADDDEF, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticadddef_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	rc = nla_put_string(msg, NLBL_UNLABEL_A_SECCTX, label);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto staticadddef_return;
Packit 51d0f7
	switch (addr->type) {
Packit 51d0f7
	case AF_INET:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4ADDR,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->addr.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadddef_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4MASK,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->mask.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadddef_return;
Packit 51d0f7
		break;
Packit 51d0f7
	case AF_INET6:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6ADDR,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->addr.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadddef_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6MASK,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->mask.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticadddef_return;
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		rc = -EINVAL;
Packit 51d0f7
		goto staticadddef_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 staticadddef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_unlbl_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto staticadddef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_unlbl_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
staticadddef_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
 * Delete a static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param dev the network interface
Packit 51d0f7
 * @param addr the network IP address
Packit 51d0f7
 *
Packit 51d0f7
 * Delete a new static label configuration to the NetLabel system.  If @hndl is
Packit 51d0f7
 * 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_unlbl_staticdel(struct nlbl_handle *hndl,
Packit 51d0f7
			 nlbl_netdev dev,
Packit 51d0f7
			 struct nlbl_netaddr *addr)
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 (dev == NULL || addr == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticdel_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICREMOVE, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticdel_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	rc = nla_put_string(msg, NLBL_UNLABEL_A_IFACE, dev);
Packit 51d0f7
	if (rc != 0)
Packit 51d0f7
		goto staticdel_return;
Packit 51d0f7
	switch (addr->type) {
Packit 51d0f7
	case AF_INET:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4ADDR,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->addr.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdel_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4MASK,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->mask.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdel_return;
Packit 51d0f7
		break;
Packit 51d0f7
	case AF_INET6:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6ADDR,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->addr.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdel_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6MASK,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->mask.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdel_return;
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		rc = -EINVAL;
Packit 51d0f7
		goto staticdel_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 staticdel_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_unlbl_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto staticdel_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_unlbl_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
staticdel_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
 * Delete the default static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param addr the network IP address
Packit 51d0f7
 *
Packit 51d0f7
 * Delete the default static label configuration to the NetLabel system.  If
Packit 51d0f7
 * @hndl is NULL then the function will handle opening and closing it's own
Packit 51d0f7
 * NetLabel handle.  Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_staticdeldef(struct nlbl_handle *hndl,
Packit 51d0f7
			    struct nlbl_netaddr *addr)
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 (addr == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticdeldef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICREMOVEDEF, 0);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticdeldef_return;
Packit 51d0f7
Packit 51d0f7
	/* add the required attributes to the message */
Packit 51d0f7
	switch (addr->type) {
Packit 51d0f7
	case AF_INET:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4ADDR,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->addr.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdeldef_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV4MASK,
Packit 51d0f7
			     sizeof(struct in_addr),
Packit 51d0f7
			     &addr->mask.v4);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdeldef_return;
Packit 51d0f7
		break;
Packit 51d0f7
	case AF_INET6:
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6ADDR,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->addr.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdeldef_return;
Packit 51d0f7
		rc = nla_put(msg,
Packit 51d0f7
			     NLBL_UNLABEL_A_IPV6MASK,
Packit 51d0f7
			     sizeof(struct in6_addr),
Packit 51d0f7
			     &addr->mask.v6);
Packit 51d0f7
		if (rc != 0)
Packit 51d0f7
			goto staticdeldef_return;
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		rc = -EINVAL;
Packit 51d0f7
		goto staticdeldef_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 staticdeldef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* read the response */
Packit 51d0f7
	rc = nlbl_unlbl_recv(p_hndl, &ans_msg);
Packit 51d0f7
	if (rc <= 0) {
Packit 51d0f7
		if (rc == 0)
Packit 51d0f7
			rc = -ENODATA;
Packit 51d0f7
		goto staticdeldef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* process the response */
Packit 51d0f7
	rc = nlbl_unlbl_parse_ack(ans_msg);
Packit 51d0f7
Packit 51d0f7
staticdeldef_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
 * Dump the static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param addrs the static label address mappings
Packit 51d0f7
 *
Packit 51d0f7
 * Dump the NetLabel static label configuration.  If @hndl is NULL then the
Packit 51d0f7
 * function will handle opening and closing it's own NetLabel handle.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_staticlist(struct nlbl_handle *hndl,
Packit 51d0f7
			  struct nlbl_addrmap **addrs)
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
	struct nlbl_addrmap *addr_array = NULL, *addr_array_new;
Packit 51d0f7
	uint32_t addr_count = 0;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (addrs == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticlist_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICLIST, NLM_F_DUMP);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticlist_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 staticlist_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 staticlist_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 staticlist_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_UNLABEL_C_STATICLIST) {
Packit 51d0f7
				rc = -EBADMSG;
Packit 51d0f7
				goto staticlist_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 array */
Packit 51d0f7
			addr_array_new = realloc(addr_array,
Packit 51d0f7
						 sizeof(*addr_array) *
Packit 51d0f7
						 (addr_count + 1));
Packit 51d0f7
			if (addr_array_new == NULL)
Packit 51d0f7
				goto staticlist_return;
Packit 51d0f7
			addr_array = addr_array_new;
Packit 51d0f7
			memset(&addr_array[addr_count], 0, sizeof(*addr_array));
Packit 51d0f7
Packit 51d0f7
			/* get the attribute information */
Packit 51d0f7
			nla = nla_find(nla_head,
Packit 51d0f7
				       data_attrlen, NLBL_UNLABEL_A_IFACE);
Packit 51d0f7
			if (nla == NULL)
Packit 51d0f7
				goto staticlist_return;
Packit 51d0f7
			addr_array[addr_count].dev = malloc(nla_len(nla));
Packit 51d0f7
			if (addr_array[addr_count].dev == NULL)
Packit 51d0f7
				goto staticlist_return;
Packit 51d0f7
			strncpy(addr_array[addr_count].dev,
Packit 51d0f7
				nla_data(nla), nla_len(nla));
Packit 51d0f7
			nla = nla_find(nla_head,
Packit 51d0f7
				       data_attrlen, NLBL_UNLABEL_A_SECCTX);
Packit 51d0f7
			if (nla == NULL)
Packit 51d0f7
				goto staticlist_return;
Packit 51d0f7
			addr_array[addr_count].label = malloc(nla_len(nla));
Packit 51d0f7
			if (addr_array[addr_count].label == NULL)
Packit 51d0f7
				goto staticlist_return;
Packit 51d0f7
			strncpy(addr_array[addr_count].label,
Packit 51d0f7
				nla_data(nla), nla_len(nla));
Packit 51d0f7
			if (nla_find(nla_head,
Packit 51d0f7
				     data_attrlen, NLBL_UNLABEL_A_IPV4ADDR)) {
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV4ADDR);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in_addr))
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.addr.v4,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV4MASK);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in_addr))
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.mask.v4,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				addr_array[addr_count].addr.type = AF_INET;
Packit 51d0f7
			} else if (nla_find(nla_head,
Packit 51d0f7
					    data_attrlen,
Packit 51d0f7
					    NLBL_UNLABEL_A_IPV6ADDR)) {
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV6ADDR);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in6_addr))
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.addr.v6,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV6MASK);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in6_addr))
Packit 51d0f7
					goto staticlist_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.mask.v6,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				addr_array[addr_count].addr.type = AF_INET6;
Packit 51d0f7
			}
Packit 51d0f7
			addr_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
	*addrs = addr_array;
Packit 51d0f7
	rc = addr_count;
Packit 51d0f7
Packit 51d0f7
staticlist_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	if (rc < 0 && addr_array) {
Packit 51d0f7
		do {
Packit 51d0f7
			if (addr_array[addr_count].dev)
Packit 51d0f7
				free(addr_array[addr_count].dev);
Packit 51d0f7
			if (addr_array[addr_count].label)
Packit 51d0f7
				free(addr_array[addr_count].label);
Packit 51d0f7
		} while (addr_count-- > 0);
Packit 51d0f7
		free(addr_array);
Packit 51d0f7
	}
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Dump the default static label configuration
Packit 51d0f7
 * @param hndl the NetLabel handle
Packit 51d0f7
 * @param addrs the static label address mappings
Packit 51d0f7
 *
Packit 51d0f7
 * Dump the NetLabel default static label configuration.  If @hndl is NULL
Packit 51d0f7
 * then the function will handle opening and closing it's own NetLabel handle.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlbl_unlbl_staticlistdef(struct nlbl_handle *hndl,
Packit 51d0f7
			     struct nlbl_addrmap **addrs)
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
	struct nlbl_addrmap *addr_array = NULL, *addr_array_new;
Packit 51d0f7
	uint32_t addr_count = 0;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (addrs == NULL)
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
	if (nlbl_unlbl_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 staticlistdef_return;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* create a new message */
Packit 51d0f7
	msg = nlbl_unlbl_msg_new(NLBL_UNLABEL_C_STATICLISTDEF, NLM_F_DUMP);
Packit 51d0f7
	if (msg == NULL)
Packit 51d0f7
		goto staticlistdef_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 staticlistdef_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 staticlistdef_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 staticlistdef_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_UNLABEL_C_STATICLISTDEF) {
Packit 51d0f7
				rc = -EBADMSG;
Packit 51d0f7
				goto staticlistdef_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 array */
Packit 51d0f7
			addr_array_new = realloc(addr_array,
Packit 51d0f7
						 sizeof(*addr_array) *
Packit 51d0f7
						 (addr_count + 1));
Packit 51d0f7
			if (addr_array_new == NULL)
Packit 51d0f7
				goto staticlistdef_return;
Packit 51d0f7
			addr_array = addr_array_new;
Packit 51d0f7
			memset(&addr_array[addr_count], 0, sizeof(*addr_array));
Packit 51d0f7
Packit 51d0f7
			/* get the attribute information */
Packit 51d0f7
			nla = nla_find(nla_head,
Packit 51d0f7
				       data_attrlen, NLBL_UNLABEL_A_SECCTX);
Packit 51d0f7
			if (nla == NULL)
Packit 51d0f7
				goto staticlistdef_return;
Packit 51d0f7
			addr_array[addr_count].label = malloc(nla_len(nla));
Packit 51d0f7
			if (addr_array[addr_count].label == NULL)
Packit 51d0f7
				goto staticlistdef_return;
Packit 51d0f7
			strncpy(addr_array[addr_count].label,
Packit 51d0f7
				nla_data(nla), nla_len(nla));
Packit 51d0f7
			if (nla_find(nla_head,
Packit 51d0f7
				     data_attrlen, NLBL_UNLABEL_A_IPV4ADDR)) {
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV4ADDR);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in_addr))
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.addr.v4,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV4MASK);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in_addr))
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.mask.v4,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				addr_array[addr_count].addr.type = AF_INET;
Packit 51d0f7
			} else if (nla_find(nla_head,
Packit 51d0f7
					    data_attrlen,
Packit 51d0f7
					    NLBL_UNLABEL_A_IPV6ADDR)) {
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV6ADDR);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in6_addr))
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.addr.v6,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				nla = nla_find(nla_head,
Packit 51d0f7
					       data_attrlen,
Packit 51d0f7
					       NLBL_UNLABEL_A_IPV6MASK);
Packit 51d0f7
				if (nla == NULL)
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				if (nla_len(nla) != sizeof(struct in6_addr))
Packit 51d0f7
					goto staticlistdef_return;
Packit 51d0f7
				memcpy(&addr_array[addr_count].addr.mask.v6,
Packit 51d0f7
				       nla_data(nla),
Packit 51d0f7
				       nla_len(nla));
Packit 51d0f7
				addr_array[addr_count].addr.type = AF_INET6;
Packit 51d0f7
			}
Packit 51d0f7
			addr_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
	*addrs = addr_array;
Packit 51d0f7
	rc = addr_count;
Packit 51d0f7
Packit 51d0f7
staticlistdef_return:
Packit 51d0f7
	if (hndl == NULL)
Packit 51d0f7
		nlbl_comm_close(p_hndl);
Packit 51d0f7
	if (rc < 0 && addr_array) {
Packit 51d0f7
		do {
Packit 51d0f7
			if (addr_array[addr_count].label)
Packit 51d0f7
				free(addr_array[addr_count].label);
Packit 51d0f7
		} while (addr_count-- > 0);
Packit 51d0f7
		free(addr_array);
Packit 51d0f7
	}
Packit 51d0f7
	nlbl_msg_free(msg);
Packit 51d0f7
	return rc;
Packit 51d0f7
}