pcap-dlpi.c revision 127664
184865Sobrien/* 284865Sobrien * Copyright (c) 1993, 1994, 1995, 1996, 1997 384865Sobrien * The Regents of the University of California. All rights reserved. 484865Sobrien * 584865Sobrien * Redistribution and use in source and binary forms, with or without 684865Sobrien * modification, are permitted provided that: (1) source code distributions 784865Sobrien * retain the above copyright notice and this paragraph in its entirety, (2) 884865Sobrien * distributions including binary code include the above copyright notice and 984865Sobrien * this paragraph in its entirety in the documentation or other materials 1084865Sobrien * provided with the distribution, and (3) all advertising materials mentioning 1184865Sobrien * features or use of this software display the following acknowledgement: 1284865Sobrien * ``This product includes software developed by the University of California, 1384865Sobrien * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1484865Sobrien * the University nor the names of its contributors may be used to endorse 1584865Sobrien * or promote products derived from this software without specific prior 1684865Sobrien * written permission. 1784865Sobrien * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1884865Sobrien * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1984865Sobrien * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2084865Sobrien * 2184865Sobrien * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), 2284865Sobrien * University College London. 2384865Sobrien */ 2484865Sobrien 2584865Sobrien/* 2684865Sobrien * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. 2784865Sobrien * 2884865Sobrien * Notes: 2984865Sobrien * 3084865Sobrien * - Apparently the DLIOCRAW ioctl() is specific to SunOS. 3184865Sobrien * 3284865Sobrien * - There is a bug in bufmod(7) such that setting the snapshot 3384865Sobrien * length results in data being left of the front of the packet. 3484865Sobrien * 35104834Sobrien * - It might be desirable to use pfmod(7) to filter packets in the 3684865Sobrien * kernel when possible. 3784865Sobrien */ 3884865Sobrien 3984865Sobrien#ifndef lint 4084865Sobrienstatic const char rcsid[] _U_ = 4184865Sobrien "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.91.2.3 2003/11/21 10:20:46 guy Exp $ (LBL)"; 4284865Sobrien#endif 4384865Sobrien 4484865Sobrien#ifdef HAVE_CONFIG_H 45104834Sobrien#include "config.h" 4684865Sobrien#endif 4784865Sobrien 4884865Sobrien#include <sys/types.h> 4984865Sobrien#include <sys/time.h> 5084865Sobrien#ifdef HAVE_SYS_BUFMOD_H 51104834Sobrien#include <sys/bufmod.h> 52104834Sobrien#endif 5384865Sobrien#include <sys/dlpi.h> 5484865Sobrien#ifdef HAVE_SYS_DLPI_EXT_H 5584865Sobrien#include <sys/dlpi_ext.h> 5684865Sobrien#endif 5784865Sobrien#ifdef HAVE_HPUX9 5884865Sobrien#include <sys/socket.h> 5984865Sobrien#endif 6084865Sobrien#ifdef DL_HP_PPA_ACK_OBS 6184865Sobrien#include <sys/stat.h> 6284865Sobrien#endif 6384865Sobrien#include <sys/stream.h> 6484865Sobrien#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 6584865Sobrien#include <sys/systeminfo.h> 6684865Sobrien#endif 6784865Sobrien 6884865Sobrien#ifdef HAVE_HPUX9 6984865Sobrien#include <net/if.h> 7084865Sobrien#endif 7184865Sobrien 7284865Sobrien#include <ctype.h> 7384865Sobrien#ifdef HAVE_HPUX9 7484865Sobrien#include <nlist.h> 7584865Sobrien#endif 7684865Sobrien#include <errno.h> 7784865Sobrien#include <fcntl.h> 7884865Sobrien#include <memory.h> 7984865Sobrien#include <stdio.h> 8084865Sobrien#include <stdlib.h> 8184865Sobrien#include <string.h> 8284865Sobrien#include <stropts.h> 8384865Sobrien#include <unistd.h> 8484865Sobrien 8584865Sobrien#include "pcap-int.h" 8684865Sobrien 8784865Sobrien#ifdef HAVE_OS_PROTO_H 8884865Sobrien#include "os-proto.h" 8984865Sobrien#endif 9084865Sobrien 9184865Sobrien#ifndef PCAP_DEV_PREFIX 9284865Sobrien#ifdef _AIX 9384865Sobrien#define PCAP_DEV_PREFIX "/dev/dlpi" 9484865Sobrien#else 9584865Sobrien#define PCAP_DEV_PREFIX "/dev" 9684865Sobrien#endif 9784865Sobrien#endif 9884865Sobrien 9984865Sobrien#define MAXDLBUF 8192 10084865Sobrien 10184865Sobrien#ifdef HAVE_SYS_BUFMOD_H 10284865Sobrien 10384865Sobrien/* 10484865Sobrien * Size of a bufmod chunk to pass upstream; that appears to be the biggest 10584865Sobrien * value to which you can set it, and setting it to that value (which 10684865Sobrien * is bigger than what appears to be the Solaris default of 8192) 10784865Sobrien * reduces the number of packet drops. 10884865Sobrien */ 10984865Sobrien#define CHUNKSIZE 65536 11084865Sobrien 11184865Sobrien/* 11284865Sobrien * Size of the buffer to allocate for packet data we read; it must be 11384865Sobrien * large enough to hold a chunk. 11484865Sobrien */ 11584865Sobrien#define PKTBUFSIZE CHUNKSIZE 11684865Sobrien 11784865Sobrien#else /* HAVE_SYS_BUFMOD_H */ 11884865Sobrien 11984865Sobrien/* 12084865Sobrien * Size of the buffer to allocate for packet data we read; this is 12184865Sobrien * what the value used to be - there's no particular reason why it 12284865Sobrien * should be tied to MAXDLBUF, but we'll leave it as this for now. 12384865Sobrien */ 12484865Sobrien#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32)) 12584865Sobrien 12684865Sobrien#endif 12784865Sobrien 12884865Sobrien/* Forwards */ 12984865Sobrienstatic char *split_dname(char *, int *, char *); 13084865Sobrienstatic int dlattachreq(int, bpf_u_int32, char *); 13184865Sobrienstatic int dlbindack(int, char *, char *); 13284865Sobrienstatic int dlbindreq(int, bpf_u_int32, char *); 13384865Sobrienstatic int dlinfoack(int, char *, char *); 13484865Sobrienstatic int dlinforeq(int, char *); 13584865Sobrienstatic int dlokack(int, const char *, char *, char *); 13684865Sobrienstatic int recv_ack(int, int, const char *, char *, char *); 13784865Sobrienstatic char *dlstrerror(bpf_u_int32); 13884865Sobrienstatic char *dlprim(bpf_u_int32); 13984865Sobrienstatic int dlpromisconreq(int, bpf_u_int32, char *); 14084865Sobrien#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 14184865Sobrienstatic char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 14284865Sobrien#endif 14384865Sobrienstatic int send_request(int, char *, int, char *, char *); 14484865Sobrien#ifdef HAVE_SYS_BUFMOD_H 14584865Sobrienstatic int strioctl(int, int, int, char *); 14684865Sobrien#endif 14784865Sobrien#ifdef HAVE_HPUX9 14884865Sobrienstatic int dlpi_kread(int, off_t, void *, u_int, char *); 14984865Sobrien#endif 15084865Sobrien#ifdef HAVE_DEV_DLPI 15184865Sobrienstatic int get_dlpi_ppa(int, const char *, int, char *); 15284865Sobrien#endif 15384865Sobrien 15484865Sobrienstatic int 15584865Sobrienpcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) 15684865Sobrien{ 15784865Sobrien 15884865Sobrien /* 15984865Sobrien * "ps_recv" counts packets handed to the filter, not packets 16084865Sobrien * that passed the filter. As filtering is done in userland, 16184865Sobrien * this does not include packets dropped because we ran out 16284865Sobrien * of buffer space. 16384865Sobrien * 16484865Sobrien * "ps_drop" counts packets dropped inside the DLPI service 16584865Sobrien * provider device device because of flow control requirements 16684865Sobrien * or resource exhaustion; it doesn't count packets dropped by 16784865Sobrien * the interface driver, or packets dropped upstream. As 16884865Sobrien * filtering is done in userland, it counts packets regardless 16984865Sobrien * of whether they would've passed the filter. 17084865Sobrien * 17184865Sobrien * These statistics don't include packets not yet read from 17284865Sobrien * the kernel by libpcap, but they may include packets not 17384865Sobrien * yet read from libpcap by the application. 17484865Sobrien */ 17584865Sobrien *ps = p->md.stat; 17684865Sobrien return (0); 17784865Sobrien} 17884865Sobrien 17984865Sobrien/* XXX Needed by HP-UX (at least) */ 18084865Sobrienstatic bpf_u_int32 ctlbuf[MAXDLBUF]; 18184865Sobrienstatic struct strbuf ctl = { 18284865Sobrien MAXDLBUF, 18384865Sobrien 0, 18484865Sobrien (char *)ctlbuf 18584865Sobrien}; 18684865Sobrien 18784865Sobrienstatic int 18884865Sobrienpcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 18984865Sobrien{ 19084865Sobrien register int cc, n, caplen, origlen; 19184865Sobrien register u_char *bp, *ep, *pk; 19284865Sobrien register struct bpf_insn *fcode; 19384865Sobrien#ifdef HAVE_SYS_BUFMOD_H 19484865Sobrien register struct sb_hdr *sbp; 195104834Sobrien#ifdef LBL_ALIGN 196104834Sobrien struct sb_hdr sbhdr; 197104834Sobrien#endif 198104834Sobrien#endif 199104834Sobrien int flags; 200104834Sobrien struct strbuf data; 201104834Sobrien struct pcap_pkthdr pkthdr; 202104834Sobrien 203104834Sobrien flags = 0; 204104834Sobrien cc = p->cc; 205104834Sobrien if (cc == 0) { 206104834Sobrien data.buf = (char *)p->buffer + p->offset; 207104834Sobrien data.maxlen = p->bufsize; 208104834Sobrien data.len = 0; 209104834Sobrien do { 210104834Sobrien /* 211104834Sobrien * Has "pcap_breakloop()" been called? 212104834Sobrien */ 213104834Sobrien if (p->break_loop) { 214104834Sobrien /* 215104834Sobrien * Yes - clear the flag that indicates 216104834Sobrien * that it has, and return -2 to 217104834Sobrien * indicate that we were told to 218104834Sobrien * break out of the loop. 21984865Sobrien */ 22084865Sobrien p->break_loop = 0; 22184865Sobrien return (-2); 22284865Sobrien } 22384865Sobrien if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 22484865Sobrien /* Don't choke when we get ptraced */ 22584865Sobrien if (errno == EINTR) { 22684865Sobrien cc = 0; 22784865Sobrien continue; 22884865Sobrien } 22984865Sobrien strlcpy(p->errbuf, pcap_strerror(errno), 23084865Sobrien sizeof(p->errbuf)); 23184865Sobrien return (-1); 23284865Sobrien } 23384865Sobrien cc = data.len; 23484865Sobrien } while (cc == 0); 23584865Sobrien bp = p->buffer + p->offset; 23684865Sobrien } else 23784865Sobrien bp = p->bp; 23884865Sobrien 23984865Sobrien /* Loop through packets */ 24084865Sobrien fcode = p->fcode.bf_insns; 24184865Sobrien ep = bp + cc; 24284865Sobrien n = 0; 24384865Sobrien#ifdef HAVE_SYS_BUFMOD_H 24484865Sobrien while (bp < ep) { 24584865Sobrien /* 24684865Sobrien * Has "pcap_breakloop()" been called? 24784865Sobrien * If so, return immediately - if we haven't read any 24884865Sobrien * packets, clear the flag and return -2 to indicate 24984865Sobrien * that we were told to break out of the loop, otherwise 25084865Sobrien * leave the flag set, so that the *next* call will break 25184865Sobrien * out of the loop without having read any packets, and 25284865Sobrien * return the number of packets we've processed so far. 25384865Sobrien */ 25484865Sobrien if (p->break_loop) { 25584865Sobrien if (n == 0) { 25684865Sobrien p->break_loop = 0; 25784865Sobrien return (-2); 25884865Sobrien } else { 25984865Sobrien p->bp = bp; 26084865Sobrien p->cc = ep - bp; 26184865Sobrien return (n); 26284865Sobrien } 26384865Sobrien } 26484865Sobrien#ifdef LBL_ALIGN 26584865Sobrien if ((long)bp & 3) { 26684865Sobrien sbp = &sbhdr; 26784865Sobrien memcpy(sbp, bp, sizeof(*sbp)); 26884865Sobrien } else 26984865Sobrien#endif 27084865Sobrien sbp = (struct sb_hdr *)bp; 27184865Sobrien p->md.stat.ps_drop = sbp->sbh_drops; 27284865Sobrien pk = bp + sizeof(*sbp); 27384865Sobrien bp += sbp->sbh_totlen; 27484865Sobrien origlen = sbp->sbh_origlen; 27584865Sobrien caplen = sbp->sbh_msglen; 27684865Sobrien#else 27784865Sobrien origlen = cc; 27884865Sobrien caplen = min(p->snapshot, cc); 27984865Sobrien pk = bp; 28084865Sobrien bp += caplen; 28184865Sobrien#endif 28284865Sobrien ++p->md.stat.ps_recv; 28384865Sobrien if (bpf_filter(fcode, pk, origlen, caplen)) { 28484865Sobrien#ifdef HAVE_SYS_BUFMOD_H 28584865Sobrien pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; 28684865Sobrien pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; 28784865Sobrien#else 28884865Sobrien (void)gettimeofday(&pkthdr.ts, NULL); 28984865Sobrien#endif 29084865Sobrien pkthdr.len = origlen; 29184865Sobrien pkthdr.caplen = caplen; 29284865Sobrien /* Insure caplen does not exceed snapshot */ 29384865Sobrien if (pkthdr.caplen > p->snapshot) 29484865Sobrien pkthdr.caplen = p->snapshot; 29584865Sobrien (*callback)(user, &pkthdr, pk); 29684865Sobrien if (++n >= cnt && cnt >= 0) { 29784865Sobrien p->cc = ep - bp; 29884865Sobrien p->bp = bp; 29984865Sobrien return (n); 30084865Sobrien } 30184865Sobrien } 30284865Sobrien#ifdef HAVE_SYS_BUFMOD_H 30384865Sobrien } 30484865Sobrien#endif 30584865Sobrien p->cc = 0; 30684865Sobrien return (n); 30784865Sobrien} 30884865Sobrien 30984865Sobrien#ifndef DL_IPATM 31084865Sobrien#define DL_IPATM 0x12 /* ATM Classical IP interface */ 31184865Sobrien#endif 31284865Sobrien 31384865Sobrien#ifdef HAVE_SOLARIS 31484865Sobrien/* 31584865Sobrien * For SunATM. 31684865Sobrien */ 31784865Sobrien#ifndef A_GET_UNITS 31884865Sobrien#define A_GET_UNITS (('A'<<8)|118) 31984865Sobrien#endif /* A_GET_UNITS */ 32084865Sobrien#ifndef A_PROMISCON_REQ 32184865Sobrien#define A_PROMISCON_REQ (('A'<<8)|121) 32284865Sobrien#endif /* A_PROMISCON_REQ */ 32384865Sobrien#endif /* HAVE_SOLARIS */ 32484865Sobrien 32584865Sobrienstatic void 32684865Sobrienpcap_close_dlpi(pcap_t *p) 32784865Sobrien{ 32884865Sobrien if (p->buffer != NULL) 32984865Sobrien free(p->buffer); 33084865Sobrien if (p->fd >= 0) 33184865Sobrien close(p->fd); 33284865Sobrien} 33384865Sobrien 33484865Sobrienpcap_t * 33584865Sobrienpcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 33684865Sobrien char *ebuf) 33784865Sobrien{ 33884865Sobrien register char *cp; 33984865Sobrien register pcap_t *p; 34084865Sobrien int ppa; 34184865Sobrien#ifdef HAVE_SOLARIS 34284865Sobrien int isatm = 0; 34384865Sobrien#endif 34484865Sobrien register dl_info_ack_t *infop; 34584865Sobrien#ifdef HAVE_SYS_BUFMOD_H 34684865Sobrien bpf_u_int32 ss, chunksize; 34784865Sobrien#ifdef HAVE_SOLARIS 34884865Sobrien register char *release; 34984865Sobrien bpf_u_int32 osmajor, osminor, osmicro; 35084865Sobrien#endif 35184865Sobrien#endif 35284865Sobrien bpf_u_int32 buf[MAXDLBUF]; 35384865Sobrien char dname[100]; 35484865Sobrien#ifndef HAVE_DEV_DLPI 35584865Sobrien char dname2[100]; 35684865Sobrien#endif 35784865Sobrien 35884865Sobrien p = (pcap_t *)malloc(sizeof(*p)); 35984865Sobrien if (p == NULL) { 36084865Sobrien strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 36184865Sobrien return (NULL); 36284865Sobrien } 36384865Sobrien memset(p, 0, sizeof(*p)); 36484865Sobrien p->fd = -1; /* indicate that it hasn't been opened yet */ 36584865Sobrien 36684865Sobrien#ifdef HAVE_DEV_DLPI 36784865Sobrien /* 36884865Sobrien ** Remove any "/dev/" on the front of the device. 36984865Sobrien */ 37084865Sobrien cp = strrchr(device, '/'); 37184865Sobrien if (cp == NULL) 37284865Sobrien strlcpy(dname, device, sizeof(dname)); 37384865Sobrien else 37484865Sobrien strlcpy(dname, cp + 1, sizeof(dname)); 37584865Sobrien 37684865Sobrien /* 37784865Sobrien * Split the device name into a device type name and a unit number; 37884865Sobrien * chop off the unit number, so "dname" is just a device type name. 37984865Sobrien */ 38084865Sobrien cp = split_dname(dname, &ppa, ebuf); 38184865Sobrien if (cp == NULL) 38284865Sobrien goto bad; 38384865Sobrien *cp = '\0'; 38484865Sobrien 38584865Sobrien /* 38684865Sobrien * Use "/dev/dlpi" as the device. 38784865Sobrien * 38884865Sobrien * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that 38984865Sobrien * the "dl_mjr_num" field is for the "major number of interface 39084865Sobrien * driver"; that's the major of "/dev/dlpi" on the system on 39184865Sobrien * which I tried this, but there may be DLPI devices that 39284865Sobrien * use a different driver, in which case we may need to 39384865Sobrien * search "/dev" for the appropriate device with that major 39484865Sobrien * device number, rather than hardwiring "/dev/dlpi". 39584865Sobrien */ 39684865Sobrien cp = "/dev/dlpi"; 39784865Sobrien if ((p->fd = open(cp, O_RDWR)) < 0) { 39884865Sobrien snprintf(ebuf, PCAP_ERRBUF_SIZE, 39984865Sobrien "%s: %s", cp, pcap_strerror(errno)); 40084865Sobrien goto bad; 40184865Sobrien } 40284865Sobrien 40384865Sobrien /* 40484865Sobrien * Get a table of all PPAs for that device, and search that 40584865Sobrien * table for the specified device type name and unit number. 40684865Sobrien */ 40784865Sobrien ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); 40884865Sobrien if (ppa < 0) 40984865Sobrien goto bad; 41084865Sobrien#else 41184865Sobrien /* 41284865Sobrien * If the device name begins with "/", assume it begins with 41384865Sobrien * the pathname of the directory containing the device to open; 41484865Sobrien * otherwise, concatenate the device directory name and the 41584865Sobrien * device name. 41684865Sobrien */ 41784865Sobrien if (*device == '/') 41884865Sobrien strlcpy(dname, device, sizeof(dname)); 41984865Sobrien else 42084865Sobrien snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, 42184865Sobrien device); 42284865Sobrien 42384865Sobrien /* 42484865Sobrien * Get the unit number, and a pointer to the end of the device 42584865Sobrien * type name. 42684865Sobrien */ 42784865Sobrien cp = split_dname(dname, &ppa, ebuf); 42884865Sobrien if (cp == NULL) 42984865Sobrien goto bad; 43084865Sobrien 43184865Sobrien /* 43284865Sobrien * Make a copy of the device pathname, and then remove the unit 43384865Sobrien * number from the device pathname. 43484865Sobrien */ 43584865Sobrien strlcpy(dname2, dname, sizeof(dname)); 43684865Sobrien *cp = '\0'; 43784865Sobrien 43884865Sobrien /* Try device without unit number */ 43984865Sobrien if ((p->fd = open(dname, O_RDWR)) < 0) { 44084865Sobrien if (errno != ENOENT) { 44184865Sobrien snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, 44284865Sobrien pcap_strerror(errno)); 44384865Sobrien goto bad; 44484865Sobrien } 44584865Sobrien 44684865Sobrien /* Try again with unit number */ 44784865Sobrien if ((p->fd = open(dname2, O_RDWR)) < 0) { 44884865Sobrien snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, 44984865Sobrien pcap_strerror(errno)); 45084865Sobrien goto bad; 45184865Sobrien } 45284865Sobrien /* XXX Assume unit zero */ 45384865Sobrien ppa = 0; 45484865Sobrien } 45584865Sobrien#endif 45684865Sobrien 45784865Sobrien p->snapshot = snaplen; 45884865Sobrien 45984865Sobrien /* 46084865Sobrien ** Attach if "style 2" provider 46184865Sobrien */ 46284865Sobrien if (dlinforeq(p->fd, ebuf) < 0 || 46384865Sobrien dlinfoack(p->fd, (char *)buf, ebuf) < 0) 46484865Sobrien goto bad; 46584865Sobrien infop = &((union DL_primitives *)buf)->info_ack; 46684865Sobrien#ifdef HAVE_SOLARIS 46784865Sobrien if (infop->dl_mac_type == DL_IPATM) 46884865Sobrien isatm = 1; 46984865Sobrien#endif 47084865Sobrien if (infop->dl_provider_style == DL_STYLE2 && 47184865Sobrien (dlattachreq(p->fd, ppa, ebuf) < 0 || 47284865Sobrien dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) 47384865Sobrien goto bad; 47484865Sobrien /* 47584865Sobrien ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if 47684865Sobrien ** using SINIX) 477104834Sobrien */ 47884865Sobrien#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) 47984865Sobrien#ifdef _AIX 48084865Sobrien /* According to IBM's AIX Support Line, the dl_sap value 48184865Sobrien ** should not be less than 0x600 (1536) for standard Ethernet. 48284865Sobrien ** However, we seem to get DL_BADADDR - "DLSAP addr in improper 48384865Sobrien ** format or invalid" - errors if we use 1537 on the "tr0" 48484865Sobrien ** device, which, given that its name starts with "tr" and that 48584865Sobrien ** it's IBM, probably means a Token Ring device. (Perhaps we 486104834Sobrien ** need to use 1537 on "/dev/dlpi/en" because that device is for 48784865Sobrien ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and 48884865Sobrien ** it rejects invalid Ethernet types.) 48984865Sobrien ** 490104834Sobrien ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea 49184865Sobrien ** says that works on Token Ring (he says that 0 does *not* 49284865Sobrien ** work; perhaps that's considered an invalid LLC SAP value - I 49384865Sobrien ** assume the SAP value in a DLPI bind is an LLC SAP for network 49484865Sobrien ** types that use 802.2 LLC). 49584865Sobrien */ 49684865Sobrien if ((dlbindreq(p->fd, 1537, ebuf) < 0 && 497 dlbindreq(p->fd, 2, ebuf) < 0) || 498#else 499 if (dlbindreq(p->fd, 0, ebuf) < 0 || 500#endif 501 dlbindack(p->fd, (char *)buf, ebuf) < 0) 502 goto bad; 503#endif 504 505#ifdef HAVE_SOLARIS 506 if (isatm) { 507 /* 508 ** Have to turn on some special ATM promiscuous mode 509 ** for SunATM. 510 ** Do *NOT* turn regular promiscuous mode on; it doesn't 511 ** help, and may break things. 512 */ 513 if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { 514 snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", 515 pcap_strerror(errno)); 516 goto bad; 517 } 518 } else 519#endif 520 if (promisc) { 521 /* 522 ** Enable promiscuous 523 */ 524 if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || 525 dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) 526 goto bad; 527 528 /* 529 ** Try to enable multicast (you would have thought 530 ** promiscuous would be sufficient). (Skip if using 531 ** HP-UX or SINIX) 532 */ 533#if !defined(__hpux) && !defined(sinix) 534 if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || 535 dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) 536 fprintf(stderr, 537 "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); 538#endif 539 } 540 /* 541 ** Try to enable sap (when not in promiscuous mode when using 542 ** using HP-UX, when not doing SunATM on Solaris, and never 543 ** under SINIX) 544 */ 545#ifndef sinix 546 if ( 547#ifdef __hpux 548 !promisc && 549#endif 550#ifdef HAVE_SOLARIS 551 !isatm && 552#endif 553 (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || 554 dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { 555 /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ 556 if (promisc) 557 fprintf(stderr, 558 "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); 559 else 560 goto bad; 561 } 562#endif 563 564 /* 565 ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous 566 ** options) 567 */ 568#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) 569 if (dlbindreq(p->fd, 0, ebuf) < 0 || 570 dlbindack(p->fd, (char *)buf, ebuf) < 0) 571 goto bad; 572#endif 573 574 /* 575 ** Determine link type 576 */ 577 if (dlinforeq(p->fd, ebuf) < 0 || 578 dlinfoack(p->fd, (char *)buf, ebuf) < 0) 579 goto bad; 580 581 infop = &((union DL_primitives *)buf)->info_ack; 582 switch (infop->dl_mac_type) { 583 584 case DL_CSMACD: 585 case DL_ETHER: 586 p->linktype = DLT_EN10MB; 587 p->offset = 2; 588 break; 589 590 case DL_FDDI: 591 p->linktype = DLT_FDDI; 592 p->offset = 3; 593 break; 594 595 case DL_TPR: 596 p->linktype = DLT_IEEE802; 597 p->offset = 2; 598 break; 599 600#ifdef HAVE_SOLARIS 601 case DL_IPATM: 602 p->linktype = DLT_SUNATM; 603 p->offset = 0; /* works for LANE and LLC encapsulation */ 604 break; 605#endif 606 607 default: 608 snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", 609 (unsigned long)infop->dl_mac_type); 610 goto bad; 611 } 612 613#ifdef DLIOCRAW 614 /* 615 ** This is a non standard SunOS hack to get the full raw link-layer 616 ** header. 617 */ 618 if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 619 snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", 620 pcap_strerror(errno)); 621 goto bad; 622 } 623#endif 624 625#ifdef HAVE_SYS_BUFMOD_H 626 /* 627 ** Another non standard call to get the data nicely buffered 628 */ 629 if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { 630 snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", 631 pcap_strerror(errno)); 632 goto bad; 633 } 634 635 /* 636 ** Now that the bufmod is pushed lets configure it. 637 ** 638 ** There is a bug in bufmod(7). When dealing with messages of 639 ** less than snaplen size it strips data from the beginning not 640 ** the end. 641 ** 642 ** This bug is supposed to be fixed in 5.3.2. Also, there is a 643 ** patch available. Ask for bugid 1149065. 644 */ 645 ss = snaplen; 646#ifdef HAVE_SOLARIS 647 release = get_release(&osmajor, &osminor, &osmicro); 648 if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 649 getenv("BUFMOD_FIXED") == NULL) { 650 fprintf(stderr, 651 "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", 652 release); 653 ss = 0; 654 } 655#endif 656 if (ss > 0 && 657 strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { 658 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", 659 pcap_strerror(errno)); 660 goto bad; 661 } 662 663 /* 664 ** Set up the bufmod timeout 665 */ 666 if (to_ms != 0) { 667 struct timeval to; 668 669 to.tv_sec = to_ms / 1000; 670 to.tv_usec = (to_ms * 1000) % 1000000; 671 if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { 672 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", 673 pcap_strerror(errno)); 674 goto bad; 675 } 676 } 677 678 /* 679 ** Set the chunk length. 680 */ 681 chunksize = CHUNKSIZE; 682 if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize) 683 != 0) { 684 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s", 685 pcap_strerror(errno)); 686 goto bad; 687 } 688#endif 689 690 /* 691 ** As the last operation flush the read side. 692 */ 693 if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 694 snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 695 pcap_strerror(errno)); 696 goto bad; 697 } 698 699 /* Allocate data buffer */ 700 p->bufsize = PKTBUFSIZE; 701 p->buffer = (u_char *)malloc(p->bufsize + p->offset); 702 if (p->buffer == NULL) { 703 strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 704 goto bad; 705 } 706 707 /* 708 * "p->fd" is an FD for a STREAMS device, so "select()" and 709 * "poll()" should work on it. 710 */ 711 p->selectable_fd = p->fd; 712 713 p->read_op = pcap_read_dlpi; 714 p->setfilter_op = install_bpf_program; /* no kernel filtering */ 715 p->set_datalink_op = NULL; /* can't change data link type */ 716 p->getnonblock_op = pcap_getnonblock_fd; 717 p->setnonblock_op = pcap_setnonblock_fd; 718 p->stats_op = pcap_stats_dlpi; 719 p->close_op = pcap_close_dlpi; 720 721 return (p); 722bad: 723 if (p->fd >= 0) 724 close(p->fd); 725 free(p); 726 return (NULL); 727} 728 729/* 730 * Split a device name into a device type name and a unit number; 731 * return the a pointer to the beginning of the unit number, which 732 * is the end of the device type name, and set "*unitp" to the unit 733 * number. 734 * 735 * Returns NULL on error, and fills "ebuf" with an error message. 736 */ 737static char * 738split_dname(char *device, int *unitp, char *ebuf) 739{ 740 char *cp; 741 char *eos; 742 int unit; 743 744 /* 745 * Look for a number at the end of the device name string. 746 */ 747 cp = device + strlen(device) - 1; 748 if (*cp < '0' || *cp > '9') { 749 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", 750 device); 751 return (NULL); 752 } 753 754 /* Digits at end of string are unit number */ 755 while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') 756 cp--; 757 758 unit = strtol(cp, &eos, 10); 759 if (*eos != '\0') { 760 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); 761 return (NULL); 762 } 763 *unitp = unit; 764 return (cp); 765} 766 767int 768pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 769{ 770#ifdef HAVE_SOLARIS 771 int fd; 772 union { 773 u_int nunits; 774 char pad[516]; /* XXX - must be at least 513; is 516 775 in "atmgetunits" */ 776 } buf; 777 char baname[2+1+1]; 778 u_int i; 779 780 /* 781 * We may have to do special magic to get ATM devices. 782 */ 783 if ((fd = open("/dev/ba", O_RDWR)) < 0) { 784 /* 785 * We couldn't open the "ba" device. 786 * For now, just give up; perhaps we should 787 * return an error if the problem is neither 788 * a "that device doesn't exist" error (ENOENT, 789 * ENXIO, etc.) or a "you're not allowed to do 790 * that" error (EPERM, EACCES). 791 */ 792 return (0); 793 } 794 795 if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { 796 snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", 797 pcap_strerror(errno)); 798 return (-1); 799 } 800 for (i = 0; i < buf.nunits; i++) { 801 snprintf(baname, sizeof baname, "ba%u", i); 802 if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) 803 return (-1); 804 } 805#endif 806 807 return (0); 808} 809 810static int 811send_request(int fd, char *ptr, int len, char *what, char *ebuf) 812{ 813 struct strbuf ctl; 814 int flags; 815 816 ctl.maxlen = 0; 817 ctl.len = len; 818 ctl.buf = ptr; 819 820 flags = 0; 821 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 822 snprintf(ebuf, PCAP_ERRBUF_SIZE, 823 "send_request: putmsg \"%s\": %s", 824 what, pcap_strerror(errno)); 825 return (-1); 826 } 827 return (0); 828} 829 830static int 831recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) 832{ 833 union DL_primitives *dlp; 834 struct strbuf ctl; 835 int flags; 836 837 ctl.maxlen = MAXDLBUF; 838 ctl.len = 0; 839 ctl.buf = bufp; 840 841 flags = 0; 842 if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 843 snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", 844 what, pcap_strerror(errno)); 845 return (-1); 846 } 847 848 dlp = (union DL_primitives *) ctl.buf; 849 switch (dlp->dl_primitive) { 850 851 case DL_INFO_ACK: 852 case DL_BIND_ACK: 853 case DL_OK_ACK: 854#ifdef DL_HP_PPA_ACK 855 case DL_HP_PPA_ACK: 856#endif 857 /* These are OK */ 858 break; 859 860 case DL_ERROR_ACK: 861 switch (dlp->error_ack.dl_errno) { 862 863 case DL_SYSERR: 864 snprintf(ebuf, PCAP_ERRBUF_SIZE, 865 "recv_ack: %s: UNIX error - %s", 866 what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 867 break; 868 869 default: 870 snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", 871 what, dlstrerror(dlp->error_ack.dl_errno)); 872 break; 873 } 874 return (-1); 875 876 default: 877 snprintf(ebuf, PCAP_ERRBUF_SIZE, 878 "recv_ack: %s: Unexpected primitive ack %s", 879 what, dlprim(dlp->dl_primitive)); 880 return (-1); 881 } 882 883 if (ctl.len < size) { 884 snprintf(ebuf, PCAP_ERRBUF_SIZE, 885 "recv_ack: %s: Ack too small (%d < %d)", 886 what, ctl.len, size); 887 return (-1); 888 } 889 return (ctl.len); 890} 891 892static char * 893dlstrerror(bpf_u_int32 dl_errno) 894{ 895 static char errstring[6+2+8+1]; 896 897 switch (dl_errno) { 898 899 case DL_ACCESS: 900 return ("Improper permissions for request"); 901 902 case DL_BADADDR: 903 return ("DLSAP addr in improper format or invalid"); 904 905 case DL_BADCORR: 906 return ("Seq number not from outstand DL_CONN_IND"); 907 908 case DL_BADDATA: 909 return ("User data exceeded provider limit"); 910 911 case DL_BADPPA: 912#ifdef HAVE_DEV_DLPI 913 /* 914 * With a single "/dev/dlpi" device used for all 915 * DLPI providers, PPAs have nothing to do with 916 * unit numbers. 917 */ 918 return ("Specified PPA was invalid"); 919#else 920 /* 921 * We have separate devices for separate devices; 922 * the PPA is just the unit number. 923 */ 924 return ("Specified PPA (device unit) was invalid"); 925#endif 926 927 case DL_BADPRIM: 928 return ("Primitive received not known by provider"); 929 930 case DL_BADQOSPARAM: 931 return ("QOS parameters contained invalid values"); 932 933 case DL_BADQOSTYPE: 934 return ("QOS structure type is unknown/unsupported"); 935 936 case DL_BADSAP: 937 return ("Bad LSAP selector"); 938 939 case DL_BADTOKEN: 940 return ("Token used not an active stream"); 941 942 case DL_BOUND: 943 return ("Attempted second bind with dl_max_conind"); 944 945 case DL_INITFAILED: 946 return ("Physical link initialization failed"); 947 948 case DL_NOADDR: 949 return ("Provider couldn't allocate alternate address"); 950 951 case DL_NOTINIT: 952 return ("Physical link not initialized"); 953 954 case DL_OUTSTATE: 955 return ("Primitive issued in improper state"); 956 957 case DL_SYSERR: 958 return ("UNIX system error occurred"); 959 960 case DL_UNSUPPORTED: 961 return ("Requested service not supplied by provider"); 962 963 case DL_UNDELIVERABLE: 964 return ("Previous data unit could not be delivered"); 965 966 case DL_NOTSUPPORTED: 967 return ("Primitive is known but not supported"); 968 969 case DL_TOOMANY: 970 return ("Limit exceeded"); 971 972 case DL_NOTENAB: 973 return ("Promiscuous mode not enabled"); 974 975 case DL_BUSY: 976 return ("Other streams for PPA in post-attached"); 977 978 case DL_NOAUTO: 979 return ("Automatic handling XID&TEST not supported"); 980 981 case DL_NOXIDAUTO: 982 return ("Automatic handling of XID not supported"); 983 984 case DL_NOTESTAUTO: 985 return ("Automatic handling of TEST not supported"); 986 987 case DL_XIDAUTO: 988 return ("Automatic handling of XID response"); 989 990 case DL_TESTAUTO: 991 return ("Automatic handling of TEST response"); 992 993 case DL_PENDING: 994 return ("Pending outstanding connect indications"); 995 996 default: 997 sprintf(errstring, "Error %02x", dl_errno); 998 return (errstring); 999 } 1000} 1001 1002static char * 1003dlprim(bpf_u_int32 prim) 1004{ 1005 static char primbuf[80]; 1006 1007 switch (prim) { 1008 1009 case DL_INFO_REQ: 1010 return ("DL_INFO_REQ"); 1011 1012 case DL_INFO_ACK: 1013 return ("DL_INFO_ACK"); 1014 1015 case DL_ATTACH_REQ: 1016 return ("DL_ATTACH_REQ"); 1017 1018 case DL_DETACH_REQ: 1019 return ("DL_DETACH_REQ"); 1020 1021 case DL_BIND_REQ: 1022 return ("DL_BIND_REQ"); 1023 1024 case DL_BIND_ACK: 1025 return ("DL_BIND_ACK"); 1026 1027 case DL_UNBIND_REQ: 1028 return ("DL_UNBIND_REQ"); 1029 1030 case DL_OK_ACK: 1031 return ("DL_OK_ACK"); 1032 1033 case DL_ERROR_ACK: 1034 return ("DL_ERROR_ACK"); 1035 1036 case DL_SUBS_BIND_REQ: 1037 return ("DL_SUBS_BIND_REQ"); 1038 1039 case DL_SUBS_BIND_ACK: 1040 return ("DL_SUBS_BIND_ACK"); 1041 1042 case DL_UNITDATA_REQ: 1043 return ("DL_UNITDATA_REQ"); 1044 1045 case DL_UNITDATA_IND: 1046 return ("DL_UNITDATA_IND"); 1047 1048 case DL_UDERROR_IND: 1049 return ("DL_UDERROR_IND"); 1050 1051 case DL_UDQOS_REQ: 1052 return ("DL_UDQOS_REQ"); 1053 1054 case DL_CONNECT_REQ: 1055 return ("DL_CONNECT_REQ"); 1056 1057 case DL_CONNECT_IND: 1058 return ("DL_CONNECT_IND"); 1059 1060 case DL_CONNECT_RES: 1061 return ("DL_CONNECT_RES"); 1062 1063 case DL_CONNECT_CON: 1064 return ("DL_CONNECT_CON"); 1065 1066 case DL_TOKEN_REQ: 1067 return ("DL_TOKEN_REQ"); 1068 1069 case DL_TOKEN_ACK: 1070 return ("DL_TOKEN_ACK"); 1071 1072 case DL_DISCONNECT_REQ: 1073 return ("DL_DISCONNECT_REQ"); 1074 1075 case DL_DISCONNECT_IND: 1076 return ("DL_DISCONNECT_IND"); 1077 1078 case DL_RESET_REQ: 1079 return ("DL_RESET_REQ"); 1080 1081 case DL_RESET_IND: 1082 return ("DL_RESET_IND"); 1083 1084 case DL_RESET_RES: 1085 return ("DL_RESET_RES"); 1086 1087 case DL_RESET_CON: 1088 return ("DL_RESET_CON"); 1089 1090 default: 1091 (void) sprintf(primbuf, "unknown primitive 0x%x", prim); 1092 return (primbuf); 1093 } 1094} 1095 1096static int 1097dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) 1098{ 1099 dl_attach_req_t req; 1100 1101 req.dl_primitive = DL_ATTACH_REQ; 1102 req.dl_ppa = ppa; 1103 1104 return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); 1105} 1106 1107static int 1108dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 1109{ 1110 1111 dl_bind_req_t req; 1112 1113 memset((char *)&req, 0, sizeof(req)); 1114 req.dl_primitive = DL_BIND_REQ; 1115#ifdef DL_HP_RAWDLS 1116 req.dl_max_conind = 1; /* XXX magic number */ 1117 /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ 1118 req.dl_sap = 22; 1119 req.dl_service_mode = DL_HP_RAWDLS; 1120#else 1121 req.dl_sap = sap; 1122#ifdef DL_CLDLS 1123 req.dl_service_mode = DL_CLDLS; 1124#endif 1125#endif 1126 1127 return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 1128} 1129 1130static int 1131dlbindack(int fd, char *bufp, char *ebuf) 1132{ 1133 1134 return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); 1135} 1136 1137static int 1138dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) 1139{ 1140 dl_promiscon_req_t req; 1141 1142 req.dl_primitive = DL_PROMISCON_REQ; 1143 req.dl_level = level; 1144 1145 return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); 1146} 1147 1148static int 1149dlokack(int fd, const char *what, char *bufp, char *ebuf) 1150{ 1151 1152 return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); 1153} 1154 1155 1156static int 1157dlinforeq(int fd, char *ebuf) 1158{ 1159 dl_info_req_t req; 1160 1161 req.dl_primitive = DL_INFO_REQ; 1162 1163 return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 1164} 1165 1166static int 1167dlinfoack(int fd, char *bufp, char *ebuf) 1168{ 1169 1170 return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); 1171} 1172 1173#ifdef HAVE_SYS_BUFMOD_H 1174static int 1175strioctl(int fd, int cmd, int len, char *dp) 1176{ 1177 struct strioctl str; 1178 int rc; 1179 1180 str.ic_cmd = cmd; 1181 str.ic_timout = -1; 1182 str.ic_len = len; 1183 str.ic_dp = dp; 1184 rc = ioctl(fd, I_STR, &str); 1185 1186 if (rc < 0) 1187 return (rc); 1188 else 1189 return (str.ic_len); 1190} 1191#endif 1192 1193#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 1194static char * 1195get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 1196{ 1197 char *cp; 1198 static char buf[32]; 1199 1200 *majorp = 0; 1201 *minorp = 0; 1202 *microp = 0; 1203 if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 1204 return ("?"); 1205 cp = buf; 1206 if (!isdigit((unsigned char)*cp)) 1207 return (buf); 1208 *majorp = strtol(cp, &cp, 10); 1209 if (*cp++ != '.') 1210 return (buf); 1211 *minorp = strtol(cp, &cp, 10); 1212 if (*cp++ != '.') 1213 return (buf); 1214 *microp = strtol(cp, &cp, 10); 1215 return (buf); 1216} 1217#endif 1218 1219#ifdef DL_HP_PPA_ACK_OBS 1220/* 1221 * Under HP-UX 10 and HP-UX 11, we can ask for the ppa 1222 */ 1223 1224 1225/* 1226 * Determine ppa number that specifies ifname. 1227 * 1228 * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, 1229 * the code that's used here is the old code for HP-UX 10.x. 1230 * 1231 * However, HP-UX 10.20, at least, appears to have such a member 1232 * in its "dl_hp_ppa_info_t" structure, so the new code is used. 1233 * The new code didn't work on an old 10.20 system on which Rick 1234 * Jones of HP tried it, but with later patches installed, it 1235 * worked - it appears that the older system had those members but 1236 * didn't put anything in them, so, if the search by name fails, we 1237 * do the old search. 1238 * 1239 * Rick suggests that making sure your system is "up on the latest 1240 * lancommon/DLPI/driver patches" is probably a good idea; it'd fix 1241 * that problem, as well as allowing libpcap to see packets sent 1242 * from the system on which the libpcap application is being run. 1243 * (On 10.20, in addition to getting the latest patches, you need 1244 * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; 1245 * a posting to "comp.sys.hp.hpux" at 1246 * 1247 * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 1248 * 1249 * says that, to see the machine's outgoing traffic, you'd need to 1250 * apply the right patches to your system, and also set that variable 1251 * with: 1252 1253echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem 1254 1255 * which could be put in, for example, "/sbin/init.d/lan". 1256 * 1257 * Setting the variable is not necessary on HP-UX 11.x. 1258 */ 1259static int 1260get_dlpi_ppa(register int fd, register const char *device, register int unit, 1261 register char *ebuf) 1262{ 1263 register dl_hp_ppa_ack_t *ap; 1264 register dl_hp_ppa_info_t *ipstart, *ip; 1265 register int i; 1266 char dname[100]; 1267 register u_long majdev; 1268 struct stat statbuf; 1269 dl_hp_ppa_req_t req; 1270 char buf[MAXDLBUF]; 1271 char *ppa_data_buf; 1272 dl_hp_ppa_ack_t *dlp; 1273 struct strbuf ctl; 1274 int flags; 1275 int ppa; 1276 1277 memset((char *)&req, 0, sizeof(req)); 1278 req.dl_primitive = DL_HP_PPA_REQ; 1279 1280 memset((char *)buf, 0, sizeof(buf)); 1281 if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) 1282 return (-1); 1283 1284 ctl.maxlen = DL_HP_PPA_ACK_SIZE; 1285 ctl.len = 0; 1286 ctl.buf = (char *)buf; 1287 1288 flags = 0; 1289 /* 1290 * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal 1291 * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) 1292 * which is NOT big enough for a DL_HP_PPA_REQ. 1293 * 1294 * This causes libpcap applications to fail on a system with HP-APA 1295 * installed. 1296 * 1297 * To figure out how big the returned data is, we first call getmsg 1298 * to get the small head and peek at the head to get the actual data 1299 * length, and then issue another getmsg to get the actual PPA data. 1300 */ 1301 /* get the head first */ 1302 if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 1303 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1304 "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 1305 return (-1); 1306 } 1307 1308 dlp = (dl_hp_ppa_ack_t *)ctl.buf; 1309 if (dlp->dl_primitive != DL_HP_PPA_ACK) { 1310 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1311 "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", 1312 (bpf_u_int32)dlp->dl_primitive); 1313 return (-1); 1314 } 1315 1316 if (ctl.len < DL_HP_PPA_ACK_SIZE) { 1317 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1318 "get_dlpi_ppa: hpppa ack too small (%d < %lu)", 1319 ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); 1320 return (-1); 1321 } 1322 1323 /* allocate buffer */ 1324 if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { 1325 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1326 "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); 1327 return (-1); 1328 } 1329 ctl.maxlen = dlp->dl_length; 1330 ctl.len = 0; 1331 ctl.buf = (char *)ppa_data_buf; 1332 /* get the data */ 1333 if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 1334 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1335 "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 1336 free(ppa_data_buf); 1337 return (-1); 1338 } 1339 if (ctl.len < dlp->dl_length) { 1340 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1341 "get_dlpi_ppa: hpppa ack too small (%d < %d)", 1342 ctl.len, dlp->dl_length); 1343 free(ppa_data_buf); 1344 return (-1); 1345 } 1346 1347 ap = (dl_hp_ppa_ack_t *)buf; 1348 ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; 1349 ip = ipstart; 1350 1351#ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1352 /* 1353 * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" 1354 * member that should, in theory, contain the part of the 1355 * name for the device that comes before the unit number, 1356 * and should also have a "dl_module_id_2" member that may 1357 * contain an alternate name (e.g., I think Ethernet devices 1358 * have both "lan", for "lanN", and "snap", for "snapN", with 1359 * the former being for Ethernet packets and the latter being 1360 * for 802.3/802.2 packets). 1361 * 1362 * Search for the device that has the specified name and 1363 * instance number. 1364 */ 1365 for (i = 0; i < ap->dl_count; i++) { 1366 if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || 1367 strcmp((const char *)ip->dl_module_id_2, device) == 0) && 1368 ip->dl_instance_num == unit) 1369 break; 1370 1371 ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1372 } 1373#else 1374 /* 1375 * We don't have that member, so the search is impossible; make it 1376 * look as if the search failed. 1377 */ 1378 i = ap->dl_count; 1379#endif 1380 1381 if (i == ap->dl_count) { 1382 /* 1383 * Well, we didn't, or can't, find the device by name. 1384 * 1385 * HP-UX 10.20, whilst it has "dl_module_id_1" and 1386 * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", 1387 * doesn't seem to fill them in unless the system is 1388 * at a reasonably up-to-date patch level. 1389 * 1390 * Older HP-UX 10.x systems might not have those fields 1391 * at all. 1392 * 1393 * Therefore, we'll search for the entry with the major 1394 * device number of a device with the name "/dev/<dev><unit>", 1395 * if such a device exists, as the old code did. 1396 */ 1397 snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); 1398 if (stat(dname, &statbuf) < 0) { 1399 snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", 1400 dname, pcap_strerror(errno)); 1401 return (-1); 1402 } 1403 majdev = major(statbuf.st_rdev); 1404 1405 ip = ipstart; 1406 1407 for (i = 0; i < ap->dl_count; i++) { 1408 if (ip->dl_mjr_num == majdev && 1409 ip->dl_instance_num == unit) 1410 break; 1411 1412 ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1413 } 1414 } 1415 if (i == ap->dl_count) { 1416 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1417 "can't find /dev/dlpi PPA for %s%d", device, unit); 1418 return (-1); 1419 } 1420 if (ip->dl_hdw_state == HDW_DEAD) { 1421 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1422 "%s%d: hardware state: DOWN\n", device, unit); 1423 free(ppa_data_buf); 1424 return (-1); 1425 } 1426 ppa = ip->dl_ppa; 1427 free(ppa_data_buf); 1428 return (ppa); 1429} 1430#endif 1431 1432#ifdef HAVE_HPUX9 1433/* 1434 * Under HP-UX 9, there is no good way to determine the ppa. 1435 * So punt and read it from /dev/kmem. 1436 */ 1437static struct nlist nl[] = { 1438#define NL_IFNET 0 1439 { "ifnet" }, 1440 { "" } 1441}; 1442 1443static char path_vmunix[] = "/hp-ux"; 1444 1445/* Determine ppa number that specifies ifname */ 1446static int 1447get_dlpi_ppa(register int fd, register const char *ifname, register int unit, 1448 register char *ebuf) 1449{ 1450 register const char *cp; 1451 register int kd; 1452 void *addr; 1453 struct ifnet ifnet; 1454 char if_name[sizeof(ifnet.if_name) + 1]; 1455 1456 cp = strrchr(ifname, '/'); 1457 if (cp != NULL) 1458 ifname = cp + 1; 1459 if (nlist(path_vmunix, &nl) < 0) { 1460 snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", 1461 path_vmunix); 1462 return (-1); 1463 } 1464 if (nl[NL_IFNET].n_value == 0) { 1465 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1466 "could't find %s kernel symbol", 1467 nl[NL_IFNET].n_name); 1468 return (-1); 1469 } 1470 kd = open("/dev/kmem", O_RDONLY); 1471 if (kd < 0) { 1472 snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", 1473 pcap_strerror(errno)); 1474 return (-1); 1475 } 1476 if (dlpi_kread(kd, nl[NL_IFNET].n_value, 1477 &addr, sizeof(addr), ebuf) < 0) { 1478 close(kd); 1479 return (-1); 1480 } 1481 for (; addr != NULL; addr = ifnet.if_next) { 1482 if (dlpi_kread(kd, (off_t)addr, 1483 &ifnet, sizeof(ifnet), ebuf) < 0 || 1484 dlpi_kread(kd, (off_t)ifnet.if_name, 1485 if_name, sizeof(ifnet.if_name), ebuf) < 0) { 1486 (void)close(kd); 1487 return (-1); 1488 } 1489 if_name[sizeof(ifnet.if_name)] = '\0'; 1490 if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) 1491 return (ifnet.if_index); 1492 } 1493 1494 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); 1495 return (-1); 1496} 1497 1498static int 1499dlpi_kread(register int fd, register off_t addr, 1500 register void *buf, register u_int len, register char *ebuf) 1501{ 1502 register int cc; 1503 1504 if (lseek(fd, addr, SEEK_SET) < 0) { 1505 snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", 1506 pcap_strerror(errno)); 1507 return (-1); 1508 } 1509 cc = read(fd, buf, len); 1510 if (cc < 0) { 1511 snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", 1512 pcap_strerror(errno)); 1513 return (-1); 1514 } else if (cc != len) { 1515 snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, 1516 len); 1517 return (-1); 1518 } 1519 return (cc); 1520} 1521#endif 1522