Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133484036
D19996.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
38 KB
Referenced Files
None
Subscribers
None
D19996.diff
View Options
Index: head/sbin/dumpon/dumpon.8
===================================================================
--- head/sbin/dumpon/dumpon.8
+++ head/sbin/dumpon/dumpon.8
@@ -28,7 +28,7 @@
.\" From: @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd November 17, 2018
+.Dd May 6, 2019
.Dt DUMPON 8
.Os
.Sh NAME
@@ -36,12 +36,16 @@
.Nd "specify a device for crash dumps"
.Sh SYNOPSIS
.Nm
+.Op Fl i Ar index
+.Op Fl r
.Op Fl v
.Op Fl k Ar pubkey
.Op Fl Z
.Op Fl z
.Ar device
.Nm
+.Op Fl i Ar index
+.Op Fl r
.Op Fl v
.Op Fl k Ar pubkey
.Op Fl Z
@@ -72,8 +76,38 @@
.Va dumpon_flags .
For more information on this usage, see
.Xr rc.conf 5 .
+.Pp
+Starting in
+.Fx 13.0 ,
+.Nm
+can configure a series of fallback dump devices.
+For example, an administrator may prefer
+.Xr netdump 4
+by default, but if the
+.Xr netdump 4
+service cannot be reached or some other failure occurs, they might choose a
+local disk dump as a second choice option.
.Ss General options
.Bl -tag -width _k_pubkey
+.It Fl i Ar index
+Insert the specified dump configuration into the prioritized fallback dump
+device list at the specified index, starting at zero.
+.Pp
+If
+.Fl i
+is not specified, the configured dump device is appended to the prioritized
+list.
+.It Fl r
+Remove the specified dump device configuration or configurations from the
+fallback dump device list rather than inserting or appending it.
+In contrast,
+.Do
+.Nm
+off
+.Dc
+removes all configured devices.
+Conflicts with
+.Fl i .
.It Fl k Ar pubkey
Configure encrypted kernel dumps.
.Pp
@@ -96,7 +130,7 @@
.Va pubkey
file should be a PEM-formatted RSA key of at least 1024 bits.
.It Fl l
-List the currently configured dump device, or /dev/null if no device is
+List the currently configured dump device(s), or /dev/null if no devices are
configured.
.It Fl v
Enable verbose mode.
Index: head/sbin/dumpon/dumpon.c
===================================================================
--- head/sbin/dumpon/dumpon.c
+++ head/sbin/dumpon/dumpon.c
@@ -86,8 +86,8 @@
usage(void)
{
fprintf(stderr,
- "usage: dumpon [-v] [-k <pubkey>] [-Zz] <device>\n"
- " dumpon [-v] [-k <pubkey>] [-Zz]\n"
+ "usage: dumpon [-i index] [-r] [-v] [-k <pubkey>] [-Zz] <device>\n"
+ " dumpon [-i index] [-r] [-v] [-k <pubkey>] [-Zz]\n"
" [-g <gateway>] -s <server> -c <client> <iface>\n"
" dumpon [-v] off\n"
" dumpon [-v] -l\n");
@@ -290,8 +290,10 @@
static void
listdumpdev(void)
{
+ static char ip[200];
+
char dumpdev[PATH_MAX];
- struct netdump_conf ndconf;
+ struct diocskerneldump_arg ndconf;
size_t len;
const char *sysctlname = "kern.shutdown.dumpdevname";
int fd;
@@ -308,10 +310,18 @@
if (strlen(dumpdev) == 0)
(void)strlcpy(dumpdev, _PATH_DEVNULL, sizeof(dumpdev));
- if (verbose)
- printf("kernel dumps on ");
- printf("%s\n", dumpdev);
+ if (verbose) {
+ char *ctx, *dd;
+ unsigned idx;
+ printf("kernel dumps on priority: device\n");
+ idx = 0;
+ ctx = dumpdev;
+ while ((dd = strsep(&ctx, ",")) != NULL)
+ printf("%u: %s\n", idx++, dd);
+ } else
+ printf("%s\n", dumpdev);
+
/* If netdump is enabled, print the configuration parameters. */
if (verbose) {
fd = open(_PATH_NETDUMP, O_RDONLY);
@@ -320,16 +330,22 @@
err(EX_OSERR, "opening %s", _PATH_NETDUMP);
return;
}
- if (ioctl(fd, NETDUMPGCONF, &ndconf) != 0) {
+ if (ioctl(fd, DIOCGKERNELDUMP, &ndconf) != 0) {
if (errno != ENXIO)
- err(EX_OSERR, "ioctl(NETDUMPGCONF)");
+ err(EX_OSERR, "ioctl(DIOCGKERNELDUMP)");
(void)close(fd);
return;
}
- printf("server address: %s\n", inet_ntoa(ndconf.ndc_server));
- printf("client address: %s\n", inet_ntoa(ndconf.ndc_client));
- printf("gateway address: %s\n", inet_ntoa(ndconf.ndc_gateway));
+ printf("server address: %s\n",
+ inet_ntop(ndconf.kda_af, &ndconf.kda_server, ip,
+ sizeof(ip)));
+ printf("client address: %s\n",
+ inet_ntop(ndconf.kda_af, &ndconf.kda_client, ip,
+ sizeof(ip)));
+ printf("gateway address: %s\n",
+ inet_ntop(ndconf.kda_af, &ndconf.kda_gateway, ip,
+ sizeof(ip)));
(void)close(fd);
}
}
@@ -359,19 +375,20 @@
main(int argc, char *argv[])
{
char dumpdev[PATH_MAX];
- struct diocskerneldump_arg _kda, *kdap;
- struct netdump_conf ndconf;
+ struct diocskerneldump_arg ndconf, *kdap;
struct addrinfo hints, *res;
const char *dev, *pubkeyfile, *server, *client, *gateway;
int ch, error, fd;
- bool enable, gzip, list, netdump, zstd;
+ bool gzip, list, netdump, zstd, insert, rflag;
+ uint8_t ins_idx;
- gzip = list = netdump = zstd = false;
+ gzip = list = netdump = zstd = insert = rflag = false;
kdap = NULL;
pubkeyfile = NULL;
server = client = gateway = NULL;
+ ins_idx = KDA_APPEND;
- while ((ch = getopt(argc, argv, "c:g:k:ls:vZz")) != -1)
+ while ((ch = getopt(argc, argv, "c:g:i:k:lrs:vZz")) != -1)
switch ((char)ch) {
case 'c':
client = optarg;
@@ -379,12 +396,28 @@
case 'g':
gateway = optarg;
break;
+ case 'i':
+ {
+ int i;
+
+ i = atoi(optarg);
+ if (i < 0 || i >= KDA_APPEND - 1)
+ errx(EX_USAGE,
+ "-i index must be between zero and %d.",
+ (int)KDA_APPEND - 2);
+ insert = true;
+ ins_idx = i;
+ }
+ break;
case 'k':
pubkeyfile = optarg;
break;
case 'l':
list = true;
break;
+ case 'r':
+ rflag = true;
+ break;
case 's':
server = optarg;
break;
@@ -404,6 +437,9 @@
if (gzip && zstd)
errx(EX_USAGE, "The -z and -Z options are mutually exclusive.");
+ if (insert && rflag)
+ errx(EX_USAGE, "The -i and -r options are mutually exclusive.");
+
argc -= optind;
argv += optind;
@@ -422,31 +458,30 @@
#endif
if (server != NULL && client != NULL) {
- enable = true;
dev = _PATH_NETDUMP;
netdump = true;
- kdap = &ndconf.ndc_kda;
} else if (server == NULL && client == NULL && argc > 0) {
- enable = strcmp(argv[0], "off") != 0;
- dev = enable ? argv[0] : _PATH_DEVNULL;
+ if (strcmp(argv[0], "off") == 0) {
+ rflag = true;
+ dev = _PATH_DEVNULL;
+ } else
+ dev = argv[0];
netdump = false;
- kdap = &_kda;
} else
usage();
fd = opendumpdev(dev, dumpdev);
- if (!netdump && !gzip)
+ if (!netdump && !gzip && !rflag)
check_size(fd, dumpdev);
+ kdap = &ndconf;
bzero(kdap, sizeof(*kdap));
- kdap->kda_enable = 0;
- if (ioctl(fd, DIOCSKERNELDUMP, kdap) != 0)
- err(EX_OSERR, "ioctl(DIOCSKERNELDUMP)");
- if (!enable)
- exit(EX_OK);
- explicit_bzero(kdap, sizeof(*kdap));
- kdap->kda_enable = 1;
+ if (rflag)
+ kdap->kda_index = KDA_REMOVE;
+ else
+ kdap->kda_index = ins_idx;
+
kdap->kda_compression = KERNELDUMP_COMP_NONE;
if (zstd)
kdap->kda_compression = KERNELDUMP_COMP_ZSTD;
@@ -467,12 +502,12 @@
((struct sockaddr_in *)(void *)res->ai_addr)->sin_addr);
freeaddrinfo(res);
- if (strlcpy(ndconf.ndc_iface, argv[0],
- sizeof(ndconf.ndc_iface)) >= sizeof(ndconf.ndc_iface))
+ if (strlcpy(ndconf.kda_iface, argv[0],
+ sizeof(ndconf.kda_iface)) >= sizeof(ndconf.kda_iface))
errx(EX_USAGE, "invalid interface name '%s'", argv[0]);
- if (inet_aton(server, &ndconf.ndc_server) == 0)
+ if (inet_aton(server, &ndconf.kda_server.in4) == 0)
errx(EX_USAGE, "invalid server address '%s'", server);
- if (inet_aton(client, &ndconf.ndc_client) == 0)
+ if (inet_aton(client, &ndconf.kda_client.in4) == 0)
errx(EX_USAGE, "invalid client address '%s'", client);
if (gateway == NULL) {
@@ -485,39 +520,41 @@
gateway = server;
}
}
- if (inet_aton(gateway, &ndconf.ndc_gateway) == 0)
+ if (inet_aton(gateway, &ndconf.kda_gateway.in4) == 0)
errx(EX_USAGE, "invalid gateway address '%s'", gateway);
+ ndconf.kda_af = AF_INET;
+ }
#ifdef HAVE_CRYPTO
- if (pubkeyfile != NULL)
- genkey(pubkeyfile, kdap);
+ if (pubkeyfile != NULL)
+ genkey(pubkeyfile, kdap);
#endif
- error = ioctl(fd, NETDUMPSCONF, &ndconf);
- if (error != 0)
- error = errno;
- explicit_bzero(kdap->kda_encryptedkey,
- kdap->kda_encryptedkeysize);
- free(kdap->kda_encryptedkey);
- explicit_bzero(kdap, sizeof(*kdap));
- if (error != 0)
- errc(EX_OSERR, error, "ioctl(NETDUMPSCONF)");
- } else {
-#ifdef HAVE_CRYPTO
- if (pubkeyfile != NULL)
- genkey(pubkeyfile, kdap);
-#endif
- error = ioctl(fd, DIOCSKERNELDUMP, kdap);
- if (error != 0)
- error = errno;
- explicit_bzero(kdap->kda_encryptedkey,
- kdap->kda_encryptedkeysize);
- free(kdap->kda_encryptedkey);
- explicit_bzero(kdap, sizeof(*kdap));
- if (error != 0)
- errc(EX_OSERR, error, "ioctl(DIOCSKERNELDUMP)");
+ error = ioctl(fd, DIOCSKERNELDUMP, kdap);
+ if (error != 0)
+ error = errno;
+ explicit_bzero(kdap->kda_encryptedkey, kdap->kda_encryptedkeysize);
+ free(kdap->kda_encryptedkey);
+ explicit_bzero(kdap, sizeof(*kdap));
+ if (error != 0) {
+ if (netdump) {
+ /*
+ * Be slightly less user-hostile for some common
+ * errors, especially as users don't have any great
+ * discoverability into which NICs support netdump.
+ */
+ if (error == ENXIO)
+ errx(EX_OSERR, "Unable to configure netdump "
+ "because the interface's link is down.");
+ else if (error == ENODEV)
+ errx(EX_OSERR, "Unable to configure netdump "
+ "because the interface driver does not yet "
+ "support netdump.");
+ }
+ errc(EX_OSERR, error, "ioctl(DIOCSKERNELDUMP)");
}
+
if (verbose)
- printf("kernel dumps on %s\n", dumpdev);
+ listdumpdev();
exit(EX_OK);
}
Index: head/sys/dev/null/null.c
===================================================================
--- head/sys/dev/null/null.c
+++ head/sys/dev/null/null.c
@@ -106,15 +106,26 @@
null_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused,
int flags __unused, struct thread *td)
{
+ struct diocskerneldump_arg kda;
int error;
error = 0;
switch (cmd) {
#ifdef COMPAT_FREEBSD11
case DIOCSKERNELDUMP_FREEBSD11:
+ gone_in(13, "FreeBSD 11.x ABI compat");
+ /* FALLTHROUGH */
#endif
+#ifdef COMPAT_FREEBSD12
+ case DIOCSKERNELDUMP_FREEBSD12:
+ if (cmd == DIOCSKERNELDUMP_FREEBSD12)
+ gone_in(14, "FreeBSD 12.x ABI compat");
+ /* FALLTHROUGH */
+#endif
case DIOCSKERNELDUMP:
- error = clear_dumper(td);
+ bzero(&kda, sizeof(kda));
+ kda.kda_index = KDA_REMOVE_ALL;
+ error = dumper_remove(NULL, &kda);
break;
case FIONBIO:
break;
Index: head/sys/geom/geom_dev.c
===================================================================
--- head/sys/geom/geom_dev.c
+++ head/sys/geom/geom_dev.c
@@ -135,15 +135,14 @@
}
static int
-g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda,
- struct thread *td)
+g_dev_setdumpdev(struct cdev *dev, struct diocskerneldump_arg *kda)
{
struct g_kerneldump kd;
struct g_consumer *cp;
int error, len;
- if (dev == NULL || kda == NULL)
- return (clear_dumper(td));
+ MPASS(dev != NULL && kda != NULL);
+ MPASS(kda->kda_index != KDA_REMOVE);
cp = dev->si_drv2;
len = sizeof(kd);
@@ -154,9 +153,7 @@
if (error != 0)
return (error);
- error = set_dumper(&kd.di, devtoname(dev), td, kda->kda_compression,
- kda->kda_encryption, kda->kda_key, kda->kda_encryptedkeysize,
- kda->kda_encryptedkey);
+ error = dumper_insert(&kd.di, devtoname(dev), kda);
if (error == 0)
dev->si_flags |= SI_DUMPDEV;
@@ -173,7 +170,7 @@
size_t len;
bzero(&kda, sizeof(kda));
- kda.kda_enable = 1;
+ kda.kda_index = KDA_APPEND;
if (dumpdev == NULL)
return (0);
@@ -190,7 +187,7 @@
if (error != 0)
return (error);
- error = g_dev_setdumpdev(dev, &kda, curthread);
+ error = g_dev_setdumpdev(dev, &kda);
if (error == 0) {
freeenv(dumpdev);
dumpdev = NULL;
@@ -509,6 +506,9 @@
struct g_provider *pp;
off_t offset, length, chunk, odd;
int i, error;
+#ifdef COMPAT_FREEBSD12
+ struct diocskerneldump_arg kda_copy;
+#endif
cp = dev->si_drv2;
pp = cp->provider;
@@ -547,31 +547,55 @@
{
struct diocskerneldump_arg kda;
+ gone_in(13, "FreeBSD 11.x ABI compat");
+
bzero(&kda, sizeof(kda));
kda.kda_encryption = KERNELDUMP_ENC_NONE;
- kda.kda_enable = (uint8_t)*(u_int *)data;
- if (kda.kda_enable == 0)
- error = g_dev_setdumpdev(NULL, NULL, td);
+ kda.kda_index = (*(u_int *)data ? 0 : KDA_REMOVE_ALL);
+ if (kda.kda_index == KDA_REMOVE_ALL)
+ error = dumper_remove(devtoname(dev), &kda);
else
- error = g_dev_setdumpdev(dev, &kda, td);
+ error = g_dev_setdumpdev(dev, &kda);
break;
}
#endif
+#ifdef COMPAT_FREEBSD12
+ case DIOCSKERNELDUMP_FREEBSD12:
+ {
+ struct diocskerneldump_arg_freebsd12 *kda12;
+
+ gone_in(14, "FreeBSD 12.x ABI compat");
+
+ kda12 = (void *)data;
+ memcpy(&kda_copy, kda12, sizeof(kda_copy));
+ kda_copy.kda_index = (kda12->kda12_enable ?
+ 0 : KDA_REMOVE_ALL);
+
+ explicit_bzero(kda12, sizeof(*kda12));
+ /* Kludge to pass kda_copy to kda in fallthrough. */
+ data = (void *)&kda_copy;
+ }
+ /* FALLTHROUGH */
+#endif
case DIOCSKERNELDUMP:
{
struct diocskerneldump_arg *kda;
uint8_t *encryptedkey;
kda = (struct diocskerneldump_arg *)data;
- if (kda->kda_enable == 0) {
- error = g_dev_setdumpdev(NULL, NULL, td);
+ if (kda->kda_index == KDA_REMOVE_ALL ||
+ kda->kda_index == KDA_REMOVE_DEV ||
+ kda->kda_index == KDA_REMOVE) {
+ error = dumper_remove(devtoname(dev), kda);
+ explicit_bzero(kda, sizeof(*kda));
break;
}
if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
- if (kda->kda_encryptedkeysize <= 0 ||
+ if (kda->kda_encryptedkeysize == 0 ||
kda->kda_encryptedkeysize >
KERNELDUMP_ENCKEY_MAX_SIZE) {
+ explicit_bzero(kda, sizeof(*kda));
return (EINVAL);
}
encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP,
@@ -583,7 +607,7 @@
}
if (error == 0) {
kda->kda_encryptedkey = encryptedkey;
- error = g_dev_setdumpdev(dev, kda, td);
+ error = g_dev_setdumpdev(dev, kda);
}
if (encryptedkey != NULL) {
explicit_bzero(encryptedkey, kda->kda_encryptedkeysize);
@@ -859,8 +883,13 @@
g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, cp->geom->name);
/* Reset any dump-area set on this device */
- if (dev->si_flags & SI_DUMPDEV)
- (void)clear_dumper(curthread);
+ if (dev->si_flags & SI_DUMPDEV) {
+ struct diocskerneldump_arg kda;
+
+ bzero(&kda, sizeof(kda));
+ kda.kda_index = KDA_REMOVE_DEV;
+ (void)dumper_remove(devtoname(dev), &kda);
+ }
/* Destroy the struct cdev *so we get no more requests */
delist_dev(dev);
Index: head/sys/geom/raid/g_raid.h
===================================================================
--- head/sys/geom/raid/g_raid.h
+++ head/sys/geom/raid/g_raid.h
@@ -155,7 +155,6 @@
struct g_raid_softc *d_softc; /* Back-pointer to softc. */
struct g_consumer *d_consumer; /* GEOM disk consumer. */
void *d_md_data; /* Disk's metadata storage. */
- struct g_kerneldump d_kd; /* Kernel dumping method/args. */
int d_candelete; /* BIO_DELETE supported. */
uint64_t d_flags; /* Additional flags. */
u_int d_state; /* Disk state. */
@@ -164,6 +163,7 @@
int d_read_errs; /* Count of the read errors */
TAILQ_HEAD(, g_raid_subdisk) d_subdisks; /* List of subdisks. */
TAILQ_ENTRY(g_raid_disk) d_next; /* Next disk in the node. */
+ struct g_kerneldump d_kd; /* Kernel dumping method/args. */
};
#define G_RAID_SUBDISK_S_NONE 0x00 /* Absent. */
Index: head/sys/kern/kern_shutdown.c
===================================================================
--- head/sys/kern/kern_shutdown.c
+++ head/sys/kern/kern_shutdown.c
@@ -43,6 +43,7 @@
#include "opt_ekcd.h"
#include "opt_kdb.h"
#include "opt_panic.h"
+#include "opt_printf.h"
#include "opt_sched.h"
#include "opt_watchdog.h"
@@ -53,6 +54,7 @@
#include <sys/conf.h>
#include <sys/compressor.h>
#include <sys/cons.h>
+#include <sys/disk.h>
#include <sys/eventhandler.h>
#include <sys/filedesc.h>
#include <sys/jail.h>
@@ -69,6 +71,7 @@
#include <sys/reboot.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
+#include <sys/sbuf.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -209,8 +212,17 @@
int dumping; /* system is dumping */
int rebooting; /* system is rebooting */
-static struct dumperinfo dumper; /* our selected dumper */
+/*
+ * Used to serialize between sysctl kern.shutdown.dumpdevname and list
+ * modifications via ioctl.
+ */
+static struct mtx dumpconf_list_lk;
+MTX_SYSINIT(dumper_configs, &dumpconf_list_lk, "dumper config list", MTX_DEF);
+/* Our selected dumper(s). */
+static TAILQ_HEAD(dumpconflist, dumperinfo) dumper_configs =
+ TAILQ_HEAD_INITIALIZER(dumper_configs);
+
/* Context information for dump-debuggers. */
static struct pcb dumppcb; /* Registers. */
lwpid_t dumptid; /* Thread ID. */
@@ -364,7 +376,7 @@
error = 0;
if (dumping)
return (EBUSY);
- if (dumper.dumper == NULL)
+ if (TAILQ_EMPTY(&dumper_configs))
return (ENXIO);
savectx(&dumppcb);
@@ -375,12 +387,19 @@
#ifdef DDB
if (textdump && textdump_pending) {
coredump = FALSE;
- textdump_dumpsys(&dumper);
+ textdump_dumpsys(TAILQ_FIRST(&dumper_configs));
}
#endif
- if (coredump)
- error = dumpsys(&dumper);
+ if (coredump) {
+ struct dumperinfo *di;
+ TAILQ_FOREACH(di, &dumper_configs, di_next) {
+ error = dumpsys(di);
+ if (error == 0)
+ break;
+ }
+ }
+
dumping--;
return (error);
}
@@ -952,10 +971,36 @@
printf("done\n");
}
-static char dumpdevname[sizeof(((struct cdev*)NULL)->si_name)];
-SYSCTL_STRING(_kern_shutdown, OID_AUTO, dumpdevname, CTLFLAG_RD,
- dumpdevname, 0, "Device for kernel dumps");
+static int
+dumpdevname_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ char buf[256];
+ struct dumperinfo *di;
+ struct sbuf sb;
+ int error;
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0)
+ return (error);
+
+ sbuf_new_for_sysctl(&sb, buf, sizeof(buf), req);
+
+ mtx_lock(&dumpconf_list_lk);
+ TAILQ_FOREACH(di, &dumper_configs, di_next) {
+ if (di != TAILQ_FIRST(&dumper_configs))
+ sbuf_putc(&sb, ',');
+ sbuf_cat(&sb, di->di_devname);
+ }
+ mtx_unlock(&dumpconf_list_lk);
+
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+SYSCTL_PROC(_kern_shutdown, OID_AUTO, dumpdevname, CTLTYPE_STRING | CTLFLAG_RD,
+ &dumper_configs, 0, dumpdevname_sysctl_handler, "A",
+ "Device(s) for kernel dumps");
+
static int _dump_append(struct dumperinfo *di, void *virtual,
vm_offset_t physical, size_t length);
@@ -1092,31 +1137,67 @@
free(kdcomp, M_DUMPER);
}
+/*
+ * Must not be present on global list.
+ */
+static void
+free_single_dumper(struct dumperinfo *di)
+{
+
+ if (di == NULL)
+ return;
+
+ if (di->blockbuf != NULL) {
+ explicit_bzero(di->blockbuf, di->blocksize);
+ free(di->blockbuf, M_DUMPER);
+ }
+
+ kerneldumpcomp_destroy(di);
+
+#ifdef EKCD
+ if (di->kdcrypto != NULL) {
+ explicit_bzero(di->kdcrypto, sizeof(*di->kdcrypto) +
+ di->kdcrypto->kdc_dumpkeysize);
+ free(di->kdcrypto, M_EKCD);
+ }
+#endif
+
+ explicit_bzero(di, sizeof(*di));
+ free(di, M_DUMPER);
+}
+
/* Registration of dumpers */
int
-set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
- uint8_t compression, uint8_t encryption, const uint8_t *key,
- uint32_t encryptedkeysize, const uint8_t *encryptedkey)
+dumper_insert(const struct dumperinfo *di_template, const char *devname,
+ const struct diocskerneldump_arg *kda)
{
- size_t wantcopy;
+ struct dumperinfo *newdi, *listdi;
+ bool inserted;
+ uint8_t index;
int error;
- error = priv_check(td, PRIV_SETDUMPER);
+ index = kda->kda_index;
+ MPASS(index != KDA_REMOVE && index != KDA_REMOVE_DEV &&
+ index != KDA_REMOVE_ALL);
+
+ error = priv_check(curthread, PRIV_SETDUMPER);
if (error != 0)
return (error);
- if (dumper.dumper != NULL)
- return (EBUSY);
- dumper = *di;
- dumper.blockbuf = NULL;
- dumper.kdcrypto = NULL;
- dumper.kdcomp = NULL;
+ newdi = malloc(sizeof(*newdi) + strlen(devname) + 1, M_DUMPER, M_WAITOK
+ | M_ZERO);
+ memcpy(newdi, di_template, sizeof(*newdi));
+ newdi->blockbuf = NULL;
+ newdi->kdcrypto = NULL;
+ newdi->kdcomp = NULL;
+ strcpy(newdi->di_devname, devname);
- if (encryption != KERNELDUMP_ENC_NONE) {
+ if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
#ifdef EKCD
- dumper.kdcrypto = kerneldumpcrypto_create(di->blocksize,
- encryption, key, encryptedkeysize, encryptedkey);
- if (dumper.kdcrypto == NULL) {
+ newdi->kdcrypto = kerneldumpcrypto_create(di_template->blocksize,
+ kda->kda_encryption, kda->kda_key,
+ kda->kda_encryptedkeysize, kda->kda_encryptedkey);
+ if (newdi->kdcrypto == NULL) {
error = EINVAL;
goto cleanup;
}
@@ -1125,66 +1206,117 @@
goto cleanup;
#endif
}
-
- wantcopy = strlcpy(dumpdevname, devname, sizeof(dumpdevname));
- if (wantcopy >= sizeof(dumpdevname)) {
- printf("set_dumper: device name truncated from '%s' -> '%s'\n",
- devname, dumpdevname);
- }
-
- if (compression != KERNELDUMP_COMP_NONE) {
+ if (kda->kda_compression != KERNELDUMP_COMP_NONE) {
/*
* We currently can't support simultaneous encryption and
- * compression.
+ * compression because our only encryption mode is an unpadded
+ * block cipher, go figure. This is low hanging fruit to fix.
*/
- if (encryption != KERNELDUMP_ENC_NONE) {
+ if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
error = EOPNOTSUPP;
goto cleanup;
}
- dumper.kdcomp = kerneldumpcomp_create(&dumper, compression);
- if (dumper.kdcomp == NULL) {
+ newdi->kdcomp = kerneldumpcomp_create(newdi,
+ kda->kda_compression);
+ if (newdi->kdcomp == NULL) {
error = EINVAL;
goto cleanup;
}
}
- dumper.blockbuf = malloc(di->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
+ newdi->blockbuf = malloc(newdi->blocksize, M_DUMPER, M_WAITOK | M_ZERO);
+
+ /* Add the new configuration to the queue */
+ mtx_lock(&dumpconf_list_lk);
+ inserted = false;
+ TAILQ_FOREACH(listdi, &dumper_configs, di_next) {
+ if (index == 0) {
+ TAILQ_INSERT_BEFORE(listdi, newdi, di_next);
+ inserted = true;
+ break;
+ }
+ index--;
+ }
+ if (!inserted)
+ TAILQ_INSERT_TAIL(&dumper_configs, newdi, di_next);
+ mtx_unlock(&dumpconf_list_lk);
+
return (0);
cleanup:
- (void)clear_dumper(td);
+ free_single_dumper(newdi);
return (error);
}
-int
-clear_dumper(struct thread *td)
+static bool
+dumper_config_match(const struct dumperinfo *di, const char *devname,
+ const struct diocskerneldump_arg *kda)
{
- int error;
+ if (kda->kda_index == KDA_REMOVE_ALL)
+ return (true);
- error = priv_check(td, PRIV_SETDUMPER);
- if (error != 0)
- return (error);
+ if (strcmp(di->di_devname, devname) != 0)
+ return (false);
-#ifdef NETDUMP
- netdump_mbuf_drain();
-#endif
+ /*
+ * Allow wildcard removal of configs matching a device on g_dev_orphan.
+ */
+ if (kda->kda_index == KDA_REMOVE_DEV)
+ return (true);
+ if (di->kdcomp != NULL) {
+ if (di->kdcomp->kdc_format != kda->kda_compression)
+ return (false);
+ } else if (kda->kda_compression != KERNELDUMP_COMP_NONE)
+ return (false);
#ifdef EKCD
- if (dumper.kdcrypto != NULL) {
- explicit_bzero(dumper.kdcrypto, sizeof(*dumper.kdcrypto) +
- dumper.kdcrypto->kdc_dumpkeysize);
- free(dumper.kdcrypto, M_EKCD);
- }
+ if (di->kdcrypto != NULL) {
+ if (di->kdcrypto->kdc_encryption != kda->kda_encryption)
+ return (false);
+ /*
+ * Do we care to verify keys match to delete? It seems weird
+ * to expect multiple fallback dump configurations on the same
+ * device that only differ in crypto key.
+ */
+ } else
#endif
+ if (kda->kda_encryption != KERNELDUMP_ENC_NONE)
+ return (false);
- kerneldumpcomp_destroy(&dumper);
+ return (true);
+}
- if (dumper.blockbuf != NULL) {
- explicit_bzero(dumper.blockbuf, dumper.blocksize);
- free(dumper.blockbuf, M_DUMPER);
+int
+dumper_remove(const char *devname, const struct diocskerneldump_arg *kda)
+{
+ struct dumperinfo *di, *sdi;
+ bool found;
+ int error;
+
+ error = priv_check(curthread, PRIV_SETDUMPER);
+ if (error != 0)
+ return (error);
+
+ /*
+ * Try to find a matching configuration, and kill it.
+ *
+ * NULL 'kda' indicates remove any configuration matching 'devname',
+ * which may remove multiple configurations in atypical configurations.
+ */
+ found = false;
+ mtx_lock(&dumpconf_list_lk);
+ TAILQ_FOREACH_SAFE(di, &dumper_configs, di_next, sdi) {
+ if (dumper_config_match(di, devname, kda)) {
+ found = true;
+ TAILQ_REMOVE(&dumper_configs, di, di_next);
+ free_single_dumper(di);
+ }
}
- explicit_bzero(&dumper, sizeof(dumper));
- dumpdevname[0] = '\0';
+ mtx_unlock(&dumpconf_list_lk);
+
+ /* Only produce ENOENT if a more targeted match didn't match. */
+ if (!found && kda->kda_index == KDA_REMOVE)
+ return (ENOENT);
return (0);
}
Index: head/sys/netinet/netdump/netdump.h
===================================================================
--- head/sys/netinet/netdump/netdump.h
+++ head/sys/netinet/netdump/netdump.h
@@ -60,18 +60,18 @@
uint32_t na_seqno; /* Match acks with msgs. */
} __packed;
-struct netdump_conf {
- struct diocskerneldump_arg ndc_kda;
- char ndc_iface[IFNAMSIZ];
- struct in_addr ndc_server;
- struct in_addr ndc_client;
- struct in_addr ndc_gateway;
+struct netdump_conf_freebsd12 {
+ struct diocskerneldump_arg_freebsd12 ndc12_kda;
+ char ndc12_iface[IFNAMSIZ];
+ struct in_addr ndc12_server;
+ struct in_addr ndc12_client;
+ struct in_addr ndc12_gateway;
};
-#define _PATH_NETDUMP "/dev/netdump"
+#define NETDUMPGCONF_FREEBSD12 _IOR('n', 1, struct netdump_conf_freebsd12)
+#define NETDUMPSCONF_FREEBSD12 _IOW('n', 2, struct netdump_conf_freebsd12)
-#define NETDUMPGCONF _IOR('n', 1, struct netdump_conf)
-#define NETDUMPSCONF _IOW('n', 2, struct netdump_conf)
+#define _PATH_NETDUMP "/dev/netdump"
#ifdef _KERNEL
#ifdef NETDUMP
Index: head/sys/netinet/netdump/netdump_client.c
===================================================================
--- head/sys/netinet/netdump/netdump_client.c
+++ head/sys/netinet/netdump/netdump_client.c
@@ -89,7 +89,8 @@
static int netdump_arp_gw(void);
static void netdump_cleanup(void);
-static int netdump_configure(struct netdump_conf *, struct thread *);
+static int netdump_configure(struct diocskerneldump_arg *,
+ struct thread *);
static int netdump_dumper(void *priv __unused, void *virtual,
vm_offset_t physical __unused, off_t offset, size_t length);
static int netdump_ether_output(struct mbuf *m, struct ifnet *ifp,
@@ -118,10 +119,10 @@
CTASSERT(sizeof(rcvd_acks) * NBBY == NETDUMP_MAX_IN_FLIGHT);
/* Configuration parameters. */
-static struct netdump_conf nd_conf;
-#define nd_server nd_conf.ndc_server
-#define nd_client nd_conf.ndc_client
-#define nd_gateway nd_conf.ndc_gateway
+static struct diocskerneldump_arg nd_conf;
+#define nd_server nd_conf.kda_server.in4
+#define nd_client nd_conf.kda_client.in4
+#define nd_gateway nd_conf.kda_gateway.in4
/* General dynamic settings. */
static struct ether_addr nd_gw_mac;
@@ -1059,7 +1060,7 @@
static struct cdev *netdump_cdev;
static int
-netdump_configure(struct netdump_conf *conf, struct thread *td)
+netdump_configure(struct diocskerneldump_arg *conf, struct thread *td)
{
struct epoch_tracker et;
struct ifnet *ifp;
@@ -1071,7 +1072,7 @@
}
NET_EPOCH_ENTER(et);
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
- if (strcmp(ifp->if_xname, conf->ndc_iface) == 0)
+ if (strcmp(ifp->if_xname, conf->kda_iface) == 0)
break;
}
/* XXX ref */
@@ -1083,7 +1084,7 @@
if ((if_getflags(ifp) & IFF_UP) == 0)
return (ENXIO);
if (!netdump_supported_nic(ifp) || ifp->if_type != IFT_ETHER)
- return (EINVAL);
+ return (ENODEV);
nd_ifp = ifp;
netdump_reinit(ifp);
@@ -1135,19 +1136,24 @@
netdump_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
int flags __unused, struct thread *td)
{
- struct diocskerneldump_arg *kda;
+ struct diocskerneldump_arg kda_copy, *conf;
struct dumperinfo dumper;
- struct netdump_conf *conf;
uint8_t *encryptedkey;
int error;
#ifdef COMPAT_FREEBSD11
u_int u;
#endif
+#ifdef COMPAT_FREEBSD12
+ struct diocskerneldump_arg_freebsd12 *kda12;
+ struct netdump_conf_freebsd12 *conf12;
+#endif
+ conf = NULL;
error = 0;
switch (cmd) {
#ifdef COMPAT_FREEBSD11
case DIOCSKERNELDUMP_FREEBSD11:
+ gone_in(13, "11.x ABI compatibility");
u = *(u_int *)addr;
if (u != 0) {
error = ENXIO;
@@ -1159,9 +1165,17 @@
}
break;
#endif
- case DIOCSKERNELDUMP:
- kda = (void *)addr;
- if (kda->kda_enable != 0) {
+#ifdef COMPAT_FREEBSD12
+ /*
+ * Used by dumpon(8) in 12.x for clearing previous
+ * configuration -- then NETDUMPSCONF_FREEBSD12 is used to
+ * actually configure netdump.
+ */
+ case DIOCSKERNELDUMP_FREEBSD12:
+ gone_in(14, "12.x ABI compatibility");
+
+ kda12 = (void *)addr;
+ if (kda12->kda12_enable) {
error = ENXIO;
break;
}
@@ -1170,28 +1184,99 @@
netdump_mbuf_drain();
}
break;
- case NETDUMPGCONF:
- conf = (struct netdump_conf *)addr;
+
+ case NETDUMPGCONF_FREEBSD12:
+ gone_in(14, "FreeBSD 12.x ABI compat");
+ conf12 = (void *)addr;
+
if (!nd_enabled) {
error = ENXIO;
break;
}
+ if (nd_conf.kda_af != AF_INET) {
+ error = EOPNOTSUPP;
+ break;
+ }
- strlcpy(conf->ndc_iface, nd_ifp->if_xname,
- sizeof(conf->ndc_iface));
- memcpy(&conf->ndc_server, &nd_server, sizeof(nd_server));
- memcpy(&conf->ndc_client, &nd_client, sizeof(nd_client));
- memcpy(&conf->ndc_gateway, &nd_gateway, sizeof(nd_gateway));
+ strlcpy(conf12->ndc12_iface, nd_ifp->if_xname,
+ sizeof(conf12->ndc12_iface));
+ memcpy(&conf12->ndc12_server, &nd_server,
+ sizeof(conf12->ndc12_server));
+ memcpy(&conf12->ndc12_client, &nd_client,
+ sizeof(conf12->ndc12_client));
+ memcpy(&conf12->ndc12_gateway, &nd_gateway,
+ sizeof(conf12->ndc12_gateway));
break;
- case NETDUMPSCONF:
- conf = (struct netdump_conf *)addr;
+#endif
+ case DIOCGKERNELDUMP:
+ conf = (void *)addr;
+ /*
+ * For now, index is ignored; netdump doesn't support multiple
+ * configurations (yet).
+ */
+ if (!nd_enabled) {
+ error = ENXIO;
+ conf = NULL;
+ break;
+ }
+
+ strlcpy(conf->kda_iface, nd_ifp->if_xname,
+ sizeof(conf->kda_iface));
+ memcpy(&conf->kda_server, &nd_server, sizeof(nd_server));
+ memcpy(&conf->kda_client, &nd_client, sizeof(nd_client));
+ memcpy(&conf->kda_gateway, &nd_gateway, sizeof(nd_gateway));
+ conf->kda_af = nd_conf.kda_af;
+ conf = NULL;
+ break;
+
+#ifdef COMPAT_FREEBSD12
+ case NETDUMPSCONF_FREEBSD12:
+ gone_in(14, "FreeBSD 12.x ABI compat");
+
+ conf12 = (struct netdump_conf_freebsd12 *)addr;
+
+ _Static_assert(offsetof(struct diocskerneldump_arg, kda_server)
+ == offsetof(struct netdump_conf_freebsd12, ndc12_server),
+ "simplifying assumption");
+
+ memset(&kda_copy, 0, sizeof(kda_copy));
+ memcpy(&kda_copy, conf12,
+ offsetof(struct diocskerneldump_arg, kda_server));
+
+ /* 12.x ABI could only configure IPv4 (INET) netdump. */
+ kda_copy.kda_af = AF_INET;
+ memcpy(&kda_copy.kda_server.in4, &conf12->ndc12_server,
+ sizeof(struct in_addr));
+ memcpy(&kda_copy.kda_client.in4, &conf12->ndc12_client,
+ sizeof(struct in_addr));
+ memcpy(&kda_copy.kda_gateway.in4, &conf12->ndc12_gateway,
+ sizeof(struct in_addr));
+
+ kda_copy.kda_index =
+ (conf12->ndc12_kda.kda12_enable ? 0 : KDA_REMOVE_ALL);
+
+ conf = &kda_copy;
+ explicit_bzero(conf12, sizeof(*conf12));
+ /* FALLTHROUGH */
+#endif
+ case DIOCSKERNELDUMP:
encryptedkey = NULL;
- kda = &conf->ndc_kda;
+ if (cmd == DIOCSKERNELDUMP) {
+ conf = (void *)addr;
+ memcpy(&kda_copy, conf, sizeof(kda_copy));
+ }
+ /* Netdump only supports IP4 at this time. */
+ if (conf->kda_af != AF_INET) {
+ error = EPROTONOSUPPORT;
+ break;
+ }
- conf->ndc_iface[sizeof(conf->ndc_iface) - 1] = '\0';
- if (kda->kda_enable == 0) {
- if (nd_enabled) {
- error = clear_dumper(td);
+ conf->kda_iface[sizeof(conf->kda_iface) - 1] = '\0';
+ if (conf->kda_index == KDA_REMOVE ||
+ conf->kda_index == KDA_REMOVE_DEV ||
+ conf->kda_index == KDA_REMOVE_ALL) {
+ if (nd_enabled || conf->kda_index == KDA_REMOVE_ALL) {
+ error = dumper_remove(conf->kda_iface, conf);
if (error == 0) {
nd_enabled = 0;
netdump_mbuf_drain();
@@ -1204,19 +1289,23 @@
if (error != 0)
break;
- if (kda->kda_encryption != KERNELDUMP_ENC_NONE) {
- if (kda->kda_encryptedkeysize <= 0 ||
- kda->kda_encryptedkeysize >
- KERNELDUMP_ENCKEY_MAX_SIZE)
- return (EINVAL);
- encryptedkey = malloc(kda->kda_encryptedkeysize, M_TEMP,
- M_WAITOK);
- error = copyin(kda->kda_encryptedkey, encryptedkey,
- kda->kda_encryptedkeysize);
+ if (conf->kda_encryption != KERNELDUMP_ENC_NONE) {
+ if (conf->kda_encryptedkeysize <= 0 ||
+ conf->kda_encryptedkeysize >
+ KERNELDUMP_ENCKEY_MAX_SIZE) {
+ error = EINVAL;
+ break;
+ }
+ encryptedkey = malloc(conf->kda_encryptedkeysize,
+ M_TEMP, M_WAITOK);
+ error = copyin(conf->kda_encryptedkey, encryptedkey,
+ conf->kda_encryptedkeysize);
if (error != 0) {
free(encryptedkey, M_TEMP);
- return (error);
+ break;
}
+
+ conf->kda_encryptedkey = encryptedkey;
}
memset(&dumper, 0, sizeof(dumper));
@@ -1229,12 +1318,10 @@
dumper.mediaoffset = 0;
dumper.mediasize = 0;
- error = set_dumper(&dumper, conf->ndc_iface, td,
- kda->kda_compression, kda->kda_encryption,
- kda->kda_key, kda->kda_encryptedkeysize,
- encryptedkey);
+ error = dumper_insert(&dumper, conf->kda_iface, conf);
if (encryptedkey != NULL) {
- explicit_bzero(encryptedkey, kda->kda_encryptedkeysize);
+ explicit_bzero(encryptedkey,
+ conf->kda_encryptedkeysize);
free(encryptedkey, M_TEMP);
}
if (error != 0) {
@@ -1243,9 +1330,12 @@
}
break;
default:
- error = EINVAL;
+ error = ENOTTY;
break;
}
+ explicit_bzero(&kda_copy, sizeof(kda_copy));
+ if (conf != NULL)
+ explicit_bzero(conf, sizeof(*conf));
return (error);
}
@@ -1265,7 +1355,7 @@
static int
netdump_modevent(module_t mod __unused, int what, void *priv __unused)
{
- struct netdump_conf conf;
+ struct diocskerneldump_arg conf;
char *arg;
int error;
@@ -1278,33 +1368,41 @@
return (error);
if ((arg = kern_getenv("net.dump.iface")) != NULL) {
- strlcpy(conf.ndc_iface, arg, sizeof(conf.ndc_iface));
+ strlcpy(conf.kda_iface, arg, sizeof(conf.kda_iface));
freeenv(arg);
if ((arg = kern_getenv("net.dump.server")) != NULL) {
- inet_aton(arg, &conf.ndc_server);
+ inet_aton(arg, &conf.kda_server.in4);
freeenv(arg);
}
if ((arg = kern_getenv("net.dump.client")) != NULL) {
- inet_aton(arg, &conf.ndc_server);
+ inet_aton(arg, &conf.kda_server.in4);
freeenv(arg);
}
if ((arg = kern_getenv("net.dump.gateway")) != NULL) {
- inet_aton(arg, &conf.ndc_server);
+ inet_aton(arg, &conf.kda_server.in4);
freeenv(arg);
}
+ conf.kda_af = AF_INET;
/* Ignore errors; we print a message to the console. */
(void)netdump_configure(&conf, curthread);
}
break;
case MOD_UNLOAD:
- destroy_dev(netdump_cdev);
if (nd_enabled) {
+ struct diocskerneldump_arg kda;
+
printf("netdump: disabling dump device for unload\n");
- (void)clear_dumper(curthread);
+
+ bzero(&kda, sizeof(kda));
+ kda.kda_index = KDA_REMOVE_DEV;
+ (void)dumper_remove(nd_conf.kda_iface, &kda);
+
+ netdump_mbuf_drain();
nd_enabled = 0;
}
+ destroy_dev(netdump_cdev);
break;
default:
error = EOPNOTSUPP;
Index: head/sys/sys/conf.h
===================================================================
--- head/sys/sys/conf.h
+++ head/sys/sys/conf.h
@@ -352,15 +352,19 @@
off_t origdumpoff; /* Starting dump offset. */
struct kerneldumpcrypto *kdcrypto; /* Kernel dump crypto. */
struct kerneldumpcomp *kdcomp; /* Kernel dump compression. */
+
+ TAILQ_ENTRY(dumperinfo) di_next;
+
+ char di_devname[];
};
extern int dumping; /* system is dumping */
int doadump(boolean_t);
-int set_dumper(struct dumperinfo *di, const char *devname, struct thread *td,
- uint8_t compression, uint8_t encryption, const uint8_t *key,
- uint32_t encryptedkeysize, const uint8_t *encryptedkey);
-int clear_dumper(struct thread *td);
+struct diocskerneldump_arg;
+int dumper_insert(const struct dumperinfo *di_template, const char *devname,
+ const struct diocskerneldump_arg *kda);
+int dumper_remove(const char *devname, const struct diocskerneldump_arg *kda);
int dump_start(struct dumperinfo *di, struct kerneldumpheader *kdh);
int dump_append(struct dumperinfo *, void *, vm_offset_t, size_t);
Index: head/sys/sys/disk.h
===================================================================
--- head/sys/sys/disk.h
+++ head/sys/sys/disk.h
@@ -19,7 +19,11 @@
#include <sys/kerneldump.h>
#include <sys/types.h>
#include <sys/disk_zone.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
#ifdef _KERNEL
#ifndef _SYS_CONF_H_
@@ -143,17 +147,66 @@
#define DIOCZONECMD _IOWR('d', 143, struct disk_zone_args)
+struct diocskerneldump_arg_freebsd12 {
+ uint8_t kda12_enable;
+ uint8_t kda12_compression;
+ uint8_t kda12_encryption;
+ uint8_t kda12_key[KERNELDUMP_KEY_MAX_SIZE];
+ uint32_t kda12_encryptedkeysize;
+ uint8_t *kda12_encryptedkey;
+};
+#define DIOCSKERNELDUMP_FREEBSD12 \
+ _IOW('d', 144, struct diocskerneldump_arg_freebsd12)
+
+union kd_ip {
+ struct in_addr in4;
+ struct in6_addr in6;
+};
+
+/*
+ * Sentinel values for kda_index.
+ *
+ * If kda_index is KDA_REMOVE_ALL, all dump configurations are cleared.
+ *
+ * If kda_index is KDA_REMOVE_DEV, all dump configurations for the specified
+ * device are cleared.
+ *
+ * If kda_index is KDA_REMOVE, only the specified dump configuration for the
+ * given device is removed from the list of fallback dump configurations.
+ *
+ * If kda_index is KDA_APPEND, the dump configuration is added after all
+ * existing dump configurations.
+ *
+ * Otherwise, the new configuration is inserted into the fallback dump list at
+ * index 'kda_index'.
+ */
+#define KDA_REMOVE UINT8_MAX
+#define KDA_REMOVE_ALL (UINT8_MAX - 1)
+#define KDA_REMOVE_DEV (UINT8_MAX - 2)
+#define KDA_APPEND (UINT8_MAX - 3)
struct diocskerneldump_arg {
- uint8_t kda_enable;
+ uint8_t kda_index;
uint8_t kda_compression;
uint8_t kda_encryption;
uint8_t kda_key[KERNELDUMP_KEY_MAX_SIZE];
uint32_t kda_encryptedkeysize;
uint8_t *kda_encryptedkey;
+ char kda_iface[IFNAMSIZ];
+ union kd_ip kda_server;
+ union kd_ip kda_client;
+ union kd_ip kda_gateway;
+ uint8_t kda_af;
};
-#define DIOCSKERNELDUMP _IOW('d', 144, struct diocskerneldump_arg)
+_Static_assert(__offsetof(struct diocskerneldump_arg, kda_iface) ==
+ sizeof(struct diocskerneldump_arg_freebsd12), "simplifying assumption");
+#define DIOCSKERNELDUMP _IOW('d', 145, struct diocskerneldump_arg)
/*
* Enable/Disable the device for kernel core dumps.
+ */
+
+#define DIOCGKERNELDUMP _IOWR('d', 146, struct diocskerneldump_arg)
+ /*
+ * Get current kernel netdump configuration details for a given index.
*/
#endif /* _SYS_DISK_H_ */
Index: head/sys/sys/param.h
===================================================================
--- head/sys/sys/param.h
+++ head/sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300022 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300023 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Oct 27, 3:24 AM (16 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24267494
Default Alt Text
D19996.diff (38 KB)
Attached To
Mode
D19996: List-ify kernel dump device configuration
Attached
Detach File
Event Timeline
Log In to Comment