aboutsummaryrefslogtreecommitdiffstats
path: root/pcap-dlpi.c
diff options
context:
space:
mode:
authorguy <guy>2008-04-09 19:58:02 +0000
committerguy <guy>2008-04-09 19:58:02 +0000
commit216c64a7ceaa12e96df1c45f90c943d2d958a9cc (patch)
treeb9cb66f808df898f5ffdb0e2d68da5a89f7bd9e3 /pcap-dlpi.c
parent745e497e4c79442396fa780f45be0381ea09d002 (diff)
Add an error for "you don't have permission to open that device", as
that often means "sorry, this platform requires you to run as root or to somehow tweak the system to give you capture privileges", and applications might want to explain that in a way that does a better job of letting the user know what they have to do. Try to return or PCAP_ERROR_PERM_DENIED for open errors, rather than just returning PCAP_ERROR, so that the application can, if it chooses, try to explain the error better (as those two errors are the ones that don't mean "there's probably some obscure OS or libpcap problem", but mean, instead, "you made an error" or "you need to get permission to capture"). Check for monitor mode *after* checking whether the device exists in the first place; a non-existent device doesn't support monitor mode, but that's because it doesn't, well, exist, and the latter would be a more meaningful error. Have pcap_open_live() supply an error message for return values other than PCAP_ERROR, PCAP_ERROR_NO_SUCH_DEVICE, and PCAP_ERROR_PERM_DENIED - those all supply error strings (PCAP_ERROR because it's for various OS problems that might require debugging, and the other two because there might be multiple causes).
Diffstat (limited to 'pcap-dlpi.c')
-rw-r--r--pcap-dlpi.c97
1 files changed, 64 insertions, 33 deletions
diff --git a/pcap-dlpi.c b/pcap-dlpi.c
index 8301c37..29aae80 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.122 2008-04-05 05:25:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.123 2008-04-09 19:58:02 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -342,13 +342,7 @@ pcap_activate_dlpi(pcap_t *p)
#ifndef HAVE_DEV_DLPI
char dname2[100];
#endif
-
- if (p->opt.rfmon) {
- /*
- * No monitor mode on any platforms that support DLPI.
- */
- return (PCAP_ERROR_RFMON_NOTSUP);
- }
+ int err = PCAP_ERROR;
p->fd = -1; /* indicate that it hasn't been opened yet */
p->send_fd = -1;
@@ -368,8 +362,10 @@ pcap_activate_dlpi(pcap_t *p)
* chop off the unit number, so "dname" is just a device type name.
*/
cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL)
+ if (cp == NULL) {
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
goto bad;
+ }
*cp = '\0';
/*
@@ -385,6 +381,8 @@ 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;
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"%s: %s", cp, pcap_strerror(errno));
goto bad;
@@ -410,8 +408,10 @@ pcap_activate_dlpi(pcap_t *p)
* table for the specified device type name and unit number.
*/
ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
- if (ppa < 0)
+ if (ppa < 0) {
+ err = ppa;
goto bad;
+ }
#else
/*
* If the device name begins with "/", assume it begins with
@@ -430,8 +430,10 @@ pcap_activate_dlpi(pcap_t *p)
* type name.
*/
cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL)
+ if (cp == NULL) {
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
goto bad;
+ }
/*
* Make a copy of the device pathname, and then remove the unit
@@ -451,10 +453,18 @@ 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;
+
/*
- * We just report "No DLPI device found"
- * with the device name, so people don't
- * get confused and think, for example,
+ * We provide an error message even
+ * for this error, for diagnostic
+ * purposes (so that, for example,
+ * the app can show the message if the
+ * user requests it).
+ *
+ * In it, we just report "No DLPI device
+ * found" with the device name, so people
+ * don't get confused and think, for example,
* that if they can't capture on "lo0"
* on Solaris the fix is to change libpcap
* (or the application that uses it) to
@@ -469,6 +479,8 @@ pcap_activate_dlpi(pcap_t *p)
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"%s: No DLPI device found", p->opt.source);
} else {
+ if (errno == EACCES)
+ err = PCAP_ERROR_PERM_DENIED;
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
dname2, pcap_strerror(errno));
}
@@ -491,7 +503,8 @@ pcap_activate_dlpi(pcap_t *p)
isatm = 1;
#endif
if (infop->dl_provider_style == DL_STYLE2) {
- if (dl_doattach(p->fd, ppa, p->errbuf) < 0)
+ err = dl_doattach(p->fd, ppa, p->errbuf);
+ if (err < 0)
goto bad;
#ifdef DL_HP_RAWDLS
if (p->send_fd >= 0) {
@@ -501,6 +514,15 @@ pcap_activate_dlpi(pcap_t *p)
#endif
}
+ if (p->opt.rfmon) {
+ /*
+ * This device exists, but we don't support monitor mode
+ * any platforms that support DLPI.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+
#ifdef HAVE_DLPI_PASSIVE
/*
* Enable Passive mode to be able to capture on aggregated link.
@@ -732,7 +754,7 @@ bad:
close(p->fd);
if (p->send_fd >= 0)
close(p->send_fd);
- return (PCAP_ERROR);
+ return (err);
}
/*
@@ -788,10 +810,13 @@ static int
dl_doattach(int fd, int ppa, char *ebuf)
{
bpf_u_int32 buf[MAXDLBUF];
+ int err;
- if (dlattachreq(fd, ppa, ebuf) < 0 ||
- dlokack(fd, "attach", (char *)buf, ebuf) < 0)
- return (-1);
+ if (dlattachreq(fd, ppa, ebuf) < 0)
+ return (PCAP_ERROR);
+ err = dlokack(fd, "attach", (char *)buf, ebuf);
+ if (err < 0)
+ return (err);
return (0);
}
@@ -931,7 +956,7 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
what, pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
dlp = (union DL_primitives *) ctl.buf;
@@ -955,27 +980,33 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: UNIX error - %s",
what, pcap_strerror(dlp->error_ack.dl_unix_errno));
+ if (dlp->error_ack.dl_unix_errno == EACCES)
+ return (PCAP_ERROR_PERM_DENIED);
break;
default:
snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
what, dlstrerror(dlp->error_ack.dl_errno));
+ if (dlp->error_ack.dl_errno == DL_BADPPA)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ else if (dlp->error_ack.dl_errno == DL_ACCESS)
+ return (PCAP_ERROR_PERM_DENIED);
break;
}
- return (-1);
+ return (PCAP_ERROR);
default:
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Unexpected primitive ack %s",
what, dlprim(dlp->dl_primitive));
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < size) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Ack too small (%d < %d)",
what, ctl.len, size);
- return (-1);
+ return (PCAP_ERROR);
}
return (ctl.len);
}
@@ -1401,7 +1432,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
memset((char *)buf, 0, sizeof(buf));
if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
- return (-1);
+ return (PCAP_ERROR);
ctl.maxlen = DL_HP_PPA_ACK_SIZE;
ctl.len = 0;
@@ -1424,7 +1455,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
dlp = (dl_hp_ppa_ack_t *)ctl.buf;
@@ -1432,21 +1463,21 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
(bpf_u_int32)dlp->dl_primitive);
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < DL_HP_PPA_ACK_SIZE) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %lu)",
ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
- return (-1);
+ return (PCAP_ERROR);
}
/* allocate buffer */
if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
ctl.maxlen = dlp->dl_length;
ctl.len = 0;
@@ -1456,14 +1487,14 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < dlp->dl_length) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %d)",
ctl.len, dlp->dl_length);
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
ap = (dl_hp_ppa_ack_t *)buf;
@@ -1520,7 +1551,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (stat(dname, &statbuf) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
dname, pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
majdev = major(statbuf.st_rdev);
@@ -1537,13 +1568,13 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (i == ap->dl_count) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"can't find /dev/dlpi PPA for %s%d", device, unit);
- return (-1);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
}
if (ip->dl_hdw_state == HDW_DEAD) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"%s%d: hardware state: DOWN\n", device, unit);
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
ppa = ip->dl_ppa;
free(ppa_data_buf);