X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/dab41bbd1ec200c11d797c74181cbbf80c5707e2..refs/pull/435/head:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 39811867..8e07d8f2 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -43,6 +43,17 @@ The Regents of the University of California. All rights reserved.\n"; #include "config.h" #endif +/* + * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on + * 0.8. That means it has pcap_findalldevs() but the header doesn't + * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs(). + */ +#ifdef HAVE_PCAP_FINDALLDEVS +#ifndef HAVE_PCAP_IF_T +#undef HAVE_PCAP_FINDALLDEVS +#endif +#endif + #include #ifdef WIN32 @@ -53,7 +64,7 @@ extern int SIZE_BUF; #define uint UINT #endif /* WIN32 */ -#ifdef HAVE_SMI_H +#ifdef USE_LIBSMI #include #endif @@ -66,6 +77,17 @@ extern int SIZE_BUF; #else #include "getopt_long.h" #endif +/* Capsicum-specific code requires macros from , which will fail + * to compile if has already been included; including the headers + * in the opposite order works fine. + */ +#ifdef HAVE_CAPSICUM +#include +#include +#include +#include +#include +#endif /* HAVE_CAPSICUM */ #include #include #include @@ -79,10 +101,18 @@ extern int SIZE_BUF; #include #endif /* WIN32 */ -/* capabilities convinience library */ +/* capabilities convenience library */ +/* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. + * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. + * Thus, the later tests are done only on HAVE_LIBCAP_NG. + */ +#ifdef HAVE_LIBCAP_NG #ifdef HAVE_CAP_NG_H #include +#else +#undef HAVE_LIBCAP_NG #endif /* HAVE_CAP_NG_H */ +#endif /* HAVE_LIBCAP_NG */ #include "netdissect.h" #include "interface.h" @@ -441,6 +471,9 @@ struct dump_info { char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; +#ifdef HAVE_CAPSICUM + int dirfd; +#endif }; #ifdef HAVE_PCAP_SET_TSTAMP_TYPE @@ -604,12 +637,6 @@ show_devices_and_exit (void) #define J_FLAG #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ -#ifdef HAVE_PCAP_FINDALLDEVS -#ifndef HAVE_PCAP_IF_T -#undef HAVE_PCAP_FINDALLDEVS -#endif -#endif - #ifdef HAVE_PCAP_FINDALLDEVS #define D_FLAG "D" #else @@ -648,10 +675,11 @@ show_devices_and_exit (void) * component of the entry for the long option, and have a case for that * option in the switch statement. */ -#define OPTION_NUMBER 128 -#define OPTION_VERSION 129 +#define OPTION_VERSION 128 +#define OPTION_TSTAMP_PRECISION 129 +#define OPTION_IMMEDIATE_MODE 130 -static struct option longopts[] = { +static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(WIN32) { "buffer-size", required_argument, NULL, 'B' }, #endif @@ -664,6 +692,9 @@ static struct option longopts[] = { #ifdef HAVE_PCAP_SET_TSTAMP_TYPE { "time-stamp-type", required_argument, NULL, 'j' }, { "list-time-stamp-types", no_argument, NULL, 'J' }, +#endif +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, #endif { "dont-verify-checksums", no_argument, NULL, 'K' }, { "list-data-link-types", no_argument, NULL, 'L' }, @@ -678,11 +709,14 @@ static struct option longopts[] = { { "packet-buffered", no_argument, NULL, 'U' }, #endif { "linktype", required_argument, NULL, 'y' }, +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, +#endif #if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) { "debug-filter-parser", no_argument, NULL, 'Y' }, #endif { "relinquish-privileges", required_argument, NULL, 'Z' }, - { "number", no_argument, NULL, OPTION_NUMBER }, + { "number", no_argument, NULL, '#' }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, 0, NULL, 0 } }; @@ -708,18 +742,14 @@ droproot(const char *username, const char *chroot_dir) exit(1); } } -#ifdef HAVE_CAP_NG_H +#ifdef HAVE_LIBCAP_NG int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); if (ret < 0) { - printf("error : ret %d\n", ret); + fprintf(stderr, "error : ret %d\n", ret); + } + else { + fprintf(stderr, "dropped privs to %s\n", username); } - /* We don't need CAP_SETUID and CAP_SETGID */ - capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); - capng_apply(CAPNG_SELECT_BOTH); - #else if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { @@ -730,13 +760,27 @@ droproot(const char *username, const char *chroot_dir) pcap_strerror(errno)); exit(1); } -#endif /* HAVE_CAP_NG_H */ + else { + fprintf(stderr, "dropped privs to %s\n", username); + } +#endif /* HAVE_LIBCAP_NG */ } else { fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", username); exit(1); } +#ifdef HAVE_LIBCAP_NG + /* We don't need CAP_SETUID and CAP_SETGID any more. */ + capng_updatev( + CAPNG_DROP, + CAPNG_EFFECTIVE | CAPNG_PERMITTED, + CAP_SETUID, + CAP_SETGID, + -1); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ + } #endif /* WIN32 */ @@ -840,6 +884,36 @@ get_next_file(FILE *VFile, char *ptr) return ret; } +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION +static int +tstamp_precision_from_string(const char *precision) +{ + if (strncmp(precision, "nano", strlen("nano")) == 0) + return PCAP_TSTAMP_PRECISION_NANO; + + if (strncmp(precision, "micro", strlen("micro")) == 0) + return PCAP_TSTAMP_PRECISION_MICRO; + + return -EINVAL; +} + +static const char * +tstamp_precision_to_string(int precision) +{ + switch (precision) { + + case PCAP_TSTAMP_PRECISION_MICRO: + return "micro"; + + case PCAP_TSTAMP_PRECISION_NANO: + return "nano"; + + default: + return "unknown"; + } +} +#endif + int main(int argc, char **argv) { @@ -870,6 +944,11 @@ main(int argc, char **argv) #endif int status; FILE *VFile; +#ifdef HAVE_CAPSICUM + cap_rights_t rights; + int cansandbox; +#endif /* HAVE_CAPSICUM */ + #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ @@ -883,6 +962,7 @@ main(int argc, char **argv) gndo->ndo_error=ndo_error; gndo->ndo_warning=ndo_warning; gndo->ndo_snaplen = DEFAULT_SNAPLEN; + gndo->ndo_immediate = 0; cnt = -1; device = NULL; @@ -897,15 +977,22 @@ main(int argc, char **argv) else program_name = argv[0]; + /* + * On platforms where the CPU doesn't support unaligned loads, + * force unaligned accesses to abort with SIGBUS, rather than + * being fixed up (slowly) by the OS kernel; on those platforms, + * misaligned accesses are bugs, and we want tcpdump to crash so + * that the bugs are reported. + */ if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) error("%s", ebuf); -#ifdef LIBSMI +#ifdef USE_LIBSMI smiInit("tcpdump"); #endif while ( - (op = getopt_long(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:", longopts, NULL)) != -1) + (op = getopt_long(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#", longopts, NULL)) != -1) switch (op) { case 'a': @@ -1081,7 +1168,7 @@ main(int argc, char **argv) break; case 'm': -#ifdef LIBSMI +#ifdef USE_LIBSMI if (smiLoadModule(optarg) == 0) { error("could not load MIB module %s", optarg); } @@ -1266,7 +1353,7 @@ main(int argc, char **argv) username = strdup(optarg); break; - case OPTION_NUMBER: + case '#': gndo->ndo_packet_number = 1; break; @@ -1275,6 +1362,20 @@ main(int argc, char **argv) exit(0); break; +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + case OPTION_TSTAMP_PRECISION: + gndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); + if (gndo->ndo_tstamp_precision < 0) + error("unsupported time stamp precision"); + break; +#endif + +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + case OPTION_IMMEDIATE_MODE: + gndo->ndo_immediate = 1; + break; +#endif + default: print_usage(); exit(1); @@ -1310,6 +1411,17 @@ main(int argc, char **argv) if (VFileName != NULL && RFileName != NULL) error("-V and -r are mutually exclusive."); +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + /* + * If we're printing dissected packets to the standard output + * rather than saving raw packets to a file, and the standard + * output is a terminal, use immediate mode, as the user's + * probably expecting to see packets pop up immediately. + */ + if (WFileName == NULL && isatty(1)) + gndo->ndo_immediate = 1; +#endif + #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ if (getuid() == 0 || geteuid() == 0) { @@ -1366,9 +1478,22 @@ main(int argc, char **argv) RFileName = VFileLine; } +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + pd = pcap_open_offline_with_tstamp_precision(RFileName, + gndo->ndo_tstamp_precision, ebuf); +#else pd = pcap_open_offline(RFileName, ebuf); +#endif + if (pd == NULL) error("%s", ebuf); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } +#endif dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { @@ -1412,6 +1537,24 @@ main(int argc, char **argv) #ifdef HAVE_PCAP_SET_TSTAMP_TYPE if (Jflag) show_tstamp_types_and_exit(device, pd); +#endif +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + status = pcap_set_tstamp_precision(pd, gndo->ndo_tstamp_precision); + if (status != 0) + error("%s: Can't set %ssecond time stamp precision: %s", + device, + tstamp_precision_to_string(gndo->ndo_tstamp_precision), + pcap_statustostr(status)); +#endif + +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + if (gndo->ndo_immediate) { + status = pcap_set_immediate_mode(pd, 1); + if (status != 0) + error("%s: Can't set immediate mode: %s", + device, + pcap_statustostr(status)); + } #endif /* * Is this an interface that supports monitor mode? @@ -1449,7 +1592,7 @@ main(int argc, char **argv) status = pcap_set_tstamp_type(pd, jflag); if (status < 0) error("%s: Can't set time stamp type: %s", - device, pcap_statustostr(status)); + device, pcap_statustostr(status)); } #endif status = pcap_activate(pd); @@ -1595,27 +1738,28 @@ main(int argc, char **argv) * savefile doesn't handle the general case. */ -#ifdef HAVE_CAP_NG_H - /* We are running as root and we will be writing to savefile */ - if ((getuid() == 0 || geteuid() == 0) && WFileName) { + if (getuid() == 0 || geteuid() == 0) { +#ifdef HAVE_LIBCAP_NG + /* Initialize capng */ + capng_clear(CAPNG_SELECT_BOTH); if (username) { - /* Drop all capabilities from effective set */ - capng_clear(CAPNG_EFFECTIVE); - /* Add capabilities we will need*/ - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID); - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID); - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE); - - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID); - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - - capng_apply(CAPNG_SELECT_BOTH); + capng_updatev( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, + CAP_SETUID, + CAP_SETGID, + -1); } - } -#endif /* HAVE_CAP_NG_H */ - if (getuid() == 0 || geteuid() == 0) { + if (WFileName) { + capng_update( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, + CAP_DAC_OVERRIDE + ); + } + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (username || chroot_dir) droproot(username, chroot_dir); @@ -1624,6 +1768,21 @@ main(int argc, char **argv) if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + if (RFileName == NULL && VFileName == NULL) { + static const unsigned long cmds[] = { BIOCGSTATS }; + + cap_rights_init(&rights, CAP_IOCTL, CAP_READ); + if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } + if (cap_ioctls_limit(pcap_fileno(pd), cmds, + sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { + error("unable to limit ioctls on pcap descriptor"); + } + } +#endif if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ @@ -1639,15 +1798,47 @@ main(int argc, char **argv) MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); p = pcap_dump_open(pd, dumpinfo.CurrentFileName); -#ifdef HAVE_CAP_NG_H - /* Give up capabilities, clear Effective set */ - capng_clear(CAPNG_EFFECTIVE); -#endif +#ifdef HAVE_LIBCAP_NG + /* Give up CAP_DAC_OVERRIDE capability. + * Only allow it to be restored if the -C or -G flag have been + * set since we may need to create more files later on. + */ + capng_update( + CAPNG_DROP, + (Cflag || Gflag ? 0 : CAPNG_PERMITTED) + | CAPNG_EFFECTIVE, + CAP_DAC_OVERRIDE + ); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (p == NULL) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif if (Cflag != 0 || Gflag != 0) { - callback = dump_packet_and_trunc; +#ifdef HAVE_CAPSICUM + dumpinfo.WFileName = strdup(basename(WFileName)); + dumpinfo.dirfd = open(dirname(WFileName), + O_DIRECTORY | O_RDONLY); + if (dumpinfo.dirfd < 0) { + error("unable to open directory %s", + dirname(WFileName)); + } + cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, + CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && + errno != ENOSYS) { + error("unable to limit directory rights"); + } +#else /* !HAVE_CAPSICUM */ dumpinfo.WFileName = WFileName; +#endif + callback = dump_packet_and_trunc; dumpinfo.pd = pd; dumpinfo.p = p; pcap_userdata = (u_char *)&dumpinfo; @@ -1717,6 +1908,15 @@ main(int argc, char **argv) (void)fflush(stderr); } #endif /* WIN32 */ + +#ifdef HAVE_CAPSICUM + cansandbox = (nflag && VFileName == NULL && zflag == NULL); + if (cansandbox && cap_enter() < 0 && errno != ENOSYS) + error("unable to enter the capability mode"); + if (cap_sandboxed()) + fprintf(stderr, "capability mode sandbox enabled\n"); +#endif /* HAVE_CAPSICUM */ + do { status = pcap_loop(pd, cnt, callback, pcap_userdata); if (WFileName == NULL) { @@ -1764,6 +1964,13 @@ main(int argc, char **argv) pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) error("%s", ebuf); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_READ); + if (cap_rights_limit(fileno(pcap_file(pd)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } +#endif new_dlt = pcap_datalink(pd); if (WFileName && new_dlt != dlt) error("%s: new dlt does not match original", RFileName); @@ -1932,6 +2139,9 @@ static void dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct dump_info *dump_info; +#ifdef HAVE_CAPSICUM + cap_rights_t rights; +#endif ++packets_captured; @@ -1960,6 +2170,11 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* If the time is greater than the specified window, rotate */ if (t - Gflag_time >= Gflag) { +#ifdef HAVE_CAPSICUM + FILE *fp; + int fd; +#endif + /* Update the Gflag_time */ Gflag_time = t; /* Update Gflag_count */ @@ -2009,17 +2224,40 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s else MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); -#ifdef HAVE_CAP_NG_H +#ifdef HAVE_LIBCAP_NG capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - capng_apply(CAPNG_EFFECTIVE); -#endif /* HAVE_CAP_NG_H */ + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ +#ifdef HAVE_CAPSICUM + fd = openat(dump_info->dirfd, + dump_info->CurrentFileName, + O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + error("unable to open file %s", + dump_info->CurrentFileName); + } + fp = fdopen(fd, "w"); + if (fp == NULL) { + error("unable to fdopen file %s", + dump_info->CurrentFileName); + } + dump_info->p = pcap_dump_fopen(dump_info->pd, fp); +#else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); -#ifdef HAVE_CAP_NG_H +#endif +#ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - capng_apply(CAPNG_EFFECTIVE); -#endif /* HAVE_CAP_NG_H */ + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif } } @@ -2028,32 +2266,74 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * larger than Cflag - the last packet written to the * file could put it over Cflag. */ - if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { - /* - * Close the current file and open a new one. - */ - pcap_dump_close(dump_info->p); + if (Cflag != 0) { + long size = pcap_dump_ftell(dump_info->p); - /* - * Compress the file we just closed, if the user asked for it - */ - if (zflag != NULL) - compress_savefile(dump_info->CurrentFileName); + if (size == -1) + error("ftell fails on output file"); + if (size > Cflag) { +#ifdef HAVE_CAPSICUM + FILE *fp; + int fd; +#endif + + /* + * Close the current file and open a new one. + */ + pcap_dump_close(dump_info->p); - Cflag_count++; - if (Wflag > 0) { - if (Cflag_count >= Wflag) - Cflag_count = 0; + /* + * Compress the file we just closed, if the user + * asked for it. + */ + if (zflag != NULL) + compress_savefile(dump_info->CurrentFileName); + + Cflag_count++; + if (Wflag > 0) { + if (Cflag_count >= Wflag) + Cflag_count = 0; + } + if (dump_info->CurrentFileName != NULL) + free(dump_info->CurrentFileName); + dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); + if (dump_info->CurrentFileName == NULL) + error("dump_packet_and_trunc: malloc"); + MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); +#ifdef HAVE_LIBCAP_NG + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ +#ifdef HAVE_CAPSICUM + fd = openat(dump_info->dirfd, dump_info->CurrentFileName, + O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + error("unable to open file %s", + dump_info->CurrentFileName); + } + fp = fdopen(fd, "w"); + if (fp == NULL) { + error("unable to fdopen file %s", + dump_info->CurrentFileName); + } + dump_info->p = pcap_dump_fopen(dump_info->pd, fp); +#else /* !HAVE_CAPSICUM */ + dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); +#endif +#ifdef HAVE_LIBCAP_NG + capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ + if (dump_info->p == NULL) + error("%s", pcap_geterr(pd)); +#ifdef HAVE_CAPSICUM + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), + &rights) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor"); + } +#endif } - if (dump_info->CurrentFileName != NULL) - free(dump_info->CurrentFileName); - dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); - if (dump_info->CurrentFileName == NULL) - error("dump_packet_and_trunc: malloc"); - MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); - dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); - if (dump_info->p == NULL) - error("%s", pcap_geterr(pd)); } pcap_dump((u_char *)dump_info->p, h, sp); @@ -2107,7 +2387,8 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) /* * Some printers want to check that they're not walking off the * end of the packet. - * Rather than pass it all the way down, we set this global. + * Rather than pass it all the way down, we set this member + * of the netdissect_options structure. */ ndo->ndo_snapend = sp + h->caplen; @@ -2117,6 +2398,11 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) hdrlen = (*print_info->p.printer)(h, sp); } + /* + * Restore the original snapend, as a printer might have + * changed it. + */ + ndo->ndo_snapend = sp + h->caplen; if (ndo->ndo_Xflag) { /* * Print the raw packet data in hex and ASCII. @@ -2215,7 +2501,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) static void ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) { - hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and identation string */ + hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ } void @@ -2291,7 +2577,7 @@ print_version(void) (void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION)); #endif -#if defined(HAVE_SMI_H) +#ifdef USE_LIBSMI (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); #endif } @@ -2302,7 +2588,7 @@ print_usage(void) { print_version(); (void)fprintf(stderr, -"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); +"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, @@ -2312,7 +2598,16 @@ print_usage(void) "\t\t[ -Q in|out|inout ]\n"); #endif (void)fprintf(stderr, -"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ] [ -V file ]\n"); +"\t\t[ -r file ] [ -s snaplen ] "); +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + (void)fprintf(stderr, "[ --time-stamp-precision precision ]\n"); + (void)fprintf(stderr, +"\t\t"); +#endif +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + (void)fprintf(stderr, "[ --immediate-mode ] "); +#endif + (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); (void)fprintf(stderr, "\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); (void)fprintf(stderr,