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[] = 41dc2c7305SBill Fenner "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.63 2000/11/22 05:32:55 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 928cf6c252SPaul Traina #define PCAP_DEV_PREFIX "/dev" 938cf6c252SPaul Traina #endif 948cf6c252SPaul Traina 958cf6c252SPaul Traina #define MAXDLBUF 8192 968cf6c252SPaul Traina 978cf6c252SPaul Traina /* Forwards */ 988cf6c252SPaul Traina static int dlattachreq(int, bpf_u_int32, char *); 998cf6c252SPaul Traina static int dlbindack(int, char *, char *); 1008cf6c252SPaul Traina static int dlbindreq(int, bpf_u_int32, char *); 1018cf6c252SPaul Traina static int dlinfoack(int, char *, char *); 1028cf6c252SPaul Traina static int dlinforeq(int, char *); 1038cf6c252SPaul Traina static int dlokack(int, const char *, char *, char *); 1048cf6c252SPaul Traina static int recv_ack(int, int, const char *, char *, char *); 1058cf6c252SPaul Traina static int dlpromisconreq(int, bpf_u_int32, char *); 1068cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 1078cf6c252SPaul Traina static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 1088cf6c252SPaul Traina #endif 1098cf6c252SPaul Traina static int send_request(int, char *, int, char *, char *); 1108cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1118cf6c252SPaul Traina static int strioctl(int, int, int, char *); 1128cf6c252SPaul Traina #endif 1138cf6c252SPaul Traina #ifdef HAVE_HPUX9 1148cf6c252SPaul Traina static int dlpi_kread(int, off_t, void *, u_int, char *); 1158cf6c252SPaul Traina #endif 1168cf6c252SPaul Traina #ifdef HAVE_DEV_DLPI 1178cf6c252SPaul Traina static int get_dlpi_ppa(int, const char *, int, char *); 1188cf6c252SPaul Traina #endif 1198cf6c252SPaul Traina 1208cf6c252SPaul Traina int 1218cf6c252SPaul Traina pcap_stats(pcap_t *p, struct pcap_stat *ps) 1228cf6c252SPaul Traina { 1238cf6c252SPaul Traina 1248cf6c252SPaul Traina *ps = p->md.stat; 1258cf6c252SPaul Traina return (0); 1268cf6c252SPaul Traina } 1278cf6c252SPaul Traina 1288cf6c252SPaul Traina /* XXX Needed by HP-UX (at least) */ 1298cf6c252SPaul Traina static bpf_u_int32 ctlbuf[MAXDLBUF]; 1308cf6c252SPaul Traina static struct strbuf ctl = { 1318cf6c252SPaul Traina MAXDLBUF, 1328cf6c252SPaul Traina 0, 1338cf6c252SPaul Traina (char *)ctlbuf 1348cf6c252SPaul Traina }; 1358cf6c252SPaul Traina 1368cf6c252SPaul Traina int 1378cf6c252SPaul Traina pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 1388cf6c252SPaul Traina { 1398cf6c252SPaul Traina register int cc, n, caplen, origlen; 1408cf6c252SPaul Traina register u_char *bp, *ep, *pk; 1418cf6c252SPaul Traina register struct bpf_insn *fcode; 1428cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1438cf6c252SPaul Traina register struct sb_hdr *sbp; 1448cf6c252SPaul Traina #ifdef LBL_ALIGN 1458cf6c252SPaul Traina struct sb_hdr sbhdr; 1468cf6c252SPaul Traina #endif 1478cf6c252SPaul Traina #endif 1488cf6c252SPaul Traina int flags; 1498cf6c252SPaul Traina struct strbuf data; 1508cf6c252SPaul Traina struct pcap_pkthdr pkthdr; 1518cf6c252SPaul Traina 1528cf6c252SPaul Traina flags = 0; 1538cf6c252SPaul Traina cc = p->cc; 1548cf6c252SPaul Traina if (cc == 0) { 1558cf6c252SPaul Traina data.buf = (char *)p->buffer + p->offset; 1568cf6c252SPaul Traina data.maxlen = MAXDLBUF; 1578cf6c252SPaul Traina data.len = 0; 1588cf6c252SPaul Traina do { 1598cf6c252SPaul Traina if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 1608cf6c252SPaul Traina /* Don't choke when we get ptraced */ 1618cf6c252SPaul Traina if (errno == EINTR) { 1628cf6c252SPaul Traina cc = 0; 1638cf6c252SPaul Traina continue; 1648cf6c252SPaul Traina } 165dc2c7305SBill Fenner strlcpy(p->errbuf, pcap_strerror(errno), 166dc2c7305SBill Fenner sizeof(p->errbuf)); 1678cf6c252SPaul Traina return (-1); 1688cf6c252SPaul Traina } 1698cf6c252SPaul Traina cc = data.len; 1708cf6c252SPaul Traina } while (cc == 0); 1718cf6c252SPaul Traina bp = p->buffer + p->offset; 1728cf6c252SPaul Traina } else 1738cf6c252SPaul Traina bp = p->bp; 1748cf6c252SPaul Traina 1758cf6c252SPaul Traina /* Loop through packets */ 1768cf6c252SPaul Traina fcode = p->fcode.bf_insns; 1778cf6c252SPaul Traina ep = bp + cc; 1788cf6c252SPaul Traina n = 0; 1798cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1808cf6c252SPaul Traina while (bp < ep) { 1818cf6c252SPaul Traina #ifdef LBL_ALIGN 1828cf6c252SPaul Traina if ((long)bp & 3) { 1838cf6c252SPaul Traina sbp = &sbhdr; 1848cf6c252SPaul Traina memcpy(sbp, bp, sizeof(*sbp)); 1858cf6c252SPaul Traina } else 1868cf6c252SPaul Traina #endif 1878cf6c252SPaul Traina sbp = (struct sb_hdr *)bp; 1888cf6c252SPaul Traina p->md.stat.ps_drop += sbp->sbh_drops; 1898cf6c252SPaul Traina pk = bp + sizeof(*sbp); 1908cf6c252SPaul Traina bp += sbp->sbh_totlen; 1918cf6c252SPaul Traina origlen = sbp->sbh_origlen; 1928cf6c252SPaul Traina caplen = sbp->sbh_msglen; 1938cf6c252SPaul Traina #else 1948cf6c252SPaul Traina origlen = cc; 1958cf6c252SPaul Traina caplen = min(p->snapshot, cc); 1968cf6c252SPaul Traina pk = bp; 1978cf6c252SPaul Traina bp += caplen; 1988cf6c252SPaul Traina #endif 1998cf6c252SPaul Traina ++p->md.stat.ps_recv; 2008cf6c252SPaul Traina if (bpf_filter(fcode, pk, origlen, caplen)) { 2018cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2028cf6c252SPaul Traina pkthdr.ts = sbp->sbh_timestamp; 2038cf6c252SPaul Traina #else 2048cf6c252SPaul Traina (void)gettimeofday(&pkthdr.ts, NULL); 2058cf6c252SPaul Traina #endif 2068cf6c252SPaul Traina pkthdr.len = origlen; 2078cf6c252SPaul Traina pkthdr.caplen = caplen; 2088cf6c252SPaul Traina /* Insure caplen does not exceed snapshot */ 2098cf6c252SPaul Traina if (pkthdr.caplen > p->snapshot) 2108cf6c252SPaul Traina pkthdr.caplen = p->snapshot; 2118cf6c252SPaul Traina (*callback)(user, &pkthdr, pk); 2128cf6c252SPaul Traina if (++n >= cnt && cnt >= 0) { 2138cf6c252SPaul Traina p->cc = ep - bp; 2148cf6c252SPaul Traina p->bp = bp; 2158cf6c252SPaul Traina return (n); 2168cf6c252SPaul Traina } 2178cf6c252SPaul Traina } 2188cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2198cf6c252SPaul Traina } 2208cf6c252SPaul Traina #endif 2218cf6c252SPaul Traina p->cc = 0; 2228cf6c252SPaul Traina return (n); 2238cf6c252SPaul Traina } 2248cf6c252SPaul Traina 2258cf6c252SPaul Traina pcap_t * 2268cf6c252SPaul Traina pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 2278cf6c252SPaul Traina { 2288cf6c252SPaul Traina register char *cp; 2298cf6c252SPaul Traina char *eos; 2308cf6c252SPaul Traina register pcap_t *p; 2318cf6c252SPaul Traina register int ppa; 2328cf6c252SPaul Traina register dl_info_ack_t *infop; 2338cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2348cf6c252SPaul Traina bpf_u_int32 ss, flag; 2358cf6c252SPaul Traina #ifdef HAVE_SOLARIS 2368cf6c252SPaul Traina register char *release; 2378cf6c252SPaul Traina bpf_u_int32 osmajor, osminor, osmicro; 2388cf6c252SPaul Traina #endif 2398cf6c252SPaul Traina #endif 2408cf6c252SPaul Traina bpf_u_int32 buf[MAXDLBUF]; 2418cf6c252SPaul Traina char dname[100]; 2428cf6c252SPaul Traina #ifndef HAVE_DEV_DLPI 2438cf6c252SPaul Traina char dname2[100]; 2448cf6c252SPaul Traina #endif 2458cf6c252SPaul Traina 2468cf6c252SPaul Traina p = (pcap_t *)malloc(sizeof(*p)); 2478cf6c252SPaul Traina if (p == NULL) { 248dc2c7305SBill Fenner strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 2498cf6c252SPaul Traina return (NULL); 2508cf6c252SPaul Traina } 2518cf6c252SPaul Traina memset(p, 0, sizeof(*p)); 2528cf6c252SPaul Traina 253dc2c7305SBill Fenner #ifdef HAVE_DEV_DLPI 254dc2c7305SBill Fenner /* 255dc2c7305SBill Fenner ** Remove any "/dev/" on the front of the device. 256dc2c7305SBill Fenner */ 257dc2c7305SBill Fenner cp = strrchr(device, '/'); 258dc2c7305SBill Fenner if (cp == NULL) 259dc2c7305SBill Fenner cp = device; 260dc2c7305SBill Fenner else 261dc2c7305SBill Fenner cp++; 262dc2c7305SBill Fenner strlcpy(dname, cp, sizeof(dname)); 263dc2c7305SBill Fenner 264dc2c7305SBill Fenner /* 265dc2c7305SBill Fenner * Split the name into a device type and a unit number. 266dc2c7305SBill Fenner */ 267dc2c7305SBill Fenner cp = strpbrk(dname, "0123456789"); 268dc2c7305SBill Fenner if (cp == NULL) { 269dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 270dc2c7305SBill Fenner "%s missing unit number", device); 271dc2c7305SBill Fenner goto bad; 272dc2c7305SBill Fenner } 273dc2c7305SBill Fenner ppa = strtol(cp, &eos, 10); 274dc2c7305SBill Fenner if (*eos != '\0') { 275dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 276dc2c7305SBill Fenner "%s bad unit number", device); 277dc2c7305SBill Fenner goto bad; 278dc2c7305SBill Fenner } 279dc2c7305SBill Fenner *cp = '\0'; 280dc2c7305SBill Fenner 281dc2c7305SBill Fenner /* 282dc2c7305SBill Fenner * Use "/dev/dlpi" as the device. 283dc2c7305SBill Fenner * 284dc2c7305SBill Fenner * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that 285dc2c7305SBill Fenner * the "dl_mjr_num" field is for the "major number of interface 286dc2c7305SBill Fenner * driver"; that's the major of "/dev/dlpi" on the system on 287dc2c7305SBill Fenner * which I tried this, but there may be DLPI devices that 288dc2c7305SBill Fenner * use a different driver, in which case we may need to 289dc2c7305SBill Fenner * search "/dev" for the appropriate device with that major 290dc2c7305SBill Fenner * device number, rather than hardwiring "/dev/dlpi". 291dc2c7305SBill Fenner */ 292dc2c7305SBill Fenner cp = "/dev/dlpi"; 293dc2c7305SBill Fenner if ((p->fd = open(cp, O_RDWR)) < 0) { 294dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 295dc2c7305SBill Fenner "%s: %s", cp, pcap_strerror(errno)); 296dc2c7305SBill Fenner goto bad; 297dc2c7305SBill Fenner } 298dc2c7305SBill Fenner 299dc2c7305SBill Fenner /* 300dc2c7305SBill Fenner * Get a table of all PPAs for that device, and search that 301dc2c7305SBill Fenner * table for the specified device type name and unit number. 302dc2c7305SBill Fenner */ 303dc2c7305SBill Fenner ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); 304dc2c7305SBill Fenner if (ppa < 0) 305dc2c7305SBill Fenner goto bad; 306dc2c7305SBill Fenner #else 3078cf6c252SPaul Traina /* 3088cf6c252SPaul Traina ** Determine device and ppa 3098cf6c252SPaul Traina */ 3108cf6c252SPaul Traina cp = strpbrk(device, "0123456789"); 3118cf6c252SPaul Traina if (cp == NULL) { 312dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", 313dc2c7305SBill Fenner device); 3148cf6c252SPaul Traina goto bad; 3158cf6c252SPaul Traina } 3168cf6c252SPaul Traina ppa = strtol(cp, &eos, 10); 3178cf6c252SPaul Traina if (*eos != '\0') { 318dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); 3198cf6c252SPaul Traina goto bad; 3208cf6c252SPaul Traina } 3218cf6c252SPaul Traina 3228cf6c252SPaul Traina if (*device == '/') 323dc2c7305SBill Fenner strlcpy(dname, device, sizeof(dname)); 3248cf6c252SPaul Traina else 325dc2c7305SBill Fenner snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, 326dc2c7305SBill Fenner device); 327dc2c7305SBill Fenner 3288cf6c252SPaul Traina /* Try device without unit number */ 329dc2c7305SBill Fenner strlcpy(dname2, dname, sizeof(dname2)); 3308cf6c252SPaul Traina cp = strchr(dname, *cp); 3318cf6c252SPaul Traina *cp = '\0'; 3328cf6c252SPaul Traina if ((p->fd = open(dname, O_RDWR)) < 0) { 3338cf6c252SPaul Traina if (errno != ENOENT) { 334dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, 335dc2c7305SBill Fenner pcap_strerror(errno)); 3368cf6c252SPaul Traina goto bad; 3378cf6c252SPaul Traina } 3388cf6c252SPaul Traina 3398cf6c252SPaul Traina /* Try again with unit number */ 3408cf6c252SPaul Traina if ((p->fd = open(dname2, O_RDWR)) < 0) { 341dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, 342dc2c7305SBill Fenner pcap_strerror(errno)); 3438cf6c252SPaul Traina goto bad; 3448cf6c252SPaul Traina } 3458cf6c252SPaul Traina /* XXX Assume unit zero */ 3468cf6c252SPaul Traina ppa = 0; 3478cf6c252SPaul Traina } 3488cf6c252SPaul Traina #endif 3498cf6c252SPaul Traina 3508cf6c252SPaul Traina p->snapshot = snaplen; 3518cf6c252SPaul Traina 3528cf6c252SPaul Traina /* 3538cf6c252SPaul Traina ** Attach if "style 2" provider 3548cf6c252SPaul Traina */ 3558cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 3568cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 3578cf6c252SPaul Traina goto bad; 3588cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 3598cf6c252SPaul Traina if (infop->dl_provider_style == DL_STYLE2 && 3608cf6c252SPaul Traina (dlattachreq(p->fd, ppa, ebuf) < 0 || 3618cf6c252SPaul Traina dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) 3628cf6c252SPaul Traina goto bad; 3638cf6c252SPaul Traina /* 364a4b5b39fSBill Fenner ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if 365a4b5b39fSBill Fenner ** using SINIX) 3668cf6c252SPaul Traina */ 367a4b5b39fSBill Fenner #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) 368dc2c7305SBill Fenner #ifdef _AIX 369dc2c7305SBill Fenner /* According to IBM's AIX Support Line, the dl_sap value 370dc2c7305SBill Fenner ** should not be less than 0x600 (1536) for standard ethernet 371dc2c7305SBill Fenner */ 372dc2c7305SBill Fenner if (dlbindreq(p->fd, 1537, ebuf) < 0 || 373dc2c7305SBill Fenner #else 3748cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 375dc2c7305SBill Fenner #endif 3768cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 3778cf6c252SPaul Traina goto bad; 3788cf6c252SPaul Traina #endif 3798cf6c252SPaul Traina 3808cf6c252SPaul Traina if (promisc) { 3818cf6c252SPaul Traina /* 3828cf6c252SPaul Traina ** Enable promiscuous 3838cf6c252SPaul Traina */ 3848cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || 3858cf6c252SPaul Traina dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) 3868cf6c252SPaul Traina goto bad; 3878cf6c252SPaul Traina 3888cf6c252SPaul Traina /* 3898cf6c252SPaul Traina ** Try to enable multicast (you would have thought 390a4b5b39fSBill Fenner ** promiscuous would be sufficient). (Skip if using 391a4b5b39fSBill Fenner ** HP-UX or SINIX) 3928cf6c252SPaul Traina */ 393a4b5b39fSBill Fenner #if !defined(__hpux) && !defined(sinix) 3948cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || 3958cf6c252SPaul Traina dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) 3968cf6c252SPaul Traina fprintf(stderr, 3978cf6c252SPaul Traina "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); 3988cf6c252SPaul Traina #endif 3998cf6c252SPaul Traina } 4008cf6c252SPaul Traina /* 401a4b5b39fSBill Fenner ** Try to enable sap (when not in promiscuous mode when using 402a4b5b39fSBill Fenner ** using HP-UX and never under SINIX) 4038cf6c252SPaul Traina */ 4048cf6c252SPaul Traina #ifndef sinix 405a4b5b39fSBill Fenner if ( 406a4b5b39fSBill Fenner #ifdef __hpux 407a4b5b39fSBill Fenner !promisc && 408a4b5b39fSBill Fenner #endif 409a4b5b39fSBill Fenner (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || 410a4b5b39fSBill Fenner dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { 4118cf6c252SPaul Traina /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ 4128cf6c252SPaul Traina if (promisc) 4138cf6c252SPaul Traina fprintf(stderr, 4148cf6c252SPaul Traina "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); 4158cf6c252SPaul Traina else 4168cf6c252SPaul Traina goto bad; 4178cf6c252SPaul Traina } 4188cf6c252SPaul Traina #endif 4198cf6c252SPaul Traina 4208cf6c252SPaul Traina /* 421a4b5b39fSBill Fenner ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous 422a4b5b39fSBill Fenner ** options) 4238cf6c252SPaul Traina */ 424a4b5b39fSBill Fenner #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) 4258cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 4268cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 4278cf6c252SPaul Traina goto bad; 4288cf6c252SPaul Traina #endif 4298cf6c252SPaul Traina 4308cf6c252SPaul Traina /* 4318cf6c252SPaul Traina ** Determine link type 4328cf6c252SPaul Traina */ 4338cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 4348cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 4358cf6c252SPaul Traina goto bad; 4368cf6c252SPaul Traina 4378cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 4388cf6c252SPaul Traina switch (infop->dl_mac_type) { 4398cf6c252SPaul Traina 4408cf6c252SPaul Traina case DL_CSMACD: 4418cf6c252SPaul Traina case DL_ETHER: 4428cf6c252SPaul Traina p->linktype = DLT_EN10MB; 4438cf6c252SPaul Traina p->offset = 2; 4448cf6c252SPaul Traina break; 4458cf6c252SPaul Traina 4468cf6c252SPaul Traina case DL_FDDI: 4478cf6c252SPaul Traina p->linktype = DLT_FDDI; 448a4b5b39fSBill Fenner p->offset = 3; 4498cf6c252SPaul Traina break; 4508cf6c252SPaul Traina 4518cf6c252SPaul Traina default: 452dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", 453dc2c7305SBill Fenner infop->dl_mac_type); 4548cf6c252SPaul Traina goto bad; 4558cf6c252SPaul Traina } 4568cf6c252SPaul Traina 4578cf6c252SPaul Traina #ifdef DLIOCRAW 4588cf6c252SPaul Traina /* 4598cf6c252SPaul Traina ** This is a non standard SunOS hack to get the ethernet header. 4608cf6c252SPaul Traina */ 4618cf6c252SPaul Traina if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 462dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", 463dc2c7305SBill Fenner pcap_strerror(errno)); 4648cf6c252SPaul Traina goto bad; 4658cf6c252SPaul Traina } 4668cf6c252SPaul Traina #endif 4678cf6c252SPaul Traina 4688cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 4698cf6c252SPaul Traina /* 4708cf6c252SPaul Traina ** Another non standard call to get the data nicely buffered 4718cf6c252SPaul Traina */ 4728cf6c252SPaul Traina if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { 473dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", 474dc2c7305SBill Fenner pcap_strerror(errno)); 4758cf6c252SPaul Traina goto bad; 4768cf6c252SPaul Traina } 4778cf6c252SPaul Traina 4788cf6c252SPaul Traina /* 4798cf6c252SPaul Traina ** Now that the bufmod is pushed lets configure it. 4808cf6c252SPaul Traina ** 4818cf6c252SPaul Traina ** There is a bug in bufmod(7). When dealing with messages of 4828cf6c252SPaul Traina ** less than snaplen size it strips data from the beginning not 4838cf6c252SPaul Traina ** the end. 4848cf6c252SPaul Traina ** 4858cf6c252SPaul Traina ** This bug is supposed to be fixed in 5.3.2. Also, there is a 4868cf6c252SPaul Traina ** patch available. Ask for bugid 1149065. 4878cf6c252SPaul Traina */ 4888cf6c252SPaul Traina ss = snaplen; 4898cf6c252SPaul Traina #ifdef HAVE_SOLARIS 4908cf6c252SPaul Traina release = get_release(&osmajor, &osminor, &osmicro); 4918cf6c252SPaul Traina if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 4928cf6c252SPaul Traina getenv("BUFMOD_FIXED") == NULL) { 4938cf6c252SPaul Traina fprintf(stderr, 4948cf6c252SPaul Traina "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", 4958cf6c252SPaul Traina release); 4968cf6c252SPaul Traina ss = 0; 4978cf6c252SPaul Traina } 4988cf6c252SPaul Traina #endif 4998cf6c252SPaul Traina if (ss > 0 && 5008cf6c252SPaul Traina strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { 501dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", 502dc2c7305SBill Fenner pcap_strerror(errno)); 5038cf6c252SPaul Traina goto bad; 5048cf6c252SPaul Traina } 5058cf6c252SPaul Traina 5068cf6c252SPaul Traina /* 5078cf6c252SPaul Traina ** Set up the bufmod flags 5088cf6c252SPaul Traina */ 5098cf6c252SPaul Traina if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) { 510dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCGFLAGS: %s", 511dc2c7305SBill Fenner pcap_strerror(errno)); 5128cf6c252SPaul Traina goto bad; 5138cf6c252SPaul Traina } 5148cf6c252SPaul Traina flag |= SB_NO_DROPS; 5158cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) { 516dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSFLAGS: %s", 517dc2c7305SBill Fenner pcap_strerror(errno)); 5188cf6c252SPaul Traina goto bad; 5198cf6c252SPaul Traina } 5208cf6c252SPaul Traina /* 5218cf6c252SPaul Traina ** Set up the bufmod timeout 5228cf6c252SPaul Traina */ 5238cf6c252SPaul Traina if (to_ms != 0) { 5248cf6c252SPaul Traina struct timeval to; 5258cf6c252SPaul Traina 5268cf6c252SPaul Traina to.tv_sec = to_ms / 1000; 5278cf6c252SPaul Traina to.tv_usec = (to_ms * 1000) % 1000000; 5288cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { 529dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", 530dc2c7305SBill Fenner pcap_strerror(errno)); 5318cf6c252SPaul Traina goto bad; 5328cf6c252SPaul Traina } 5338cf6c252SPaul Traina } 5348cf6c252SPaul Traina #endif 5358cf6c252SPaul Traina 5368cf6c252SPaul Traina /* 5378cf6c252SPaul Traina ** As the last operation flush the read side. 5388cf6c252SPaul Traina */ 5398cf6c252SPaul Traina if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 540dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 541dc2c7305SBill Fenner pcap_strerror(errno)); 5428cf6c252SPaul Traina goto bad; 5438cf6c252SPaul Traina } 5448cf6c252SPaul Traina /* Allocate data buffer */ 5458cf6c252SPaul Traina p->bufsize = MAXDLBUF * sizeof(bpf_u_int32); 5468cf6c252SPaul Traina p->buffer = (u_char *)malloc(p->bufsize + p->offset); 5478cf6c252SPaul Traina 5488cf6c252SPaul Traina return (p); 5498cf6c252SPaul Traina bad: 5508cf6c252SPaul Traina free(p); 5518cf6c252SPaul Traina return (NULL); 5528cf6c252SPaul Traina } 5538cf6c252SPaul Traina 5548cf6c252SPaul Traina int 5558cf6c252SPaul Traina pcap_setfilter(pcap_t *p, struct bpf_program *fp) 5568cf6c252SPaul Traina { 5578cf6c252SPaul Traina 558dc2c7305SBill Fenner if (install_bpf_program(p, fp) < 0) 559dc2c7305SBill Fenner return (-1); 5608cf6c252SPaul Traina return (0); 5618cf6c252SPaul Traina } 5628cf6c252SPaul Traina 5638cf6c252SPaul Traina static int 5648cf6c252SPaul Traina send_request(int fd, char *ptr, int len, char *what, char *ebuf) 5658cf6c252SPaul Traina { 5668cf6c252SPaul Traina struct strbuf ctl; 5678cf6c252SPaul Traina int flags; 5688cf6c252SPaul Traina 5698cf6c252SPaul Traina ctl.maxlen = 0; 5708cf6c252SPaul Traina ctl.len = len; 5718cf6c252SPaul Traina ctl.buf = ptr; 5728cf6c252SPaul Traina 5738cf6c252SPaul Traina flags = 0; 5748cf6c252SPaul Traina if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 575dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 576dc2c7305SBill Fenner "send_request: putmsg \"%s\": %s", 5778cf6c252SPaul Traina what, pcap_strerror(errno)); 5788cf6c252SPaul Traina return (-1); 5798cf6c252SPaul Traina } 5808cf6c252SPaul Traina return (0); 5818cf6c252SPaul Traina } 5828cf6c252SPaul Traina 5838cf6c252SPaul Traina static int 5848cf6c252SPaul Traina recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) 5858cf6c252SPaul Traina { 5868cf6c252SPaul Traina union DL_primitives *dlp; 5878cf6c252SPaul Traina struct strbuf ctl; 5888cf6c252SPaul Traina int flags; 5898cf6c252SPaul Traina 5908cf6c252SPaul Traina ctl.maxlen = MAXDLBUF; 5918cf6c252SPaul Traina ctl.len = 0; 5928cf6c252SPaul Traina ctl.buf = bufp; 5938cf6c252SPaul Traina 5948cf6c252SPaul Traina flags = 0; 5958cf6c252SPaul Traina if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 596dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", 5978cf6c252SPaul Traina what, pcap_strerror(errno)); 5988cf6c252SPaul Traina return (-1); 5998cf6c252SPaul Traina } 6008cf6c252SPaul Traina 6018cf6c252SPaul Traina dlp = (union DL_primitives *) ctl.buf; 6028cf6c252SPaul Traina switch (dlp->dl_primitive) { 6038cf6c252SPaul Traina 6048cf6c252SPaul Traina case DL_INFO_ACK: 6058cf6c252SPaul Traina case DL_BIND_ACK: 6068cf6c252SPaul Traina case DL_OK_ACK: 6078cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK 6088cf6c252SPaul Traina case DL_HP_PPA_ACK: 6098cf6c252SPaul Traina #endif 6108cf6c252SPaul Traina 6118cf6c252SPaul Traina /* These are OK */ 6128cf6c252SPaul Traina break; 6138cf6c252SPaul Traina 6148cf6c252SPaul Traina case DL_ERROR_ACK: 6158cf6c252SPaul Traina switch (dlp->error_ack.dl_errno) { 6168cf6c252SPaul Traina 6178cf6c252SPaul Traina case DL_BADPPA: 618dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 619dc2c7305SBill Fenner "recv_ack: %s bad ppa (device unit)", what); 6208cf6c252SPaul Traina break; 6218cf6c252SPaul Traina 6223052b236SBill Fenner 6238cf6c252SPaul Traina case DL_SYSERR: 624dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", 6258cf6c252SPaul Traina what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 6268cf6c252SPaul Traina break; 6278cf6c252SPaul Traina 6283052b236SBill Fenner case DL_UNSUPPORTED: 629dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 6303052b236SBill Fenner "recv_ack: %s: Service not supplied by provider", 6313052b236SBill Fenner what); 6323052b236SBill Fenner break; 6333052b236SBill Fenner 6348cf6c252SPaul Traina default: 635dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 636dc2c7305SBill Fenner "recv_ack: %s error 0x%x", 6378cf6c252SPaul Traina what, (bpf_u_int32)dlp->error_ack.dl_errno); 6388cf6c252SPaul Traina break; 6398cf6c252SPaul Traina } 6408cf6c252SPaul Traina return (-1); 6418cf6c252SPaul Traina 6428cf6c252SPaul Traina default: 643dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 644dc2c7305SBill Fenner "recv_ack: %s unexpected primitive ack 0x%x ", 6458cf6c252SPaul Traina what, (bpf_u_int32)dlp->dl_primitive); 6468cf6c252SPaul Traina return (-1); 6478cf6c252SPaul Traina } 6488cf6c252SPaul Traina 6498cf6c252SPaul Traina if (ctl.len < size) { 650dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 651dc2c7305SBill Fenner "recv_ack: %s ack too small (%d < %d)", 6528cf6c252SPaul Traina what, ctl.len, size); 6538cf6c252SPaul Traina return (-1); 6548cf6c252SPaul Traina } 6558cf6c252SPaul Traina return (ctl.len); 6568cf6c252SPaul Traina } 6578cf6c252SPaul Traina 6588cf6c252SPaul Traina static int 6598cf6c252SPaul Traina dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) 6608cf6c252SPaul Traina { 6618cf6c252SPaul Traina dl_attach_req_t req; 6628cf6c252SPaul Traina 6638cf6c252SPaul Traina req.dl_primitive = DL_ATTACH_REQ; 6648cf6c252SPaul Traina req.dl_ppa = ppa; 6658cf6c252SPaul Traina 6668cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); 6678cf6c252SPaul Traina } 6688cf6c252SPaul Traina 6698cf6c252SPaul Traina static int 6708cf6c252SPaul Traina dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 6718cf6c252SPaul Traina { 6728cf6c252SPaul Traina 6738cf6c252SPaul Traina dl_bind_req_t req; 6748cf6c252SPaul Traina 6758cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 6768cf6c252SPaul Traina req.dl_primitive = DL_BIND_REQ; 6778cf6c252SPaul Traina #ifdef DL_HP_RAWDLS 6788cf6c252SPaul Traina req.dl_max_conind = 1; /* XXX magic number */ 6798cf6c252SPaul Traina /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ 6808cf6c252SPaul Traina req.dl_sap = 22; 6818cf6c252SPaul Traina req.dl_service_mode = DL_HP_RAWDLS; 6828cf6c252SPaul Traina #else 6838cf6c252SPaul Traina req.dl_sap = sap; 6843052b236SBill Fenner #ifdef DL_CLDLS 6853052b236SBill Fenner req.dl_service_mode = DL_CLDLS; 6863052b236SBill Fenner #endif 6878cf6c252SPaul Traina #endif 6888cf6c252SPaul Traina 6898cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 6908cf6c252SPaul Traina } 6918cf6c252SPaul Traina 6928cf6c252SPaul Traina static int 6938cf6c252SPaul Traina dlbindack(int fd, char *bufp, char *ebuf) 6948cf6c252SPaul Traina { 6958cf6c252SPaul Traina 6968cf6c252SPaul Traina return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); 6978cf6c252SPaul Traina } 6988cf6c252SPaul Traina 6998cf6c252SPaul Traina static int 7008cf6c252SPaul Traina dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) 7018cf6c252SPaul Traina { 7028cf6c252SPaul Traina dl_promiscon_req_t req; 7038cf6c252SPaul Traina 7048cf6c252SPaul Traina req.dl_primitive = DL_PROMISCON_REQ; 7058cf6c252SPaul Traina req.dl_level = level; 7068cf6c252SPaul Traina 7078cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); 7088cf6c252SPaul Traina } 7098cf6c252SPaul Traina 7108cf6c252SPaul Traina static int 7118cf6c252SPaul Traina dlokack(int fd, const char *what, char *bufp, char *ebuf) 7128cf6c252SPaul Traina { 7138cf6c252SPaul Traina 7148cf6c252SPaul Traina return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); 7158cf6c252SPaul Traina } 7168cf6c252SPaul Traina 7178cf6c252SPaul Traina 7188cf6c252SPaul Traina static int 7198cf6c252SPaul Traina dlinforeq(int fd, char *ebuf) 7208cf6c252SPaul Traina { 7218cf6c252SPaul Traina dl_info_req_t req; 7228cf6c252SPaul Traina 7238cf6c252SPaul Traina req.dl_primitive = DL_INFO_REQ; 7248cf6c252SPaul Traina 7258cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 7268cf6c252SPaul Traina } 7278cf6c252SPaul Traina 7288cf6c252SPaul Traina static int 7298cf6c252SPaul Traina dlinfoack(int fd, char *bufp, char *ebuf) 7308cf6c252SPaul Traina { 7318cf6c252SPaul Traina 7328cf6c252SPaul Traina return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); 7338cf6c252SPaul Traina } 7348cf6c252SPaul Traina 7358cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 7368cf6c252SPaul Traina static int 7378cf6c252SPaul Traina strioctl(int fd, int cmd, int len, char *dp) 7388cf6c252SPaul Traina { 7398cf6c252SPaul Traina struct strioctl str; 7408cf6c252SPaul Traina int rc; 7418cf6c252SPaul Traina 7428cf6c252SPaul Traina str.ic_cmd = cmd; 7438cf6c252SPaul Traina str.ic_timout = -1; 7448cf6c252SPaul Traina str.ic_len = len; 7458cf6c252SPaul Traina str.ic_dp = dp; 7468cf6c252SPaul Traina rc = ioctl(fd, I_STR, &str); 7478cf6c252SPaul Traina 7488cf6c252SPaul Traina if (rc < 0) 7498cf6c252SPaul Traina return (rc); 7508cf6c252SPaul Traina else 7518cf6c252SPaul Traina return (str.ic_len); 7528cf6c252SPaul Traina } 7538cf6c252SPaul Traina #endif 7548cf6c252SPaul Traina 7558cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 7568cf6c252SPaul Traina static char * 7578cf6c252SPaul Traina get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 7588cf6c252SPaul Traina { 7598cf6c252SPaul Traina char *cp; 7608cf6c252SPaul Traina static char buf[32]; 7618cf6c252SPaul Traina 7628cf6c252SPaul Traina *majorp = 0; 7638cf6c252SPaul Traina *minorp = 0; 7648cf6c252SPaul Traina *microp = 0; 7658cf6c252SPaul Traina if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 7668cf6c252SPaul Traina return ("?"); 7678cf6c252SPaul Traina cp = buf; 7688cf6c252SPaul Traina if (!isdigit(*cp)) 7698cf6c252SPaul Traina return (buf); 7708cf6c252SPaul Traina *majorp = strtol(cp, &cp, 10); 7718cf6c252SPaul Traina if (*cp++ != '.') 7728cf6c252SPaul Traina return (buf); 7738cf6c252SPaul Traina *minorp = strtol(cp, &cp, 10); 7748cf6c252SPaul Traina if (*cp++ != '.') 7758cf6c252SPaul Traina return (buf); 7768cf6c252SPaul Traina *microp = strtol(cp, &cp, 10); 7778cf6c252SPaul Traina return (buf); 7788cf6c252SPaul Traina } 7798cf6c252SPaul Traina #endif 7808cf6c252SPaul Traina 7818cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK_OBS 7828cf6c252SPaul Traina /* 783dc2c7305SBill Fenner * Under HP-UX 10 and HP-UX 11, we can ask for the ppa 7848cf6c252SPaul Traina */ 7858cf6c252SPaul Traina 7868cf6c252SPaul Traina 787dc2c7305SBill Fenner /* 788dc2c7305SBill Fenner * Determine ppa number that specifies ifname. 789dc2c7305SBill Fenner * 790dc2c7305SBill Fenner * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, 791dc2c7305SBill Fenner * the code that's used here is the old code for HP-UX 10.x. 792dc2c7305SBill Fenner * 793dc2c7305SBill Fenner * However, HP-UX 10.20, at least, appears to have such a member 794dc2c7305SBill Fenner * in its "dl_hp_ppa_info_t" structure, so the new code is used. 795dc2c7305SBill Fenner * The new code didn't work on an old 10.20 system on which Rick 796dc2c7305SBill Fenner * Jones of HP tried it, but with later patches installed, it 797dc2c7305SBill Fenner * worked - it appears that the older system had those members but 798dc2c7305SBill Fenner * didn't put anything in them, so, if the search by name fails, we 799dc2c7305SBill Fenner * do the old search. 800dc2c7305SBill Fenner * 801dc2c7305SBill Fenner * Rick suggests that making sure your system is "up on the latest 802dc2c7305SBill Fenner * lancommon/DLPI/driver patches" is probably a good idea; it'd fix 803dc2c7305SBill Fenner * that problem, as well as allowing libpcap to see packets sent 804dc2c7305SBill Fenner * from the system on which the libpcap application is being run. 805dc2c7305SBill Fenner * (On 10.20, in addition to getting the latest patches, you need 806dc2c7305SBill Fenner * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; 807dc2c7305SBill Fenner * a posting to "comp.sys.hp.hpux" at 808dc2c7305SBill Fenner * 809dc2c7305SBill Fenner * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 810dc2c7305SBill Fenner * 811dc2c7305SBill Fenner * says that, to see the machine's outgoing traffic, you'd need to 812dc2c7305SBill Fenner * apply the right patches to your system, and also set that variable 813dc2c7305SBill Fenner * with: 814dc2c7305SBill Fenner 815dc2c7305SBill Fenner echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem 816dc2c7305SBill Fenner 817dc2c7305SBill Fenner * which could be put in, for example, "/sbin/init.d/lan". 818dc2c7305SBill Fenner * 819dc2c7305SBill Fenner * Setting the variable is not necessary on HP-UX 11.x. 820dc2c7305SBill Fenner */ 8218cf6c252SPaul Traina static int 8228cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *device, register int unit, 8238cf6c252SPaul Traina register char *ebuf) 8248cf6c252SPaul Traina { 8258cf6c252SPaul Traina register dl_hp_ppa_ack_t *ap; 826dc2c7305SBill Fenner register dl_hp_ppa_info_t *ipstart, *ip; 8278cf6c252SPaul Traina register int i; 828dc2c7305SBill Fenner char dname[100]; 8298cf6c252SPaul Traina register u_long majdev; 8308cf6c252SPaul Traina struct stat statbuf; 831dc2c7305SBill Fenner dl_hp_ppa_req_t req; 8328cf6c252SPaul Traina bpf_u_int32 buf[MAXDLBUF]; 8338cf6c252SPaul Traina 8348cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 8358cf6c252SPaul Traina req.dl_primitive = DL_HP_PPA_REQ; 8368cf6c252SPaul Traina 8378cf6c252SPaul Traina memset((char *)buf, 0, sizeof(buf)); 8388cf6c252SPaul Traina if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0 || 8398cf6c252SPaul Traina recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0) 8408cf6c252SPaul Traina return (-1); 8418cf6c252SPaul Traina 8428cf6c252SPaul Traina ap = (dl_hp_ppa_ack_t *)buf; 843dc2c7305SBill Fenner ipstart = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset); 844dc2c7305SBill Fenner ip = ipstart; 8458cf6c252SPaul Traina 846dc2c7305SBill Fenner #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 847dc2c7305SBill Fenner /* 848dc2c7305SBill Fenner * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" 849dc2c7305SBill Fenner * member that should, in theory, contain the part of the 850dc2c7305SBill Fenner * name for the device that comes before the unit number, 851dc2c7305SBill Fenner * and should also have a "dl_module_id_2" member that may 852dc2c7305SBill Fenner * contain an alternate name (e.g., I think Ethernet devices 853dc2c7305SBill Fenner * have both "lan", for "lanN", and "snap", for "snapN", with 854dc2c7305SBill Fenner * the former being for Ethernet packets and the latter being 855dc2c7305SBill Fenner * for 802.3/802.2 packets). 856dc2c7305SBill Fenner * 857dc2c7305SBill Fenner * Search for the device that has the specified name and 858dc2c7305SBill Fenner * instance number. 859dc2c7305SBill Fenner */ 8608cf6c252SPaul Traina for (i = 0; i < ap->dl_count; i++) { 861dc2c7305SBill Fenner if ((strcmp(ip->dl_module_id_1, device) == 0 || 862dc2c7305SBill Fenner strcmp(ip->dl_module_id_2, device) == 0) && 863dc2c7305SBill Fenner ip->dl_instance_num == unit) 8648cf6c252SPaul Traina break; 8658cf6c252SPaul Traina 866dc2c7305SBill Fenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 867dc2c7305SBill Fenner } 868dc2c7305SBill Fenner #else 869dc2c7305SBill Fenner /* 870dc2c7305SBill Fenner * We don't have that member, so the search is impossible; make it 871dc2c7305SBill Fenner * look as if the search failed. 872dc2c7305SBill Fenner */ 873dc2c7305SBill Fenner i = ap->dl_count; 874dc2c7305SBill Fenner #endif 875dc2c7305SBill Fenner 876dc2c7305SBill Fenner if (i == ap->dl_count) { 877dc2c7305SBill Fenner /* 878dc2c7305SBill Fenner * Well, we didn't, or can't, find the device by name. 879dc2c7305SBill Fenner * 880dc2c7305SBill Fenner * HP-UX 10.20, whilst it has "dl_module_id_1" and 881dc2c7305SBill Fenner * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", 882dc2c7305SBill Fenner * doesn't seem to fill them in unless the system is 883dc2c7305SBill Fenner * at a reasonably up-to-date patch level. 884dc2c7305SBill Fenner * 885dc2c7305SBill Fenner * Older HP-UX 10.x systems might not have those fields 886dc2c7305SBill Fenner * at all. 887dc2c7305SBill Fenner * 888dc2c7305SBill Fenner * Therefore, we'll search for the entry with the major 889dc2c7305SBill Fenner * device number of a device with the name "/dev/<dev><unit>", 890dc2c7305SBill Fenner * if such a device exists, as the old code did. 891dc2c7305SBill Fenner */ 892dc2c7305SBill Fenner snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); 893dc2c7305SBill Fenner if (stat(dname, &statbuf) < 0) { 894dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", 895dc2c7305SBill Fenner dname, pcap_strerror(errno)); 896dc2c7305SBill Fenner return (-1); 897dc2c7305SBill Fenner } 898dc2c7305SBill Fenner majdev = major(statbuf.st_rdev); 899dc2c7305SBill Fenner 900dc2c7305SBill Fenner ip = ipstart; 901dc2c7305SBill Fenner 902dc2c7305SBill Fenner for (i = 0; i < ap->dl_count; i++) { 903dc2c7305SBill Fenner if (ip->dl_mjr_num == majdev && 904dc2c7305SBill Fenner ip->dl_instance_num == unit) 905dc2c7305SBill Fenner break; 906dc2c7305SBill Fenner 907dc2c7305SBill Fenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 908dc2c7305SBill Fenner } 9098cf6c252SPaul Traina } 9108cf6c252SPaul Traina if (i == ap->dl_count) { 911dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 912dc2c7305SBill Fenner "can't find /dev/dlpi PPA for %s%d", device, unit); 9138cf6c252SPaul Traina return (-1); 9148cf6c252SPaul Traina } 9158cf6c252SPaul Traina if (ip->dl_hdw_state == HDW_DEAD) { 916dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 917dc2c7305SBill Fenner "%s%d: hardware state: DOWN\n", device, unit); 9188cf6c252SPaul Traina return (-1); 9198cf6c252SPaul Traina } 9208cf6c252SPaul Traina return ((int)ip->dl_ppa); 9218cf6c252SPaul Traina } 9228cf6c252SPaul Traina #endif 9238cf6c252SPaul Traina 9248cf6c252SPaul Traina #ifdef HAVE_HPUX9 9258cf6c252SPaul Traina /* 9268cf6c252SPaul Traina * Under HP-UX 9, there is no good way to determine the ppa. 9278cf6c252SPaul Traina * So punt and read it from /dev/kmem. 9288cf6c252SPaul Traina */ 9298cf6c252SPaul Traina static struct nlist nl[] = { 9308cf6c252SPaul Traina #define NL_IFNET 0 9318cf6c252SPaul Traina { "ifnet" }, 9328cf6c252SPaul Traina { "" } 9338cf6c252SPaul Traina }; 9348cf6c252SPaul Traina 9358cf6c252SPaul Traina static char path_vmunix[] = "/hp-ux"; 9368cf6c252SPaul Traina 9378cf6c252SPaul Traina /* Determine ppa number that specifies ifname */ 9388cf6c252SPaul Traina static int 9398cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *ifname, register int unit, 9408cf6c252SPaul Traina register char *ebuf) 9418cf6c252SPaul Traina { 9428cf6c252SPaul Traina register const char *cp; 9438cf6c252SPaul Traina register int kd; 9448cf6c252SPaul Traina void *addr; 9458cf6c252SPaul Traina struct ifnet ifnet; 946dc2c7305SBill Fenner char if_name[sizeof(ifnet.if_name) + 1]; 9478cf6c252SPaul Traina 9488cf6c252SPaul Traina cp = strrchr(ifname, '/'); 9498cf6c252SPaul Traina if (cp != NULL) 9508cf6c252SPaul Traina ifname = cp + 1; 9518cf6c252SPaul Traina if (nlist(path_vmunix, &nl) < 0) { 952dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", 953dc2c7305SBill Fenner path_vmunix); 9548cf6c252SPaul Traina return (-1); 9558cf6c252SPaul Traina } 9568cf6c252SPaul Traina if (nl[NL_IFNET].n_value == 0) { 957dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 958dc2c7305SBill Fenner "could't find %s kernel symbol", 9598cf6c252SPaul Traina nl[NL_IFNET].n_name); 9608cf6c252SPaul Traina return (-1); 9618cf6c252SPaul Traina } 9628cf6c252SPaul Traina kd = open("/dev/kmem", O_RDONLY); 9638cf6c252SPaul Traina if (kd < 0) { 964dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", 965dc2c7305SBill Fenner pcap_strerror(errno)); 9668cf6c252SPaul Traina return (-1); 9678cf6c252SPaul Traina } 9688cf6c252SPaul Traina if (dlpi_kread(kd, nl[NL_IFNET].n_value, 9698cf6c252SPaul Traina &addr, sizeof(addr), ebuf) < 0) { 9708cf6c252SPaul Traina close(kd); 9718cf6c252SPaul Traina return (-1); 9728cf6c252SPaul Traina } 9738cf6c252SPaul Traina for (; addr != NULL; addr = ifnet.if_next) { 9748cf6c252SPaul Traina if (dlpi_kread(kd, (off_t)addr, 9758cf6c252SPaul Traina &ifnet, sizeof(ifnet), ebuf) < 0 || 9768cf6c252SPaul Traina dlpi_kread(kd, (off_t)ifnet.if_name, 977dc2c7305SBill Fenner if_name, sizeof(ifnet.if_name), ebuf) < 0) { 9788cf6c252SPaul Traina (void)close(kd); 9798cf6c252SPaul Traina return (-1); 9808cf6c252SPaul Traina } 981dc2c7305SBill Fenner if_name[sizeof(ifnet.if_name)] = '\0'; 982dc2c7305SBill Fenner if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) 9838cf6c252SPaul Traina return (ifnet.if_index); 9848cf6c252SPaul Traina } 9858cf6c252SPaul Traina 986dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); 9878cf6c252SPaul Traina return (-1); 9888cf6c252SPaul Traina } 9898cf6c252SPaul Traina 9908cf6c252SPaul Traina static int 9918cf6c252SPaul Traina dlpi_kread(register int fd, register off_t addr, 9928cf6c252SPaul Traina register void *buf, register u_int len, register char *ebuf) 9938cf6c252SPaul Traina { 9948cf6c252SPaul Traina register int cc; 9958cf6c252SPaul Traina 996a4b5b39fSBill Fenner if (lseek(fd, addr, SEEK_SET) < 0) { 997dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", 998dc2c7305SBill Fenner pcap_strerror(errno)); 9998cf6c252SPaul Traina return (-1); 10008cf6c252SPaul Traina } 10018cf6c252SPaul Traina cc = read(fd, buf, len); 10028cf6c252SPaul Traina if (cc < 0) { 1003dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", 1004dc2c7305SBill Fenner pcap_strerror(errno)); 10058cf6c252SPaul Traina return (-1); 10068cf6c252SPaul Traina } else if (cc != len) { 1007dc2c7305SBill Fenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, 1008dc2c7305SBill Fenner len); 10098cf6c252SPaul Traina return (-1); 10108cf6c252SPaul Traina } 10118cf6c252SPaul Traina return (cc); 10128cf6c252SPaul Traina } 10138cf6c252SPaul Traina #endif 1014