Blame netlabelctl/main.c

Packit 51d0f7
/*
Packit 51d0f7
 * NetLabel Control Utility, netlabelctl
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 <configure.h>
Packit 51d0f7
Packit 51d0f7
#include <stdlib.h>
Packit 51d0f7
#include <stdio.h>
Packit 51d0f7
#include <string.h>
Packit 51d0f7
#include <errno.h>
Packit 51d0f7
#include <unistd.h>
Packit 51d0f7
#include <getopt.h>
Packit 51d0f7
#include <arpa/inet.h>
Packit 51d0f7
Packit 51d0f7
#include <libnetlabel.h>
Packit 51d0f7
Packit 51d0f7
#include "netlabelctl.h"
Packit 51d0f7
Packit 51d0f7
/* return values */
Packit 51d0f7
#define RET_OK		0
Packit 51d0f7
#define RET_ERR		1
Packit 51d0f7
#define RET_USAGE	2
Packit 51d0f7
Packit 51d0f7
/* option variables */
Packit 51d0f7
uint32_t opt_verbose = 0;
Packit 51d0f7
uint32_t opt_timeout = 10;
Packit 51d0f7
uint32_t opt_pretty = 0;
Packit 51d0f7
Packit 51d0f7
/* program name */
Packit 51d0f7
char *nlctl_name = NULL;
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Display usage information
Packit 51d0f7
 * @param fp the output file pointer
Packit 51d0f7
 *
Packit 51d0f7
 * Display brief usage information.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static void nlctl_usage_print(FILE *fp)
Packit 51d0f7
{
Packit 51d0f7
	fprintf(fp, "usage: %s [<flags>] <module> [<commands>]\n", nlctl_name);
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Display version information
Packit 51d0f7
 * @param fp the output file pointer
Packit 51d0f7
 *
Packit 51d0f7
 * Display the version string.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static void nlctl_ver_print(FILE *fp)
Packit 51d0f7
{
Packit 51d0f7
	fprintf(fp, "NetLabel Control Utility, version %s\n", VERSION);
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Display help information
Packit 51d0f7
 * @param fp the output file pointer
Packit 51d0f7
 *
Packit 51d0f7
 * Display help and usage information.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static void nlctl_help_print(FILE *fp)
Packit 51d0f7
{
Packit 51d0f7
	nlctl_ver_print(fp);
Packit 51d0f7
	fprintf(fp,
Packit 51d0f7
		" Usage: %s [<flags>] <module> [<commands>]\n"
Packit 51d0f7
		"\n"
Packit 51d0f7
		" Flags:\n"
Packit 51d0f7
		"   -h        : help/usage message\n"
Packit 51d0f7
		"   -p        : make the output pretty\n"
Packit 51d0f7
		"   -t <secs> : timeout\n"
Packit 51d0f7
		"   -v        : verbose mode\n"
Packit 51d0f7
		"\n"
Packit 51d0f7
		" Modules and Commands:\n"
Packit 51d0f7
		"  mgmt : NetLabel management\n"
Packit 51d0f7
		"    version\n"
Packit 51d0f7
		"    protocols\n"
Packit 51d0f7
		"  map : Domain/Protocol mapping\n"
Packit 51d0f7
		"    add default|domain:<domain> [address:<ADDR>[/<MASK>]]\n"
Packit 51d0f7
		"                                protocol:<protocol>[,<extra>]\n"
Packit 51d0f7
		"    del default|domain:<domain>\n"
Packit 51d0f7
		"    list\n"
Packit 51d0f7
		"  unlbl : Unlabeled packet handling\n"
Packit 51d0f7
		"    accept on|off\n"
Packit 51d0f7
		"    add default|interface:<DEV> address:<ADDR>[/<MASK>]\n"
Packit 51d0f7
		"                                label:<LABEL>\n"
Packit 51d0f7
		"    del default|interface:<DEV> address:<ADDR>[/<MASK>]\n"
Packit 51d0f7
		"    list\n"
Packit 51d0f7
		"  cipso|cipsov4 : CIPSO/IPv4 packet handling\n"
Packit 51d0f7
		"    add trans doi:<DOI> tags:<T1>,<Tn>\n"
Packit 51d0f7
		"            levels:<LL1>=<RL1>,<LLn>=<RLn>\n"
Packit 51d0f7
		"            categories:<LC1>=<RC1>,<LCn>=<RCn>\n"
Packit 51d0f7
		"    add pass doi:<DOI> tags:<T1>,<Tn>\n"
Packit 51d0f7
		"    add local doi:<DOI>\n"
Packit 51d0f7
		"    del doi:<DOI>\n"
Packit 51d0f7
		"    list [doi:<DOI>]\n"
Packit 51d0f7
		"  calipso : CALIPSO/IPv6 packet handling\n"
Packit 51d0f7
		"    add pass doi:<DOI>\n"
Packit 51d0f7
		"    del doi:<DOI>\n"
Packit 51d0f7
		"    list [doi:<DOI>]\n"
Packit 51d0f7
		"\n",
Packit 51d0f7
		nlctl_name);
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Convert a errno value into a human readable string
Packit 51d0f7
 * @param rc the errno return value
Packit 51d0f7
 *
Packit 51d0f7
 * Return a pointer to a human readable string describing the error in
Packit 51d0f7
 * @rc.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static char *nlctl_strerror(int rc)
Packit 51d0f7
{
Packit 51d0f7
	char *str = NULL;
Packit 51d0f7
Packit 51d0f7
	switch (rc) {
Packit 51d0f7
	case 0:
Packit 51d0f7
		str = "operation succeeded";
Packit 51d0f7
		break;
Packit 51d0f7
	case EINVAL:
Packit 51d0f7
		str = "invalid argument or parameter";
Packit 51d0f7
		break;
Packit 51d0f7
	case ENOMEM:
Packit 51d0f7
		str = "out of memory";
Packit 51d0f7
		break;
Packit 51d0f7
	case ENOENT:
Packit 51d0f7
		str = "entry does not exist";
Packit 51d0f7
		break;
Packit 51d0f7
	case ENODATA:
Packit 51d0f7
		str = "no data was available";
Packit 51d0f7
		break;
Packit 51d0f7
	case EBADMSG:
Packit 51d0f7
		str = "bad message";
Packit 51d0f7
		break;
Packit 51d0f7
	case ENOPROTOOPT:
Packit 51d0f7
		str = "not supported";
Packit 51d0f7
		break;
Packit 51d0f7
	case EAGAIN:
Packit 51d0f7
		str = "try again";
Packit 51d0f7
		break;
Packit 51d0f7
	case ENOMSG:
Packit 51d0f7
		str = "no message was received";
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		str = strerror(rc);
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	return str;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Display a network address
Packit 51d0f7
 * @param addr the IP address to display
Packit 51d0f7
 *
Packit 51d0f7
 * Print the IP address and mask, specified in @addr, to STDIO.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
void nlctl_addr_print(const struct nlbl_netaddr *addr)
Packit 51d0f7
{
Packit 51d0f7
	char addr_s[80];
Packit 51d0f7
	socklen_t addr_s_len = 80;
Packit 51d0f7
	struct in_addr mask4;
Packit 51d0f7
	struct in6_addr mask6;
Packit 51d0f7
	uint32_t mask_size;
Packit 51d0f7
	uint32_t mask_off;
Packit 51d0f7
Packit 51d0f7
	switch (addr->type) {
Packit 51d0f7
	case AF_INET:
Packit 51d0f7
		mask4.s_addr = ntohl(addr->mask.v4.s_addr);
Packit 51d0f7
		for (mask_size = 0; mask4.s_addr != 0; mask_size++)
Packit 51d0f7
			mask4.s_addr <<= 1;
Packit 51d0f7
		printf("%s/%u",
Packit 51d0f7
		       inet_ntop(AF_INET, &addr->addr.v4, addr_s, addr_s_len),
Packit 51d0f7
		       mask_size);
Packit 51d0f7
		break;
Packit 51d0f7
	case AF_INET6:
Packit 51d0f7
		for (mask_size = 0, mask_off = 0; mask_off < 4; mask_off++) {
Packit 51d0f7
			mask6.s6_addr32[mask_off] =
Packit 51d0f7
				ntohl(addr->mask.v6.s6_addr32[mask_off]);
Packit 51d0f7
			while (mask6.s6_addr32[mask_off] != 0) {
Packit 51d0f7
				mask_size++;
Packit 51d0f7
				mask6.s6_addr32[mask_off] <<= 1;
Packit 51d0f7
			}
Packit 51d0f7
		}
Packit 51d0f7
		printf("%s/%u",
Packit 51d0f7
		       inet_ntop(AF_INET6, &addr->addr.v6, addr_s, addr_s_len),
Packit 51d0f7
		       mask_size);
Packit 51d0f7
		break;
Packit 51d0f7
	default:
Packit 51d0f7
		printf("UNKNOWN(%u)", addr->type);
Packit 51d0f7
		break;
Packit 51d0f7
	}
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Parse an unsigned interger number
Packit 51d0f7
 * @param str the number string
Packit 51d0f7
 * @param num pointer to number to return
Packit 51d0f7
 *
Packit 51d0f7
 * Parse an unsigned integer number string and returns the value in @num.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
static int _nlctl_num_parse(char *str, uint32_t *num)
Packit 51d0f7
{
Packit 51d0f7
	char *spot = str;
Packit 51d0f7
Packit 51d0f7
	while (*spot != '\0') {
Packit 51d0f7
		if (*spot < '0' || *spot > '9')
Packit 51d0f7
			return -EINVAL;
Packit 51d0f7
		spot++;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	*num = atoi(str);
Packit 51d0f7
	return 0;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/**
Packit 51d0f7
 * Parse a network address/mask pair
Packit 51d0f7
 * @param addr_str the IP address/mask in string format
Packit 51d0f7
 * @param addr the IP address/mask in native NetLabel format
Packit 51d0f7
 *
Packit 51d0f7
 * Parse the IP address/mask string into the given nlbl_netaddr structure.
Packit 51d0f7
 * Returns zero on success, negative values on failure.
Packit 51d0f7
 *
Packit 51d0f7
 */
Packit 51d0f7
int nlctl_addr_parse(char *addr_str, struct nlbl_netaddr *addr)
Packit 51d0f7
{
Packit 51d0f7
	int rc;
Packit 51d0f7
	char *mask;
Packit 51d0f7
	uint32_t iter_a;
Packit 51d0f7
	uint32_t iter_b;
Packit 51d0f7
Packit 51d0f7
	/* sanity checks */
Packit 51d0f7
	if (addr_str == NULL || addr_str[0] == '\0')
Packit 51d0f7
		return -EINVAL;
Packit 51d0f7
Packit 51d0f7
	/* separate the address mask */
Packit 51d0f7
	mask = strstr(addr_str, "/");
Packit 51d0f7
	if (mask != NULL) {
Packit 51d0f7
		mask[0] = '\0';
Packit 51d0f7
		mask++;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* ipv4 */
Packit 51d0f7
	rc = inet_pton(AF_INET, addr_str, &addr->addr.v4);
Packit 51d0f7
	if (rc > 0) {
Packit 51d0f7
		addr->type = AF_INET;
Packit 51d0f7
		if (mask != NULL) {
Packit 51d0f7
			rc = _nlctl_num_parse(mask, &iter_a);
Packit 51d0f7
			if (rc < 0 || iter_a > 32)
Packit 51d0f7
				return -EINVAL;
Packit 51d0f7
		} else
Packit 51d0f7
			iter_a = 32;
Packit 51d0f7
		for (; iter_a > 0; iter_a--) {
Packit 51d0f7
			addr->mask.v4.s_addr >>= 1;
Packit 51d0f7
			addr->mask.v4.s_addr |= 0x80000000;
Packit 51d0f7
		}
Packit 51d0f7
		addr->mask.v4.s_addr = htonl(addr->mask.v4.s_addr);
Packit 51d0f7
		return 0;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* ipv6 */
Packit 51d0f7
	rc = inet_pton(AF_INET6, addr_str, &addr->addr.v6);
Packit 51d0f7
	if (rc > 0) {
Packit 51d0f7
		addr->type = AF_INET6;
Packit 51d0f7
		if (mask != NULL) {
Packit 51d0f7
			rc = _nlctl_num_parse(mask, &iter_a);
Packit 51d0f7
			if (rc < 0 || iter_a > 128)
Packit 51d0f7
				return -EINVAL;
Packit 51d0f7
		} else
Packit 51d0f7
			iter_a = 128;
Packit 51d0f7
		for (iter_b = 0; iter_a > 0 && iter_b < 4; iter_b++) {
Packit 51d0f7
			for (; iter_a > 0 &&
Packit 51d0f7
			     addr->mask.v6.s6_addr32[iter_b] < 0xffffffff;
Packit 51d0f7
			     iter_a--) {
Packit 51d0f7
				addr->mask.v6.s6_addr32[iter_b] >>= 1;
Packit 51d0f7
				addr->mask.v6.s6_addr32[iter_b] |= 0x80000000;
Packit 51d0f7
			}
Packit 51d0f7
			addr->mask.v6.s6_addr32[iter_b] =
Packit 51d0f7
				htonl(addr->mask.v6.s6_addr32[iter_b]);
Packit 51d0f7
		}
Packit 51d0f7
		return 0;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	return -EINVAL;
Packit 51d0f7
}
Packit 51d0f7
Packit 51d0f7
/*
Packit 51d0f7
 * main
Packit 51d0f7
 */
Packit 51d0f7
int main(int argc, char *argv[])
Packit 51d0f7
{
Packit 51d0f7
	int rc = RET_ERR;
Packit 51d0f7
	int arg_iter;
Packit 51d0f7
	main_function_t *module_main = NULL;
Packit 51d0f7
	char *module_name;
Packit 51d0f7
Packit 51d0f7
	/* save the invoked program name for use in user notifications */
Packit 51d0f7
	nlctl_name = strrchr(argv[0], '/');
Packit 51d0f7
	if (nlctl_name == NULL)
Packit 51d0f7
		nlctl_name = argv[0];
Packit 51d0f7
	else if (nlctl_name[0] == '/')
Packit 51d0f7
		nlctl_name += 1;
Packit 51d0f7
	else
Packit 51d0f7
		nlctl_name = strdup("unknown");
Packit 51d0f7
Packit 51d0f7
	/* get the command line arguments and module information */
Packit 51d0f7
	do {
Packit 51d0f7
		arg_iter = getopt(argc, argv, "hvt:pV");
Packit 51d0f7
		switch (arg_iter) {
Packit 51d0f7
		case 'h':
Packit 51d0f7
			/* help */
Packit 51d0f7
			nlctl_help_print(stdout);
Packit 51d0f7
			return RET_OK;
Packit 51d0f7
			break;
Packit 51d0f7
		case 'v':
Packit 51d0f7
			/* verbose */
Packit 51d0f7
			opt_verbose = 1;
Packit 51d0f7
			break;
Packit 51d0f7
		case 'p':
Packit 51d0f7
			/* pretty */
Packit 51d0f7
			opt_pretty = 1;
Packit 51d0f7
			break;
Packit 51d0f7
		case 't':
Packit 51d0f7
			/* timeout */
Packit 51d0f7
			if (atoi(optarg) < 0) {
Packit 51d0f7
				nlctl_usage_print(stderr);
Packit 51d0f7
				return RET_USAGE;
Packit 51d0f7
			}
Packit 51d0f7
			opt_timeout = atoi(optarg);
Packit 51d0f7
			break;
Packit 51d0f7
		case 'V':
Packit 51d0f7
			/* version */
Packit 51d0f7
			nlctl_ver_print(stdout);
Packit 51d0f7
			return RET_OK;
Packit 51d0f7
			break;
Packit 51d0f7
		}
Packit 51d0f7
	} while (arg_iter > 0);
Packit 51d0f7
	module_name = argv[optind];
Packit 51d0f7
	if (!module_name) {
Packit 51d0f7
		nlctl_usage_print(stderr);
Packit 51d0f7
		return RET_USAGE;
Packit 51d0f7
	}
Packit 51d0f7
Packit 51d0f7
	/* perform any setup we have to do */
Packit 51d0f7
	rc = nlbl_init();
Packit 51d0f7
	if (rc < 0) {
Packit 51d0f7
		fprintf(stderr,
Packit 51d0f7
			MSG_ERR("failed to initialize the NetLabel library\n"));
Packit 51d0f7
		goto exit;
Packit 51d0f7
	}
Packit 51d0f7
	nlbl_comm_timeout(opt_timeout);
Packit 51d0f7
Packit 51d0f7
	/* transfer control to the module */
Packit 51d0f7
	if (!strcmp(module_name, "mgmt")) {
Packit 51d0f7
		module_main = mgmt_main;
Packit 51d0f7
	} else if (!strcmp(module_name, "map")) {
Packit 51d0f7
		module_main = map_main;
Packit 51d0f7
	} else if (!strcmp(module_name, "unlbl")) {
Packit 51d0f7
		module_main = unlbl_main;
Packit 51d0f7
	} else if (!strcmp(module_name, "cipsov4") ||
Packit 51d0f7
		   !strcmp(module_name, "cipso")) {
Packit 51d0f7
		module_main = cipso_main;
Packit 51d0f7
	} else if (!strcmp(module_name, "calipso")) {
Packit 51d0f7
		module_main = calipso_main;
Packit 51d0f7
	} else {
Packit 51d0f7
		fprintf(stderr,
Packit 51d0f7
			MSG_ERR("unknown or missing module '%s'\n"),
Packit 51d0f7
			module_name);
Packit 51d0f7
		rc = RET_ERR;
Packit 51d0f7
		goto exit;
Packit 51d0f7
	}
Packit 51d0f7
	rc = module_main(argc - optind - 1, argv + optind + 1);
Packit 51d0f7
	if (rc < 0) {
Packit 51d0f7
		fprintf(stderr, MSG_ERR("%s\n"), nlctl_strerror(-rc));
Packit 51d0f7
		rc = RET_ERR;
Packit 51d0f7
	} else
Packit 51d0f7
		rc = RET_OK;
Packit 51d0f7
exit:
Packit 51d0f7
	nlbl_exit();
Packit 51d0f7
	return rc;
Packit 51d0f7
}