forked from pool/s390-tools
1247 lines
33 KiB
Diff
1247 lines
33 KiB
Diff
|
Subject: zcryptctl: new tool zcryptctl for multiple zcrypt node management
|
||
|
From: Harald Freudenberger <freude@linux.ibm.com>
|
||
|
|
||
|
Summary: zcryptctl: new tool zcryptctl for multiple zcrypt node
|
||
|
Description: There is a new zcrypt kernel feature which provides
|
||
|
multiple customizable device nodes for the zcrypt
|
||
|
device driver. Here is the userspace part of this
|
||
|
which adds a new application zcryptctl for user
|
||
|
friendly management of this feature.
|
||
|
Upstream-ID: f05f7d656b13c3904f0c55e86ebe9e9b19fcd222
|
||
|
Problem-ID: SEC1710
|
||
|
|
||
|
Upstream-Description:
|
||
|
|
||
|
zcryptctl: new tool zcryptctl for multiple zcrypt node management
|
||
|
|
||
|
With the latest kernel comes an extension for the zcrypt
|
||
|
device driver to support multiple zcrypt device nodes.
|
||
|
|
||
|
Here is the userspace part of this which adds a new
|
||
|
application zcryptctl for user friendly management of
|
||
|
this feature.
|
||
|
|
||
|
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
|
||
|
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
|
||
|
|
||
|
|
||
|
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
|
||
|
---
|
||
|
zconf/zcrypt/Makefile | 7
|
||
|
zconf/zcrypt/zcryptctl.8 | 147 ++++++
|
||
|
zconf/zcrypt/zcryptctl.c | 1030 +++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
3 files changed, 1182 insertions(+), 2 deletions(-)
|
||
|
|
||
|
--- a/zconf/zcrypt/Makefile
|
||
|
+++ b/zconf/zcrypt/Makefile
|
||
|
@@ -1,21 +1,24 @@
|
||
|
include ../../common.mak
|
||
|
|
||
|
-all: chzcrypt lszcrypt
|
||
|
+all: chzcrypt lszcrypt zcryptctl
|
||
|
|
||
|
libs = $(rootdir)/libutil/libutil.a
|
||
|
|
||
|
chzcrypt: chzcrypt.o misc.o $(libs)
|
||
|
lszcrypt: lszcrypt.o misc.o $(libs)
|
||
|
+zcryptctl: zcryptctl.o misc.o $(libs)
|
||
|
|
||
|
install: all
|
||
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)
|
||
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 chzcrypt $(DESTDIR)$(BINDIR)
|
||
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 lszcrypt $(DESTDIR)$(BINDIR)
|
||
|
+ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 zcryptctl $(DESTDIR)$(BINDIR)
|
||
|
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man8
|
||
|
$(INSTALL) -m 644 -c chzcrypt.8 $(DESTDIR)$(MANDIR)/man8
|
||
|
$(INSTALL) -m 644 -c lszcrypt.8 $(DESTDIR)$(MANDIR)/man8
|
||
|
+ $(INSTALL) -m 644 -c zcryptctl.8 $(DESTDIR)$(MANDIR)/man8
|
||
|
|
||
|
clean:
|
||
|
- rm -f *.o chzcrypt lszcrypt
|
||
|
+ rm -f *.o chzcrypt lszcrypt zcryptctl
|
||
|
|
||
|
.PHONY: all install clean
|
||
|
--- /dev/null
|
||
|
+++ b/zconf/zcrypt/zcryptctl.8
|
||
|
@@ -0,0 +1,147 @@
|
||
|
+.\" zcryptctl.8
|
||
|
+.\"
|
||
|
+.\" Copyright 2018 IBM Corp.
|
||
|
+.\" s390-tools is free software; you can redistribute it and/or modify
|
||
|
+.\" it under the terms of the MIT license. See LICENSE for details.
|
||
|
+.\"
|
||
|
+.\" use
|
||
|
+.\" groff -man -Tutf8 zcryptctl.8
|
||
|
+.\" or
|
||
|
+.\" nroff -man zcryptctl.8
|
||
|
+.\" to process this source
|
||
|
+.\"
|
||
|
+.TH ZCRYPTCTL 8 "AUG 2018" "s390-tools"
|
||
|
+.SH NAME
|
||
|
+zcryptctl \- display information and administrate zcrypt multiple device nodes
|
||
|
+.SH SYNOPSIS
|
||
|
+.TP 8
|
||
|
+.B zcryptctl list
|
||
|
+.TP
|
||
|
+.B zcryptctl create
|
||
|
+.R [
|
||
|
+.I node-name
|
||
|
+.R ]
|
||
|
+.TP
|
||
|
+.B zcryptctl destroy
|
||
|
+.I node-name
|
||
|
+.TP
|
||
|
+.B zcryptctl addap
|
||
|
+.R |
|
||
|
+.B delap
|
||
|
+.I node-name adapter-nr
|
||
|
+.TP
|
||
|
+.B zcryptctl adddom
|
||
|
+.R |
|
||
|
+.B deldom
|
||
|
+.I node-name domain-nr
|
||
|
+.TP
|
||
|
+.B zcryptctl addioctl
|
||
|
+.R |
|
||
|
+.B delioctl
|
||
|
+.I node-name ioctl-term
|
||
|
+.TP
|
||
|
+.B zcryptctl config
|
||
|
+.I config-file
|
||
|
+.TP
|
||
|
+.B zcryptctl listconfig
|
||
|
+.SH DESCRIPTION
|
||
|
+The
|
||
|
+.B zcryptctl
|
||
|
+command displays information and maintains the multi device node
|
||
|
+extension for the zcrypt device driver.
|
||
|
+.P
|
||
|
+With the multi device node extension you can create and configure
|
||
|
+additional zcrypt device nodes which can be used as alternate device
|
||
|
+nodes to access the crypto hardware provided by the zcrypt device
|
||
|
+driver. Each zcrypt device node can be restricted in terms of crypto
|
||
|
+cards, domains, and available ioctls. Such a device node can be used
|
||
|
+as a base for container solutions like Docker to control and restrict
|
||
|
+the access to crypto resources.
|
||
|
+.SH COMMANDS
|
||
|
+.TP 8
|
||
|
+.B zcryptctl list
|
||
|
+Show all the additional device nodes that are currently active.
|
||
|
+.TP
|
||
|
+.B zcryptctl create
|
||
|
+.R [
|
||
|
+.I node-name
|
||
|
+.R ]
|
||
|
+Create a new zcrypt device node. The \fInode-name\fP might be given
|
||
|
+and needs to be unique and not in use. If there is no node name
|
||
|
+provided, the zcrypt device driver will create a new one with pattern
|
||
|
+zcrypt_\fIx\fP, with \fIx\fP being the next free number. Up to 256
|
||
|
+additional device nodes can be created. The newly created additional
|
||
|
+device node appears in /dev and has read and write permissions enabled
|
||
|
+only for root. By default all adapters, domains and ioctls are
|
||
|
+initially disabled on this new device node.
|
||
|
+.TP
|
||
|
+.B zcryptctl destroy
|
||
|
+.I node-name
|
||
|
+Destroy an additional zcrypt device node. The device node is only
|
||
|
+marked for disposal and destroyed when it is no longer used.
|
||
|
+.TP
|
||
|
+.B zcryptctl addap
|
||
|
+.R |
|
||
|
+.B delap
|
||
|
+.I node-name adapter-nr
|
||
|
+Update the filter for the specified zcrypt device node and add or
|
||
|
+delete a crypto adapter to be accessible via this node. The symbol
|
||
|
+\fBALL\fP can be used to enable or disable all adapters.
|
||
|
+.TP
|
||
|
+.B zcryptctl adddom
|
||
|
+.R |
|
||
|
+.B deldom
|
||
|
+.I node-name domain-nr
|
||
|
+Update the filter for the specified zcrypt device node and add or
|
||
|
+delete a domain to be accessible through this node. The symbol
|
||
|
+\fBALL\fP can be used to enable or disable all domains.
|
||
|
+.TP
|
||
|
+.B zcryptctl addioctl
|
||
|
+.R |
|
||
|
+.B delioctl
|
||
|
+.I node-name ioctl-term
|
||
|
+Update the filter for the specified zcrypt device node and add or
|
||
|
+delete an ioctl. The ioctl might be specified as symbolic string (one
|
||
|
+of \fBICARSAMODEXPO\fP, \fBICARSACRT\fP, \fBZSECSENDCPRB\fP,
|
||
|
+\fBZSENDEP11CPRB\fP, \fBZCRYPT_DEVICE_STATUS\fP,
|
||
|
+\fBZCRYPT_STATUS_MASK\fP, \fBZCRYPT_QDEPTH_MASK\fP,
|
||
|
+\fBZCRYPT_PERDEV_REQCNT\fP) or numeric value in the range 0-255 and
|
||
|
+the symbol \fBALL\fP can be used to include all ioctls.
|
||
|
+.TP
|
||
|
+.B zcryptctl config
|
||
|
+.I config-file
|
||
|
+Process a config file. The given configuration file is read line by
|
||
|
+line and the settings are applied. Syntax is simple:
|
||
|
+.RS
|
||
|
+.IP "node=<node-name>"
|
||
|
+.IP "aps=<list of ap numbers separated by space, tab or ','>"
|
||
|
+.IP "doms=<list of domain numbers separated by space, tab or ','>"
|
||
|
+.IP "ioctls=<list of ioctl as numeric or symbolic number separated by space, tab or ','>"
|
||
|
+.LP
|
||
|
+Empty lines are ignored and the '#' marks the rest of the
|
||
|
+line as comment.
|
||
|
+.LP
|
||
|
+The \fBnode=\fP line creates a new zcrypt device node, the \fBaps=\fP,
|
||
|
+\fBdoms=\fP and \fBioctls=\fP lines customize the previously created
|
||
|
+node. The symbol \fBALL\fP is also recognized for aps, doms, and
|
||
|
+ioctls.
|
||
|
+.LP
|
||
|
+Each action must fit into one line, spreading over multiple lines is
|
||
|
+not supported. But you can use more than one \fBaps=\fP, \fBdoms=\fP
|
||
|
+and \fBioctls=\fP lines to customize the very same node.
|
||
|
+.LP
|
||
|
+Processing stops when a line cannot be parsed or the current action
|
||
|
+fails. In this case the exit status is non zero but the successful
|
||
|
+actions until the failure occurs are not rolled back.
|
||
|
+.RE
|
||
|
+.TP
|
||
|
+.B zcryptctl listconfig
|
||
|
+List the current configuration in a form suitable for input to the
|
||
|
+\fBzcryptctl config\fP command.
|
||
|
+.LP
|
||
|
+.SH EXIT STATUS
|
||
|
+On successful completion of the command the exit status is 0. A non
|
||
|
+zero return code (and some kind of failure message) is emitted if the
|
||
|
+processing could not complete successful.
|
||
|
+.SH SEE ALSO
|
||
|
+\fBlszcrypt\fR(8)
|
||
|
--- /dev/null
|
||
|
+++ b/zconf/zcrypt/zcryptctl.c
|
||
|
@@ -0,0 +1,1030 @@
|
||
|
+/*
|
||
|
+ * zcryptctl - Maintain zcrypt multi device nodes.
|
||
|
+ *
|
||
|
+ * by Harald Freudenberger <freude@linux.ibm.com>
|
||
|
+ * Copyright IBM Corp. 2018
|
||
|
+ *
|
||
|
+ * s390-tools is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the MIT license. See LICENSE for details.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <ctype.h>
|
||
|
+#include <dirent.h>
|
||
|
+#include <err.h>
|
||
|
+#include <errno.h>
|
||
|
+#include <fcntl.h>
|
||
|
+#include <limits.h>
|
||
|
+#include <pthread.h>
|
||
|
+#include <stdarg.h>
|
||
|
+#include <stdint.h>
|
||
|
+#include <stdint.h>
|
||
|
+#include <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <string.h>
|
||
|
+#include <sys/ioctl.h>
|
||
|
+#include <sys/stat.h>
|
||
|
+#include <sys/sysmacros.h>
|
||
|
+#include <unistd.h>
|
||
|
+
|
||
|
+#include "lib/util_base.h"
|
||
|
+#include "lib/util_file.h"
|
||
|
+#include "lib/util_opt.h"
|
||
|
+#include "lib/util_panic.h"
|
||
|
+#include "lib/util_path.h"
|
||
|
+#include "lib/util_prg.h"
|
||
|
+#include "lib/util_proc.h"
|
||
|
+#include "lib/util_rec.h"
|
||
|
+#include "lib/util_scandir.h"
|
||
|
+#include "lib/zt_common.h"
|
||
|
+
|
||
|
+#define MAX_ZDEV_IOCTLS 256
|
||
|
+#define ZCRYPT_NAME "zcrypt"
|
||
|
+#define MAX_ZDEV_CARDIDS_EXT 256
|
||
|
+#define MAX_ZDEV_DOMAINS_EXT 256
|
||
|
+#define ZCRYPTDEVICE "/dev/z90crypt"
|
||
|
+#define _UNUSED_ __attribute__((unused))
|
||
|
+
|
||
|
+/*
|
||
|
+ * Currently known commands
|
||
|
+ */
|
||
|
+#define CMD_LIST 0x0001
|
||
|
+#define CMD_CREATE 0x0002
|
||
|
+#define CMD_DESTROY 0x0003
|
||
|
+#define CMD_ADD_AP 0x0004
|
||
|
+#define CMD_DEL_AP 0x0005
|
||
|
+#define CMD_ADD_DOM 0x0006
|
||
|
+#define CMD_DEL_DOM 0x0007
|
||
|
+#define CMD_ADD_IOCTL 0x0008
|
||
|
+#define CMD_DEL_IOCTL 0x0009
|
||
|
+#define CMD_CONFIG 0x000A
|
||
|
+#define CMD_LISTCONFIG 0x000B
|
||
|
+
|
||
|
+/*
|
||
|
+ * Program configuration
|
||
|
+ */
|
||
|
+static const struct util_prg prg = {
|
||
|
+ .args = "",
|
||
|
+ .command_args = "COMMAND [COMMAND-PARAMS]",
|
||
|
+ .desc = "Display and administrate zcrypt multiple device nodes.",
|
||
|
+ .copyright_vec = {
|
||
|
+ {
|
||
|
+ .owner = "IBM Corp.",
|
||
|
+ .pub_first = 2018,
|
||
|
+ .pub_last = 2018,
|
||
|
+ },
|
||
|
+ UTIL_PRG_COPYRIGHT_END
|
||
|
+ }
|
||
|
+};
|
||
|
+
|
||
|
+static struct util_opt opt_vec[] = {
|
||
|
+ UTIL_OPT_HELP,
|
||
|
+ UTIL_OPT_VERSION,
|
||
|
+ UTIL_OPT_END
|
||
|
+};
|
||
|
+
|
||
|
+/*
|
||
|
+ * List of currently known and supported ioctls
|
||
|
+ */
|
||
|
+static struct zcryptctl_ioctls_s {
|
||
|
+ int nr;
|
||
|
+ const char *name;
|
||
|
+} zcryptctl_ioctls[] = {
|
||
|
+ {
|
||
|
+ .name = "ICARSAMODEXPO",
|
||
|
+ .nr = 0x05,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ICARSACRT",
|
||
|
+ .nr = 0x06,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZSECSENDCPRB",
|
||
|
+ .nr = 0x81,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZSENDEP11CPRB",
|
||
|
+ .nr = 0x04,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZCRYPT_DEVICE_STATUS",
|
||
|
+ .nr = 0x5f,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZCRYPT_STATUS_MASK",
|
||
|
+ .nr = 0x58,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZCRYPT_QDEPTH_MASK",
|
||
|
+ .nr = 0x59,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = "ZCRYPT_PERDEV_REQCNT",
|
||
|
+ .nr = 0x5a,
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .name = NULL,
|
||
|
+ .nr = 0,
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+static int ioctlstr2value(const char *str)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; zcryptctl_ioctls[i].name; i++)
|
||
|
+ if (strcasecmp(str, zcryptctl_ioctls[i].name) == 0)
|
||
|
+ return zcryptctl_ioctls[i].nr;
|
||
|
+
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+static const char *value2ioctlstr(int value)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; zcryptctl_ioctls[i].name; i++)
|
||
|
+ if (value == zcryptctl_ioctls[i].nr)
|
||
|
+ return zcryptctl_ioctls[i].name;
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static int check_nodename(const char *nodename)
|
||
|
+{
|
||
|
+ struct stat sb;
|
||
|
+ const char *node;
|
||
|
+ char pathname[PATH_MAX];
|
||
|
+
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ snprintf(pathname, sizeof(pathname), "/dev/%s", node);
|
||
|
+ pathname[sizeof(pathname) - 1] = '\0';
|
||
|
+ if (stat(pathname, &sb) != 0)
|
||
|
+ return -1;
|
||
|
+ if (!S_ISCHR(sb.st_mode))
|
||
|
+ return -2;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int check_zcrypt_class_dir(void)
|
||
|
+{
|
||
|
+ int rc = 0;
|
||
|
+ char *afile;
|
||
|
+
|
||
|
+ afile = util_path_sysfs("class/%s", ZCRYPT_NAME);
|
||
|
+ if (!util_path_is_dir(afile))
|
||
|
+ rc = -1;
|
||
|
+
|
||
|
+ free(afile);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int fetch_major_minor(const char *nodename, int *major, int *minor)
|
||
|
+{
|
||
|
+ FILE *f;
|
||
|
+ int rc = 0;
|
||
|
+ char *afile;
|
||
|
+ const char *node;
|
||
|
+
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ afile = util_path_sysfs("class/%s/%s/dev", ZCRYPT_NAME, node);
|
||
|
+ f = fopen(afile, "r");
|
||
|
+ if (!f) {
|
||
|
+ rc = -1;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ if (fscanf(f, "%i:%i", major, minor) != 2) {
|
||
|
+ fclose(f);
|
||
|
+ rc = -2;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ fclose(f);
|
||
|
+
|
||
|
+out:
|
||
|
+ free(afile);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int write_dn_attr(const char *nodename, const char *attr,
|
||
|
+ const char *value)
|
||
|
+{
|
||
|
+ FILE *f;
|
||
|
+ int rc = 0;
|
||
|
+ char *afile;
|
||
|
+ const char *node;
|
||
|
+
|
||
|
+ if (nodename) {
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ afile = util_path_sysfs("class/%s/%s/%s",
|
||
|
+ ZCRYPT_NAME, node, attr);
|
||
|
+ } else
|
||
|
+ afile = util_path_sysfs("class/%s/%s", ZCRYPT_NAME, attr);
|
||
|
+ f = fopen(afile, "w");
|
||
|
+ if (!f) {
|
||
|
+ rc = -1;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ if (fprintf(f, "%s\n", value) < 0) {
|
||
|
+ fclose(f);
|
||
|
+ rc = -2;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ fflush(f);
|
||
|
+ if (ferror(f)) {
|
||
|
+ fclose(f);
|
||
|
+ rc = -2;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ fclose(f);
|
||
|
+
|
||
|
+out:
|
||
|
+ free(afile);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int read_dn_attr(const char *nodename, const char *attr,
|
||
|
+ char *value, int valuelen)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ FILE *f;
|
||
|
+ char *afile;
|
||
|
+ const char *node;
|
||
|
+
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ afile = util_path_sysfs("class/%s/%s/%s", ZCRYPT_NAME, node, attr);
|
||
|
+ f = fopen(afile, "r");
|
||
|
+ if (!f) {
|
||
|
+ rc = -1;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ value = fgets(value, valuelen, f);
|
||
|
+ fclose(f);
|
||
|
+ rc = value ? 0 : -2;
|
||
|
+
|
||
|
+out:
|
||
|
+ free(afile);
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+static int test_bit(int n, const char *hexbytestr)
|
||
|
+{
|
||
|
+ char c;
|
||
|
+ int v, i = 0;
|
||
|
+
|
||
|
+ if (strncmp(hexbytestr, "0x", 2) == 0)
|
||
|
+ i += 2;
|
||
|
+ c = hexbytestr[i + n / 4];
|
||
|
+ if (c >= '0' && c <= '9')
|
||
|
+ v = c - '0';
|
||
|
+ else if (c >= 'a' && c <= 'f')
|
||
|
+ v = 10 + c - 'a';
|
||
|
+ else if (c >= 'A' && c <= 'F')
|
||
|
+ v = 10 + c - 'A';
|
||
|
+ else
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not parse hex digit '%c'", c);
|
||
|
+
|
||
|
+ return v & (1 << (3 - (n % 4)));
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_list(int cmd,
|
||
|
+ const char *node _UNUSED_,
|
||
|
+ const char *arg _UNUSED_)
|
||
|
+{
|
||
|
+ DIR *dir;
|
||
|
+ char *dirname;
|
||
|
+ const char *p;
|
||
|
+ struct dirent *de;
|
||
|
+ int i, n, major, minor, count = 0;
|
||
|
+ char buf[80], tab = (cmd == CMD_LISTCONFIG ? ' ' : '\t');
|
||
|
+
|
||
|
+ dirname = util_path_sysfs("class/%s", ZCRYPT_NAME);
|
||
|
+ dir = opendir(dirname);
|
||
|
+ if (!dir)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not read directory '%s' errno=%d (%s)",
|
||
|
+ dirname, errno, strerror(errno));
|
||
|
+ while ((de = readdir(dir)) != NULL) {
|
||
|
+ if (de->d_name[0] == '.' || de->d_type == DT_REG)
|
||
|
+ continue;
|
||
|
+ if (fetch_major_minor(de->d_name, &major, &minor) != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not fetch major/minor from sysfs for zcrypt node '%s'",
|
||
|
+ de->d_name);
|
||
|
+ if (cmd == CMD_LISTCONFIG) {
|
||
|
+ printf("node = %s\n", de->d_name);
|
||
|
+ printf(" aps =");
|
||
|
+ } else {
|
||
|
+ printf("zcrypt node name:\t%s\n", de->d_name);
|
||
|
+ printf(" device node:\t/dev/%s\n", de->d_name);
|
||
|
+ printf(" major:minor:\t%d:%d\n", major, minor);
|
||
|
+ printf(" adapter:");
|
||
|
+ }
|
||
|
+ if (read_dn_attr(de->d_name, "apmask", buf, sizeof(buf)) != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not fetch apmask attribute from sysfs for zcrypt node '%s'",
|
||
|
+ de->d_name);
|
||
|
+ for (i = n = 0; i < MAX_ZDEV_CARDIDS_EXT; i++)
|
||
|
+ if (test_bit(i, buf))
|
||
|
+ printf("%c%d", n++ == 0 ? tab : ',', i);
|
||
|
+ putchar('\n');
|
||
|
+ if (cmd == CMD_LISTCONFIG)
|
||
|
+ printf(" doms =");
|
||
|
+ else
|
||
|
+ printf(" domains:");
|
||
|
+ if (read_dn_attr(de->d_name, "aqmask", buf, sizeof(buf)) != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not fetch aqmask attribute from sysfs for zcrypt node '%s'",
|
||
|
+ de->d_name);
|
||
|
+ for (i = n = 0; i < MAX_ZDEV_DOMAINS_EXT; i++)
|
||
|
+ if (test_bit(i, buf))
|
||
|
+ printf("%c%d", n++ == 0 ? tab : ',', i);
|
||
|
+ putchar('\n');
|
||
|
+ if (cmd == CMD_LISTCONFIG)
|
||
|
+ printf(" ioctls =");
|
||
|
+ else
|
||
|
+ printf(" ioctls:");
|
||
|
+ if (read_dn_attr(de->d_name, "ioctlmask",
|
||
|
+ buf, sizeof(buf)) != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not fetch ioctlmask attribute from sysfs for zcrypt node '%s'",
|
||
|
+ de->d_name);
|
||
|
+ for (i = n = 0; i < MAX_ZDEV_IOCTLS; i++) {
|
||
|
+ if (test_bit(i, buf)) {
|
||
|
+ p = value2ioctlstr(i);
|
||
|
+ if (p)
|
||
|
+ printf("%c%s",
|
||
|
+ n++ == 0 ? tab : ',', p);
|
||
|
+ else
|
||
|
+ printf("%c%d",
|
||
|
+ n++ == 0 ? tab : ',', i);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ putchar('\n');
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ closedir(dir);
|
||
|
+
|
||
|
+ if (count == 0)
|
||
|
+ printf("No additional zcrypt device nodes defined\n");
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_create(int cmd _UNUSED_,
|
||
|
+ const char *nodename,
|
||
|
+ const char *arg _UNUSED_)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ const char *node;
|
||
|
+ char buf[PATH_MAX];
|
||
|
+
|
||
|
+ if (nodename) {
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ strncpy(buf, node, sizeof(buf) - 1);
|
||
|
+ } else
|
||
|
+ strncpy(buf, "\n", sizeof(buf) - 1);
|
||
|
+ buf[sizeof(buf) - 1] = 0;
|
||
|
+
|
||
|
+ rc = write_dn_attr(NULL, "create", buf);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not write into sysfs entry to create zdev node");
|
||
|
+
|
||
|
+ printf("Device node created\n");
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_destroy(int cmd _UNUSED_,
|
||
|
+ const char *nodename,
|
||
|
+ const char *arg _UNUSED_)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ struct stat sb;
|
||
|
+ const char *node;
|
||
|
+ char pathname[PATH_MAX];
|
||
|
+
|
||
|
+ node = strrchr(nodename, '/');
|
||
|
+ node = node ? node + 1 : nodename;
|
||
|
+ snprintf(pathname, sizeof(pathname), "/dev/%s", node);
|
||
|
+ pathname[sizeof(pathname) - 1] = '\0';
|
||
|
+ rc = stat(pathname, &sb);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not check status for '%s'", pathname);
|
||
|
+ if (!S_ISCHR(sb.st_mode))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "File '%s' is not a character device node", pathname);
|
||
|
+
|
||
|
+ rc = write_dn_attr(NULL, "destroy", node);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not write into sysfs entry to destroy zdev node '%s'",
|
||
|
+ node);
|
||
|
+
|
||
|
+ printf("Device node '%s' marked for destruction\n", node);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void add_del_ap(int cmd, const char *node, int ap)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ char buf[PATH_MAX];
|
||
|
+
|
||
|
+ if (cmd == CMD_ADD_AP)
|
||
|
+ sprintf(buf, "+%d", ap);
|
||
|
+ else
|
||
|
+ sprintf(buf, "-%d", ap);
|
||
|
+ rc = write_dn_attr(node, "apmask", buf);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not write into sysfs entry to %s adapter %d for zdev node '%s'",
|
||
|
+ cmd == CMD_ADD_AP ? "add" : "remove", ap, node);
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_add_del_ap(int cmd, const char *node, const char *arg)
|
||
|
+{
|
||
|
+ int ap, all = 0;
|
||
|
+
|
||
|
+ if (strcasecmp(arg, "ALL") == 0) {
|
||
|
+ all = 1;
|
||
|
+ } else {
|
||
|
+ if (sscanf(arg, "%i", &ap) != 1)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Invalid adapter argument '%s'", arg);
|
||
|
+ if (ap < 0 || ap >= MAX_ZDEV_CARDIDS_EXT)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Adapter argument '%s' out of range [0..%d]",
|
||
|
+ arg, MAX_ZDEV_CARDIDS_EXT - 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!all) {
|
||
|
+ add_del_ap(cmd, node, ap);
|
||
|
+ printf("Adapter %d %s\n", ap,
|
||
|
+ (cmd == CMD_ADD_AP ? "added" : "removed"));
|
||
|
+ } else {
|
||
|
+ for (ap = 0; ap < MAX_ZDEV_CARDIDS_EXT; ap++)
|
||
|
+ add_del_ap(cmd, node, ap);
|
||
|
+ printf("All adapters %s\n",
|
||
|
+ (cmd == CMD_ADD_AP ? "added" : "removed"));
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void add_del_dom(int cmd, const char *node, int dom)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ char buf[PATH_MAX];
|
||
|
+
|
||
|
+ if (cmd == CMD_ADD_DOM)
|
||
|
+ sprintf(buf, "+%d", dom);
|
||
|
+ else
|
||
|
+ sprintf(buf, "-%d", dom);
|
||
|
+ rc = write_dn_attr(node, "aqmask", buf);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not write into sysfs entry to %s domain %d for zdev node '%s'",
|
||
|
+ cmd == CMD_ADD_DOM ? "add" : "remove", dom, node);
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_add_del_dom(int cmd, const char *node, const char *arg)
|
||
|
+{
|
||
|
+ int dom, all = 0;
|
||
|
+
|
||
|
+ if (strcasecmp(arg, "ALL") == 0) {
|
||
|
+ all = 1;
|
||
|
+ } else {
|
||
|
+ if (sscanf(arg, "%i", &dom) != 1)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Invalid domain argument '%s'", arg);
|
||
|
+ if (dom < 0 || dom >= MAX_ZDEV_DOMAINS_EXT)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Domain argument '%s' out of range [0..%d]",
|
||
|
+ arg, MAX_ZDEV_DOMAINS_EXT - 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!all) {
|
||
|
+ add_del_dom(cmd, node, dom);
|
||
|
+ printf("Domain %d %s\n", dom,
|
||
|
+ (cmd == CMD_ADD_DOM ? "added" : "removed"));
|
||
|
+ } else {
|
||
|
+ for (dom = 0; dom < MAX_ZDEV_DOMAINS_EXT; dom++)
|
||
|
+ add_del_dom(cmd, node, dom);
|
||
|
+ printf("All domains %s\n",
|
||
|
+ (cmd == CMD_ADD_DOM ? "added" : "removed"));
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void add_del_ioctl(int cmd, const char *node, int ioctlnr)
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ char buf[PATH_MAX];
|
||
|
+
|
||
|
+ if (cmd == CMD_ADD_IOCTL)
|
||
|
+ sprintf(buf, "+%d", ioctlnr);
|
||
|
+ else
|
||
|
+ sprintf(buf, "-%d", ioctlnr);
|
||
|
+ rc = write_dn_attr(node, "ioctlmask", buf);
|
||
|
+ if (rc != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not write into sysfs entry to %s ioctl %d for zdev node '%s'",
|
||
|
+ cmd == CMD_ADD_IOCTL ? "add" : "remove", ioctlnr, node);
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_add_del_ioctl(int cmd, const char *node, const char *arg)
|
||
|
+{
|
||
|
+ int ioctlnr, all = 0;
|
||
|
+
|
||
|
+ if (strcasecmp(arg, "ALL") == 0) {
|
||
|
+ all = 1;
|
||
|
+ } else {
|
||
|
+ ioctlnr = ioctlstr2value(arg);
|
||
|
+ if (ioctlnr < 0)
|
||
|
+ if (sscanf(arg, "%i", &ioctlnr) != 1)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Invalid ioctl argument '%s'", arg);
|
||
|
+ if (ioctlnr < 0 || ioctlnr >= MAX_ZDEV_IOCTLS)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Ioctl argument '%s' out of range [0..%d]",
|
||
|
+ arg, MAX_ZDEV_IOCTLS - 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!all) {
|
||
|
+ add_del_ioctl(cmd, node, ioctlnr);
|
||
|
+ printf("Ioctl %s %s\n", arg,
|
||
|
+ (cmd == CMD_ADD_IOCTL ? "added" : "removed"));
|
||
|
+ } else {
|
||
|
+ for (ioctlnr = 0; ioctlnr < MAX_ZDEV_IOCTLS; ioctlnr++)
|
||
|
+ add_del_ioctl(cmd, node, ioctlnr);
|
||
|
+ printf("All Ioctls %s\n",
|
||
|
+ (cmd == CMD_ADD_IOCTL ? "added" : "removed"));
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int _match_keyword(char **p, const char *keyword)
|
||
|
+{
|
||
|
+ int n = strlen(keyword);
|
||
|
+
|
||
|
+ if (strncmp(*p, keyword, n) == 0) {
|
||
|
+ *p += n;
|
||
|
+ return n;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int _match_character(char **p, char c)
|
||
|
+{
|
||
|
+ char *q = *p;
|
||
|
+
|
||
|
+ while (isblank(*q))
|
||
|
+ q++;
|
||
|
+ if (*q != c)
|
||
|
+ return 0;
|
||
|
+ q++;
|
||
|
+ while (isblank(*q))
|
||
|
+ q++;
|
||
|
+ *p = q;
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static int _match_string(char **p, char *buf)
|
||
|
+{
|
||
|
+ int n = 0;
|
||
|
+ char *q = *p;
|
||
|
+
|
||
|
+ while (isblank(*q))
|
||
|
+ q++;
|
||
|
+ while (*q && *q != ',' && !isspace(*q)) {
|
||
|
+ buf[n++] = *q;
|
||
|
+ q++;
|
||
|
+ }
|
||
|
+ while (isblank(*q))
|
||
|
+ q++;
|
||
|
+
|
||
|
+ if (n > 0) {
|
||
|
+ buf[n] = '\0';
|
||
|
+ *p = q;
|
||
|
+ }
|
||
|
+
|
||
|
+ return n;
|
||
|
+}
|
||
|
+
|
||
|
+static int cmd_config(int cmd _UNUSED_,
|
||
|
+ const char *nodename _UNUSED_,
|
||
|
+ const char *arg)
|
||
|
+{
|
||
|
+ ssize_t n;
|
||
|
+ size_t linesize = 0;
|
||
|
+ int nr = 0, havenode = 0;
|
||
|
+ FILE *f = fopen(arg, "r");
|
||
|
+ char *p, *line = NULL, node[128], buf[128];
|
||
|
+
|
||
|
+ if (!f)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Could not open file '%s'", arg);
|
||
|
+
|
||
|
+ while ((n = getline(&line, &linesize, f)) != -1) {
|
||
|
+ nr++;
|
||
|
+ p = line;
|
||
|
+ while (isspace(*p))
|
||
|
+ p++;
|
||
|
+ if (*p == '\0' || *p == '#')
|
||
|
+ continue;
|
||
|
+ if (_match_keyword(&p, "node")) {
|
||
|
+ if (!_match_character(&p, '='))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing '=' at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ if (!_match_string(&p, node))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing node name at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ cmd_create(CMD_CREATE, node, NULL);
|
||
|
+ havenode = 1;
|
||
|
+ } else if (_match_keyword(&p, "aps")) {
|
||
|
+ if (!havenode)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing node=... before processing any aps=... statements in line %d '%s'",
|
||
|
+ nr, line);
|
||
|
+ if (!_match_character(&p, '='))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing '=' at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ while (1) {
|
||
|
+ while (isspace(*p))
|
||
|
+ p++;
|
||
|
+ if (*p == '\0' || *p == '#')
|
||
|
+ break;
|
||
|
+ if (!_match_string(&p, buf))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing argument(s) for aps=... at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ cmd_add_del_ap(CMD_ADD_AP, node, buf);
|
||
|
+ while (isblank(*p) || *p == ',')
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+ } else if (_match_keyword(&p, "doms")) {
|
||
|
+ if (!havenode)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing node=... before processing any doms=... statements in line %d '%s'",
|
||
|
+ nr, line);
|
||
|
+ if (!_match_character(&p, '='))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing '=' at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ while (1) {
|
||
|
+ while (isspace(*p))
|
||
|
+ p++;
|
||
|
+ if (*p == '\0' || *p == '#')
|
||
|
+ break;
|
||
|
+ if (!_match_string(&p, buf))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing argument(s) for aps=... at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ cmd_add_del_dom(CMD_ADD_DOM, node, buf);
|
||
|
+ while (isblank(*p) || *p == ',')
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+ } else if (_match_keyword(&p, "ioctls")) {
|
||
|
+ if (!havenode)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing node=... before processing any ioctls=... statements in line %d '%s'",
|
||
|
+ nr, line);
|
||
|
+ if (!_match_character(&p, '='))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing '=' at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ while (1) {
|
||
|
+ while (isspace(*p))
|
||
|
+ p++;
|
||
|
+ if (*p == '\0' || *p == '#')
|
||
|
+ break;
|
||
|
+ if (!_match_string(&p, buf))
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Missing argument(s) for aps=... at '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ cmd_add_del_ioctl(CMD_ADD_IOCTL, node, buf);
|
||
|
+ while (isblank(*p) || *p == ',')
|
||
|
+ p++;
|
||
|
+ }
|
||
|
+ } else
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Unknown keyword '%-8.8s...' in line %d '%s'",
|
||
|
+ p, nr, line);
|
||
|
+ }
|
||
|
+
|
||
|
+ free(line);
|
||
|
+ fclose(f);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static struct zcryptctl_cmds_s {
|
||
|
+ int cmd;
|
||
|
+ const char *usage;
|
||
|
+ const char *command;
|
||
|
+ const char *description;
|
||
|
+ int (*function)(int cmd, const char *node, const char *arg);
|
||
|
+} zcryptctl_cmds[] = {
|
||
|
+ {
|
||
|
+ .cmd = CMD_LIST,
|
||
|
+ .command = "list",
|
||
|
+ .function = cmd_list,
|
||
|
+ .usage = "zcryptctl list",
|
||
|
+ .description =
|
||
|
+ "List all currently known additional zcrypt device nodes.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_CREATE,
|
||
|
+ .command = "create",
|
||
|
+ .function = cmd_create,
|
||
|
+ .usage = "zcryptctl create [nodename]",
|
||
|
+ .description =
|
||
|
+ "Create a new zcrypt device node.\n"
|
||
|
+ "The node-name might be given and needs to be unique and not\n"
|
||
|
+ "in use. If there is no node name provided, the zcrypt device\n"
|
||
|
+ "driver will create a new one with pattern zcrypt_<x>\n"
|
||
|
+ "with <x> being the next free number. By default all\n"
|
||
|
+ "adapters, domains and ioctls are initially disabled on this\n"
|
||
|
+ "new device node."
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_DESTROY,
|
||
|
+ .command = "destroy",
|
||
|
+ .function = cmd_destroy,
|
||
|
+ .usage = "zcryptctl destroy <nodename>",
|
||
|
+ .description =
|
||
|
+ "Destroy an additional zcrypt device node.\n"
|
||
|
+ "Mark the given zcrypt device node as disposable. The removal\n"
|
||
|
+ "will take place when it is no longer used.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_ADD_AP,
|
||
|
+ .command = "addap",
|
||
|
+ .function = cmd_add_del_ap,
|
||
|
+ .usage = "zcryptctl addap <adapter>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "add an crypto adapter to be accessible via this node. The\n"
|
||
|
+ "adapter argument may be a number in the range 0-255 or the\n"
|
||
|
+ "symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_DEL_AP,
|
||
|
+ .command = "delap",
|
||
|
+ .function = cmd_add_del_ap,
|
||
|
+ .usage = "zcryptctl delap <adapter>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "remove a crypto adapter from the allowed adapters list. The\n"
|
||
|
+ "adapter argument may be a number in the range 0-255 or the\n"
|
||
|
+ "symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_ADD_DOM,
|
||
|
+ .command = "adddom",
|
||
|
+ .function = cmd_add_del_dom,
|
||
|
+ .usage = "zcryptctl adddom <domain>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "add a crypto domain to be accessible via this node. The\n"
|
||
|
+ "domain argument may be a number in the range 0-255 or the\n"
|
||
|
+ "symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_DEL_DOM,
|
||
|
+ .command = "deldom",
|
||
|
+ .function = cmd_add_del_dom,
|
||
|
+ .usage = "zcryptctl deldom <adapter>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "remove a crypto domain from the allowed domains list. The\n"
|
||
|
+ "domain argument may be a number in the range 0-255 or the\n"
|
||
|
+ "symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_ADD_IOCTL,
|
||
|
+ .command = "addioctl",
|
||
|
+ .function = cmd_add_del_ioctl,
|
||
|
+ .usage = "zcryptctl addioctl <ioctlexp>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "add an ioctl number to be accessible via this node. The\n"
|
||
|
+ "ioctlexp argument may be one of symbols ICARSAMODEXPO,\n"
|
||
|
+ "ICARSACRT, ZSECSENDCPRB, ZSENDEP11CPRB, ZCRYPT_DEVICE_STATUS\n"
|
||
|
+ "ZCRYPT_STATUS_MASK, ZCRYPT_QDEPTH_MASK, ZCRYPT_PERDEV_REQCNT\n"
|
||
|
+ "or a number in the range 0-255 or the symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_DEL_IOCTL,
|
||
|
+ .command = "delioctl",
|
||
|
+ .function = cmd_add_del_ioctl,
|
||
|
+ .usage = "zcryptctl delioctl <ioctlexp>",
|
||
|
+ .description =
|
||
|
+ "Update the filter for the specified zcrypt device node and\n"
|
||
|
+ "remove an ioctl number from the allowed ioctls list. The\n"
|
||
|
+ "ioctlexp argument may be one of symbols ICARSAMODEXPO,\n"
|
||
|
+ "ICARSACRT, ZSECSENDCPRB, ZSENDEP11CPRB, ZCRYPT_DEVICE_STATUS\n"
|
||
|
+ "ZCRYPT_STATUS_MASK, ZCRYPT_QDEPTH_MASK, ZCRYPT_PERDEV_REQCNT\n"
|
||
|
+ "or a number in the range 0-255 or the symbol ALL.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_CONFIG,
|
||
|
+ .command = "config",
|
||
|
+ .function = cmd_config,
|
||
|
+ .usage = "zcryptctl config <configfile>",
|
||
|
+ .description =
|
||
|
+ "Process a config file. The given config file is read line by\n"
|
||
|
+ "line and the settings are applied. Syntax is simple:\n"
|
||
|
+ " node=<node_name>\n"
|
||
|
+ " aps=<list of ap numbers separated by space, tab or ','>\n"
|
||
|
+ " doms=<list of domains separated by space, tab or ','>\n"
|
||
|
+ " ioctls=<list of ioctl as number or symbolic number\n"
|
||
|
+ " separated by space, tab or ','>\n"
|
||
|
+ "Empty lines are ignored and the '#' marks the rest of the\n"
|
||
|
+ "line as comment.\n"
|
||
|
+ "The node= line creates a new zcrypt device node, the\n"
|
||
|
+ "aps=, doms= and ioctls= lines customize the previously\n"
|
||
|
+ "created node. The symbol ALL is also recognized for aps,\n"
|
||
|
+ "doms, and ioctls.\n"
|
||
|
+ "Each action must fit into one line, spreading over multiple\n"
|
||
|
+ "lines is not supported. But you can use more than one\n"
|
||
|
+ "aps=, doms= and ioctls= lines to customize the very same\n"
|
||
|
+ "node.\n"
|
||
|
+ "Processing stops when a line cannot be parsed or the\n"
|
||
|
+ "current action fails. When the config file has been\n"
|
||
|
+ "processed successful, the zcryptctl return code is 0. A non\n"
|
||
|
+ "zero return code (and some kind of failure message) is\n"
|
||
|
+ "emitted on partial completion.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .cmd = CMD_LISTCONFIG,
|
||
|
+ .command = "listconfig",
|
||
|
+ .function = cmd_list,
|
||
|
+ .usage = "zcryptctl listconfig",
|
||
|
+ .description =
|
||
|
+ "List all currently known additional zcrypt device nodes\n"
|
||
|
+ "in a format suitable for the 'config' command.",
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .command = NULL,
|
||
|
+ .cmd = 0,
|
||
|
+ }
|
||
|
+};
|
||
|
+
|
||
|
+static int get_command_index(const char *cmdstr)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; zcryptctl_cmds[i].command; i++)
|
||
|
+ if (!strcmp(zcryptctl_cmds[i].command, cmdstr))
|
||
|
+ return i;
|
||
|
+
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+static void commands_print_help(void)
|
||
|
+{
|
||
|
+ int i;
|
||
|
+
|
||
|
+ for (i = 0; zcryptctl_cmds[i].command; i++)
|
||
|
+ if (zcryptctl_cmds[i].usage)
|
||
|
+ printf(" %s\n", zcryptctl_cmds[i].usage);
|
||
|
+}
|
||
|
+
|
||
|
+int main(int argc, char *argv[])
|
||
|
+{
|
||
|
+ int c, cmdindex = -1;
|
||
|
+ int rc = EXIT_SUCCESS;
|
||
|
+
|
||
|
+ util_prg_init(&prg);
|
||
|
+ util_opt_init(opt_vec, NULL);
|
||
|
+
|
||
|
+ for (c = 1; c < argc; c++) {
|
||
|
+ cmdindex = get_command_index(argv[c]);
|
||
|
+ if (cmdindex >= 0)
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ while (1) {
|
||
|
+ c = util_opt_getopt_long(argc, argv);
|
||
|
+ if (c == -1)
|
||
|
+ break;
|
||
|
+ switch (c) {
|
||
|
+ case 'h':
|
||
|
+ if (cmdindex < 0) {
|
||
|
+ util_prg_print_help();
|
||
|
+ commands_print_help();
|
||
|
+ util_opt_print_help();
|
||
|
+ } else {
|
||
|
+ printf("Usage: %s\n",
|
||
|
+ zcryptctl_cmds[cmdindex].usage);
|
||
|
+ printf("%s\n",
|
||
|
+ zcryptctl_cmds[cmdindex].description);
|
||
|
+ }
|
||
|
+ return EXIT_SUCCESS;
|
||
|
+ case 'v':
|
||
|
+ util_prg_print_version();
|
||
|
+ return EXIT_SUCCESS;
|
||
|
+ default:
|
||
|
+ util_opt_print_parse_error(c, argv);
|
||
|
+ return EXIT_FAILURE;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (cmdindex < 0)
|
||
|
+ errx(EXIT_FAILURE, "Missing or invalid command argument");
|
||
|
+
|
||
|
+ if (check_zcrypt_class_dir() != 0)
|
||
|
+ errx(EXIT_FAILURE,
|
||
|
+ "Directory class/%s is missing in sysfs.\n"
|
||
|
+ "Multiple zcrypt node support is not available",
|
||
|
+ ZCRYPT_NAME);
|
||
|
+
|
||
|
+ c = zcryptctl_cmds[cmdindex].cmd;
|
||
|
+ switch (c) {
|
||
|
+ case CMD_LIST:
|
||
|
+ case CMD_LISTCONFIG:
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c, NULL, NULL);
|
||
|
+ break;
|
||
|
+ case CMD_CREATE:
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c,
|
||
|
+ optind + 1 < argc ?
|
||
|
+ argv[optind + 1] : NULL,
|
||
|
+ NULL);
|
||
|
+ break;
|
||
|
+ case CMD_DESTROY:
|
||
|
+ if (optind + 1 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing node name argument");
|
||
|
+ if (check_nodename(argv[optind + 1]) != 0)
|
||
|
+ errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'",
|
||
|
+ argv[optind + 1]);
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c,
|
||
|
+ argv[optind + 1], NULL);
|
||
|
+ break;
|
||
|
+ case CMD_ADD_AP:
|
||
|
+ case CMD_DEL_AP:
|
||
|
+ if (optind + 1 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing node name argument");
|
||
|
+ if (optind + 2 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing adapter argument");
|
||
|
+ if (check_nodename(argv[optind + 1]) != 0)
|
||
|
+ errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'",
|
||
|
+ argv[optind + 1]);
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c,
|
||
|
+ argv[optind + 1],
|
||
|
+ argv[optind + 2]);
|
||
|
+ break;
|
||
|
+ case CMD_ADD_DOM:
|
||
|
+ case CMD_DEL_DOM:
|
||
|
+ if (optind + 1 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing node name argument");
|
||
|
+ if (optind + 2 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing domain argument");
|
||
|
+ if (check_nodename(argv[optind + 1]) != 0)
|
||
|
+ errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'",
|
||
|
+ argv[optind + 1]);
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c,
|
||
|
+ argv[optind + 1],
|
||
|
+ argv[optind + 2]);
|
||
|
+ break;
|
||
|
+ case CMD_ADD_IOCTL:
|
||
|
+ case CMD_DEL_IOCTL:
|
||
|
+ if (optind + 1 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing node name argument");
|
||
|
+ if (optind + 2 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing ioctl argument");
|
||
|
+ if (check_nodename(argv[optind + 1]) != 0)
|
||
|
+ errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'",
|
||
|
+ argv[optind + 1]);
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c,
|
||
|
+ argv[optind + 1],
|
||
|
+ argv[optind + 2]);
|
||
|
+ break;
|
||
|
+ case CMD_CONFIG:
|
||
|
+ if (optind + 1 >= argc)
|
||
|
+ errx(EXIT_FAILURE, "Missing filename argument");
|
||
|
+ rc = zcryptctl_cmds[cmdindex].function(c, NULL,
|
||
|
+ argv[optind + 1]);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ errx(EXIT_FAILURE, "Unknown command %d", c);
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|