From a590c2138097e55e2a4ff9fc294f31b0c717460b Mon Sep 17 00:00:00 2001 From: guy Date: Wed, 9 Apr 2008 21:26:12 +0000 Subject: [PATCH] Add some PCAP_WARNING return values for "success, but you might want to know that..."; currently, only pcap_activate() returns them, but we might want some more warning returns for some other calls, such as the ones that set filters. It's a little cleaner than "clear out the error message buffer and, if it's not empty after a successful return, it has a warning", and a little cleaner than spewing a warning to the standard error (as that might not be visible to the user if they're running a GUI application). --- pcap-bpf.c | 57 +++++++++++++++++++++++---------------------- pcap-dlpi.c | 42 +++++++++++++++++---------------- pcap-linux.c | 19 ++++++++------- pcap.c | 10 ++++---- pcap/pcap.h | 17 ++++++++++++-- pcap_activate.3pcap | 23 ++++++++++++------ 6 files changed, 97 insertions(+), 71 deletions(-) diff --git a/pcap-bpf.c b/pcap-bpf.c index 2fc0d72..0ab60a9 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -20,7 +20,7 @@ */ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.107 2008-04-09 19:58:02 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.108 2008-04-09 21:26:12 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -1028,7 +1028,7 @@ check_setif_failure(pcap_t *p, int error) static int pcap_activate_bpf(pcap_t *p) { - int err; + int status = 0; int fd; struct ifreq ifr; struct bpf_version bv; @@ -1053,7 +1053,7 @@ pcap_activate_bpf(pcap_t *p) fd = bpf_open(p); if (fd < 0) { - err = fd; + status = fd; goto bad; } @@ -1062,14 +1062,14 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } @@ -1102,7 +1102,7 @@ pcap_activate_bpf(pcap_t *p) /* * 10.3 (Darwin 7.x) or earlier. */ - err = PCAP_ERROR_RFMON_NOTSUP; + status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } if (osinfo.release[0] == '8' && @@ -1129,10 +1129,10 @@ pcap_activate_bpf(pcap_t *p) * device doesn't * exist. */ - err = PCAP_ERROR_NO_SUCH_DEVICE; + status = PCAP_ERROR_NO_SUCH_DEVICE; strcpy(p->errbuf, ""); } else - err = PCAP_ERROR_RFMON_NOTSUP; + status = PCAP_ERROR_RFMON_NOTSUP; close(sockfd); } else { /* @@ -1140,7 +1140,7 @@ pcap_activate_bpf(pcap_t *p) * the device exists, so just * report "no such device". */ - err = PCAP_ERROR_NO_SUCH_DEVICE; + status = PCAP_ERROR_NO_SUCH_DEVICE; strcpy(p->errbuf, ""); } goto bad; @@ -1150,7 +1150,7 @@ pcap_activate_bpf(pcap_t *p) (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } strcpy(wltdev, "wlt"); @@ -1177,7 +1177,7 @@ pcap_activate_bpf(pcap_t *p) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: %s", p->opt.source, pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } @@ -1187,7 +1187,7 @@ pcap_activate_bpf(pcap_t *p) (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { - err = check_setif_failure(p, errno); + status = check_setif_failure(p, errno); goto bad; } } else { @@ -1217,7 +1217,7 @@ pcap_activate_bpf(pcap_t *p) break; /* that size worked; we're done */ if (errno != ENOBUFS) { - err = check_setif_failure(p, errno); + status = check_setif_failure(p, errno); goto bad; } } @@ -1226,7 +1226,7 @@ pcap_activate_bpf(pcap_t *p) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSBLEN: %s: No buffer size worked", p->opt.source); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } } @@ -1235,7 +1235,7 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } @@ -1268,7 +1268,7 @@ pcap_activate_bpf(pcap_t *p) */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", v); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } #endif @@ -1301,7 +1301,7 @@ pcap_activate_bpf(pcap_t *p) * not fatal; we just don't get to use the feature later. */ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) { - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } p->dlt_count = bdl.bfl_len; @@ -1386,7 +1386,7 @@ pcap_activate_bpf(pcap_t *p) * link-layer types, so they * can't have it. */ - err = PCAP_ERROR_RFMON_NOTSUP; + status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } } @@ -1401,8 +1401,8 @@ pcap_activate_bpf(pcap_t *p) /* * Try to put the interface into monitor mode. */ - err = monitor_mode(p, 1); - if (err != 0) { + status = monitor_mode(p, 1); + if (status != 0) { /* * We failed. */ @@ -1479,7 +1479,7 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSHDRCMPLT: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } #endif @@ -1496,7 +1496,7 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } } @@ -1553,7 +1553,7 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } #endif /* BIOCIMMEDIATE */ @@ -1564,13 +1564,14 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", pcap_strerror(errno)); + status = PCAP_WARNING_PROMISC_NOTSUP; } } if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } p->bufsize = v; @@ -1578,7 +1579,7 @@ pcap_activate_bpf(pcap_t *p) if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } #ifdef _AIX @@ -1606,7 +1607,7 @@ pcap_activate_bpf(pcap_t *p) if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto bad; } @@ -1668,14 +1669,14 @@ pcap_activate_bpf(pcap_t *p) p->stats_op = pcap_stats_bpf; p->close_op = pcap_close_bpf; - return (0); + return (status); bad: (void)close(fd); if (p->buffer != NULL) { free(p->buffer); p->buffer = NULL; } - return (err); + return (status); } int diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 29aae80..2632dc5 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -70,7 +70,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.123 2008-04-09 19:58:02 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.124 2008-04-09 21:26:12 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -342,7 +342,7 @@ pcap_activate_dlpi(pcap_t *p) #ifndef HAVE_DEV_DLPI char dname2[100]; #endif - int err = PCAP_ERROR; + int status = PCAP_ERROR; p->fd = -1; /* indicate that it hasn't been opened yet */ p->send_fd = -1; @@ -363,7 +363,7 @@ pcap_activate_dlpi(pcap_t *p) */ cp = split_dname(dname, &ppa, p->errbuf); if (cp == NULL) { - err = PCAP_ERROR_NO_SUCH_DEVICE; + status = PCAP_ERROR_NO_SUCH_DEVICE; goto bad; } *cp = '\0'; @@ -382,7 +382,7 @@ pcap_activate_dlpi(pcap_t *p) cp = "/dev/dlpi"; if ((p->fd = open(cp, O_RDWR)) < 0) { if (errno == EPERM || errno == EACCES) - err = PCAP_ERROR_PERM_DENIED; + status = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", cp, pcap_strerror(errno)); goto bad; @@ -409,7 +409,7 @@ pcap_activate_dlpi(pcap_t *p) */ ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf); if (ppa < 0) { - err = ppa; + status = ppa; goto bad; } #else @@ -431,7 +431,7 @@ pcap_activate_dlpi(pcap_t *p) */ cp = split_dname(dname, &ppa, p->errbuf); if (cp == NULL) { - err = PCAP_ERROR_NO_SUCH_DEVICE; + status = PCAP_ERROR_NO_SUCH_DEVICE; goto bad; } @@ -453,7 +453,7 @@ pcap_activate_dlpi(pcap_t *p) /* Try again with unit number */ if ((p->fd = open(dname2, O_RDWR)) < 0) { if (errno == ENOENT) { - err = PCAP_ERROR_NO_SUCH_DEVICE; + status = PCAP_ERROR_NO_SUCH_DEVICE; /* * We provide an error message even @@ -480,7 +480,7 @@ pcap_activate_dlpi(pcap_t *p) "%s: No DLPI device found", p->opt.source); } else { if (errno == EACCES) - err = PCAP_ERROR_PERM_DENIED; + status = PCAP_ERROR_PERM_DENIED; snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, pcap_strerror(errno)); } @@ -503,8 +503,8 @@ pcap_activate_dlpi(pcap_t *p) isatm = 1; #endif if (infop->dl_provider_style == DL_STYLE2) { - err = dl_doattach(p->fd, ppa, p->errbuf); - if (err < 0) + status = dl_doattach(p->fd, ppa, p->errbuf); + if (status < 0) goto bad; #ifdef DL_HP_RAWDLS if (p->send_fd >= 0) { @@ -519,7 +519,7 @@ pcap_activate_dlpi(pcap_t *p) * This device exists, but we don't support monitor mode * any platforms that support DLPI. */ - err = PCAP_ERROR_RFMON_NOTSUP; + status = PCAP_ERROR_RFMON_NOTSUP; goto bad; } @@ -615,9 +615,7 @@ pcap_activate_dlpi(pcap_t *p) #if !defined(__hpux) && !defined(sinix) if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, p->errbuf) < 0 || dlokack(p->fd, "promisc_multi", (char *)buf, p->errbuf) < 0) - fprintf(stderr, - "WARNING: DL_PROMISC_MULTI failed (%s)\n", - p->errbuf); + status = PCAP_WARNING; #endif } /* @@ -637,8 +635,7 @@ pcap_activate_dlpi(pcap_t *p) dlokack(p->fd, "promisc_sap", (char *)buf, p->errbuf) < 0)) { /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ if (p->opt.promisc) - fprintf(stderr, - "WARNING: DL_PROMISC_SAP failed (%s)\n", p->errbuf); + status = PCAP_WARNING; else goto bad; } @@ -706,10 +703,11 @@ pcap_activate_dlpi(pcap_t *p) release = get_release(&osmajor, &osminor, &osmicro); if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && getenv("BUFMOD_FIXED") == NULL) { - fprintf(stderr, - "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", + snprintf(p->errbuf, + "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.", release); ss = 0; + status = PCAP_WARNING; } #endif @@ -732,6 +730,10 @@ pcap_activate_dlpi(pcap_t *p) if (pcap_alloc_databuf(p) != 0) goto bad; + /* Success - but perhaps with a warning */ + if (status < 0) + status = 0; + /* * "p->fd" is an FD for a STREAMS device, so "select()" and * "poll()" should work on it. @@ -748,13 +750,13 @@ pcap_activate_dlpi(pcap_t *p) p->stats_op = pcap_stats_dlpi; p->close_op = pcap_close_dlpi; - return (0); + return (status); bad: if (p->fd >= 0) close(p->fd); if (p->send_fd >= 0) close(p->send_fd); - return (err); + return (status); } /* diff --git a/pcap-linux.c b/pcap-linux.c index 55e5a26..0ef4edf 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -34,7 +34,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.144 2008-04-09 19:58:02 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.145 2008-04-09 21:26:12 guy Exp $ (LBL)"; #endif /* @@ -486,7 +486,7 @@ static int pcap_activate_linux(pcap_t *handle) { const char *device; - int err; + int status = 0; int activate_ok = 0; device = handle->opt.source; @@ -513,6 +513,7 @@ pcap_activate_linux(pcap_t *handle) /* Just a warning. */ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Promiscuous mode not supported on the \"any\" device"); + status = PCAP_WARNING_PROMISC_NOTSUP; } } else @@ -534,7 +535,7 @@ pcap_activate_linux(pcap_t *handle) * trying both methods with the newer method preferred. */ - if ((err = activate_new(handle)) == 1) { + if ((status = activate_new(handle)) == 1) { activate_ok = 1; /* * Try to use memory-mapped access. @@ -542,9 +543,9 @@ pcap_activate_linux(pcap_t *handle) if (activate_mmap(handle) == 1) return 0; /* we succeeded; nothing more to do */ } - else if (err == 0) { + else if (status == 0) { /* Non-fatal error; try old way */ - if ((err = activate_old(handle)) == 1) + if ((status = activate_old(handle)) == 1) activate_ok = 1; } if (!activate_ok) { @@ -565,7 +566,7 @@ pcap_activate_linux(pcap_t *handle) sizeof(handle->opt.buffer_size)) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "SO_RCVBUF: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto fail; } } @@ -576,7 +577,7 @@ pcap_activate_linux(pcap_t *handle) if (!handle->buffer) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); - err = PCAP_ERROR; + status = PCAP_ERROR; goto fail; } @@ -586,7 +587,7 @@ pcap_activate_linux(pcap_t *handle) */ handle->selectable_fd = handle->fd; - return 0; + return status; fail: close(handle->fd); @@ -594,7 +595,7 @@ fail: free(handle->md.device); handle->md.device = NULL; } - return err; + return status; } /* diff --git a/pcap.c b/pcap.c index 7494c32..4330fd3 100644 --- a/pcap.c +++ b/pcap.c @@ -33,7 +33,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.117 2008-04-09 19:58:02 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.118 2008-04-09 21:26:12 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -211,12 +211,12 @@ pcap_set_buffer_size(pcap_t *p, int buffer_size) int pcap_activate(pcap_t *p) { - int err; + int status; - err = p->activate_op(p); - if (err == 0) + status = p->activate_op(p); + if (status >= 0) p->activated = 1; - return (err); + return (status); } pcap_t * diff --git a/pcap/pcap.h b/pcap/pcap.h index 9135832..49fd95b 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.8 2008-04-09 19:58:02 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.9 2008-04-09 21:26:12 guy Exp $ (LBL) */ #ifndef lib_pcap_pcap_h @@ -226,7 +226,12 @@ struct pcap_addr { typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); -/* list of known error codes for pcap API */ +/* + * Error codes for the pcap API. + * These will all be negative, so you can check for the success or + * failure of a call that returns these codes by checking for a + * negative value. + */ #define PCAP_ERROR -1 /* generic error code */ #define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */ #define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */ @@ -236,6 +241,14 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, #define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */ #define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ +/* + * Warning codes for the pcap API. + * These will all be positive and non-zero, so they won't look like + * errors. + */ +#define PCAP_WARNING 1 /* generic warning code */ +#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */ + char *pcap_lookupdev(char *); int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap index 6368a8c..0adf6ac 100644 --- a/pcap_activate.3pcap +++ b/pcap_activate.3pcap @@ -1,4 +1,4 @@ -.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.3 2008-04-09 20:20:17 guy Exp $ +.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.4 2008-04-09 21:26:12 guy Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -39,7 +39,12 @@ at packets on the network, with the options that were set on the handle being in effect. .SH RETURN VALUE .B pcap_activate() -returns 0 on success, +returns 0 on success without warnings, +.B PCAP_WARNING_PROMISC_NOTSUP +on success on a device that doesn't support promiscuous mode if +promiscuous mode was requested, +.B PCAP_WARNING +on success with any other warning, .B PCAP_ERROR_ACTIVATED if the handle has already been activated, .B PCAP_ERROR_NO_SUCH_DEVICE @@ -53,6 +58,8 @@ monitor mode, and .B PCAP_ERROR if an error occurred. If +.B PCAP_WARNING +or .B PCAP_ERROR is returned, .B pcap_geterr() @@ -60,9 +67,11 @@ or .B pcap_perror() may be called with .I p -as an argument to fetch or display the error text. +as an argument to fetch or display a message describing the warning or +error. If -.B PCAP_ERROR_NO_SUCH_DEVICE +.BR PCAP_WARNING_PROMISC_NOTSUP , +.BR PCAP_ERROR_NO_SUCH_DEVICE , or .B PCAP_ERROR_PERM_DENIED is returned, @@ -71,8 +80,8 @@ or .B pcap_perror() may be called with .I p -as an argument to fetch or display an error message giving additional -details about the error that might be useful for debugging the error if -it's unexpected. +as an argument to fetch or display an message giving additional details +about the problem that might be useful for debugging the problem if it's +unexpected. .SH SEE ALSO pcap(3PCAP)