18fae3551SRodney W. Grimes /*- 2d503fad0SPoul-Henning Kamp * Copyright (c) 2002 Poul-Henning Kamp 3d503fad0SPoul-Henning Kamp * Copyright (c) 2002 Networks Associates Technology, Inc. 4d503fad0SPoul-Henning Kamp * All rights reserved. 5d503fad0SPoul-Henning Kamp * 6d503fad0SPoul-Henning Kamp * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7d503fad0SPoul-Henning Kamp * and NAI Labs, the Security Research Division of Network Associates, Inc. 8d503fad0SPoul-Henning Kamp * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9d503fad0SPoul-Henning Kamp * DARPA CHATS research program. 108fae3551SRodney W. Grimes * 118fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 128fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 138fae3551SRodney W. Grimes * are met: 148fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 158fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 168fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 178fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 188fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 19d503fad0SPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 20d503fad0SPoul-Henning Kamp * products derived from this software without specific prior written 21d503fad0SPoul-Henning Kamp * permission. 228fae3551SRodney W. Grimes * 23d503fad0SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 248fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 258fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26d503fad0SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 278fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 288fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 298fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 308fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 318fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 328fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 338fae3551SRodney W. Grimes * SUCH DAMAGE. 34d503fad0SPoul-Henning Kamp * 35d503fad0SPoul-Henning Kamp * $FreeBSD$ 368fae3551SRodney W. Grimes */ 378fae3551SRodney W. Grimes 388fae3551SRodney W. Grimes #include <stdio.h> 398fae3551SRodney W. Grimes #include <unistd.h> 40d503fad0SPoul-Henning Kamp #include <err.h> 41d503fad0SPoul-Henning Kamp #include <fcntl.h> 42d503fad0SPoul-Henning Kamp #include <fstab.h> 43d503fad0SPoul-Henning Kamp #include <errno.h> 44d503fad0SPoul-Henning Kamp #include <time.h> 45d503fad0SPoul-Henning Kamp #include <md5.h> 46d503fad0SPoul-Henning Kamp #include <unistd.h> 47d503fad0SPoul-Henning Kamp #include <sys/disklabel.h> 48d503fad0SPoul-Henning Kamp #include <sys/kerneldump.h> 49dff462c3SKris Kennaway 50d503fad0SPoul-Henning Kamp static void 515cb87b0cSMarcel Moolenaar printheader(FILE *f, const struct kerneldumpheader *h, const char *devname, 525cb87b0cSMarcel Moolenaar const char *md5) 53d503fad0SPoul-Henning Kamp { 545cb87b0cSMarcel Moolenaar uint64_t dumplen; 55d503fad0SPoul-Henning Kamp time_t t; 568fae3551SRodney W. Grimes 57d503fad0SPoul-Henning Kamp fprintf(f, "Good dump found on device %s\n", devname); 58d503fad0SPoul-Henning Kamp fprintf(f, " Architecture: %s\n", h->architecture); 595cb87b0cSMarcel Moolenaar fprintf(f, " Architecture version: %d\n", 605cb87b0cSMarcel Moolenaar dtoh32(h->architectureversion)); 615cb87b0cSMarcel Moolenaar dumplen = dtoh64(h->dumplength); 625cb87b0cSMarcel Moolenaar fprintf(f, " Dump length: %lldB (%lld MB)\n", (long long)dumplen, 635cb87b0cSMarcel Moolenaar (long long)(dumplen >> 20)); 645cb87b0cSMarcel Moolenaar fprintf(f, " Blocksize: %d\n", dtoh32(h->blocksize)); 655cb87b0cSMarcel Moolenaar t = dtoh64(h->dumptime); 66d503fad0SPoul-Henning Kamp fprintf(f, " Dumptime: %s", ctime(&t)); 67d503fad0SPoul-Henning Kamp fprintf(f, " Hostname: %s\n", h->hostname); 68d503fad0SPoul-Henning Kamp fprintf(f, " Versionstring: %s", h->versionstring); 69d503fad0SPoul-Henning Kamp fprintf(f, " Panicstring: %s\n", h->panicstring); 70d503fad0SPoul-Henning Kamp fprintf(f, " MD5: %s\n", md5); 71d503fad0SPoul-Henning Kamp } 728fae3551SRodney W. Grimes 738fae3551SRodney W. Grimes 74d503fad0SPoul-Henning Kamp static void 75d503fad0SPoul-Henning Kamp DoFile(const char *devname) 76d503fad0SPoul-Henning Kamp { 77d503fad0SPoul-Henning Kamp int fd, fdcore, fdinfo, error, wl; 78d503fad0SPoul-Henning Kamp off_t mediasize, dumpsize, firsthd, lasthd; 79d503fad0SPoul-Henning Kamp u_int sectorsize; 80d503fad0SPoul-Henning Kamp struct kerneldumpheader kdhf, kdhl; 81d503fad0SPoul-Henning Kamp char *md5; 82d503fad0SPoul-Henning Kamp FILE *info; 83d503fad0SPoul-Henning Kamp char buf[BUFSIZ]; 848fae3551SRodney W. Grimes 85d503fad0SPoul-Henning Kamp mediasize = 0; 86d503fad0SPoul-Henning Kamp fd = open(devname, O_RDONLY); 87d503fad0SPoul-Henning Kamp if (fd < 0) { 88d503fad0SPoul-Henning Kamp warn("%s", devname); 89d503fad0SPoul-Henning Kamp return; 90d503fad0SPoul-Henning Kamp } 91d503fad0SPoul-Henning Kamp error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); 92d503fad0SPoul-Henning Kamp if (!error) 93d503fad0SPoul-Henning Kamp error = ioctl(fd, DIOCGSECTORSIZE, §orsize); 94d503fad0SPoul-Henning Kamp if (error) { 95d503fad0SPoul-Henning Kamp warn("Couldn't find media and/or sector size of %s)", devname); 96d503fad0SPoul-Henning Kamp return; 97d503fad0SPoul-Henning Kamp } 983837db64SJohn Baldwin printf("Mediasize = %lld\n", (long long)mediasize); 99d503fad0SPoul-Henning Kamp printf("Sectorsize = %u\n", sectorsize); 100d503fad0SPoul-Henning Kamp lasthd = mediasize - sectorsize; 101d503fad0SPoul-Henning Kamp lseek(fd, lasthd, SEEK_SET); 102d503fad0SPoul-Henning Kamp error = read(fd, &kdhl, sizeof kdhl); 103d503fad0SPoul-Henning Kamp if (error != sizeof kdhl) { 104d503fad0SPoul-Henning Kamp warn("Error Reading last dump header at offset %lld in %s", 1053837db64SJohn Baldwin (long long)lasthd, devname); 106d503fad0SPoul-Henning Kamp return; 107d503fad0SPoul-Henning Kamp } 108d503fad0SPoul-Henning Kamp if (kerneldump_parity(&kdhl)) { 109d503fad0SPoul-Henning Kamp warnx("Parity error on last dump header on %s\n", devname); 110d503fad0SPoul-Henning Kamp return; 111d503fad0SPoul-Henning Kamp } 112d503fad0SPoul-Henning Kamp if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic)) { 113d503fad0SPoul-Henning Kamp warnx("Magic mismatch on last dump header on %s\n", devname); 114d503fad0SPoul-Henning Kamp return; 115d503fad0SPoul-Henning Kamp } 1165cb87b0cSMarcel Moolenaar if (dtoh32(kdhl.version) != KERNELDUMPVERSION) { 117d503fad0SPoul-Henning Kamp warnx("Unknown version (%d) in last dump header on %s\n", 1185cb87b0cSMarcel Moolenaar dtoh32(kdhl.version), devname); 119d503fad0SPoul-Henning Kamp return; 120d503fad0SPoul-Henning Kamp } 1215cb87b0cSMarcel Moolenaar dumpsize = dtoh64(kdhl.dumplength); 1225cb87b0cSMarcel Moolenaar firsthd = lasthd - dumpsize - sizeof kdhf; 123d503fad0SPoul-Henning Kamp lseek(fd, firsthd, SEEK_SET); 124d503fad0SPoul-Henning Kamp error = read(fd, &kdhf, sizeof kdhf); 125d503fad0SPoul-Henning Kamp if (error != sizeof kdhf) { 126d503fad0SPoul-Henning Kamp warn("Error Reading first dump header at offset %lld in %s", 1273837db64SJohn Baldwin (long long)firsthd, devname); 128d503fad0SPoul-Henning Kamp return; 129d503fad0SPoul-Henning Kamp } 130d503fad0SPoul-Henning Kamp if (memcmp(&kdhl, &kdhf, sizeof kdhl)) { 131d503fad0SPoul-Henning Kamp warn("First and last dump headers disagree on %s\n", devname); 132d503fad0SPoul-Henning Kamp return; 133d503fad0SPoul-Henning Kamp } 134d503fad0SPoul-Henning Kamp md5 = MD5Data((unsigned char *)&kdhl, sizeof kdhl, NULL); 135d503fad0SPoul-Henning Kamp sprintf(buf, "%s.info", md5); 136d503fad0SPoul-Henning Kamp fdinfo = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0600); 137d503fad0SPoul-Henning Kamp if (fdinfo < 0 && errno == EEXIST) { 138d503fad0SPoul-Henning Kamp printf("Dump on device %s already saved\n", devname); 139d503fad0SPoul-Henning Kamp return; 140d503fad0SPoul-Henning Kamp } 141d503fad0SPoul-Henning Kamp if (fdinfo < 0) { 142d503fad0SPoul-Henning Kamp warn("%s", buf); 143d503fad0SPoul-Henning Kamp return; 144d503fad0SPoul-Henning Kamp } 145d503fad0SPoul-Henning Kamp sprintf(buf, "%s.core", md5); 146d503fad0SPoul-Henning Kamp fdcore = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0600); 147d503fad0SPoul-Henning Kamp if (fdcore < 0) { 148d503fad0SPoul-Henning Kamp warn("%s", buf); 149d503fad0SPoul-Henning Kamp return; 150d503fad0SPoul-Henning Kamp } 151d503fad0SPoul-Henning Kamp info = fdopen(fdinfo, "w"); 152d503fad0SPoul-Henning Kamp printheader(stdout, &kdhl, devname, md5); 153d503fad0SPoul-Henning Kamp printheader(info, &kdhl, devname, md5); 154d503fad0SPoul-Henning Kamp printf("Saving dump to file...\n"); 155d503fad0SPoul-Henning Kamp while (dumpsize > 0) { 156d503fad0SPoul-Henning Kamp wl = sizeof(buf); 157d503fad0SPoul-Henning Kamp if (wl > dumpsize) 158d503fad0SPoul-Henning Kamp wl = dumpsize; 159d503fad0SPoul-Henning Kamp error = read(fd, buf, wl); 160d503fad0SPoul-Henning Kamp if (error != wl) { 161d503fad0SPoul-Henning Kamp warn("read error on %s\n", devname); 162d503fad0SPoul-Henning Kamp return; 163d503fad0SPoul-Henning Kamp } 164d503fad0SPoul-Henning Kamp error = write(fdcore, buf, wl); 165d503fad0SPoul-Henning Kamp if (error != wl) { 166d503fad0SPoul-Henning Kamp warn("write error on %s.core file\n", md5); 167d503fad0SPoul-Henning Kamp return; 168d503fad0SPoul-Henning Kamp } 169d503fad0SPoul-Henning Kamp dumpsize -= wl; 170d503fad0SPoul-Henning Kamp } 171d503fad0SPoul-Henning Kamp close (fdinfo); 172d503fad0SPoul-Henning Kamp close (fdcore); 173d503fad0SPoul-Henning Kamp printf("Dump saved\n"); 174d503fad0SPoul-Henning Kamp } 1759b0a8ba3SPeter Wemm 176d503fad0SPoul-Henning Kamp static void 177d503fad0SPoul-Henning Kamp usage(void) 178d503fad0SPoul-Henning Kamp { 179d503fad0SPoul-Henning Kamp errx(1, "usage: ..."); 180d503fad0SPoul-Henning Kamp exit (1); 181d503fad0SPoul-Henning Kamp } 1828fae3551SRodney W. Grimes 1838fae3551SRodney W. Grimes int 184d503fad0SPoul-Henning Kamp main(int argc, char **argv) 1858fae3551SRodney W. Grimes { 186d503fad0SPoul-Henning Kamp int i, ch, error; 187d503fad0SPoul-Henning Kamp struct fstab *fsp; 1888fae3551SRodney W. Grimes 189867dd038SDag-Erling Smørgrav while ((ch = getopt(argc, argv, "cdfkN:vz")) != -1) 1908fae3551SRodney W. Grimes switch(ch) { 1918fae3551SRodney W. Grimes case 'c': 192d503fad0SPoul-Henning Kamp case 'd': 1938fae3551SRodney W. Grimes case 'v': 1948fae3551SRodney W. Grimes case 'f': 195532c1901SDag-Erling Smørgrav case 'k': 1968fae3551SRodney W. Grimes case 'N': 1978fae3551SRodney W. Grimes case 'z': 1988fae3551SRodney W. Grimes case '?': 1998fae3551SRodney W. Grimes default: 2008fae3551SRodney W. Grimes usage(); 2018fae3551SRodney W. Grimes } 2028fae3551SRodney W. Grimes argc -= optind; 2038fae3551SRodney W. Grimes argv += optind; 204d503fad0SPoul-Henning Kamp if (argc >= 1) { 205d503fad0SPoul-Henning Kamp error = chdir(argv[0]); 206d503fad0SPoul-Henning Kamp if (error) 207d503fad0SPoul-Henning Kamp err(1, "chdir(%s)", argv[0]); 208d503fad0SPoul-Henning Kamp argc--; 209d503fad0SPoul-Henning Kamp argv++; 2108fae3551SRodney W. Grimes } 211d503fad0SPoul-Henning Kamp if (argc == 0) { 212d503fad0SPoul-Henning Kamp for (;;) { 213d503fad0SPoul-Henning Kamp fsp = getfsent(); 214d503fad0SPoul-Henning Kamp if (fsp == NULL) 215d503fad0SPoul-Henning Kamp break; 216d503fad0SPoul-Henning Kamp if (strcmp(fsp->fs_vfstype, "swap") && 217d503fad0SPoul-Henning Kamp strcmp(fsp->fs_vfstype, "dump")) 218d503fad0SPoul-Henning Kamp continue; 219d503fad0SPoul-Henning Kamp DoFile(fsp->fs_spec); 2208fae3551SRodney W. Grimes } 221dff462c3SKris Kennaway } else { 222d503fad0SPoul-Henning Kamp for (i = 0; i < argc; i++) 223d503fad0SPoul-Henning Kamp DoFile(argv[i]); 224532c1901SDag-Erling Smørgrav } 225c74e16f9SDag-Erling Smørgrav return (0); 226c74e16f9SDag-Erling Smørgrav } 227