summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/pcap-dlpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/pcap-dlpi.c')
-rw-r--r--contrib/libpcap/pcap-dlpi.c199
1 files changed, 135 insertions, 64 deletions
diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c
index c927629..a9a4dc3 100644
--- a/contrib/libpcap/pcap-dlpi.c
+++ b/contrib/libpcap/pcap-dlpi.c
@@ -20,8 +20,9 @@
*
* This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
* University College London, and subsequently modified by
- * Guy Harris (guy@alum.mit.edu) and Mark Pizzolato
- * <List-tcpdump-workers@subscriptions.pizzolato.net>.
+ * Guy Harris (guy@alum.mit.edu), Mark Pizzolato
+ * <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * and Mark C. Brown (mbrown@hp.com).
*/
/*
@@ -37,7 +38,8 @@
* - It might be desirable to use pfmod(7) to filter packets in the
* kernel when possible.
*
- * - The HP-UX 10.20 DLPI Programmer's Guide used to be available
+ * - An older version of the HP-UX DLPI Programmer's Guide, which
+ * I think was advertised as the 10.20 version, used to be available
* at
*
* http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
@@ -48,21 +50,27 @@
*
* in PDF form.
*
- * - The HP-UX 11.00 DLPI Programmer's Guide is available at
+ * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI
+ * Programmer's Guide, which I think was once advertised as the
+ * 11.00 version is available at
*
- * http://docs.hp.com/hpux/onlinedocs/B2355-90139/B2355-90139.html
+ * http://docs.hp.com/en/B2355-90139/index.html
*
- * and in PDF form at
+ * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide
+ * is available at
*
- * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90139.pdf
+ * http://docs.hp.com/en/B2355-90871/index.html
*
- * - Both of the HP documents describe raw-mode services, which are
- * what we use if DL_HP_RAWDLS is defined.
+ * - All of the HP documents describe raw-mode services, which are
+ * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux
+ * in some places to test for HP-UX, but use DL_HP_RAWDLS in
+ * other places; do we support any versions of HP-UX without
+ * DL_HP_RAWDLS?
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108 2004/10/19 07:06:12 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.5 2005/05/03 18:54:35 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -158,9 +166,12 @@ static const char rcsid[] _U_ =
/* Forwards */
static char *split_dname(char *, int *, char *);
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 dlbindreq(int, bpf_u_int32, char *);
-static int dlbindack(int, char *, 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 *);
@@ -168,7 +179,7 @@ static int dlinfoack(int, char *, char *);
#ifdef DL_HP_RAWDLS
static int dlrawdatareq(int, const u_char *, int);
#endif
-static int recv_ack(int, int, const char *, char *, char *);
+static int recv_ack(int, int, const char *, char *, char *, int *);
static char *dlstrerror(bpf_u_int32);
static char *dlprim(bpf_u_int32);
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
@@ -411,7 +422,7 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
ret = -1;
#endif /* raw mode */
return (ret);
-}
+}
#ifndef DL_IPATM
#define DL_IPATM 0x12 /* ATM Classical IP interface */
@@ -510,9 +521,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifdef DL_HP_RAWDLS
/*
* XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
- * receiving packets on the same descriptor - you have to bind the
- * descriptor on which you receive to a SAP of 22 and bind the
- * descriptor on which you send to a SAP of 24.
+ * receiving packets on the same descriptor - you need separate
+ * descriptors for sending and receiving, bound to different SAPs.
*
* If the open fails, we just leave -1 in "p->send_fd" and reject
* attempts to send packets, just as if, in pcap-bpf.c, we fail
@@ -622,12 +632,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
/*
- ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if
- ** using SINIX)
+ ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
+ ** skip if using SINIX)
*/
-#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix)
+#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)
#ifdef _AIX
- /* According to IBM's AIX Support Line, the dl_sap value
+ /*
+ ** AIX.
+ ** According to IBM's AIX Support Line, the dl_sap value
** should not be less than 0x600 (1536) for standard Ethernet.
** However, we seem to get DL_BADADDR - "DLSAP addr in improper
** format or invalid" - errors if we use 1537 on the "tr0"
@@ -645,34 +657,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
if ((dlbindreq(p->fd, 1537, ebuf) < 0 &&
dlbindreq(p->fd, 2, ebuf) < 0) ||
- dlbindack(p->fd, (char *)buf, ebuf) < 0)
+ dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)
goto bad;
#elif defined(DL_HP_RAWDLS)
/*
- ** This is the descriptor on which we receive packets; we
- ** bind it to 22, as that's INSAP, as per the HP-UX DLPI
- ** Programmer's Guide.
+ ** HP-UX 10.0x and 10.1x.
*/
- if (dlbindreq(p->fd, 22, ebuf) < 0 ||
- dlbindack(p->fd, (char *)buf, ebuf) < 0)
+ if (dl_dohpuxbind(p->fd, ebuf) < 0)
goto bad;
-
if (p->send_fd >= 0) {
/*
- ** This is the descriptor on which we send packets; we
- ** bind it to 24, as that's OUTSAP, as per the HP-UX
- ** DLPI Programmer's Guide.
+ ** XXX - if this fails, just close send_fd and
+ ** set it to -1, so that you can't send but can
+ ** still receive?
*/
- if (dlbindreq(p->send_fd, 24, ebuf) < 0 ||
- dlbindack(p->send_fd, (char *)buf, ebuf) < 0)
+ if (dl_dohpuxbind(p->send_fd, ebuf) < 0)
goto bad;
}
#else /* neither AIX nor HP-UX */
+ /*
+ ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
+ ** OS using DLPI.
+ **/
if (dlbindreq(p->fd, 0, ebuf) < 0 ||
- dlbindack(p->fd, (char *)buf, ebuf) < 0)
+ dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)
goto bad;
-#endif /* SAP to bind to */
-#endif /* HP-UX 9 or 10.20 or SINIX */
+#endif /* AIX vs. HP-UX vs. other */
+#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
#ifdef HAVE_SOLARIS
if (isatm) {
@@ -710,8 +721,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#endif
}
/*
- ** Try to enable sap (when not in promiscuous mode when using
- ** using HP-UX, when not doing SunATM on Solaris, and never
+ ** Try to enable SAP promiscuity (when not in promiscuous mode
+ ** when using HP-UX, when not doing SunATM on Solaris, and never
** under SINIX) (Not necessary on send FD)
*/
#ifndef sinix
@@ -731,16 +742,29 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
else
goto bad;
}
-#endif
+#endif /* sinix */
/*
- ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous
- ** options)
+ ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting
+ ** promiscuous options.
*/
-#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20)
- if (dlbindreq(p->fd, 0, ebuf) < 0 ||
- dlbindack(p->fd, (char *)buf, ebuf) < 0)
+#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
+ if (dl_dohpuxbind(p->fd, ebuf) < 0)
goto bad;
+ /*
+ ** We don't set promiscuous mode on the send FD, but we'll defer
+ ** binding it anyway, just to keep the HP-UX 9/10.20 or later
+ ** code together.
+ */
+ if (p->send_fd >= 0) {
+ /*
+ ** XXX - if this fails, just close send_fd and
+ ** set it to -1, so that you can't send but can
+ ** still receive?
+ */
+ if (dl_dohpuxbind(p->send_fd, ebuf) < 0)
+ goto bad;
+ }
#endif
/*
@@ -909,6 +933,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->read_op = pcap_read_dlpi;
p->inject_op = pcap_inject_dlpi;
p->setfilter_op = install_bpf_program; /* no kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented.*/
p->set_datalink_op = NULL; /* can't change data link type */
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
@@ -990,6 +1015,47 @@ dl_doattach(int fd, int ppa, char *ebuf)
return (0);
}
+#ifdef DL_HP_RAWDLS
+static int
+dl_dohpuxbind(int fd, char *ebuf)
+{
+ int hpsap;
+ int uerror;
+ bpf_u_int32 buf[MAXDLBUF];
+
+ /*
+ * XXX - we start at 22 because we used to use only 22, but
+ * that was just because that was the value used in some
+ * sample code from HP. With what value *should* we start?
+ * Does it matter, given that we're enabling SAP promiscuity
+ * on the input FD?
+ */
+ hpsap = 22;
+ for (;;) {
+ if (dlbindreq(fd, hpsap, ebuf) < 0)
+ return (-1);
+ if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0)
+ break;
+ /*
+ * For any error other than a UNIX EBUSY, give up.
+ */
+ if (uerror != EBUSY)
+ return (-1);
+
+ /*
+ * For EBUSY, try the next SAP value; that means that
+ * somebody else is using that SAP. Clear ebuf so
+ * that application doesn't report the "Device busy"
+ * error as a warning.
+ */
+ *ebuf = '\0';
+ hpsap++;
+ if (hpsap > 100)
+ return (-1);
+ }
+}
+#endif
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
@@ -1054,7 +1120,7 @@ send_request(int fd, char *ptr, int len, char *what, char *ebuf)
}
static int
-recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf)
+recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror)
{
union DL_primitives *dlp;
struct strbuf ctl;
@@ -1087,12 +1153,16 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf)
switch (dlp->error_ack.dl_errno) {
case DL_SYSERR:
+ if (uerror != NULL)
+ *uerror = dlp->error_ack.dl_unix_errno;
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: UNIX error - %s",
what, pcap_strerror(dlp->error_ack.dl_unix_errno));
break;
default:
+ if (uerror != NULL)
+ *uerror = 0;
snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
what, dlstrerror(dlp->error_ack.dl_errno));
break;
@@ -1100,6 +1170,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf)
return (-1);
default:
+ if (uerror != NULL)
+ *uerror = 0;
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Unexpected primitive ack %s",
what, dlprim(dlp->dl_primitive));
@@ -1107,6 +1179,8 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf)
}
if (ctl.len < size) {
+ if (uerror != NULL)
+ *uerror = 0;
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Ack too small (%d < %d)",
what, ctl.len, size);
@@ -1338,26 +1412,23 @@ dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
memset((char *)&req, 0, sizeof(req));
req.dl_primitive = DL_BIND_REQ;
-#ifdef DL_HP_RAWDLS
+ /* XXX - what if neither of these are defined? */
+#if defined(DL_HP_RAWDLS)
req.dl_max_conind = 1; /* XXX magic number */
- /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */
- req.dl_sap = 22;
req.dl_service_mode = DL_HP_RAWDLS;
-#else
- req.dl_sap = sap;
-#ifdef DL_CLDLS
+#elif defined(DL_CLDLS)
req.dl_service_mode = DL_CLDLS;
#endif
-#endif
+ req.dl_sap = sap;
return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
}
static int
-dlbindack(int fd, char *bufp, char *ebuf)
+dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
{
- return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf));
+ return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
}
static int
@@ -1375,7 +1446,7 @@ static int
dlokack(int fd, const char *what, char *bufp, char *ebuf)
{
- return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf));
+ return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));
}
@@ -1393,7 +1464,7 @@ static int
dlinfoack(int fd, char *bufp, char *ebuf)
{
- return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf));
+ return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
}
#ifdef DL_HP_RAWDLS
@@ -1674,20 +1745,20 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
}
}
- if (i == ap->dl_count) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ if (i == ap->dl_count) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
"can't find /dev/dlpi PPA for %s%d", device, unit);
return (-1);
- }
- if (ip->dl_hdw_state == HDW_DEAD) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ }
+ 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);
- }
- ppa = ip->dl_ppa;
- free(ppa_data_buf);
- return (ppa);
+ }
+ ppa = ip->dl_ppa;
+ free(ppa_data_buf);
+ return (ppa);
}
#endif
OpenPOWER on IntegriCloud