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 51d503fad0SPoul-Henning Kamp printheader(FILE *f, const struct kerneldumpheader *h, const char *devname, const char *md5) 52d503fad0SPoul-Henning Kamp { 53d503fad0SPoul-Henning Kamp time_t t; 548fae3551SRodney W. Grimes 55d503fad0SPoul-Henning Kamp fprintf(f, "Good dump found on device %s\n", devname); 56d503fad0SPoul-Henning Kamp fprintf(f, " Architecture: %s\n", h->architecture); 57d503fad0SPoul-Henning Kamp fprintf(f, " Architecture version: %d\n", h->architectureversion); 58d503fad0SPoul-Henning Kamp fprintf(f, " Dump length: %lldB (%lld MB)\n", 59d503fad0SPoul-Henning Kamp h->dumplength, h->dumplength / (1024 * 1024)); 60d503fad0SPoul-Henning Kamp fprintf(f, " Blocksize: %d\n", h->blocksize); 61d503fad0SPoul-Henning Kamp t = h->dumptime; 62d503fad0SPoul-Henning Kamp fprintf(f, " Dumptime: %s", ctime(&t)); 63d503fad0SPoul-Henning Kamp fprintf(f, " Hostname: %s\n", h->hostname); 64d503fad0SPoul-Henning Kamp fprintf(f, " Versionstring: %s", h->versionstring); 65d503fad0SPoul-Henning Kamp fprintf(f, " Panicstring: %s\n", h->panicstring); 66d503fad0SPoul-Henning Kamp fprintf(f, " MD5: %s\n", md5); 67d503fad0SPoul-Henning Kamp } 688fae3551SRodney W. Grimes 698fae3551SRodney W. Grimes 70d503fad0SPoul-Henning Kamp static void 71d503fad0SPoul-Henning Kamp DoFile(const char *devname) 72d503fad0SPoul-Henning Kamp { 73d503fad0SPoul-Henning Kamp int fd, fdcore, fdinfo, error, wl; 74d503fad0SPoul-Henning Kamp off_t mediasize, dumpsize, firsthd, lasthd; 75d503fad0SPoul-Henning Kamp u_int sectorsize; 76d503fad0SPoul-Henning Kamp struct kerneldumpheader kdhf, kdhl; 77d503fad0SPoul-Henning Kamp char *md5; 78d503fad0SPoul-Henning Kamp FILE *info; 79d503fad0SPoul-Henning Kamp char buf[BUFSIZ]; 808fae3551SRodney W. Grimes 81d503fad0SPoul-Henning Kamp mediasize = 0; 82d503fad0SPoul-Henning Kamp fd = open(devname, O_RDONLY); 83d503fad0SPoul-Henning Kamp if (fd < 0) { 84d503fad0SPoul-Henning Kamp warn("%s", devname); 85d503fad0SPoul-Henning Kamp return; 86d503fad0SPoul-Henning Kamp } 87d503fad0SPoul-Henning Kamp error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); 88d503fad0SPoul-Henning Kamp if (!error) 89d503fad0SPoul-Henning Kamp error = ioctl(fd, DIOCGSECTORSIZE, §orsize); 90d503fad0SPoul-Henning Kamp if (error) { 91d503fad0SPoul-Henning Kamp warn("Couldn't find media and/or sector size of %s)", devname); 92d503fad0SPoul-Henning Kamp return; 93d503fad0SPoul-Henning Kamp } 94d503fad0SPoul-Henning Kamp printf("Mediasize = %lld\n", mediasize); 95d503fad0SPoul-Henning Kamp printf("Sectorsize = %u\n", sectorsize); 96d503fad0SPoul-Henning Kamp lasthd = mediasize - sectorsize; 97d503fad0SPoul-Henning Kamp lseek(fd, lasthd, SEEK_SET); 98d503fad0SPoul-Henning Kamp error = read(fd, &kdhl, sizeof kdhl); 99d503fad0SPoul-Henning Kamp if (error != sizeof kdhl) { 100d503fad0SPoul-Henning Kamp warn("Error Reading last dump header at offset %lld in %s", 101d503fad0SPoul-Henning Kamp lasthd, devname); 102d503fad0SPoul-Henning Kamp return; 103d503fad0SPoul-Henning Kamp } 104d503fad0SPoul-Henning Kamp if (kerneldump_parity(&kdhl)) { 105d503fad0SPoul-Henning Kamp warnx("Parity error on last dump header on %s\n", devname); 106d503fad0SPoul-Henning Kamp return; 107d503fad0SPoul-Henning Kamp } 108d503fad0SPoul-Henning Kamp if (memcmp(kdhl.magic, KERNELDUMPMAGIC, sizeof kdhl.magic)) { 109d503fad0SPoul-Henning Kamp warnx("Magic mismatch on last dump header on %s\n", devname); 110d503fad0SPoul-Henning Kamp return; 111d503fad0SPoul-Henning Kamp } 112d503fad0SPoul-Henning Kamp if (kdhl.version != KERNELDUMPVERSION) { 113d503fad0SPoul-Henning Kamp warnx("Unknown version (%d) in last dump header on %s\n", 114d503fad0SPoul-Henning Kamp kdhl.version, devname); 115d503fad0SPoul-Henning Kamp return; 116d503fad0SPoul-Henning Kamp } 117d503fad0SPoul-Henning Kamp firsthd = lasthd - kdhl.dumplength - sizeof kdhf; 118d503fad0SPoul-Henning Kamp lseek(fd, firsthd, SEEK_SET); 119d503fad0SPoul-Henning Kamp error = read(fd, &kdhf, sizeof kdhf); 120d503fad0SPoul-Henning Kamp if (error != sizeof kdhf) { 121d503fad0SPoul-Henning Kamp warn("Error Reading first dump header at offset %lld in %s", 122d503fad0SPoul-Henning Kamp firsthd, devname); 123d503fad0SPoul-Henning Kamp return; 124d503fad0SPoul-Henning Kamp } 125d503fad0SPoul-Henning Kamp if (memcmp(&kdhl, &kdhf, sizeof kdhl)) { 126d503fad0SPoul-Henning Kamp warn("First and last dump headers disagree on %s\n", devname); 127d503fad0SPoul-Henning Kamp return; 128d503fad0SPoul-Henning Kamp } 129d503fad0SPoul-Henning Kamp md5 = MD5Data((unsigned char *)&kdhl, sizeof kdhl, NULL); 130d503fad0SPoul-Henning Kamp sprintf(buf, "%s.info", md5); 131d503fad0SPoul-Henning Kamp fdinfo = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0600); 132d503fad0SPoul-Henning Kamp if (fdinfo < 0 && errno == EEXIST) { 133d503fad0SPoul-Henning Kamp printf("Dump on device %s already saved\n", devname); 134d503fad0SPoul-Henning Kamp return; 135d503fad0SPoul-Henning Kamp } 136d503fad0SPoul-Henning Kamp if (fdinfo < 0) { 137d503fad0SPoul-Henning Kamp warn("%s", buf); 138d503fad0SPoul-Henning Kamp return; 139d503fad0SPoul-Henning Kamp } 140d503fad0SPoul-Henning Kamp sprintf(buf, "%s.core", md5); 141d503fad0SPoul-Henning Kamp fdcore = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0600); 142d503fad0SPoul-Henning Kamp if (fdcore < 0) { 143d503fad0SPoul-Henning Kamp warn("%s", buf); 144d503fad0SPoul-Henning Kamp return; 145d503fad0SPoul-Henning Kamp } 146d503fad0SPoul-Henning Kamp info = fdopen(fdinfo, "w"); 147d503fad0SPoul-Henning Kamp printheader(stdout, &kdhl, devname, md5); 148d503fad0SPoul-Henning Kamp printheader(info, &kdhl, devname, md5); 149d503fad0SPoul-Henning Kamp dumpsize = kdhl.dumplength; 150d503fad0SPoul-Henning Kamp printf("Saving dump to file...\n"); 151d503fad0SPoul-Henning Kamp while (dumpsize > 0) { 152d503fad0SPoul-Henning Kamp wl = sizeof(buf); 153d503fad0SPoul-Henning Kamp if (wl > dumpsize) 154d503fad0SPoul-Henning Kamp wl = dumpsize; 155d503fad0SPoul-Henning Kamp error = read(fd, buf, wl); 156d503fad0SPoul-Henning Kamp if (error != wl) { 157d503fad0SPoul-Henning Kamp warn("read error on %s\n", devname); 158d503fad0SPoul-Henning Kamp return; 159d503fad0SPoul-Henning Kamp } 160d503fad0SPoul-Henning Kamp error = write(fdcore, buf, wl); 161d503fad0SPoul-Henning Kamp if (error != wl) { 162d503fad0SPoul-Henning Kamp warn("write error on %s.core file\n", md5); 163d503fad0SPoul-Henning Kamp return; 164d503fad0SPoul-Henning Kamp } 165d503fad0SPoul-Henning Kamp dumpsize -= wl; 166d503fad0SPoul-Henning Kamp } 167d503fad0SPoul-Henning Kamp close (fdinfo); 168d503fad0SPoul-Henning Kamp close (fdcore); 169d503fad0SPoul-Henning Kamp printf("Dump saved\n"); 170d503fad0SPoul-Henning Kamp } 1719b0a8ba3SPeter Wemm 172d503fad0SPoul-Henning Kamp static void 173d503fad0SPoul-Henning Kamp usage(void) 174d503fad0SPoul-Henning Kamp { 175d503fad0SPoul-Henning Kamp errx(1, "usage: ..."); 176d503fad0SPoul-Henning Kamp exit (1); 177d503fad0SPoul-Henning Kamp } 1788fae3551SRodney W. Grimes 1798fae3551SRodney W. Grimes int 180d503fad0SPoul-Henning Kamp main(int argc, char **argv) 1818fae3551SRodney W. Grimes { 182d503fad0SPoul-Henning Kamp int i, ch, error; 183d503fad0SPoul-Henning Kamp struct fstab *fsp; 1848fae3551SRodney W. Grimes 185867dd038SDag-Erling Smørgrav while ((ch = getopt(argc, argv, "cdfkN:vz")) != -1) 1868fae3551SRodney W. Grimes switch(ch) { 1878fae3551SRodney W. Grimes case 'c': 188d503fad0SPoul-Henning Kamp case 'd': 1898fae3551SRodney W. Grimes case 'v': 1908fae3551SRodney W. Grimes case 'f': 191532c1901SDag-Erling Smørgrav case 'k': 1928fae3551SRodney W. Grimes case 'N': 1938fae3551SRodney W. Grimes case 'z': 1948fae3551SRodney W. Grimes case '?': 1958fae3551SRodney W. Grimes default: 1968fae3551SRodney W. Grimes usage(); 1978fae3551SRodney W. Grimes } 1988fae3551SRodney W. Grimes argc -= optind; 1998fae3551SRodney W. Grimes argv += optind; 200d503fad0SPoul-Henning Kamp if (argc >= 1) { 201d503fad0SPoul-Henning Kamp error = chdir(argv[0]); 202d503fad0SPoul-Henning Kamp if (error) 203d503fad0SPoul-Henning Kamp err(1, "chdir(%s)", argv[0]); 204d503fad0SPoul-Henning Kamp argc--; 205d503fad0SPoul-Henning Kamp argv++; 2068fae3551SRodney W. Grimes } 207d503fad0SPoul-Henning Kamp if (argc == 0) { 208d503fad0SPoul-Henning Kamp for (;;) { 209d503fad0SPoul-Henning Kamp fsp = getfsent(); 210d503fad0SPoul-Henning Kamp if (fsp == NULL) 211d503fad0SPoul-Henning Kamp break; 212d503fad0SPoul-Henning Kamp if (strcmp(fsp->fs_vfstype, "swap") && 213d503fad0SPoul-Henning Kamp strcmp(fsp->fs_vfstype, "dump")) 214d503fad0SPoul-Henning Kamp continue; 215d503fad0SPoul-Henning Kamp DoFile(fsp->fs_spec); 2168fae3551SRodney W. Grimes } 217dff462c3SKris Kennaway } else { 218d503fad0SPoul-Henning Kamp for (i = 0; i < argc; i++) 219d503fad0SPoul-Henning Kamp DoFile(argv[i]); 220532c1901SDag-Erling Smørgrav } 221c74e16f9SDag-Erling Smørgrav return (0); 222c74e16f9SDag-Erling Smørgrav } 223