aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-09-21 02:07:05 -0700
committerGuy Harris <guy@alum.mit.edu>2010-09-21 02:07:05 -0700
commit74b7b4259fde15dbb07cde3a5920e9f7e0ed4484 (patch)
treec7281be68f5536401eec53bbe0245b0fe79c2232
parentb26d8d2aa849c8021cdfa872901e82fb469460ef (diff)
Return PCAP_ERROR_PROMISC_PERM_DENIED if you have permission to open the
DLPI device but don't have permission to put the interface in promiscuous mode; some systems using DLPI work that way. Change the libdlpi code to return a warning if you *are* using physical promiscuous mode and you fail to turn on SAP promiscuous mode, not if you *aren't* using physical promiscuous mode and you fail to turn on SAP promiscuous mode; that matches with the no-libdlpi code does, and matches what the comment says. Pull dlattachreq up into dl_doattach().
-rw-r--r--pcap-dlpi.c84
-rw-r--r--pcap-libdlpi.c68
-rw-r--r--pcap.c6
-rw-r--r--pcap/pcap.h1
-rw-r--r--pcap_activate.3pcap3
5 files changed, 105 insertions, 57 deletions
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)
{
@@ -1222,17 +1254,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)
{
@@ -1260,17 +1281,6 @@ dlbindack(int fd, char *bufp, char *ebuf, int *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,