18cf6c252SPaul Traina /* 2a4b5b39fSBill Fenner * Copyright (c) 1993, 1994, 1995, 1996, 1997 38cf6c252SPaul Traina * The Regents of the University of California. All rights reserved. 48cf6c252SPaul Traina * 58cf6c252SPaul Traina * Redistribution and use in source and binary forms, with or without 68cf6c252SPaul Traina * modification, are permitted provided that: (1) source code distributions 78cf6c252SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 88cf6c252SPaul Traina * distributions including binary code include the above copyright notice and 98cf6c252SPaul Traina * this paragraph in its entirety in the documentation or other materials 108cf6c252SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 118cf6c252SPaul Traina * features or use of this software display the following acknowledgement: 128cf6c252SPaul Traina * ``This product includes software developed by the University of California, 138cf6c252SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 148cf6c252SPaul Traina * the University nor the names of its contributors may be used to endorse 158cf6c252SPaul Traina * or promote products derived from this software without specific prior 168cf6c252SPaul Traina * written permission. 178cf6c252SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 188cf6c252SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 198cf6c252SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 208cf6c252SPaul Traina * 218cf6c252SPaul Traina * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), 228cf6c252SPaul Traina * University College London. 238cf6c252SPaul Traina */ 248cf6c252SPaul Traina 258cf6c252SPaul Traina /* 268cf6c252SPaul Traina * Packet capture routine for dlpi under SunOS 5 278cf6c252SPaul Traina * 288cf6c252SPaul Traina * Notes: 298cf6c252SPaul Traina * 308cf6c252SPaul Traina * - Apparently the DLIOCRAW ioctl() is specific to SunOS. 318cf6c252SPaul Traina * 328cf6c252SPaul Traina * - There is a bug in bufmod(7) such that setting the snapshot 338cf6c252SPaul Traina * length results in data being left of the front of the packet. 348cf6c252SPaul Traina * 358cf6c252SPaul Traina * - It might be desirable to use pfmod(7) to filter packets in the 368cf6c252SPaul Traina * kernel. 378cf6c252SPaul Traina */ 388cf6c252SPaul Traina 393052b236SBill Fenner #ifndef lint 403052b236SBill Fenner static const char rcsid[] = 410a94d38fSBill Fenner "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.74 2001/12/10 07:14:15 guy Exp $ (LBL)"; 42dc2c7305SBill Fenner #endif 43dc2c7305SBill Fenner 44dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H 45dc2c7305SBill Fenner #include "config.h" 463052b236SBill Fenner #endif 473052b236SBill Fenner 488cf6c252SPaul Traina #include <sys/types.h> 498cf6c252SPaul Traina #include <sys/time.h> 508cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 518cf6c252SPaul Traina #include <sys/bufmod.h> 528cf6c252SPaul Traina #endif 538cf6c252SPaul Traina #include <sys/dlpi.h> 548cf6c252SPaul Traina #ifdef HAVE_SYS_DLPI_EXT_H 558cf6c252SPaul Traina #include <sys/dlpi_ext.h> 568cf6c252SPaul Traina #endif 578cf6c252SPaul Traina #ifdef HAVE_HPUX9 588cf6c252SPaul Traina #include <sys/socket.h> 598cf6c252SPaul Traina #endif 608cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK_OBS 618cf6c252SPaul Traina #include <sys/stat.h> 628cf6c252SPaul Traina #endif 638cf6c252SPaul Traina #include <sys/stream.h> 648cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 658cf6c252SPaul Traina #include <sys/systeminfo.h> 668cf6c252SPaul Traina #endif 678cf6c252SPaul Traina 688cf6c252SPaul Traina #ifdef HAVE_HPUX9 698cf6c252SPaul Traina #include <net/if.h> 708cf6c252SPaul Traina #endif 718cf6c252SPaul Traina 728cf6c252SPaul Traina #include <ctype.h> 738cf6c252SPaul Traina #ifdef HAVE_HPUX9 748cf6c252SPaul Traina #include <nlist.h> 758cf6c252SPaul Traina #endif 768cf6c252SPaul Traina #include <errno.h> 778cf6c252SPaul Traina #include <fcntl.h> 788cf6c252SPaul Traina #include <memory.h> 798cf6c252SPaul Traina #include <stdio.h> 808cf6c252SPaul Traina #include <stdlib.h> 818cf6c252SPaul Traina #include <string.h> 828cf6c252SPaul Traina #include <stropts.h> 838cf6c252SPaul Traina #include <unistd.h> 848cf6c252SPaul Traina 858cf6c252SPaul Traina #include "pcap-int.h" 868cf6c252SPaul Traina 878cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 888cf6c252SPaul Traina #include "os-proto.h" 898cf6c252SPaul Traina #endif 908cf6c252SPaul Traina 918cf6c252SPaul Traina #ifndef PCAP_DEV_PREFIX 920a94d38fSBill Fenner #ifdef _AIX 930a94d38fSBill Fenner #define PCAP_DEV_PREFIX "/dev/dlpi" 940a94d38fSBill Fenner #else 958cf6c252SPaul Traina #define PCAP_DEV_PREFIX "/dev" 968cf6c252SPaul Traina #endif 970a94d38fSBill Fenner #endif 988cf6c252SPaul Traina 998cf6c252SPaul Traina #define MAXDLBUF 8192 1008cf6c252SPaul Traina 1018cf6c252SPaul Traina /* Forwards */ 1020a94d38fSBill Fenner static char *split_dname(char *, int *, char *); 1038cf6c252SPaul Traina static int dlattachreq(int, bpf_u_int32, char *); 1048cf6c252SPaul Traina static int dlbindack(int, char *, char *); 1058cf6c252SPaul Traina static int dlbindreq(int, bpf_u_int32, char *); 1068cf6c252SPaul Traina static int dlinfoack(int, char *, char *); 1078cf6c252SPaul Traina static int dlinforeq(int, char *); 1088cf6c252SPaul Traina static int dlokack(int, const char *, char *, char *); 1098cf6c252SPaul Traina static int recv_ack(int, int, const char *, char *, char *); 1100a94d38fSBill Fenner static char *dlstrerror(bpf_u_int32); 1110a94d38fSBill Fenner static char *dlprim(bpf_u_int32); 1128cf6c252SPaul Traina static int dlpromisconreq(int, bpf_u_int32, char *); 1138cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 1148cf6c252SPaul Traina static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 1158cf6c252SPaul Traina #endif 1168cf6c252SPaul Traina static int send_request(int, char *, int, char *, char *); 1178cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1188cf6c252SPaul Traina static int strioctl(int, int, int, char *); 1198cf6c252SPaul Traina #endif 1208cf6c252SPaul Traina #ifdef HAVE_HPUX9 1218cf6c252SPaul Traina static int dlpi_kread(int, off_t, void *, u_int, char *); 1228cf6c252SPaul Traina #endif 1238cf6c252SPaul Traina #ifdef HAVE_DEV_DLPI 1248cf6c252SPaul Traina static int get_dlpi_ppa(int, const char *, int, char *); 1258cf6c252SPaul Traina #endif 1268cf6c252SPaul Traina 1278cf6c252SPaul Traina int 1288cf6c252SPaul Traina pcap_stats(pcap_t *p, struct pcap_stat *ps) 1298cf6c252SPaul Traina { 1308cf6c252SPaul Traina 1310a94d38fSBill Fenner /* 1320a94d38fSBill Fenner * "ps_recv" counts packets handed to the filter, not packets 1330a94d38fSBill Fenner * that passed the filter. As filtering is done in userland, 1340a94d38fSBill Fenner * this does not include packets dropped because we ran out 1350a94d38fSBill Fenner * of buffer space. 1360a94d38fSBill Fenner * 1370a94d38fSBill Fenner * "ps_drop" counts packets dropped inside the DLPI service 1380a94d38fSBill Fenner * provider device device because of flow control requirements 1390a94d38fSBill Fenner * or resource exhaustion; it doesn't count packets dropped by 1400a94d38fSBill Fenner * the interface driver, or packets dropped upstream. As 1410a94d38fSBill Fenner * filtering is done in userland, it counts packets regardless 1420a94d38fSBill Fenner * of whether they would've passed the filter. 1430a94d38fSBill Fenner * 1440a94d38fSBill Fenner * These statistics don't include packets not yet read from 1450a94d38fSBill Fenner * the kernel by libpcap, but they may include packets not 1460a94d38fSBill Fenner * yet read from libpcap by the application. 1470a94d38fSBill Fenner */ 1488cf6c252SPaul Traina *ps = p->md.stat; 1498cf6c252SPaul Traina return (0); 1508cf6c252SPaul Traina } 1518cf6c252SPaul Traina 1528cf6c252SPaul Traina /* XXX Needed by HP-UX (at least) */ 1538cf6c252SPaul Traina static bpf_u_int32 ctlbuf[MAXDLBUF]; 1548cf6c252SPaul Traina static struct strbuf ctl = { 1558cf6c252SPaul Traina MAXDLBUF, 1568cf6c252SPaul Traina 0, 1578cf6c252SPaul Traina (char *)ctlbuf 1588cf6c252SPaul Traina }; 1598cf6c252SPaul Traina 1608cf6c252SPaul Traina int 1618cf6c252SPaul Traina pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 1628cf6c252SPaul Traina { 1638cf6c252SPaul Traina register int cc, n, caplen, origlen; 1648cf6c252SPaul Traina register u_char *bp, *ep, *pk; 1658cf6c252SPaul Traina register struct bpf_insn *fcode; 1668cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1678cf6c252SPaul Traina register struct sb_hdr *sbp; 1688cf6c252SPaul Traina #ifdef LBL_ALIGN 1698cf6c252SPaul Traina struct sb_hdr sbhdr; 1708cf6c252SPaul Traina #endif 1718cf6c252SPaul Traina #endif 1728cf6c252SPaul Traina int flags; 1738cf6c252SPaul Traina struct strbuf data; 1748cf6c252SPaul Traina struct pcap_pkthdr pkthdr; 1758cf6c252SPaul Traina 1768cf6c252SPaul Traina flags = 0; 1778cf6c252SPaul Traina cc = p->cc; 1788cf6c252SPaul Traina if (cc == 0) { 1798cf6c252SPaul Traina data.buf = (char *)p->buffer + p->offset; 1808cf6c252SPaul Traina data.maxlen = MAXDLBUF; 1818cf6c252SPaul Traina data.len = 0; 1828cf6c252SPaul Traina do { 1838cf6c252SPaul Traina if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 1848cf6c252SPaul Traina /* Don't choke when we get ptraced */ 1858cf6c252SPaul Traina if (errno == EINTR) { 1868cf6c252SPaul Traina cc = 0; 1878cf6c252SPaul Traina continue; 1888cf6c252SPaul Traina } 189dc2c7305SBill Fenner strlcpy(p->errbuf, pcap_strerror(errno), 190dc2c7305SBill Fenner sizeof(p->errbuf)); 1918cf6c252SPaul Traina return (-1); 1928cf6c252SPaul Traina } 1938cf6c252SPaul Traina cc = data.len; 1948cf6c252SPaul Traina } while (cc == 0); 1958cf6c252SPaul Traina bp = p->buffer + p->offset; 1968cf6c252SPaul Traina } else 1978cf6c252SPaul Traina bp = p->bp; 1988cf6c252SPaul Traina 1998cf6c252SPaul Traina /* Loop through packets */ 2008cf6c252SPaul Traina fcode = p->fcode.bf_insns; 2018cf6c252SPaul Traina ep = bp + cc; 2028cf6c252SPaul Traina n = 0; 2038cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2048cf6c252SPaul Traina while (bp < ep) { 2058cf6c252SPaul Traina #ifdef LBL_ALIGN 2068cf6c252SPaul Traina if ((long)bp & 3) { 2078cf6c252SPaul Traina sbp = &sbhdr; 2088cf6c252SPaul Traina memcpy(sbp, bp, sizeof(*sbp)); 2098cf6c252SPaul Traina } else 2108cf6c252SPaul Traina #endif 2118cf6c252SPaul Traina sbp = (struct sb_hdr *)bp; 2128cf6c252SPaul Traina p->md.stat.ps_drop += sbp->sbh_drops; 2138cf6c252SPaul Traina pk = bp + sizeof(*sbp); 2148cf6c252SPaul Traina bp += sbp->sbh_totlen; 2158cf6c252SPaul Traina origlen = sbp->sbh_origlen; 2168cf6c252SPaul Traina caplen = sbp->sbh_msglen; 2178cf6c252SPaul Traina #else 2188cf6c252SPaul Traina origlen = cc; 2198cf6c252SPaul Traina caplen = min(p->snapshot, cc); 2208cf6c252SPaul Traina pk = bp; 2218cf6c252SPaul Traina bp += caplen; 2228cf6c252SPaul Traina #endif 2238cf6c252SPaul Traina ++p->md.stat.ps_recv; 2248cf6c252SPaul Traina if (bpf_filter(fcode, pk, origlen, caplen)) { 2258cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2268cf6c252SPaul Traina pkthdr.ts = sbp->sbh_timestamp; 2278cf6c252SPaul Traina #else 2288cf6c252SPaul Traina (void)gettimeofday(&pkthdr.ts, NULL); 2298cf6c252SPaul Traina #endif 2308cf6c252SPaul Traina pkthdr.len = origlen; 2318cf6c252SPaul Traina pkthdr.caplen = caplen; 2328cf6c252SPaul Traina /* Insure caplen does not exceed snapshot */ 2338cf6c252SPaul Traina if (pkthdr.caplen > p->snapshot) 2348cf6c252SPaul Traina pkthdr.caplen = p->snapshot; 2358cf6c252SPaul Traina (*callback)(user, &pkthdr, pk); 2368cf6c252SPaul Traina if (++n >= cnt && cnt >= 0) { 2378cf6c252SPaul Traina p->cc = ep - bp; 2388cf6c252SPaul Traina p->bp = bp; 2398cf6c252SPaul Traina return (n); 2408cf6c252SPaul Traina } 2418cf6c252SPaul Traina } 2428cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2438cf6c252SPaul Traina } 2448cf6c252SPaul Traina #endif 2458cf6c252SPaul Traina p->cc = 0; 2468cf6c252SPaul Traina return (n); 2478cf6c252SPaul Traina } 2488cf6c252SPaul Traina 2498cf6c252SPaul Traina pcap_t * 2508cf6c252SPaul Traina pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 2518cf6c252SPaul Traina { 2528cf6c252SPaul Traina register char *cp; 2538cf6c252SPaul Traina register pcap_t *p; 2540a94d38fSBill Fenner int ppa; 2558cf6c252SPaul Traina register dl_info_ack_t *infop; 2568cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2578cf6c252SPaul Traina bpf_u_int32 ss, flag; 2588cf6c252SPaul Traina #ifdef HAVE_SOLARIS 2598cf6c252SPaul Traina register char *release; 2608cf6c252SPaul Traina bpf_u_int32 osmajor, osminor, osmicro; 2618cf6c252SPaul Traina #endif 2628cf6c252SPaul Traina #endif 2638cf6c252SPaul Traina bpf_u_int32 buf[MAXDLBUF]; 2648cf6c252SPaul Traina char dname[100]; 2658cf6c252SPaul Traina #ifndef HAVE_DEV_DLPI 2668cf6c252SPaul Traina char dname2[100]; 2678cf6c252SPaul Traina #endif 2688cf6c252SPaul Traina 2698cf6c252SPaul Traina p = (pcap_t *)malloc(sizeof(*p)); 2708cf6c252SPaul Traina if (p == NULL) { 271dc2c7305SBill Fenner strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 2728cf6c252SPaul Traina return (NULL); 2738cf6c252SPaul Traina } 2748cf6c252SPaul Traina memset(p, 0, sizeof(*p)); 2750a94d38fSBill Fenner p->fd = -1; /* indicate that it hasn't been opened yet */ 2768cf6c252SPaul Traina 277dc2c7305SBill Fenner #ifdef HAVE_DEV_DLPI 278dc2c7305SBill Fenner /* 279dc2c7305SBill Fenner ** Remove any "/dev/" on the front of the device. 280dc2c7305SBill Fenner */ 281dc2c7305SBill Fenner cp = strrchr(device, '/'); 282dc2c7305SBill Fenner if (cp == NULL) 283dc2c7305SBill Fenner cp = device; 284dc2c7305SBill Fenner else 285dc2c7305SBill Fenner cp++; 286dc2c7305SBill Fenner strlcpy(dname, cp, sizeof(dname)); 287dc2c7305SBill Fenner 288dc2c7305SBill Fenner /* 2890a94d38fSBill Fenner * Split the device name into a device type name and a unit number; 2900a94d38fSBill Fenner * chop off the unit number, so "dname" is just a device type name. 291dc2c7305SBill Fenner */ 2920a94d38fSBill Fenner cp = split_dname(dname, &ppa, ebuf); 2930a94d38fSBill Fenner if (cp == NULL) 294dc2c7305SBill Fenner goto bad; 295dc2c7305SBill Fenner *cp = '\0'; 296dc2c7305SBill Fenner 297dc2c7305SBill Fenner /* 298dc2c7305SBill Fenner * Use "/dev/dlpi" as the device. 299dc2c7305SBill Fenner * 300dc2c7305SBill Fenner * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that 301dc2c7305SBill Fenner * the "dl_mjr_num" field is for the "major number of interface 302dc2c7305SBill Fenner * driver"; that's the major of "/dev/dlpi" on the system on 303dc2c7305SBill Fenner * which I tried this, but there may be DLPI devices that 304dc2c7305SBill Fenner * use a different driver, in which case we may need to 305dc2c7305SBill Fenner * search "/dev" for the appropriate device with that major 306dc2c7305SBill Fenner * device number, rather than hardwiring "/dev/dlpi". 307dc2c7305SBill Fenner */ 308dc2c7305SBill Fenner cp = "/dev/dlpi"; 309dc2c7305SBill Fenner if ((p->fd = open(cp, O_RDWR)) < 0) { 310dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 311dc2c7305SBill Fenner "%s: %s", cp, pcap_strerror(errno)); 312dc2c7305SBill Fenner goto bad; 313dc2c7305SBill Fenner } 314dc2c7305SBill Fenner 315dc2c7305SBill Fenner /* 316dc2c7305SBill Fenner * Get a table of all PPAs for that device, and search that 317dc2c7305SBill Fenner * table for the specified device type name and unit number. 318dc2c7305SBill Fenner */ 319dc2c7305SBill Fenner ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); 320dc2c7305SBill Fenner if (ppa < 0) 321dc2c7305SBill Fenner goto bad; 322dc2c7305SBill Fenner #else 3238cf6c252SPaul Traina /* 3240a94d38fSBill Fenner * Get the unit number, and a pointer to the end of the device 3250a94d38fSBill Fenner * type name. 3268cf6c252SPaul Traina */ 3270a94d38fSBill Fenner cp = split_dname(device, &ppa, ebuf); 3280a94d38fSBill Fenner if (cp == NULL) 3298cf6c252SPaul Traina goto bad; 3308cf6c252SPaul Traina 3310a94d38fSBill Fenner /* 3320a94d38fSBill Fenner * If the device name begins with "/", assume it begins with 3330a94d38fSBill Fenner * the pathname of the directory containing the device to open; 3340a94d38fSBill Fenner * otherwise, concatenate the device directory name and the 3350a94d38fSBill Fenner * device name. 3360a94d38fSBill Fenner */ 3378cf6c252SPaul Traina if (*device == '/') 338dc2c7305SBill Fenner strlcpy(dname, device, sizeof(dname)); 3398cf6c252SPaul Traina else 340dc2c7305SBill Fenner snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, 341dc2c7305SBill Fenner device); 342dc2c7305SBill Fenner 3430a94d38fSBill Fenner /* 3440a94d38fSBill Fenner * Make a copy of the device pathname, and then remove the unit 3450a94d38fSBill Fenner * number from the device pathname. 3460a94d38fSBill Fenner */ 3470a94d38fSBill Fenner strlcpy(dname2, dname, sizeof(dname)); 3480a94d38fSBill Fenner *(dname + strlen(dname) - strlen(cp)) = '\0'; 3490a94d38fSBill Fenner 3508cf6c252SPaul Traina /* Try device without unit number */ 3518cf6c252SPaul Traina if ((p->fd = open(dname, O_RDWR)) < 0) { 3528cf6c252SPaul Traina if (errno != ENOENT) { 353dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, 354dc2c7305SBill Fenner pcap_strerror(errno)); 3558cf6c252SPaul Traina goto bad; 3568cf6c252SPaul Traina } 3578cf6c252SPaul Traina 3588cf6c252SPaul Traina /* Try again with unit number */ 3598cf6c252SPaul Traina if ((p->fd = open(dname2, O_RDWR)) < 0) { 360dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, 361dc2c7305SBill Fenner pcap_strerror(errno)); 3628cf6c252SPaul Traina goto bad; 3638cf6c252SPaul Traina } 3648cf6c252SPaul Traina /* XXX Assume unit zero */ 3658cf6c252SPaul Traina ppa = 0; 3668cf6c252SPaul Traina } 3678cf6c252SPaul Traina #endif 3688cf6c252SPaul Traina 3698cf6c252SPaul Traina p->snapshot = snaplen; 3708cf6c252SPaul Traina 3718cf6c252SPaul Traina /* 3728cf6c252SPaul Traina ** Attach if "style 2" provider 3738cf6c252SPaul Traina */ 3748cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 3758cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 3768cf6c252SPaul Traina goto bad; 3778cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 3788cf6c252SPaul Traina if (infop->dl_provider_style == DL_STYLE2 && 3798cf6c252SPaul Traina (dlattachreq(p->fd, ppa, ebuf) < 0 || 3808cf6c252SPaul Traina dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) 3818cf6c252SPaul Traina goto bad; 3828cf6c252SPaul Traina /* 383a4b5b39fSBill Fenner ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if 384a4b5b39fSBill Fenner ** using SINIX) 3858cf6c252SPaul Traina */ 386a4b5b39fSBill Fenner #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) 387dc2c7305SBill Fenner #ifdef _AIX 388dc2c7305SBill Fenner /* According to IBM's AIX Support Line, the dl_sap value 3890a94d38fSBill Fenner ** should not be less than 0x600 (1536) for standard Ethernet. 3900a94d38fSBill Fenner ** However, we seem to get DL_BADADDR - "DLSAP addr in improper 3910a94d38fSBill Fenner ** format or invalid" - errors if we use 1537 on the "tr0" 3920a94d38fSBill Fenner ** device, which, given that its name starts with "tr" and that 3930a94d38fSBill Fenner ** it's IBM, probably means a Token Ring device. (Perhaps we 3940a94d38fSBill Fenner ** need to use 1537 on "/dev/dlpi/en" because that device is for 3950a94d38fSBill Fenner ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and 3960a94d38fSBill Fenner ** it rejects invalid Ethernet types.) 3970a94d38fSBill Fenner ** 3980a94d38fSBill Fenner ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea 3990a94d38fSBill Fenner ** says that works on Token Ring (he says that 0 does *not* 4000a94d38fSBill Fenner ** work; perhaps that's considered an invalid LLC SAP value - I 4010a94d38fSBill Fenner ** assume the SAP value in a DLPI bind is an LLC SAP for network 4020a94d38fSBill Fenner ** types that use 802.2 LLC). 403dc2c7305SBill Fenner */ 4040a94d38fSBill Fenner if ((dlbindreq(p->fd, 1537, ebuf) < 0 && 4050a94d38fSBill Fenner dlbindreq(p->fd, 2, ebuf) < 0) || 406dc2c7305SBill Fenner #else 4078cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 408dc2c7305SBill Fenner #endif 4098cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 4108cf6c252SPaul Traina goto bad; 4118cf6c252SPaul Traina #endif 4128cf6c252SPaul Traina 4138cf6c252SPaul Traina if (promisc) { 4148cf6c252SPaul Traina /* 4158cf6c252SPaul Traina ** Enable promiscuous 4168cf6c252SPaul Traina */ 4178cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || 4188cf6c252SPaul Traina dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) 4198cf6c252SPaul Traina goto bad; 4208cf6c252SPaul Traina 4218cf6c252SPaul Traina /* 4228cf6c252SPaul Traina ** Try to enable multicast (you would have thought 423a4b5b39fSBill Fenner ** promiscuous would be sufficient). (Skip if using 424a4b5b39fSBill Fenner ** HP-UX or SINIX) 4258cf6c252SPaul Traina */ 426a4b5b39fSBill Fenner #if !defined(__hpux) && !defined(sinix) 4278cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || 4288cf6c252SPaul Traina dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) 4298cf6c252SPaul Traina fprintf(stderr, 4308cf6c252SPaul Traina "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); 4318cf6c252SPaul Traina #endif 4328cf6c252SPaul Traina } 4338cf6c252SPaul Traina /* 434a4b5b39fSBill Fenner ** Try to enable sap (when not in promiscuous mode when using 435a4b5b39fSBill Fenner ** using HP-UX and never under SINIX) 4368cf6c252SPaul Traina */ 4378cf6c252SPaul Traina #ifndef sinix 438a4b5b39fSBill Fenner if ( 439a4b5b39fSBill Fenner #ifdef __hpux 440a4b5b39fSBill Fenner !promisc && 441a4b5b39fSBill Fenner #endif 442a4b5b39fSBill Fenner (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || 443a4b5b39fSBill Fenner dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { 4448cf6c252SPaul Traina /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ 4458cf6c252SPaul Traina if (promisc) 4468cf6c252SPaul Traina fprintf(stderr, 4478cf6c252SPaul Traina "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); 4488cf6c252SPaul Traina else 4498cf6c252SPaul Traina goto bad; 4508cf6c252SPaul Traina } 4518cf6c252SPaul Traina #endif 4528cf6c252SPaul Traina 4538cf6c252SPaul Traina /* 454a4b5b39fSBill Fenner ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous 455a4b5b39fSBill Fenner ** options) 4568cf6c252SPaul Traina */ 457a4b5b39fSBill Fenner #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) 4588cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 4598cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 4608cf6c252SPaul Traina goto bad; 4618cf6c252SPaul Traina #endif 4628cf6c252SPaul Traina 4638cf6c252SPaul Traina /* 4648cf6c252SPaul Traina ** Determine link type 4658cf6c252SPaul Traina */ 4668cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 4678cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 4688cf6c252SPaul Traina goto bad; 4698cf6c252SPaul Traina 4708cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 4718cf6c252SPaul Traina switch (infop->dl_mac_type) { 4728cf6c252SPaul Traina 4738cf6c252SPaul Traina case DL_CSMACD: 4748cf6c252SPaul Traina case DL_ETHER: 4758cf6c252SPaul Traina p->linktype = DLT_EN10MB; 4768cf6c252SPaul Traina p->offset = 2; 4778cf6c252SPaul Traina break; 4788cf6c252SPaul Traina 4798cf6c252SPaul Traina case DL_FDDI: 4808cf6c252SPaul Traina p->linktype = DLT_FDDI; 481a4b5b39fSBill Fenner p->offset = 3; 4828cf6c252SPaul Traina break; 4838cf6c252SPaul Traina 4840a94d38fSBill Fenner case DL_TPR: 4850a94d38fSBill Fenner p->linktype = DLT_IEEE802; 4860a94d38fSBill Fenner p->offset = 2; 4870a94d38fSBill Fenner break; 4880a94d38fSBill Fenner 4898cf6c252SPaul Traina default: 490dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", 491dc2c7305SBill Fenner infop->dl_mac_type); 4928cf6c252SPaul Traina goto bad; 4938cf6c252SPaul Traina } 4948cf6c252SPaul Traina 4958cf6c252SPaul Traina #ifdef DLIOCRAW 4968cf6c252SPaul Traina /* 4978cf6c252SPaul Traina ** This is a non standard SunOS hack to get the ethernet header. 4988cf6c252SPaul Traina */ 4998cf6c252SPaul Traina if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 500dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", 501dc2c7305SBill Fenner pcap_strerror(errno)); 5028cf6c252SPaul Traina goto bad; 5038cf6c252SPaul Traina } 5048cf6c252SPaul Traina #endif 5058cf6c252SPaul Traina 5068cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 5078cf6c252SPaul Traina /* 5088cf6c252SPaul Traina ** Another non standard call to get the data nicely buffered 5098cf6c252SPaul Traina */ 5108cf6c252SPaul Traina if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { 511dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", 512dc2c7305SBill Fenner pcap_strerror(errno)); 5138cf6c252SPaul Traina goto bad; 5148cf6c252SPaul Traina } 5158cf6c252SPaul Traina 5168cf6c252SPaul Traina /* 5178cf6c252SPaul Traina ** Now that the bufmod is pushed lets configure it. 5188cf6c252SPaul Traina ** 5198cf6c252SPaul Traina ** There is a bug in bufmod(7). When dealing with messages of 5208cf6c252SPaul Traina ** less than snaplen size it strips data from the beginning not 5218cf6c252SPaul Traina ** the end. 5228cf6c252SPaul Traina ** 5238cf6c252SPaul Traina ** This bug is supposed to be fixed in 5.3.2. Also, there is a 5248cf6c252SPaul Traina ** patch available. Ask for bugid 1149065. 5258cf6c252SPaul Traina */ 5268cf6c252SPaul Traina ss = snaplen; 5278cf6c252SPaul Traina #ifdef HAVE_SOLARIS 5288cf6c252SPaul Traina release = get_release(&osmajor, &osminor, &osmicro); 5298cf6c252SPaul Traina if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 5308cf6c252SPaul Traina getenv("BUFMOD_FIXED") == NULL) { 5318cf6c252SPaul Traina fprintf(stderr, 5328cf6c252SPaul Traina "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", 5338cf6c252SPaul Traina release); 5348cf6c252SPaul Traina ss = 0; 5358cf6c252SPaul Traina } 5368cf6c252SPaul Traina #endif 5378cf6c252SPaul Traina if (ss > 0 && 5388cf6c252SPaul Traina strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { 539dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", 540dc2c7305SBill Fenner pcap_strerror(errno)); 5418cf6c252SPaul Traina goto bad; 5428cf6c252SPaul Traina } 5438cf6c252SPaul Traina 5448cf6c252SPaul Traina /* 5458cf6c252SPaul Traina ** Set up the bufmod flags 5468cf6c252SPaul Traina */ 5478cf6c252SPaul Traina if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) { 548dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCGFLAGS: %s", 549dc2c7305SBill Fenner pcap_strerror(errno)); 5508cf6c252SPaul Traina goto bad; 5518cf6c252SPaul Traina } 5528cf6c252SPaul Traina flag |= SB_NO_DROPS; 5538cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) { 554dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSFLAGS: %s", 555dc2c7305SBill Fenner pcap_strerror(errno)); 5568cf6c252SPaul Traina goto bad; 5578cf6c252SPaul Traina } 5588cf6c252SPaul Traina /* 5598cf6c252SPaul Traina ** Set up the bufmod timeout 5608cf6c252SPaul Traina */ 5618cf6c252SPaul Traina if (to_ms != 0) { 5628cf6c252SPaul Traina struct timeval to; 5638cf6c252SPaul Traina 5648cf6c252SPaul Traina to.tv_sec = to_ms / 1000; 5658cf6c252SPaul Traina to.tv_usec = (to_ms * 1000) % 1000000; 5668cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { 567dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", 568dc2c7305SBill Fenner pcap_strerror(errno)); 5698cf6c252SPaul Traina goto bad; 5708cf6c252SPaul Traina } 5718cf6c252SPaul Traina } 5728cf6c252SPaul Traina #endif 5738cf6c252SPaul Traina 5748cf6c252SPaul Traina /* 5758cf6c252SPaul Traina ** As the last operation flush the read side. 5768cf6c252SPaul Traina */ 5778cf6c252SPaul Traina if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 578dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 579dc2c7305SBill Fenner pcap_strerror(errno)); 5808cf6c252SPaul Traina goto bad; 5818cf6c252SPaul Traina } 5828cf6c252SPaul Traina /* Allocate data buffer */ 5838cf6c252SPaul Traina p->bufsize = MAXDLBUF * sizeof(bpf_u_int32); 5848cf6c252SPaul Traina p->buffer = (u_char *)malloc(p->bufsize + p->offset); 5858cf6c252SPaul Traina 5868cf6c252SPaul Traina return (p); 5878cf6c252SPaul Traina bad: 5880a94d38fSBill Fenner if (p->fd >= 0) 5890a94d38fSBill Fenner close(p->fd); 5908cf6c252SPaul Traina free(p); 5918cf6c252SPaul Traina return (NULL); 5928cf6c252SPaul Traina } 5938cf6c252SPaul Traina 5940a94d38fSBill Fenner /* 5950a94d38fSBill Fenner * Split a device name into a device type name and a unit number; 5960a94d38fSBill Fenner * return the a pointer to the beginning of the unit number, which 5970a94d38fSBill Fenner * is the end of the device type name, and set "*unitp" to the unit 5980a94d38fSBill Fenner * number. 5990a94d38fSBill Fenner * 6000a94d38fSBill Fenner * Returns NULL on error, and fills "ebuf" with an error message. 6010a94d38fSBill Fenner */ 6020a94d38fSBill Fenner static char * 6030a94d38fSBill Fenner split_dname(char *device, int *unitp, char *ebuf) 6040a94d38fSBill Fenner { 6050a94d38fSBill Fenner char *cp; 6060a94d38fSBill Fenner char *eos; 6070a94d38fSBill Fenner int unit; 6080a94d38fSBill Fenner 6090a94d38fSBill Fenner /* 6100a94d38fSBill Fenner * Look for a number at the end of the device name string. 6110a94d38fSBill Fenner */ 6120a94d38fSBill Fenner cp = device + strlen(device) - 1; 6130a94d38fSBill Fenner if (*cp < '0' || *cp > '9') { 6140a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", 6150a94d38fSBill Fenner device); 6160a94d38fSBill Fenner return (NULL); 6170a94d38fSBill Fenner } 6180a94d38fSBill Fenner 6190a94d38fSBill Fenner /* Digits at end of string are unit number */ 6200a94d38fSBill Fenner while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') 6210a94d38fSBill Fenner cp--; 6220a94d38fSBill Fenner 6230a94d38fSBill Fenner unit = strtol(cp, &eos, 10); 6240a94d38fSBill Fenner if (*eos != '\0') { 6250a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); 6260a94d38fSBill Fenner return (NULL); 6270a94d38fSBill Fenner } 6280a94d38fSBill Fenner *unitp = unit; 6290a94d38fSBill Fenner return (cp); 6300a94d38fSBill Fenner } 6310a94d38fSBill Fenner 6328cf6c252SPaul Traina int 6338cf6c252SPaul Traina pcap_setfilter(pcap_t *p, struct bpf_program *fp) 6348cf6c252SPaul Traina { 6358cf6c252SPaul Traina 636dc2c7305SBill Fenner if (install_bpf_program(p, fp) < 0) 637dc2c7305SBill Fenner return (-1); 6388cf6c252SPaul Traina return (0); 6398cf6c252SPaul Traina } 6408cf6c252SPaul Traina 6418cf6c252SPaul Traina static int 6428cf6c252SPaul Traina send_request(int fd, char *ptr, int len, char *what, char *ebuf) 6438cf6c252SPaul Traina { 6448cf6c252SPaul Traina struct strbuf ctl; 6458cf6c252SPaul Traina int flags; 6468cf6c252SPaul Traina 6478cf6c252SPaul Traina ctl.maxlen = 0; 6488cf6c252SPaul Traina ctl.len = len; 6498cf6c252SPaul Traina ctl.buf = ptr; 6508cf6c252SPaul Traina 6518cf6c252SPaul Traina flags = 0; 6528cf6c252SPaul Traina if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 653dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 654dc2c7305SBill Fenner "send_request: putmsg \"%s\": %s", 6558cf6c252SPaul Traina what, pcap_strerror(errno)); 6568cf6c252SPaul Traina return (-1); 6578cf6c252SPaul Traina } 6588cf6c252SPaul Traina return (0); 6598cf6c252SPaul Traina } 6608cf6c252SPaul Traina 6618cf6c252SPaul Traina static int 6628cf6c252SPaul Traina recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) 6638cf6c252SPaul Traina { 6648cf6c252SPaul Traina union DL_primitives *dlp; 6658cf6c252SPaul Traina struct strbuf ctl; 6668cf6c252SPaul Traina int flags; 6678cf6c252SPaul Traina 6688cf6c252SPaul Traina ctl.maxlen = MAXDLBUF; 6698cf6c252SPaul Traina ctl.len = 0; 6708cf6c252SPaul Traina ctl.buf = bufp; 6718cf6c252SPaul Traina 6728cf6c252SPaul Traina flags = 0; 6738cf6c252SPaul Traina if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 674dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", 6758cf6c252SPaul Traina what, pcap_strerror(errno)); 6768cf6c252SPaul Traina return (-1); 6778cf6c252SPaul Traina } 6788cf6c252SPaul Traina 6798cf6c252SPaul Traina dlp = (union DL_primitives *) ctl.buf; 6808cf6c252SPaul Traina switch (dlp->dl_primitive) { 6818cf6c252SPaul Traina 6828cf6c252SPaul Traina case DL_INFO_ACK: 6838cf6c252SPaul Traina case DL_BIND_ACK: 6848cf6c252SPaul Traina case DL_OK_ACK: 6858cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK 6868cf6c252SPaul Traina case DL_HP_PPA_ACK: 6878cf6c252SPaul Traina #endif 6888cf6c252SPaul Traina /* These are OK */ 6898cf6c252SPaul Traina break; 6908cf6c252SPaul Traina 6918cf6c252SPaul Traina case DL_ERROR_ACK: 6928cf6c252SPaul Traina switch (dlp->error_ack.dl_errno) { 6938cf6c252SPaul Traina 6948cf6c252SPaul Traina case DL_SYSERR: 6950a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 6960a94d38fSBill Fenner "recv_ack: %s: UNIX error - %s", 6978cf6c252SPaul Traina what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 6988cf6c252SPaul Traina break; 6998cf6c252SPaul Traina 7008cf6c252SPaul Traina default: 7010a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", 7020a94d38fSBill Fenner what, dlstrerror(dlp->error_ack.dl_errno)); 7038cf6c252SPaul Traina break; 7048cf6c252SPaul Traina } 7058cf6c252SPaul Traina return (-1); 7068cf6c252SPaul Traina 7078cf6c252SPaul Traina default: 708dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 7090a94d38fSBill Fenner "recv_ack: %s: Unexpected primitive ack %s", 7100a94d38fSBill Fenner what, dlprim(dlp->dl_primitive)); 7118cf6c252SPaul Traina return (-1); 7128cf6c252SPaul Traina } 7138cf6c252SPaul Traina 7148cf6c252SPaul Traina if (ctl.len < size) { 715dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 7160a94d38fSBill Fenner "recv_ack: %s: Ack too small (%d < %d)", 7178cf6c252SPaul Traina what, ctl.len, size); 7188cf6c252SPaul Traina return (-1); 7198cf6c252SPaul Traina } 7208cf6c252SPaul Traina return (ctl.len); 7218cf6c252SPaul Traina } 7228cf6c252SPaul Traina 7230a94d38fSBill Fenner static char * 7240a94d38fSBill Fenner dlstrerror(bpf_u_int32 dl_errno) 7250a94d38fSBill Fenner { 7260a94d38fSBill Fenner static char errstring[6+2+8+1]; 7270a94d38fSBill Fenner 7280a94d38fSBill Fenner switch (dl_errno) { 7290a94d38fSBill Fenner 7300a94d38fSBill Fenner case DL_ACCESS: 7310a94d38fSBill Fenner return ("Improper permissions for request"); 7320a94d38fSBill Fenner 7330a94d38fSBill Fenner case DL_BADADDR: 7340a94d38fSBill Fenner return ("DLSAP addr in improper format or invalid"); 7350a94d38fSBill Fenner 7360a94d38fSBill Fenner case DL_BADCORR: 7370a94d38fSBill Fenner return ("Seq number not from outstand DL_CONN_IND"); 7380a94d38fSBill Fenner 7390a94d38fSBill Fenner case DL_BADDATA: 7400a94d38fSBill Fenner return ("User data exceeded provider limit"); 7410a94d38fSBill Fenner 7420a94d38fSBill Fenner case DL_BADPPA: 7430a94d38fSBill Fenner #ifdef HAVE_DEV_DLPI 7440a94d38fSBill Fenner /* 7450a94d38fSBill Fenner * With a single "/dev/dlpi" device used for all 7460a94d38fSBill Fenner * DLPI providers, PPAs have nothing to do with 7470a94d38fSBill Fenner * unit numbers. 7480a94d38fSBill Fenner */ 7490a94d38fSBill Fenner return ("Specified PPA was invalid"); 7500a94d38fSBill Fenner #else 7510a94d38fSBill Fenner /* 7520a94d38fSBill Fenner * We have separate devices for separate devices; 7530a94d38fSBill Fenner * the PPA is just the unit number. 7540a94d38fSBill Fenner */ 7550a94d38fSBill Fenner return ("Specified PPA (device unit) was invalid"); 7560a94d38fSBill Fenner #endif 7570a94d38fSBill Fenner 7580a94d38fSBill Fenner case DL_BADPRIM: 7590a94d38fSBill Fenner return ("Primitive received not known by provider"); 7600a94d38fSBill Fenner 7610a94d38fSBill Fenner case DL_BADQOSPARAM: 7620a94d38fSBill Fenner return ("QOS parameters contained invalid values"); 7630a94d38fSBill Fenner 7640a94d38fSBill Fenner case DL_BADQOSTYPE: 7650a94d38fSBill Fenner return ("QOS structure type is unknown/unsupported"); 7660a94d38fSBill Fenner 7670a94d38fSBill Fenner case DL_BADSAP: 7680a94d38fSBill Fenner return ("Bad LSAP selector"); 7690a94d38fSBill Fenner 7700a94d38fSBill Fenner case DL_BADTOKEN: 7710a94d38fSBill Fenner return ("Token used not an active stream"); 7720a94d38fSBill Fenner 7730a94d38fSBill Fenner case DL_BOUND: 7740a94d38fSBill Fenner return ("Attempted second bind with dl_max_conind"); 7750a94d38fSBill Fenner 7760a94d38fSBill Fenner case DL_INITFAILED: 7770a94d38fSBill Fenner return ("Physical link initialization failed"); 7780a94d38fSBill Fenner 7790a94d38fSBill Fenner case DL_NOADDR: 7800a94d38fSBill Fenner return ("Provider couldn't allocate alternate address"); 7810a94d38fSBill Fenner 7820a94d38fSBill Fenner case DL_NOTINIT: 7830a94d38fSBill Fenner return ("Physical link not initialized"); 7840a94d38fSBill Fenner 7850a94d38fSBill Fenner case DL_OUTSTATE: 7860a94d38fSBill Fenner return ("Primitive issued in improper state"); 7870a94d38fSBill Fenner 7880a94d38fSBill Fenner case DL_SYSERR: 7890a94d38fSBill Fenner return ("UNIX system error occurred"); 7900a94d38fSBill Fenner 7910a94d38fSBill Fenner case DL_UNSUPPORTED: 7920a94d38fSBill Fenner return ("Requested service not supplied by provider"); 7930a94d38fSBill Fenner 7940a94d38fSBill Fenner case DL_UNDELIVERABLE: 7950a94d38fSBill Fenner return ("Previous data unit could not be delivered"); 7960a94d38fSBill Fenner 7970a94d38fSBill Fenner case DL_NOTSUPPORTED: 7980a94d38fSBill Fenner return ("Primitive is known but not supported"); 7990a94d38fSBill Fenner 8000a94d38fSBill Fenner case DL_TOOMANY: 8010a94d38fSBill Fenner return ("Limit exceeded"); 8020a94d38fSBill Fenner 8030a94d38fSBill Fenner case DL_NOTENAB: 8040a94d38fSBill Fenner return ("Promiscuous mode not enabled"); 8050a94d38fSBill Fenner 8060a94d38fSBill Fenner case DL_BUSY: 8070a94d38fSBill Fenner return ("Other streams for PPA in post-attached"); 8080a94d38fSBill Fenner 8090a94d38fSBill Fenner case DL_NOAUTO: 8100a94d38fSBill Fenner return ("Automatic handling XID&TEST not supported"); 8110a94d38fSBill Fenner 8120a94d38fSBill Fenner case DL_NOXIDAUTO: 8130a94d38fSBill Fenner return ("Automatic handling of XID not supported"); 8140a94d38fSBill Fenner 8150a94d38fSBill Fenner case DL_NOTESTAUTO: 8160a94d38fSBill Fenner return ("Automatic handling of TEST not supported"); 8170a94d38fSBill Fenner 8180a94d38fSBill Fenner case DL_XIDAUTO: 8190a94d38fSBill Fenner return ("Automatic handling of XID response"); 8200a94d38fSBill Fenner 8210a94d38fSBill Fenner case DL_TESTAUTO: 8220a94d38fSBill Fenner return ("Automatic handling of TEST response"); 8230a94d38fSBill Fenner 8240a94d38fSBill Fenner case DL_PENDING: 8250a94d38fSBill Fenner return ("Pending outstanding connect indications"); 8260a94d38fSBill Fenner 8270a94d38fSBill Fenner default: 8280a94d38fSBill Fenner sprintf(errstring, "Error %02x", dl_errno); 8290a94d38fSBill Fenner return (errstring); 8300a94d38fSBill Fenner } 8310a94d38fSBill Fenner } 8320a94d38fSBill Fenner 8330a94d38fSBill Fenner static char * 8340a94d38fSBill Fenner dlprim(bpf_u_int32 prim) 8350a94d38fSBill Fenner { 8360a94d38fSBill Fenner static char primbuf[80]; 8370a94d38fSBill Fenner 8380a94d38fSBill Fenner switch (prim) { 8390a94d38fSBill Fenner 8400a94d38fSBill Fenner case DL_INFO_REQ: 8410a94d38fSBill Fenner return ("DL_INFO_REQ"); 8420a94d38fSBill Fenner 8430a94d38fSBill Fenner case DL_INFO_ACK: 8440a94d38fSBill Fenner return ("DL_INFO_ACK"); 8450a94d38fSBill Fenner 8460a94d38fSBill Fenner case DL_ATTACH_REQ: 8470a94d38fSBill Fenner return ("DL_ATTACH_REQ"); 8480a94d38fSBill Fenner 8490a94d38fSBill Fenner case DL_DETACH_REQ: 8500a94d38fSBill Fenner return ("DL_DETACH_REQ"); 8510a94d38fSBill Fenner 8520a94d38fSBill Fenner case DL_BIND_REQ: 8530a94d38fSBill Fenner return ("DL_BIND_REQ"); 8540a94d38fSBill Fenner 8550a94d38fSBill Fenner case DL_BIND_ACK: 8560a94d38fSBill Fenner return ("DL_BIND_ACK"); 8570a94d38fSBill Fenner 8580a94d38fSBill Fenner case DL_UNBIND_REQ: 8590a94d38fSBill Fenner return ("DL_UNBIND_REQ"); 8600a94d38fSBill Fenner 8610a94d38fSBill Fenner case DL_OK_ACK: 8620a94d38fSBill Fenner return ("DL_OK_ACK"); 8630a94d38fSBill Fenner 8640a94d38fSBill Fenner case DL_ERROR_ACK: 8650a94d38fSBill Fenner return ("DL_ERROR_ACK"); 8660a94d38fSBill Fenner 8670a94d38fSBill Fenner case DL_SUBS_BIND_REQ: 8680a94d38fSBill Fenner return ("DL_SUBS_BIND_REQ"); 8690a94d38fSBill Fenner 8700a94d38fSBill Fenner case DL_SUBS_BIND_ACK: 8710a94d38fSBill Fenner return ("DL_SUBS_BIND_ACK"); 8720a94d38fSBill Fenner 8730a94d38fSBill Fenner case DL_UNITDATA_REQ: 8740a94d38fSBill Fenner return ("DL_UNITDATA_REQ"); 8750a94d38fSBill Fenner 8760a94d38fSBill Fenner case DL_UNITDATA_IND: 8770a94d38fSBill Fenner return ("DL_UNITDATA_IND"); 8780a94d38fSBill Fenner 8790a94d38fSBill Fenner case DL_UDERROR_IND: 8800a94d38fSBill Fenner return ("DL_UDERROR_IND"); 8810a94d38fSBill Fenner 8820a94d38fSBill Fenner case DL_UDQOS_REQ: 8830a94d38fSBill Fenner return ("DL_UDQOS_REQ"); 8840a94d38fSBill Fenner 8850a94d38fSBill Fenner case DL_CONNECT_REQ: 8860a94d38fSBill Fenner return ("DL_CONNECT_REQ"); 8870a94d38fSBill Fenner 8880a94d38fSBill Fenner case DL_CONNECT_IND: 8890a94d38fSBill Fenner return ("DL_CONNECT_IND"); 8900a94d38fSBill Fenner 8910a94d38fSBill Fenner case DL_CONNECT_RES: 8920a94d38fSBill Fenner return ("DL_CONNECT_RES"); 8930a94d38fSBill Fenner 8940a94d38fSBill Fenner case DL_CONNECT_CON: 8950a94d38fSBill Fenner return ("DL_CONNECT_CON"); 8960a94d38fSBill Fenner 8970a94d38fSBill Fenner case DL_TOKEN_REQ: 8980a94d38fSBill Fenner return ("DL_TOKEN_REQ"); 8990a94d38fSBill Fenner 9000a94d38fSBill Fenner case DL_TOKEN_ACK: 9010a94d38fSBill Fenner return ("DL_TOKEN_ACK"); 9020a94d38fSBill Fenner 9030a94d38fSBill Fenner case DL_DISCONNECT_REQ: 9040a94d38fSBill Fenner return ("DL_DISCONNECT_REQ"); 9050a94d38fSBill Fenner 9060a94d38fSBill Fenner case DL_DISCONNECT_IND: 9070a94d38fSBill Fenner return ("DL_DISCONNECT_IND"); 9080a94d38fSBill Fenner 9090a94d38fSBill Fenner case DL_RESET_REQ: 9100a94d38fSBill Fenner return ("DL_RESET_REQ"); 9110a94d38fSBill Fenner 9120a94d38fSBill Fenner case DL_RESET_IND: 9130a94d38fSBill Fenner return ("DL_RESET_IND"); 9140a94d38fSBill Fenner 9150a94d38fSBill Fenner case DL_RESET_RES: 9160a94d38fSBill Fenner return ("DL_RESET_RES"); 9170a94d38fSBill Fenner 9180a94d38fSBill Fenner case DL_RESET_CON: 9190a94d38fSBill Fenner return ("DL_RESET_CON"); 9200a94d38fSBill Fenner 9210a94d38fSBill Fenner default: 9220a94d38fSBill Fenner (void) sprintf(primbuf, "unknown primitive 0x%x", prim); 9230a94d38fSBill Fenner return (primbuf); 9240a94d38fSBill Fenner } 9250a94d38fSBill Fenner } 9260a94d38fSBill Fenner 9278cf6c252SPaul Traina static int 9288cf6c252SPaul Traina dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) 9298cf6c252SPaul Traina { 9308cf6c252SPaul Traina dl_attach_req_t req; 9318cf6c252SPaul Traina 9328cf6c252SPaul Traina req.dl_primitive = DL_ATTACH_REQ; 9338cf6c252SPaul Traina req.dl_ppa = ppa; 9348cf6c252SPaul Traina 9358cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); 9368cf6c252SPaul Traina } 9378cf6c252SPaul Traina 9388cf6c252SPaul Traina static int 9398cf6c252SPaul Traina dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 9408cf6c252SPaul Traina { 9418cf6c252SPaul Traina 9428cf6c252SPaul Traina dl_bind_req_t req; 9438cf6c252SPaul Traina 9448cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 9458cf6c252SPaul Traina req.dl_primitive = DL_BIND_REQ; 9468cf6c252SPaul Traina #ifdef DL_HP_RAWDLS 9478cf6c252SPaul Traina req.dl_max_conind = 1; /* XXX magic number */ 9488cf6c252SPaul Traina /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ 9498cf6c252SPaul Traina req.dl_sap = 22; 9508cf6c252SPaul Traina req.dl_service_mode = DL_HP_RAWDLS; 9518cf6c252SPaul Traina #else 9528cf6c252SPaul Traina req.dl_sap = sap; 9533052b236SBill Fenner #ifdef DL_CLDLS 9543052b236SBill Fenner req.dl_service_mode = DL_CLDLS; 9553052b236SBill Fenner #endif 9568cf6c252SPaul Traina #endif 9578cf6c252SPaul Traina 9588cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 9598cf6c252SPaul Traina } 9608cf6c252SPaul Traina 9618cf6c252SPaul Traina static int 9628cf6c252SPaul Traina dlbindack(int fd, char *bufp, char *ebuf) 9638cf6c252SPaul Traina { 9648cf6c252SPaul Traina 9658cf6c252SPaul Traina return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); 9668cf6c252SPaul Traina } 9678cf6c252SPaul Traina 9688cf6c252SPaul Traina static int 9698cf6c252SPaul Traina dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) 9708cf6c252SPaul Traina { 9718cf6c252SPaul Traina dl_promiscon_req_t req; 9728cf6c252SPaul Traina 9738cf6c252SPaul Traina req.dl_primitive = DL_PROMISCON_REQ; 9748cf6c252SPaul Traina req.dl_level = level; 9758cf6c252SPaul Traina 9768cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); 9778cf6c252SPaul Traina } 9788cf6c252SPaul Traina 9798cf6c252SPaul Traina static int 9808cf6c252SPaul Traina dlokack(int fd, const char *what, char *bufp, char *ebuf) 9818cf6c252SPaul Traina { 9828cf6c252SPaul Traina 9838cf6c252SPaul Traina return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); 9848cf6c252SPaul Traina } 9858cf6c252SPaul Traina 9868cf6c252SPaul Traina 9878cf6c252SPaul Traina static int 9888cf6c252SPaul Traina dlinforeq(int fd, char *ebuf) 9898cf6c252SPaul Traina { 9908cf6c252SPaul Traina dl_info_req_t req; 9918cf6c252SPaul Traina 9928cf6c252SPaul Traina req.dl_primitive = DL_INFO_REQ; 9938cf6c252SPaul Traina 9948cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 9958cf6c252SPaul Traina } 9968cf6c252SPaul Traina 9978cf6c252SPaul Traina static int 9988cf6c252SPaul Traina dlinfoack(int fd, char *bufp, char *ebuf) 9998cf6c252SPaul Traina { 10008cf6c252SPaul Traina 10018cf6c252SPaul Traina return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); 10028cf6c252SPaul Traina } 10038cf6c252SPaul Traina 10048cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 10058cf6c252SPaul Traina static int 10068cf6c252SPaul Traina strioctl(int fd, int cmd, int len, char *dp) 10078cf6c252SPaul Traina { 10088cf6c252SPaul Traina struct strioctl str; 10098cf6c252SPaul Traina int rc; 10108cf6c252SPaul Traina 10118cf6c252SPaul Traina str.ic_cmd = cmd; 10128cf6c252SPaul Traina str.ic_timout = -1; 10138cf6c252SPaul Traina str.ic_len = len; 10148cf6c252SPaul Traina str.ic_dp = dp; 10158cf6c252SPaul Traina rc = ioctl(fd, I_STR, &str); 10168cf6c252SPaul Traina 10178cf6c252SPaul Traina if (rc < 0) 10188cf6c252SPaul Traina return (rc); 10198cf6c252SPaul Traina else 10208cf6c252SPaul Traina return (str.ic_len); 10218cf6c252SPaul Traina } 10228cf6c252SPaul Traina #endif 10238cf6c252SPaul Traina 10248cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 10258cf6c252SPaul Traina static char * 10268cf6c252SPaul Traina get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 10278cf6c252SPaul Traina { 10288cf6c252SPaul Traina char *cp; 10298cf6c252SPaul Traina static char buf[32]; 10308cf6c252SPaul Traina 10318cf6c252SPaul Traina *majorp = 0; 10328cf6c252SPaul Traina *minorp = 0; 10338cf6c252SPaul Traina *microp = 0; 10348cf6c252SPaul Traina if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 10358cf6c252SPaul Traina return ("?"); 10368cf6c252SPaul Traina cp = buf; 10370a94d38fSBill Fenner if (!isdigit((unsigned char)*cp)) 10388cf6c252SPaul Traina return (buf); 10398cf6c252SPaul Traina *majorp = strtol(cp, &cp, 10); 10408cf6c252SPaul Traina if (*cp++ != '.') 10418cf6c252SPaul Traina return (buf); 10428cf6c252SPaul Traina *minorp = strtol(cp, &cp, 10); 10438cf6c252SPaul Traina if (*cp++ != '.') 10448cf6c252SPaul Traina return (buf); 10458cf6c252SPaul Traina *microp = strtol(cp, &cp, 10); 10468cf6c252SPaul Traina return (buf); 10478cf6c252SPaul Traina } 10488cf6c252SPaul Traina #endif 10498cf6c252SPaul Traina 10508cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK_OBS 10518cf6c252SPaul Traina /* 1052dc2c7305SBill Fenner * Under HP-UX 10 and HP-UX 11, we can ask for the ppa 10538cf6c252SPaul Traina */ 10548cf6c252SPaul Traina 10558cf6c252SPaul Traina 1056dc2c7305SBill Fenner /* 1057dc2c7305SBill Fenner * Determine ppa number that specifies ifname. 1058dc2c7305SBill Fenner * 1059dc2c7305SBill Fenner * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, 1060dc2c7305SBill Fenner * the code that's used here is the old code for HP-UX 10.x. 1061dc2c7305SBill Fenner * 1062dc2c7305SBill Fenner * However, HP-UX 10.20, at least, appears to have such a member 1063dc2c7305SBill Fenner * in its "dl_hp_ppa_info_t" structure, so the new code is used. 1064dc2c7305SBill Fenner * The new code didn't work on an old 10.20 system on which Rick 1065dc2c7305SBill Fenner * Jones of HP tried it, but with later patches installed, it 1066dc2c7305SBill Fenner * worked - it appears that the older system had those members but 1067dc2c7305SBill Fenner * didn't put anything in them, so, if the search by name fails, we 1068dc2c7305SBill Fenner * do the old search. 1069dc2c7305SBill Fenner * 1070dc2c7305SBill Fenner * Rick suggests that making sure your system is "up on the latest 1071dc2c7305SBill Fenner * lancommon/DLPI/driver patches" is probably a good idea; it'd fix 1072dc2c7305SBill Fenner * that problem, as well as allowing libpcap to see packets sent 1073dc2c7305SBill Fenner * from the system on which the libpcap application is being run. 1074dc2c7305SBill Fenner * (On 10.20, in addition to getting the latest patches, you need 1075dc2c7305SBill Fenner * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; 1076dc2c7305SBill Fenner * a posting to "comp.sys.hp.hpux" at 1077dc2c7305SBill Fenner * 1078dc2c7305SBill Fenner * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 1079dc2c7305SBill Fenner * 1080dc2c7305SBill Fenner * says that, to see the machine's outgoing traffic, you'd need to 1081dc2c7305SBill Fenner * apply the right patches to your system, and also set that variable 1082dc2c7305SBill Fenner * with: 1083dc2c7305SBill Fenner 1084dc2c7305SBill Fenner echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem 1085dc2c7305SBill Fenner 1086dc2c7305SBill Fenner * which could be put in, for example, "/sbin/init.d/lan". 1087dc2c7305SBill Fenner * 1088dc2c7305SBill Fenner * Setting the variable is not necessary on HP-UX 11.x. 1089dc2c7305SBill Fenner */ 10908cf6c252SPaul Traina static int 10918cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *device, register int unit, 10928cf6c252SPaul Traina register char *ebuf) 10938cf6c252SPaul Traina { 10948cf6c252SPaul Traina register dl_hp_ppa_ack_t *ap; 1095dc2c7305SBill Fenner register dl_hp_ppa_info_t *ipstart, *ip; 10968cf6c252SPaul Traina register int i; 1097dc2c7305SBill Fenner char dname[100]; 10988cf6c252SPaul Traina register u_long majdev; 10998cf6c252SPaul Traina struct stat statbuf; 1100dc2c7305SBill Fenner dl_hp_ppa_req_t req; 11010a94d38fSBill Fenner char buf[MAXDLBUF]; 11020a94d38fSBill Fenner char *ppa_data_buf; 11030a94d38fSBill Fenner dl_hp_ppa_ack_t *dlp; 11040a94d38fSBill Fenner struct strbuf ctl; 11050a94d38fSBill Fenner int flags; 11060a94d38fSBill Fenner int ppa; 11078cf6c252SPaul Traina 11088cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 11098cf6c252SPaul Traina req.dl_primitive = DL_HP_PPA_REQ; 11108cf6c252SPaul Traina 11118cf6c252SPaul Traina memset((char *)buf, 0, sizeof(buf)); 11120a94d38fSBill Fenner if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) 11138cf6c252SPaul Traina return (-1); 11148cf6c252SPaul Traina 11150a94d38fSBill Fenner ctl.maxlen = DL_HP_PPA_ACK_SIZE; 11160a94d38fSBill Fenner ctl.len = 0; 11170a94d38fSBill Fenner ctl.buf = (char *)buf; 11180a94d38fSBill Fenner 11190a94d38fSBill Fenner flags = 0; 11200a94d38fSBill Fenner /* 11210a94d38fSBill Fenner * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal 11220a94d38fSBill Fenner * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) 11230a94d38fSBill Fenner * which is NOT big enough for a DL_HP_PPA_REQ. 11240a94d38fSBill Fenner * 11250a94d38fSBill Fenner * This causes libpcap applications to fail on a system with HP-APA 11260a94d38fSBill Fenner * installed. 11270a94d38fSBill Fenner * 11280a94d38fSBill Fenner * To figure out how big the returned data is, we first call getmsg 11290a94d38fSBill Fenner * to get the small head and peek at the head to get the actual data 11300a94d38fSBill Fenner * length, and then issue another getmsg to get the actual PPA data. 11310a94d38fSBill Fenner */ 11320a94d38fSBill Fenner /* get the head first */ 11330a94d38fSBill Fenner if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 11340a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11350a94d38fSBill Fenner "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 11360a94d38fSBill Fenner return (-1); 11370a94d38fSBill Fenner } 11380a94d38fSBill Fenner 11390a94d38fSBill Fenner dlp = (dl_hp_ppa_ack_t *)ctl.buf; 11400a94d38fSBill Fenner if (dlp->dl_primitive != DL_HP_PPA_ACK) { 11410a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11420a94d38fSBill Fenner "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", 11430a94d38fSBill Fenner (bpf_u_int32)dlp->dl_primitive); 11440a94d38fSBill Fenner return (-1); 11450a94d38fSBill Fenner } 11460a94d38fSBill Fenner 11470a94d38fSBill Fenner if (ctl.len < DL_HP_PPA_ACK_SIZE) { 11480a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11490a94d38fSBill Fenner "get_dlpi_ppa: hpppa ack too small (%d < %d)", 11500a94d38fSBill Fenner ctl.len, DL_HP_PPA_ACK_SIZE); 11510a94d38fSBill Fenner return (-1); 11520a94d38fSBill Fenner } 11530a94d38fSBill Fenner 11540a94d38fSBill Fenner /* allocate buffer */ 11550a94d38fSBill Fenner if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { 11560a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11570a94d38fSBill Fenner "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); 11580a94d38fSBill Fenner return (-1); 11590a94d38fSBill Fenner } 11600a94d38fSBill Fenner ctl.maxlen = dlp->dl_length; 11610a94d38fSBill Fenner ctl.len = 0; 11620a94d38fSBill Fenner ctl.buf = (char *)ppa_data_buf; 11630a94d38fSBill Fenner /* get the data */ 11640a94d38fSBill Fenner if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 11650a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11660a94d38fSBill Fenner "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 11670a94d38fSBill Fenner free(ppa_data_buf); 11680a94d38fSBill Fenner return (-1); 11690a94d38fSBill Fenner } 11700a94d38fSBill Fenner if (ctl.len < dlp->dl_length) { 11710a94d38fSBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 11720a94d38fSBill Fenner "get_dlpi_ppa: hpppa ack too small (%d < %d)", 11730a94d38fSBill Fenner ctl.len, dlp->dl_length); 11740a94d38fSBill Fenner free(ppa_data_buf); 11750a94d38fSBill Fenner return (-1); 11760a94d38fSBill Fenner } 11770a94d38fSBill Fenner 11788cf6c252SPaul Traina ap = (dl_hp_ppa_ack_t *)buf; 11790a94d38fSBill Fenner ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; 1180dc2c7305SBill Fenner ip = ipstart; 11818cf6c252SPaul Traina 1182dc2c7305SBill Fenner #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1183dc2c7305SBill Fenner /* 1184dc2c7305SBill Fenner * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" 1185dc2c7305SBill Fenner * member that should, in theory, contain the part of the 1186dc2c7305SBill Fenner * name for the device that comes before the unit number, 1187dc2c7305SBill Fenner * and should also have a "dl_module_id_2" member that may 1188dc2c7305SBill Fenner * contain an alternate name (e.g., I think Ethernet devices 1189dc2c7305SBill Fenner * have both "lan", for "lanN", and "snap", for "snapN", with 1190dc2c7305SBill Fenner * the former being for Ethernet packets and the latter being 1191dc2c7305SBill Fenner * for 802.3/802.2 packets). 1192dc2c7305SBill Fenner * 1193dc2c7305SBill Fenner * Search for the device that has the specified name and 1194dc2c7305SBill Fenner * instance number. 1195dc2c7305SBill Fenner */ 11968cf6c252SPaul Traina for (i = 0; i < ap->dl_count; i++) { 11970a94d38fSBill Fenner if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || 11980a94d38fSBill Fenner strcmp((const char *)ip->dl_module_id_2, device) == 0) && 1199dc2c7305SBill Fenner ip->dl_instance_num == unit) 12008cf6c252SPaul Traina break; 12018cf6c252SPaul Traina 1202dc2c7305SBill Fenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1203dc2c7305SBill Fenner } 1204dc2c7305SBill Fenner #else 1205dc2c7305SBill Fenner /* 1206dc2c7305SBill Fenner * We don't have that member, so the search is impossible; make it 1207dc2c7305SBill Fenner * look as if the search failed. 1208dc2c7305SBill Fenner */ 1209dc2c7305SBill Fenner i = ap->dl_count; 1210dc2c7305SBill Fenner #endif 1211dc2c7305SBill Fenner 1212dc2c7305SBill Fenner if (i == ap->dl_count) { 1213dc2c7305SBill Fenner /* 1214dc2c7305SBill Fenner * Well, we didn't, or can't, find the device by name. 1215dc2c7305SBill Fenner * 1216dc2c7305SBill Fenner * HP-UX 10.20, whilst it has "dl_module_id_1" and 1217dc2c7305SBill Fenner * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", 1218dc2c7305SBill Fenner * doesn't seem to fill them in unless the system is 1219dc2c7305SBill Fenner * at a reasonably up-to-date patch level. 1220dc2c7305SBill Fenner * 1221dc2c7305SBill Fenner * Older HP-UX 10.x systems might not have those fields 1222dc2c7305SBill Fenner * at all. 1223dc2c7305SBill Fenner * 1224dc2c7305SBill Fenner * Therefore, we'll search for the entry with the major 1225dc2c7305SBill Fenner * device number of a device with the name "/dev/<dev><unit>", 1226dc2c7305SBill Fenner * if such a device exists, as the old code did. 1227dc2c7305SBill Fenner */ 1228dc2c7305SBill Fenner snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); 1229dc2c7305SBill Fenner if (stat(dname, &statbuf) < 0) { 1230dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", 1231dc2c7305SBill Fenner dname, pcap_strerror(errno)); 1232dc2c7305SBill Fenner return (-1); 1233dc2c7305SBill Fenner } 1234dc2c7305SBill Fenner majdev = major(statbuf.st_rdev); 1235dc2c7305SBill Fenner 1236dc2c7305SBill Fenner ip = ipstart; 1237dc2c7305SBill Fenner 1238dc2c7305SBill Fenner for (i = 0; i < ap->dl_count; i++) { 1239dc2c7305SBill Fenner if (ip->dl_mjr_num == majdev && 1240dc2c7305SBill Fenner ip->dl_instance_num == unit) 1241dc2c7305SBill Fenner break; 1242dc2c7305SBill Fenner 1243dc2c7305SBill Fenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1244dc2c7305SBill Fenner } 12458cf6c252SPaul Traina } 12468cf6c252SPaul Traina if (i == ap->dl_count) { 1247dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 1248dc2c7305SBill Fenner "can't find /dev/dlpi PPA for %s%d", device, unit); 12498cf6c252SPaul Traina return (-1); 12508cf6c252SPaul Traina } 12518cf6c252SPaul Traina if (ip->dl_hdw_state == HDW_DEAD) { 1252dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 1253dc2c7305SBill Fenner "%s%d: hardware state: DOWN\n", device, unit); 12540a94d38fSBill Fenner free(ppa_data_buf); 12558cf6c252SPaul Traina return (-1); 12568cf6c252SPaul Traina } 12570a94d38fSBill Fenner ppa = ip->dl_ppa; 12580a94d38fSBill Fenner free(ppa_data_buf); 12590a94d38fSBill Fenner return (ppa); 12608cf6c252SPaul Traina } 12618cf6c252SPaul Traina #endif 12628cf6c252SPaul Traina 12638cf6c252SPaul Traina #ifdef HAVE_HPUX9 12648cf6c252SPaul Traina /* 12658cf6c252SPaul Traina * Under HP-UX 9, there is no good way to determine the ppa. 12668cf6c252SPaul Traina * So punt and read it from /dev/kmem. 12678cf6c252SPaul Traina */ 12688cf6c252SPaul Traina static struct nlist nl[] = { 12698cf6c252SPaul Traina #define NL_IFNET 0 12708cf6c252SPaul Traina { "ifnet" }, 12718cf6c252SPaul Traina { "" } 12728cf6c252SPaul Traina }; 12738cf6c252SPaul Traina 12748cf6c252SPaul Traina static char path_vmunix[] = "/hp-ux"; 12758cf6c252SPaul Traina 12768cf6c252SPaul Traina /* Determine ppa number that specifies ifname */ 12778cf6c252SPaul Traina static int 12788cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *ifname, register int unit, 12798cf6c252SPaul Traina register char *ebuf) 12808cf6c252SPaul Traina { 12818cf6c252SPaul Traina register const char *cp; 12828cf6c252SPaul Traina register int kd; 12838cf6c252SPaul Traina void *addr; 12848cf6c252SPaul Traina struct ifnet ifnet; 1285dc2c7305SBill Fenner char if_name[sizeof(ifnet.if_name) + 1]; 12868cf6c252SPaul Traina 12878cf6c252SPaul Traina cp = strrchr(ifname, '/'); 12888cf6c252SPaul Traina if (cp != NULL) 12898cf6c252SPaul Traina ifname = cp + 1; 12908cf6c252SPaul Traina if (nlist(path_vmunix, &nl) < 0) { 1291dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", 1292dc2c7305SBill Fenner path_vmunix); 12938cf6c252SPaul Traina return (-1); 12948cf6c252SPaul Traina } 12958cf6c252SPaul Traina if (nl[NL_IFNET].n_value == 0) { 1296dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 1297dc2c7305SBill Fenner "could't find %s kernel symbol", 12988cf6c252SPaul Traina nl[NL_IFNET].n_name); 12998cf6c252SPaul Traina return (-1); 13008cf6c252SPaul Traina } 13018cf6c252SPaul Traina kd = open("/dev/kmem", O_RDONLY); 13028cf6c252SPaul Traina if (kd < 0) { 1303dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", 1304dc2c7305SBill Fenner pcap_strerror(errno)); 13058cf6c252SPaul Traina return (-1); 13068cf6c252SPaul Traina } 13078cf6c252SPaul Traina if (dlpi_kread(kd, nl[NL_IFNET].n_value, 13088cf6c252SPaul Traina &addr, sizeof(addr), ebuf) < 0) { 13098cf6c252SPaul Traina close(kd); 13108cf6c252SPaul Traina return (-1); 13118cf6c252SPaul Traina } 13128cf6c252SPaul Traina for (; addr != NULL; addr = ifnet.if_next) { 13138cf6c252SPaul Traina if (dlpi_kread(kd, (off_t)addr, 13148cf6c252SPaul Traina &ifnet, sizeof(ifnet), ebuf) < 0 || 13158cf6c252SPaul Traina dlpi_kread(kd, (off_t)ifnet.if_name, 1316dc2c7305SBill Fenner if_name, sizeof(ifnet.if_name), ebuf) < 0) { 13178cf6c252SPaul Traina (void)close(kd); 13188cf6c252SPaul Traina return (-1); 13198cf6c252SPaul Traina } 1320dc2c7305SBill Fenner if_name[sizeof(ifnet.if_name)] = '\0'; 1321dc2c7305SBill Fenner if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) 13228cf6c252SPaul Traina return (ifnet.if_index); 13238cf6c252SPaul Traina } 13248cf6c252SPaul Traina 1325dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); 13268cf6c252SPaul Traina return (-1); 13278cf6c252SPaul Traina } 13288cf6c252SPaul Traina 13298cf6c252SPaul Traina static int 13308cf6c252SPaul Traina dlpi_kread(register int fd, register off_t addr, 13318cf6c252SPaul Traina register void *buf, register u_int len, register char *ebuf) 13328cf6c252SPaul Traina { 13338cf6c252SPaul Traina register int cc; 13348cf6c252SPaul Traina 1335a4b5b39fSBill Fenner if (lseek(fd, addr, SEEK_SET) < 0) { 1336dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", 1337dc2c7305SBill Fenner pcap_strerror(errno)); 13388cf6c252SPaul Traina return (-1); 13398cf6c252SPaul Traina } 13408cf6c252SPaul Traina cc = read(fd, buf, len); 13418cf6c252SPaul Traina if (cc < 0) { 1342dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", 1343dc2c7305SBill Fenner pcap_strerror(errno)); 13448cf6c252SPaul Traina return (-1); 13458cf6c252SPaul Traina } else if (cc != len) { 1346dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, 1347dc2c7305SBill Fenner len); 13488cf6c252SPaul Traina return (-1); 13498cf6c252SPaul Traina } 13508cf6c252SPaul Traina return (cc); 13518cf6c252SPaul Traina } 13528cf6c252SPaul Traina #endif 1353