18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 483f9dfabSGarrett Wollman * Copyright (c) 1980, 1993 583f9dfabSGarrett Wollman * The Regents of the University of California. All rights reserved. 683f9dfabSGarrett Wollman * 783f9dfabSGarrett Wollman * Redistribution and use in source and binary forms, with or without 883f9dfabSGarrett Wollman * modification, are permitted provided that the following conditions 983f9dfabSGarrett Wollman * are met: 1083f9dfabSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 1183f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer. 1283f9dfabSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 1383f9dfabSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 1483f9dfabSGarrett Wollman * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1683f9dfabSGarrett Wollman * may be used to endorse or promote products derived from this software 1783f9dfabSGarrett Wollman * without specific prior written permission. 1883f9dfabSGarrett Wollman * 1983f9dfabSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2083f9dfabSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2183f9dfabSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2283f9dfabSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2383f9dfabSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2483f9dfabSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2583f9dfabSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2683f9dfabSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2783f9dfabSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2883f9dfabSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2983f9dfabSGarrett Wollman * SUCH DAMAGE. 3083f9dfabSGarrett Wollman */ 3183f9dfabSGarrett Wollman 32c69284caSDavid E. O'Brien #if 0 3383f9dfabSGarrett Wollman #ifndef lint 348f034b11SPhilippe Charnier static const char copyright[] = 3583f9dfabSGarrett Wollman "@(#) Copyright (c) 1980, 1993\n\ 3683f9dfabSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 3783f9dfabSGarrett Wollman #endif /* not lint */ 3883f9dfabSGarrett Wollman 3983f9dfabSGarrett Wollman #ifndef lint 408f034b11SPhilippe Charnier static char sccsid[] = "From: @(#)swapon.c 8.1 (Berkeley) 6/5/93"; 4183f9dfabSGarrett Wollman #endif /* not lint */ 42c69284caSDavid E. O'Brien #endif 43c69284caSDavid E. O'Brien #include <sys/cdefs.h> 44c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4583f9dfabSGarrett Wollman 4683f9dfabSGarrett Wollman #include <sys/param.h> 47480f31c2SKonrad Witaszczyk #include <sys/capsicum.h> 482dd527b3SPoul-Henning Kamp #include <sys/disk.h> 490ff40d3dSMark Johnston #include <sys/socket.h> 50c0046e26SDag-Erling Smørgrav #include <sys/sysctl.h> 5183f9dfabSGarrett Wollman 52480f31c2SKonrad Witaszczyk #include <assert.h> 537672a014SMariusz Zaborski #include <capsicum_helpers.h> 54c0046e26SDag-Erling Smørgrav #include <err.h> 55f6848434SAlfred Perlstein #include <errno.h> 56c0046e26SDag-Erling Smørgrav #include <fcntl.h> 570ff40d3dSMark Johnston #include <ifaddrs.h> 580ff40d3dSMark Johnston #include <netdb.h> 59c0046e26SDag-Erling Smørgrav #include <paths.h> 60480f31c2SKonrad Witaszczyk #include <stdbool.h> 61c0046e26SDag-Erling Smørgrav #include <stdint.h> 62c0046e26SDag-Erling Smørgrav #include <stdio.h> 63c0046e26SDag-Erling Smørgrav #include <stdlib.h> 64c0046e26SDag-Erling Smørgrav #include <string.h> 65c0046e26SDag-Erling Smørgrav #include <sysexits.h> 66c0046e26SDag-Erling Smørgrav #include <unistd.h> 67c0046e26SDag-Erling Smørgrav 680ff40d3dSMark Johnston #include <arpa/inet.h> 690ff40d3dSMark Johnston 700ff40d3dSMark Johnston #include <net/if.h> 710ff40d3dSMark Johnston #include <net/if_dl.h> 720ff40d3dSMark Johnston #include <net/route.h> 730ff40d3dSMark Johnston 740ff40d3dSMark Johnston #include <netinet/in.h> 750ff40d3dSMark Johnston #include <netinet/netdump/netdump.h> 760ff40d3dSMark Johnston 77480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 78480f31c2SKonrad Witaszczyk #include <openssl/err.h> 79480f31c2SKonrad Witaszczyk #include <openssl/pem.h> 80480f31c2SKonrad Witaszczyk #include <openssl/rsa.h> 81480f31c2SKonrad Witaszczyk #endif 82480f31c2SKonrad Witaszczyk 83c0046e26SDag-Erling Smørgrav static int verbose; 84c0046e26SDag-Erling Smørgrav 850ff40d3dSMark Johnston static void _Noreturn 86c0046e26SDag-Erling Smørgrav usage(void) 87c0046e26SDag-Erling Smørgrav { 880ff40d3dSMark Johnston fprintf(stderr, 890ff40d3dSMark Johnston "usage: dumpon [-v] [-k <pubkey>] [-Zz] <device>\n" 900ff40d3dSMark Johnston " dumpon [-v] [-k <pubkey>] [-Zz]\n" 91e5fff57dSMark Johnston " [-g <gateway>] -s <server> -c <client> <iface>\n" 920ff40d3dSMark Johnston " dumpon [-v] off\n" 930ff40d3dSMark Johnston " dumpon [-v] -l\n"); 94c0046e26SDag-Erling Smørgrav exit(EX_USAGE); 95c0046e26SDag-Erling Smørgrav } 96c0046e26SDag-Erling Smørgrav 970ff40d3dSMark Johnston /* 980ff40d3dSMark Johnston * Look for a default route on the specified interface. 990ff40d3dSMark Johnston */ 1000ff40d3dSMark Johnston static char * 1010ff40d3dSMark Johnston find_gateway(const char *ifname) 1020ff40d3dSMark Johnston { 1030ff40d3dSMark Johnston struct ifaddrs *ifa, *ifap; 1040ff40d3dSMark Johnston struct rt_msghdr *rtm; 1050ff40d3dSMark Johnston struct sockaddr *sa; 1060ff40d3dSMark Johnston struct sockaddr_dl *sdl; 1070ff40d3dSMark Johnston struct sockaddr_in *dst, *mask, *gw; 1080ff40d3dSMark Johnston char *buf, *next, *ret; 1090ff40d3dSMark Johnston size_t sz; 1100ff40d3dSMark Johnston int error, i, ifindex, mib[7]; 1110ff40d3dSMark Johnston 1120ff40d3dSMark Johnston /* First look up the interface index. */ 1130ff40d3dSMark Johnston if (getifaddrs(&ifap) != 0) 1140ff40d3dSMark Johnston err(EX_OSERR, "getifaddrs"); 1150ff40d3dSMark Johnston for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 1160ff40d3dSMark Johnston if (ifa->ifa_addr->sa_family != AF_LINK) 1170ff40d3dSMark Johnston continue; 1180ff40d3dSMark Johnston if (strcmp(ifa->ifa_name, ifname) == 0) { 1190ff40d3dSMark Johnston sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr; 1200ff40d3dSMark Johnston ifindex = sdl->sdl_index; 1210ff40d3dSMark Johnston break; 1220ff40d3dSMark Johnston } 1230ff40d3dSMark Johnston } 1240ff40d3dSMark Johnston if (ifa == NULL) 1250ff40d3dSMark Johnston errx(1, "couldn't find interface index for '%s'", ifname); 1260ff40d3dSMark Johnston freeifaddrs(ifap); 1270ff40d3dSMark Johnston 1280ff40d3dSMark Johnston /* Now get the IPv4 routing table. */ 1290ff40d3dSMark Johnston mib[0] = CTL_NET; 1300ff40d3dSMark Johnston mib[1] = PF_ROUTE; 1310ff40d3dSMark Johnston mib[2] = 0; 1320ff40d3dSMark Johnston mib[3] = AF_INET; 1330ff40d3dSMark Johnston mib[4] = NET_RT_DUMP; 1340ff40d3dSMark Johnston mib[5] = 0; 1350ff40d3dSMark Johnston mib[6] = -1; /* FIB */ 1360ff40d3dSMark Johnston 1370ff40d3dSMark Johnston for (;;) { 1380ff40d3dSMark Johnston if (sysctl(mib, nitems(mib), NULL, &sz, NULL, 0) != 0) 1390ff40d3dSMark Johnston err(EX_OSERR, "sysctl(NET_RT_DUMP)"); 1400ff40d3dSMark Johnston buf = malloc(sz); 1410ff40d3dSMark Johnston error = sysctl(mib, nitems(mib), buf, &sz, NULL, 0); 1420ff40d3dSMark Johnston if (error == 0) 1430ff40d3dSMark Johnston break; 1440ff40d3dSMark Johnston if (errno != ENOMEM) 1450ff40d3dSMark Johnston err(EX_OSERR, "sysctl(NET_RT_DUMP)"); 1460ff40d3dSMark Johnston free(buf); 1470ff40d3dSMark Johnston } 1480ff40d3dSMark Johnston 149e5fff57dSMark Johnston ret = NULL; 1500ff40d3dSMark Johnston for (next = buf; next < buf + sz; next += rtm->rtm_msglen) { 1510ff40d3dSMark Johnston rtm = (struct rt_msghdr *)(void *)next; 1520ff40d3dSMark Johnston if (rtm->rtm_version != RTM_VERSION) 1530ff40d3dSMark Johnston continue; 1540ff40d3dSMark Johnston if ((rtm->rtm_flags & RTF_GATEWAY) == 0 || 1550ff40d3dSMark Johnston rtm->rtm_index != ifindex) 1560ff40d3dSMark Johnston continue; 1570ff40d3dSMark Johnston 1580ff40d3dSMark Johnston dst = gw = mask = NULL; 1590ff40d3dSMark Johnston sa = (struct sockaddr *)(rtm + 1); 1600ff40d3dSMark Johnston for (i = 0; i < RTAX_MAX; i++) { 1610ff40d3dSMark Johnston if ((rtm->rtm_addrs & (1 << i)) != 0) { 1620ff40d3dSMark Johnston switch (i) { 1630ff40d3dSMark Johnston case RTAX_DST: 1640ff40d3dSMark Johnston dst = (void *)sa; 1650ff40d3dSMark Johnston break; 1660ff40d3dSMark Johnston case RTAX_GATEWAY: 1670ff40d3dSMark Johnston gw = (void *)sa; 1680ff40d3dSMark Johnston break; 1690ff40d3dSMark Johnston case RTAX_NETMASK: 1700ff40d3dSMark Johnston mask = (void *)sa; 1710ff40d3dSMark Johnston break; 1720ff40d3dSMark Johnston } 1730ff40d3dSMark Johnston } 1740ff40d3dSMark Johnston sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa)); 1750ff40d3dSMark Johnston } 1760ff40d3dSMark Johnston 1770ff40d3dSMark Johnston if (dst->sin_addr.s_addr == INADDR_ANY && 1780ff40d3dSMark Johnston mask->sin_addr.s_addr == 0) { 1790ff40d3dSMark Johnston ret = inet_ntoa(gw->sin_addr); 1800ff40d3dSMark Johnston break; 1810ff40d3dSMark Johnston } 1820ff40d3dSMark Johnston } 1830ff40d3dSMark Johnston free(buf); 1840ff40d3dSMark Johnston return (ret); 1850ff40d3dSMark Johnston } 1860ff40d3dSMark Johnston 187c0046e26SDag-Erling Smørgrav static void 188c0046e26SDag-Erling Smørgrav check_size(int fd, const char *fn) 189c0046e26SDag-Erling Smørgrav { 190c0046e26SDag-Erling Smørgrav int name[] = { CTL_HW, HW_PHYSMEM }; 1910bfc2a12SMarcelo Araujo size_t namelen = nitems(name); 192c0046e26SDag-Erling Smørgrav unsigned long physmem; 193ce893772SPaul Saab size_t len; 194c0046e26SDag-Erling Smørgrav off_t mediasize; 195ce893772SPaul Saab int minidump; 196c0046e26SDag-Erling Smørgrav 197b54a17cdSJohn Baldwin len = sizeof(minidump); 198ce893772SPaul Saab if (sysctlbyname("debug.minidump", &minidump, &len, NULL, 0) == 0 && 199ce893772SPaul Saab minidump == 1) 200ce893772SPaul Saab return; 201b54a17cdSJohn Baldwin len = sizeof(physmem); 202c0046e26SDag-Erling Smørgrav if (sysctl(name, namelen, &physmem, &len, NULL, 0) != 0) 203c0046e26SDag-Erling Smørgrav err(EX_OSERR, "can't get memory size"); 204c0046e26SDag-Erling Smørgrav if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0) 205c0046e26SDag-Erling Smørgrav err(EX_OSERR, "%s: can't get size", fn); 2069872f15dSDag-Erling Smørgrav if ((uintmax_t)mediasize < (uintmax_t)physmem) { 207c0046e26SDag-Erling Smørgrav if (verbose) 208c0046e26SDag-Erling Smørgrav printf("%s is smaller than physical memory\n", fn); 209c0046e26SDag-Erling Smørgrav exit(EX_IOERR); 210c0046e26SDag-Erling Smørgrav } 211c0046e26SDag-Erling Smørgrav } 21283f9dfabSGarrett Wollman 213480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 214480f31c2SKonrad Witaszczyk static void 2150ff40d3dSMark Johnston genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap) 216480f31c2SKonrad Witaszczyk { 217480f31c2SKonrad Witaszczyk FILE *fp; 218480f31c2SKonrad Witaszczyk RSA *pubkey; 219480f31c2SKonrad Witaszczyk 220480f31c2SKonrad Witaszczyk assert(pubkeyfile != NULL); 2210ff40d3dSMark Johnston assert(kdap != NULL); 222480f31c2SKonrad Witaszczyk 223480f31c2SKonrad Witaszczyk fp = NULL; 224480f31c2SKonrad Witaszczyk pubkey = NULL; 225480f31c2SKonrad Witaszczyk 226480f31c2SKonrad Witaszczyk fp = fopen(pubkeyfile, "r"); 227480f31c2SKonrad Witaszczyk if (fp == NULL) 228480f31c2SKonrad Witaszczyk err(1, "Unable to open %s", pubkeyfile); 229480f31c2SKonrad Witaszczyk 2307672a014SMariusz Zaborski if (caph_enter() < 0) 231480f31c2SKonrad Witaszczyk err(1, "Unable to enter capability mode"); 232480f31c2SKonrad Witaszczyk 233480f31c2SKonrad Witaszczyk pubkey = RSA_new(); 234480f31c2SKonrad Witaszczyk if (pubkey == NULL) { 235480f31c2SKonrad Witaszczyk errx(1, "Unable to allocate an RSA structure: %s", 236480f31c2SKonrad Witaszczyk ERR_error_string(ERR_get_error(), NULL)); 237480f31c2SKonrad Witaszczyk } 238480f31c2SKonrad Witaszczyk 239480f31c2SKonrad Witaszczyk pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL); 240480f31c2SKonrad Witaszczyk fclose(fp); 241480f31c2SKonrad Witaszczyk fp = NULL; 242480f31c2SKonrad Witaszczyk if (pubkey == NULL) 243480f31c2SKonrad Witaszczyk errx(1, "Unable to read data from %s.", pubkeyfile); 244480f31c2SKonrad Witaszczyk 245f27d255cSConrad Meyer /* 246f27d255cSConrad Meyer * RSA keys under ~1024 bits are trivially factorable (2018). OpenSSL 247f27d255cSConrad Meyer * provides an API for RSA keys to estimate the symmetric-cipher 248f27d255cSConrad Meyer * "equivalent" bits of security (defined in NIST SP800-57), which as 249f27d255cSConrad Meyer * of this writing equates a 2048-bit RSA key to 112 symmetric cipher 250f27d255cSConrad Meyer * bits. 251f27d255cSConrad Meyer * 252f27d255cSConrad Meyer * Use this API as a seatbelt to avoid suggesting to users that their 253f27d255cSConrad Meyer * privacy is protected by encryption when the key size is insufficient 254f27d255cSConrad Meyer * to prevent compromise via factoring. 255f27d255cSConrad Meyer * 256f27d255cSConrad Meyer * Future work: Sanity check for weak 'e', and sanity check for absence 257f27d255cSConrad Meyer * of 'd' (i.e., the supplied key is a public key rather than a full 258f27d255cSConrad Meyer * keypair). 259f27d255cSConrad Meyer */ 260f27d255cSConrad Meyer #if OPENSSL_VERSION_NUMBER >= 0x10100000L 261f27d255cSConrad Meyer if (RSA_security_bits(pubkey) < 112) 262f27d255cSConrad Meyer #else 263f27d255cSConrad Meyer if (RSA_size(pubkey) * 8 < 2048) 264f27d255cSConrad Meyer #endif 265f27d255cSConrad Meyer errx(1, "Small RSA keys (you provided: %db) can be " 266f27d255cSConrad Meyer "factored cheaply. Please generate a larger key.", 267f27d255cSConrad Meyer RSA_size(pubkey) * 8); 268f27d255cSConrad Meyer 2690ff40d3dSMark Johnston kdap->kda_encryptedkeysize = RSA_size(pubkey); 2700ff40d3dSMark Johnston if (kdap->kda_encryptedkeysize > KERNELDUMP_ENCKEY_MAX_SIZE) { 271480f31c2SKonrad Witaszczyk errx(1, "Public key has to be at most %db long.", 272480f31c2SKonrad Witaszczyk 8 * KERNELDUMP_ENCKEY_MAX_SIZE); 273480f31c2SKonrad Witaszczyk } 274480f31c2SKonrad Witaszczyk 2750ff40d3dSMark Johnston kdap->kda_encryptedkey = calloc(1, kdap->kda_encryptedkeysize); 2760ff40d3dSMark Johnston if (kdap->kda_encryptedkey == NULL) 277480f31c2SKonrad Witaszczyk err(1, "Unable to allocate encrypted key"); 278480f31c2SKonrad Witaszczyk 2790ff40d3dSMark Johnston kdap->kda_encryption = KERNELDUMP_ENC_AES_256_CBC; 2800ff40d3dSMark Johnston arc4random_buf(kdap->kda_key, sizeof(kdap->kda_key)); 2810ff40d3dSMark Johnston if (RSA_public_encrypt(sizeof(kdap->kda_key), kdap->kda_key, 2820ff40d3dSMark Johnston kdap->kda_encryptedkey, pubkey, 2830ff40d3dSMark Johnston RSA_PKCS1_PADDING) != (int)kdap->kda_encryptedkeysize) { 284480f31c2SKonrad Witaszczyk errx(1, "Unable to encrypt the one-time key."); 285480f31c2SKonrad Witaszczyk } 286480f31c2SKonrad Witaszczyk RSA_free(pubkey); 287480f31c2SKonrad Witaszczyk } 288480f31c2SKonrad Witaszczyk #endif 289480f31c2SKonrad Witaszczyk 290f6848434SAlfred Perlstein static void 291f6848434SAlfred Perlstein listdumpdev(void) 292f6848434SAlfred Perlstein { 293f6848434SAlfred Perlstein char dumpdev[PATH_MAX]; 2940ff40d3dSMark Johnston struct netdump_conf ndconf; 295f6848434SAlfred Perlstein size_t len; 296f6848434SAlfred Perlstein const char *sysctlname = "kern.shutdown.dumpdevname"; 2970ff40d3dSMark Johnston int fd; 298f6848434SAlfred Perlstein 299f6848434SAlfred Perlstein len = sizeof(dumpdev); 300f6848434SAlfred Perlstein if (sysctlbyname(sysctlname, &dumpdev, &len, NULL, 0) != 0) { 301f6848434SAlfred Perlstein if (errno == ENOMEM) { 302f6848434SAlfred Perlstein err(EX_OSERR, "Kernel returned too large of a buffer for '%s'\n", 303f6848434SAlfred Perlstein sysctlname); 304f6848434SAlfred Perlstein } else { 305f6848434SAlfred Perlstein err(EX_OSERR, "Sysctl get '%s'\n", sysctlname); 306f6848434SAlfred Perlstein } 307f6848434SAlfred Perlstein } 3080ff40d3dSMark Johnston if (strlen(dumpdev) == 0) 3090ff40d3dSMark Johnston (void)strlcpy(dumpdev, _PATH_DEVNULL, sizeof(dumpdev)); 3100ff40d3dSMark Johnston 3110ff40d3dSMark Johnston if (verbose) 312f6848434SAlfred Perlstein printf("kernel dumps on "); 313f6848434SAlfred Perlstein printf("%s\n", dumpdev); 3140ff40d3dSMark Johnston 3150ff40d3dSMark Johnston /* If netdump is enabled, print the configuration parameters. */ 3160ff40d3dSMark Johnston if (verbose) { 3170ff40d3dSMark Johnston fd = open(_PATH_NETDUMP, O_RDONLY); 3180ff40d3dSMark Johnston if (fd < 0) { 3190ff40d3dSMark Johnston if (errno != ENOENT) 3200ff40d3dSMark Johnston err(EX_OSERR, "opening %s", _PATH_NETDUMP); 3210ff40d3dSMark Johnston return; 322f6848434SAlfred Perlstein } 3230ff40d3dSMark Johnston if (ioctl(fd, NETDUMPGCONF, &ndconf) != 0) { 3240ff40d3dSMark Johnston if (errno != ENXIO) 3250ff40d3dSMark Johnston err(EX_OSERR, "ioctl(NETDUMPGCONF)"); 3260ff40d3dSMark Johnston (void)close(fd); 3270ff40d3dSMark Johnston return; 3280ff40d3dSMark Johnston } 3290ff40d3dSMark Johnston 3300ff40d3dSMark Johnston printf("server address: %s\n", inet_ntoa(ndconf.ndc_server)); 3310ff40d3dSMark Johnston printf("client address: %s\n", inet_ntoa(ndconf.ndc_client)); 3320ff40d3dSMark Johnston printf("gateway address: %s\n", inet_ntoa(ndconf.ndc_gateway)); 3330ff40d3dSMark Johnston (void)close(fd); 3340ff40d3dSMark Johnston } 3350ff40d3dSMark Johnston } 3360ff40d3dSMark Johnston 3370ff40d3dSMark Johnston static int 3380ff40d3dSMark Johnston opendumpdev(const char *arg, char *dumpdev) 3390ff40d3dSMark Johnston { 3400ff40d3dSMark Johnston int fd, i; 3410ff40d3dSMark Johnston 3420ff40d3dSMark Johnston if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 3430ff40d3dSMark Johnston strlcpy(dumpdev, arg, PATH_MAX); 3440ff40d3dSMark Johnston else { 3450ff40d3dSMark Johnston i = snprintf(dumpdev, PATH_MAX, "%s%s", _PATH_DEV, arg); 3460ff40d3dSMark Johnston if (i < 0) 3470ff40d3dSMark Johnston err(EX_OSERR, "%s", arg); 3480ff40d3dSMark Johnston if (i >= PATH_MAX) 3490ff40d3dSMark Johnston errc(EX_DATAERR, EINVAL, "%s", arg); 3500ff40d3dSMark Johnston } 3510ff40d3dSMark Johnston 3520ff40d3dSMark Johnston fd = open(dumpdev, O_RDONLY); 3530ff40d3dSMark Johnston if (fd < 0) 3540ff40d3dSMark Johnston err(EX_OSFILE, "%s", dumpdev); 3550ff40d3dSMark Johnston return (fd); 356f6848434SAlfred Perlstein } 357f6848434SAlfred Perlstein 35883f9dfabSGarrett Wollman int 359d1a939c1SWarner Losh main(int argc, char *argv[]) 36083f9dfabSGarrett Wollman { 3610ff40d3dSMark Johnston char dumpdev[PATH_MAX]; 3620ff40d3dSMark Johnston struct diocskerneldump_arg _kda, *kdap; 3630ff40d3dSMark Johnston struct netdump_conf ndconf; 3640ff40d3dSMark Johnston struct addrinfo hints, *res; 3650ff40d3dSMark Johnston const char *dev, *pubkeyfile, *server, *client, *gateway; 3660ff40d3dSMark Johnston int ch, error, fd; 3670ff40d3dSMark Johnston bool enable, gzip, list, netdump, zstd; 36883f9dfabSGarrett Wollman 3690ff40d3dSMark Johnston gzip = list = netdump = zstd = false; 3700ff40d3dSMark Johnston kdap = NULL; 371480f31c2SKonrad Witaszczyk pubkeyfile = NULL; 3720ff40d3dSMark Johnston server = client = gateway = NULL; 373480f31c2SKonrad Witaszczyk 3740ff40d3dSMark Johnston while ((ch = getopt(argc, argv, "c:g:k:ls:vZz")) != -1) 37583f9dfabSGarrett Wollman switch ((char)ch) { 3760ff40d3dSMark Johnston case 'c': 3770ff40d3dSMark Johnston client = optarg; 3780ff40d3dSMark Johnston break; 3790ff40d3dSMark Johnston case 'g': 3800ff40d3dSMark Johnston gateway = optarg; 3810ff40d3dSMark Johnston break; 382480f31c2SKonrad Witaszczyk case 'k': 383480f31c2SKonrad Witaszczyk pubkeyfile = optarg; 384480f31c2SKonrad Witaszczyk break; 385f6848434SAlfred Perlstein case 'l': 3860ff40d3dSMark Johnston list = true; 3870ff40d3dSMark Johnston break; 3880ff40d3dSMark Johnston case 's': 3890ff40d3dSMark Johnston server = optarg; 390f6848434SAlfred Perlstein break; 39183f9dfabSGarrett Wollman case 'v': 39283f9dfabSGarrett Wollman verbose = 1; 39383f9dfabSGarrett Wollman break; 3946026dcd7SMark Johnston case 'Z': 3956026dcd7SMark Johnston zstd = true; 3966026dcd7SMark Johnston break; 39764a16434SMark Johnston case 'z': 39864a16434SMark Johnston gzip = true; 39964a16434SMark Johnston break; 40083f9dfabSGarrett Wollman default: 40183f9dfabSGarrett Wollman usage(); 40283f9dfabSGarrett Wollman } 403c0046e26SDag-Erling Smørgrav 4046026dcd7SMark Johnston if (gzip && zstd) 4056026dcd7SMark Johnston errx(EX_USAGE, "The -z and -Z options are mutually exclusive."); 4066026dcd7SMark Johnston 407c0046e26SDag-Erling Smørgrav argc -= optind; 40883f9dfabSGarrett Wollman argv += optind; 40983f9dfabSGarrett Wollman 4100ff40d3dSMark Johnston if (list) { 411f6848434SAlfred Perlstein listdumpdev(); 412f6848434SAlfred Perlstein exit(EX_OK); 413f6848434SAlfred Perlstein } 414f6848434SAlfred Perlstein 415c0046e26SDag-Erling Smørgrav if (argc != 1) 41683f9dfabSGarrett Wollman usage(); 41783f9dfabSGarrett Wollman 418480f31c2SKonrad Witaszczyk #ifndef HAVE_CRYPTO 4190ff40d3dSMark Johnston if (pubkeyfile != NULL) 42021a8e0b1SSean Bruno errx(EX_UNAVAILABLE,"Unable to use the public key." 42121a8e0b1SSean Bruno " Recompile dumpon with OpenSSL support."); 422480f31c2SKonrad Witaszczyk #endif 423480f31c2SKonrad Witaszczyk 4240ff40d3dSMark Johnston if (server != NULL && client != NULL) { 4250ff40d3dSMark Johnston enable = true; 4260ff40d3dSMark Johnston dev = _PATH_NETDUMP; 4270ff40d3dSMark Johnston netdump = true; 4280ff40d3dSMark Johnston kdap = &ndconf.ndc_kda; 4290ff40d3dSMark Johnston } else if (server == NULL && client == NULL && argc > 0) { 4300ff40d3dSMark Johnston enable = strcmp(argv[0], "off") != 0; 4310ff40d3dSMark Johnston dev = enable ? argv[0] : _PATH_DEVNULL; 4320ff40d3dSMark Johnston netdump = false; 4330ff40d3dSMark Johnston kdap = &_kda; 4340ff40d3dSMark Johnston } else 4350ff40d3dSMark Johnston usage(); 43645a9027dSSteven Hartland 4370ff40d3dSMark Johnston fd = opendumpdev(dev, dumpdev); 4380ff40d3dSMark Johnston if (!netdump && !gzip) 43964a16434SMark Johnston check_size(fd, dumpdev); 44064a16434SMark Johnston 4410ff40d3dSMark Johnston bzero(kdap, sizeof(*kdap)); 4420ff40d3dSMark Johnston kdap->kda_enable = 0; 4430ff40d3dSMark Johnston if (ioctl(fd, DIOCSKERNELDUMP, kdap) != 0) 4440ff40d3dSMark Johnston err(EX_OSERR, "ioctl(DIOCSKERNELDUMP)"); 4450ff40d3dSMark Johnston if (!enable) 4460ff40d3dSMark Johnston exit(EX_OK); 4470ff40d3dSMark Johnston 4480ff40d3dSMark Johnston explicit_bzero(kdap, sizeof(*kdap)); 4490ff40d3dSMark Johnston kdap->kda_enable = 1; 4500ff40d3dSMark Johnston kdap->kda_compression = KERNELDUMP_COMP_NONE; 4510ff40d3dSMark Johnston if (zstd) 4520ff40d3dSMark Johnston kdap->kda_compression = KERNELDUMP_COMP_ZSTD; 4530ff40d3dSMark Johnston else if (gzip) 4540ff40d3dSMark Johnston kdap->kda_compression = KERNELDUMP_COMP_GZIP; 4550ff40d3dSMark Johnston 4560ff40d3dSMark Johnston if (netdump) { 4570ff40d3dSMark Johnston memset(&hints, 0, sizeof(hints)); 4580ff40d3dSMark Johnston hints.ai_family = AF_INET; 4590ff40d3dSMark Johnston hints.ai_protocol = IPPROTO_UDP; 4600ff40d3dSMark Johnston res = NULL; 4610ff40d3dSMark Johnston error = getaddrinfo(server, NULL, &hints, &res); 4620ff40d3dSMark Johnston if (error != 0) 4630ff40d3dSMark Johnston err(1, "%s", gai_strerror(error)); 4640ff40d3dSMark Johnston if (res == NULL) 4650ff40d3dSMark Johnston errx(1, "failed to resolve '%s'", server); 4660ff40d3dSMark Johnston server = inet_ntoa( 4670ff40d3dSMark Johnston ((struct sockaddr_in *)(void *)res->ai_addr)->sin_addr); 4680ff40d3dSMark Johnston freeaddrinfo(res); 4690ff40d3dSMark Johnston 4700ff40d3dSMark Johnston if (strlcpy(ndconf.ndc_iface, argv[0], 4710ff40d3dSMark Johnston sizeof(ndconf.ndc_iface)) >= sizeof(ndconf.ndc_iface)) 4720ff40d3dSMark Johnston errx(EX_USAGE, "invalid interface name '%s'", argv[0]); 4730ff40d3dSMark Johnston if (inet_aton(server, &ndconf.ndc_server) == 0) 4740ff40d3dSMark Johnston errx(EX_USAGE, "invalid server address '%s'", server); 4750ff40d3dSMark Johnston if (inet_aton(client, &ndconf.ndc_client) == 0) 4760ff40d3dSMark Johnston errx(EX_USAGE, "invalid client address '%s'", client); 4770ff40d3dSMark Johnston 478*79dd8f69SMark Johnston if (gateway == NULL) { 479e5fff57dSMark Johnston gateway = find_gateway(argv[0]); 480e5fff57dSMark Johnston if (gateway == NULL) { 481e5fff57dSMark Johnston if (verbose) 482*79dd8f69SMark Johnston printf( 483*79dd8f69SMark Johnston "failed to look up gateway for %s\n", 484e5fff57dSMark Johnston server); 4850ff40d3dSMark Johnston gateway = server; 486e5fff57dSMark Johnston } 487*79dd8f69SMark Johnston } 4880ff40d3dSMark Johnston if (inet_aton(gateway, &ndconf.ndc_gateway) == 0) 4890ff40d3dSMark Johnston errx(EX_USAGE, "invalid gateway address '%s'", gateway); 490480f31c2SKonrad Witaszczyk 491480f31c2SKonrad Witaszczyk #ifdef HAVE_CRYPTO 492480f31c2SKonrad Witaszczyk if (pubkeyfile != NULL) 4930ff40d3dSMark Johnston genkey(pubkeyfile, kdap); 494480f31c2SKonrad Witaszczyk #endif 4950ff40d3dSMark Johnston error = ioctl(fd, NETDUMPSCONF, &ndconf); 4960ff40d3dSMark Johnston if (error != 0) 4970ff40d3dSMark Johnston error = errno; 4980ff40d3dSMark Johnston explicit_bzero(kdap->kda_encryptedkey, 4990ff40d3dSMark Johnston kdap->kda_encryptedkeysize); 5000ff40d3dSMark Johnston free(kdap->kda_encryptedkey); 5010ff40d3dSMark Johnston explicit_bzero(kdap, sizeof(*kdap)); 5020ff40d3dSMark Johnston if (error != 0) 5030ff40d3dSMark Johnston errc(EX_OSERR, error, "ioctl(NETDUMPSCONF)"); 50483f9dfabSGarrett Wollman } else { 5050ff40d3dSMark Johnston #ifdef HAVE_CRYPTO 5060ff40d3dSMark Johnston if (pubkeyfile != NULL) 5070ff40d3dSMark Johnston genkey(pubkeyfile, kdap); 5080ff40d3dSMark Johnston #endif 5090ff40d3dSMark Johnston error = ioctl(fd, DIOCSKERNELDUMP, kdap); 5100ff40d3dSMark Johnston if (error != 0) 5110ff40d3dSMark Johnston error = errno; 5120ff40d3dSMark Johnston explicit_bzero(kdap->kda_encryptedkey, 5130ff40d3dSMark Johnston kdap->kda_encryptedkeysize); 5140ff40d3dSMark Johnston free(kdap->kda_encryptedkey); 5150ff40d3dSMark Johnston explicit_bzero(kdap, sizeof(*kdap)); 5160ff40d3dSMark Johnston if (error != 0) 5170ff40d3dSMark Johnston errc(EX_OSERR, error, "ioctl(DIOCSKERNELDUMP)"); 51883f9dfabSGarrett Wollman } 5190ff40d3dSMark Johnston if (verbose) 5200ff40d3dSMark Johnston printf("kernel dumps on %s\n", dumpdev); 52183f9dfabSGarrett Wollman 5220ff40d3dSMark Johnston exit(EX_OK); 52383f9dfabSGarrett Wollman } 524