|
Packit |
51d0f7 |
/** @file
|
|
Packit |
51d0f7 |
* CALIPSO Module Functions
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
* Author: Paul Moore <paul@paul-moore.com>
|
|
Packit |
51d0f7 |
* Author: Huw Davies <huw@codeweavers.com>
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
*/
|
|
Packit |
51d0f7 |
|
|
Packit |
51d0f7 |
/*
|
|
Packit |
51d0f7 |
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006
|
|
Packit |
51d0f7 |
* (c) Copyright Huw Davies <huw@codeweavers.com>, 2015
|
|
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_calipso_fid = 0;
|
|
Packit |
51d0f7 |
|
|
Packit |
51d0f7 |
/*
|
|
Packit |
51d0f7 |
* Helper functions
|
|
Packit |
51d0f7 |
*/
|
|
Packit |
51d0f7 |
|
|
Packit |
51d0f7 |
/**
|
|
Packit |
51d0f7 |
* Create a new NetLabel CALIPSO 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 CALIPSO 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_calipso_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_calipso_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 CALIPSO message
|
|
Packit |
51d0f7 |
* @param hndl the NetLabel handle
|
|
Packit |
51d0f7 |
* @param msg the message
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
* Try to read a NetLabel CALIPSO 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_calipso_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_calipso_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_calipso_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 CALIPSO component, including determining the
|
|
Packit |
51d0f7 |
* NetLabel CALIPSO Generic Netlink family ID. Returns zero on success,
|
|
Packit |
51d0f7 |
* negative values on error.
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
*/
|
|
Packit |
51d0f7 |
int nlbl_calipso_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_CALIPSO_NAME);
|
|
Packit |
51d0f7 |
if (rc < 0)
|
|
Packit |
51d0f7 |
goto init_return;
|
|
Packit |
51d0f7 |
nlbl_calipso_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 pass-through CALIPSO label mapping
|
|
Packit |
51d0f7 |
* @param hndl the NetLabel handle
|
|
Packit |
51d0f7 |
* @param doi the CALIPSO DOI number
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
* Add the specified static CALIPSO 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_calipso_add_pass(struct nlbl_handle *hndl,
|
|
Packit |
51d0f7 |
nlbl_clp_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_calipso_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_calipso_msg_new(NLBL_CALIPSO_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_CALIPSO_A_DOI, doi);
|
|
Packit |
51d0f7 |
if (rc != 0)
|
|
Packit |
51d0f7 |
goto add_pass_return;
|
|
Packit |
51d0f7 |
rc = nla_put_u32(msg, NLBL_CALIPSO_A_MTYPE, CALIPSO_MAP_PASS);
|
|
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_calipso_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_calipso_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 |
* Delete a CALIPSO label mapping
|
|
Packit |
51d0f7 |
* @param hndl the NetLabel handle
|
|
Packit |
51d0f7 |
* @param doi the CALIPSO DOI number
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
* Remove the CALIPSO 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_calipso_del(struct nlbl_handle *hndl, nlbl_clp_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_calipso_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_calipso_msg_new(NLBL_CALIPSO_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_CALIPSO_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_calipso_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_calipso_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 CALIPSO label mapping
|
|
Packit |
51d0f7 |
* @param hndl the NetLabel handle
|
|
Packit |
51d0f7 |
* @param doi the CALIPSO DOI number
|
|
Packit |
51d0f7 |
* @param mtype the DOI mapping type
|
|
Packit |
51d0f7 |
*
|
|
Packit |
51d0f7 |
* Query the kernel for the specified CALIPSO 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_calipso_list(struct nlbl_handle *hndl,
|
|
Packit |
51d0f7 |
nlbl_clp_doi doi,
|
|
Packit |
51d0f7 |
nlbl_clp_mtype *mtype)
|
|
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 |
|
|
Packit |
51d0f7 |
/* sanity checks */
|
|
Packit |
51d0f7 |
if (doi == 0 || mtype == NULL)
|
|
Packit |
51d0f7 |
return -EINVAL;
|
|
Packit |
51d0f7 |
if (nlbl_calipso_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_calipso_msg_new(NLBL_CALIPSO_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_CALIPSO_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_calipso_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_calipso_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_CALIPSO_C_LIST) {
|
|
Packit |
51d0f7 |
rc = -EBADMSG;
|
|
Packit |
51d0f7 |
goto list_return;
|
|
Packit |
51d0f7 |
}
|
|
Packit |
51d0f7 |
|
|
Packit |
51d0f7 |
/* process the response */
|
|
Packit |
51d0f7 |
|
|
Packit |
51d0f7 |
nla_a = nlbl_attr_find(ans_msg, NLBL_CALIPSO_A_MTYPE);
|
|
Packit |
51d0f7 |
if (nla_a == NULL)
|
|
Packit |
51d0f7 |
goto list_return;
|
|
Packit |
51d0f7 |
*mtype = nla_get_u32(nla_a);
|
|
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 CALIPSO 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 CALIPSO 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_calipso_listall(struct nlbl_handle *hndl,
|
|
Packit |
51d0f7 |
nlbl_clp_doi **dois,
|
|
Packit |
51d0f7 |
nlbl_clp_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_clp_doi *doi_a = NULL, *doi_a_new;
|
|
Packit |
51d0f7 |
nlbl_clp_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_calipso_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_calipso_msg_new(NLBL_CALIPSO_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_CALIPSO_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_clp_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_clp_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_CALIPSO_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_CALIPSO_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 |
}
|