diff options
Diffstat (limited to 'contrib/libpcap/pcap-dlpi.c')
-rw-r--r-- | contrib/libpcap/pcap-dlpi.c | 199 |
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 |