diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 8f938fe..ec2f32d 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -143,10 +143,9 @@ static int dl_doattach(int, int, char *); #ifdef DL_HP_RAWDLS static int dl_dohpuxbind(int, char *); #endif -static int dlattachreq(int, bpf_u_int32, char *); +static int dlpromiscon(pcap_t *, bpf_u_int32); static int dlbindreq(int, bpf_u_int32, char *); static int dlbindack(int, char *, char *, int *); -static int dlpromisconreq(int, bpf_u_int32, char *); static int dlokack(int, const char *, char *, char *); static int dlinforeq(int, char *); static int dlinfoack(int, char *, char *); @@ -610,9 +609,12 @@ pcap_activate_dlpi(pcap_t *p) /* ** Enable promiscuous (not necessary on send FD) */ - if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, p->errbuf) < 0 || - dlokack(p->fd, "promisc_phys", (char *)buf, p->errbuf) < 0) + status = dlpromiscon(p, DL_PROMISC_PHYS); + if (status < 0) { + if (status == PCAP_ERROR_PERM_DENIED) + status = PCAP_ERROR_PROMISC_PERM_DENIED; goto bad; + } /* ** Try to enable multicast (you would have thought @@ -620,8 +622,8 @@ pcap_activate_dlpi(pcap_t *p) ** HP-UX or SINIX) (Not necessary on send FD) */ #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) + status = dlpromiscon(p, DL_PROMISC_MULTI); + if (status < 0) status = PCAP_WARNING; #endif } @@ -636,15 +638,20 @@ pcap_activate_dlpi(pcap_t *p) !p->opt.promisc && #endif #ifdef HAVE_SOLARIS - !isatm && + !isatm #endif - (dlpromisconreq(p->fd, DL_PROMISC_SAP, p->errbuf) < 0 || - dlokack(p->fd, "promisc_sap", (char *)buf, p->errbuf) < 0)) { - /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ - if (p->opt.promisc) - status = PCAP_WARNING; - else - goto bad; + ) { + status = dlpromiscon(p, DL_PROMISC_SAP); + if (status < 0) { + /* + * Not fatal, since the DL_PROMISC_PHYS mode worked. + * Report it as a warning, however. + */ + if (p->opt.promisc) + status = PCAP_WARNING; + else + goto bad; + } } #endif /* sinix */ @@ -815,11 +822,15 @@ split_dname(char *device, int *unitp, char *ebuf) static int dl_doattach(int fd, int ppa, char *ebuf) { + dl_attach_req_t req; bpf_u_int32 buf[MAXDLBUF]; int err; - if (dlattachreq(fd, ppa, ebuf) < 0) + req.dl_primitive = DL_ATTACH_REQ; + req.dl_ppa = ppa; + if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0) return (PCAP_ERROR); + err = dlokack(fd, "attach", (char *)buf, ebuf); if (err < 0) return (err); @@ -877,6 +888,27 @@ dl_dohpuxbind(int fd, char *ebuf) } #endif +#define STRINGIFY(n) #n + +static int +dlpromiscon(pcap_t *p, bpf_u_int32 level) +{ + dl_promiscon_req_t req; + bpf_u_int32 buf[MAXDLBUF]; + int err; + + req.dl_primitive = DL_PROMISCON_REQ; + req.dl_level = level; + if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon", + p->errbuf) < 0) + return (PCAP_ERROR); + err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf, + p->errbuf); + if (err < 0) + return (err); + return (0); +} + int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) { @@ -1221,17 +1253,6 @@ dlprim(bpf_u_int32 prim) } } -static int -dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) -{ - dl_attach_req_t req; - - req.dl_primitive = DL_ATTACH_REQ; - req.dl_ppa = ppa; - - return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); -} - static int dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) { @@ -1259,17 +1280,6 @@ dlbindack(int fd, char *bufp, char *ebuf, int *uerror) return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror)); } -static int -dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) -{ - dl_promiscon_req_t req; - - req.dl_primitive = DL_PROMISCON_REQ; - req.dl_level = level; - - return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); -} - static int dlokack(int fd, const char *what, char *bufp, char *ebuf) { diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c index 87cd08b..56dadc4 100644 --- a/pcap-libdlpi.c +++ b/pcap-libdlpi.c @@ -49,6 +49,7 @@ static const char rcsid[] _U_ = #include "dlpisubs.h" /* Forwards. */ +static int dlpromiscon(pcap_t *, bpf_u_int32); static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *); static int pcap_inject_libdlpi(pcap_t *, const void *, size_t); static void pcap_close_libdlpi(pcap_t *); @@ -139,34 +140,43 @@ pcap_activate_libdlpi(pcap_t *p) /* Enable promiscuous mode. */ if (p->opt.promisc) { - retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_PHYS); - if (retv != DLPI_SUCCESS) { - pcap_libdlpi_err(p->opt.source, - "dlpi_promisc(PHYSICAL)", retv, p->errbuf); + err = dlpromiscon(p, DL_PROMISC_PHYS); + if (err < 0) { + /* + * "You don't have permission to capture on + * this device" and "you don't have permission + * to capture in promiscuous mode on this + * device" are different; let the user know, + * so if they can't get permission to + * capture in promiscuous mode, they can at + * least try to capture in non-promiscuous + * mode. + * + * XXX - you might have to capture in + * promiscuous mode to see outgoing packets. + */ + if (err == PCAP_ERROR_PERM_DENIED) + err = PCAP_ERROR_PROMISC_PERM_DENIED; goto bad; } } else { /* Try to enable multicast. */ - retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_MULTI); - if (retv != DLPI_SUCCESS) { - pcap_libdlpi_err(p->opt.source, "dlpi_promisc(MULTI)", - retv, p->errbuf); + err = dlpromiscon(p, DL_PROMISC_MULTI); + if (err < 0) goto bad; - } } /* Try to enable SAP promiscuity. */ - retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_SAP); - if (retv != DLPI_SUCCESS) { - if (p->opt.promisc) { - pcap_libdlpi_err(p->opt.source, "dlpi_promisc(SAP)", - retv, p->errbuf); + err = dlpromiscon(p, DL_PROMISC_SAP); + if (err < 0) { + /* + * Not fatal, since the DL_PROMISC_PHYS mode worked. + * Report it as a warning, however. + */ + if (p->opt.promisc) + err = PCAP_WARNING; + else goto bad; - } - - /* Not fatal, since the DL_PROMISC_PHYS mode worked. */ - fprintf(stderr, "WARNING: dlpi_promisc(SAP) failed on" - " %s:(%s)\n", p->opt.source, dlpi_strerror(retv)); } /* Determine link type. */ @@ -219,6 +229,26 @@ bad: return (err); } +#define STRINGIFY(n) #n + +static int +dlpromiscon(pcap_t *p, bpf_u_int32 level) +{ + int err; + + retv = dlpi_promiscon(p->hd, level); + if (retv != DLPI_SUCCESS) { + if (retv == DL_SYSERR && errno == EACCES) + err = PCAP_ERROR_PERM_DENIED; + else + err = PCAP_ERROR; + pcap_libdlpi_err(p->opt.source, "dlpi_promiscon" STRINGIFY(level), + retv, p->errbuf); + return (err); + } + return (0); +} + /* * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find * network links that are plumbed and are up. dlpi_walk(3DLPI) will find diff --git a/pcap.c b/pcap.c index 143b712..4b64a38 100644 --- a/pcap.c +++ b/pcap.c @@ -470,7 +470,8 @@ fail: snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, p->errbuf); else if (status == PCAP_ERROR_NO_SUCH_DEVICE || - status == PCAP_ERROR_PERM_DENIED) + status == PCAP_ERROR_PERM_DENIED || + status == PCAP_ERROR_PROMISC_PERM_DENIED) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), p->errbuf); else @@ -1149,6 +1150,9 @@ pcap_statustostr(int errnum) case PCAP_ERROR_CANTSET_TSTAMP_TYPE: return ("That device doesn't support setting the time stamp type"); + + case PCAP_ERROR_PROMISC_PERM_DENIED: + return ("You don't have permission to capture in promiscuous mode on that device"); } (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); return(ebuf); diff --git a/pcap/pcap.h b/pcap/pcap.h index 172670b..073ce67 100644 --- a/pcap/pcap.h +++ b/pcap/pcap.h @@ -252,6 +252,7 @@ typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, #define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */ #define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */ #define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */ +#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */ /* * Warning codes for the pcap API. diff --git a/pcap_activate.3pcap b/pcap_activate.3pcap index c93df9e..f963d35 100644 --- a/pcap_activate.3pcap +++ b/pcap_activate.3pcap @@ -57,6 +57,9 @@ if the capture source specified when the handle was created doesn't exist, .B PCAP_ERROR_PERM_DENIED if the process doesn't have permission to open the capture source, +.B PCAP_ERROR_PROMISC_PERM_DENIED +if the process has permission to open the capture source but doesn't +have permission to put it into promiscuous mode, .B PCAP_ERROR_RFMON_NOTSUP if monitor mode was specified but the capture source doesn't support monitor mode,