18cf6c252SPaul Traina /* 28cf6c252SPaul Traina * Copyright (c) 1993, 1994, 1995, 1996 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 #ifndef lint 258cf6c252SPaul Traina static char rcsid[] = 268cf6c252SPaul Traina "@(#)$Header: pcap-dlpi.c,v 1.42 96/07/23 14:20:32 leres Exp $ (LBL)"; 278cf6c252SPaul Traina #endif 288cf6c252SPaul Traina 298cf6c252SPaul Traina /* 308cf6c252SPaul Traina * Packet capture routine for dlpi under SunOS 5 318cf6c252SPaul Traina * 328cf6c252SPaul Traina * Notes: 338cf6c252SPaul Traina * 348cf6c252SPaul Traina * - Apparently the DLIOCRAW ioctl() is specific to SunOS. 358cf6c252SPaul Traina * 368cf6c252SPaul Traina * - There is a bug in bufmod(7) such that setting the snapshot 378cf6c252SPaul Traina * length results in data being left of the front of the packet. 388cf6c252SPaul Traina * 398cf6c252SPaul Traina * - It might be desirable to use pfmod(7) to filter packets in the 408cf6c252SPaul Traina * kernel. 418cf6c252SPaul Traina */ 428cf6c252SPaul Traina 438cf6c252SPaul Traina #include <sys/types.h> 448cf6c252SPaul Traina #include <sys/time.h> 458cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 468cf6c252SPaul Traina #include <sys/bufmod.h> 478cf6c252SPaul Traina #endif 488cf6c252SPaul Traina #include <sys/dlpi.h> 498cf6c252SPaul Traina #ifdef HAVE_SYS_DLPI_EXT_H 508cf6c252SPaul Traina #include <sys/dlpi_ext.h> 518cf6c252SPaul Traina #endif 528cf6c252SPaul Traina #ifdef HAVE_HPUX9 538cf6c252SPaul Traina #include <sys/socket.h> 548cf6c252SPaul Traina #endif 558cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK_OBS 568cf6c252SPaul Traina #include <sys/stat.h> 578cf6c252SPaul Traina #endif 588cf6c252SPaul Traina #include <sys/stream.h> 598cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 608cf6c252SPaul Traina #include <sys/systeminfo.h> 618cf6c252SPaul Traina #endif 628cf6c252SPaul Traina 638cf6c252SPaul Traina #ifdef HAVE_HPUX9 648cf6c252SPaul Traina #include <net/if.h> 658cf6c252SPaul Traina #endif 668cf6c252SPaul Traina 678cf6c252SPaul Traina #include <ctype.h> 688cf6c252SPaul Traina #ifdef HAVE_HPUX9 698cf6c252SPaul Traina #include <nlist.h> 708cf6c252SPaul Traina #endif 718cf6c252SPaul Traina #include <errno.h> 728cf6c252SPaul Traina #include <fcntl.h> 738cf6c252SPaul Traina #include <memory.h> 748cf6c252SPaul Traina #include <stdio.h> 758cf6c252SPaul Traina #include <stdlib.h> 768cf6c252SPaul Traina #include <string.h> 778cf6c252SPaul Traina #include <stropts.h> 788cf6c252SPaul Traina #include <unistd.h> 798cf6c252SPaul Traina 808cf6c252SPaul Traina #include "pcap-int.h" 818cf6c252SPaul Traina 828cf6c252SPaul Traina #include "gnuc.h" 838cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H 848cf6c252SPaul Traina #include "os-proto.h" 858cf6c252SPaul Traina #endif 868cf6c252SPaul Traina 878cf6c252SPaul Traina #ifndef PCAP_DEV_PREFIX 888cf6c252SPaul Traina #define PCAP_DEV_PREFIX "/dev" 898cf6c252SPaul Traina #endif 908cf6c252SPaul Traina 918cf6c252SPaul Traina #define MAXDLBUF 8192 928cf6c252SPaul Traina 938cf6c252SPaul Traina /* Forwards */ 948cf6c252SPaul Traina static int dlattachreq(int, bpf_u_int32, char *); 958cf6c252SPaul Traina static int dlbindack(int, char *, char *); 968cf6c252SPaul Traina static int dlbindreq(int, bpf_u_int32, char *); 978cf6c252SPaul Traina static int dlinfoack(int, char *, char *); 988cf6c252SPaul Traina static int dlinforeq(int, char *); 998cf6c252SPaul Traina static int dlokack(int, const char *, char *, char *); 1008cf6c252SPaul Traina static int recv_ack(int, int, const char *, char *, char *); 1018cf6c252SPaul Traina static int dlpromisconreq(int, bpf_u_int32, char *); 1028cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 1038cf6c252SPaul Traina static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 1048cf6c252SPaul Traina #endif 1058cf6c252SPaul Traina static int send_request(int, char *, int, char *, char *); 1068cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1078cf6c252SPaul Traina static int strioctl(int, int, int, char *); 1088cf6c252SPaul Traina #endif 1098cf6c252SPaul Traina #ifdef HAVE_HPUX9 1108cf6c252SPaul Traina static int dlpi_kread(int, off_t, void *, u_int, char *); 1118cf6c252SPaul Traina #endif 1128cf6c252SPaul Traina #ifdef HAVE_DEV_DLPI 1138cf6c252SPaul Traina static int get_dlpi_ppa(int, const char *, int, char *); 1148cf6c252SPaul Traina #endif 1158cf6c252SPaul Traina 1168cf6c252SPaul Traina int 1178cf6c252SPaul Traina pcap_stats(pcap_t *p, struct pcap_stat *ps) 1188cf6c252SPaul Traina { 1198cf6c252SPaul Traina 1208cf6c252SPaul Traina *ps = p->md.stat; 1218cf6c252SPaul Traina return (0); 1228cf6c252SPaul Traina } 1238cf6c252SPaul Traina 1248cf6c252SPaul Traina /* XXX Needed by HP-UX (at least) */ 1258cf6c252SPaul Traina static bpf_u_int32 ctlbuf[MAXDLBUF]; 1268cf6c252SPaul Traina static struct strbuf ctl = { 1278cf6c252SPaul Traina MAXDLBUF, 1288cf6c252SPaul Traina 0, 1298cf6c252SPaul Traina (char *)ctlbuf 1308cf6c252SPaul Traina }; 1318cf6c252SPaul Traina 1328cf6c252SPaul Traina int 1338cf6c252SPaul Traina pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 1348cf6c252SPaul Traina { 1358cf6c252SPaul Traina register int cc, n, caplen, origlen; 1368cf6c252SPaul Traina register u_char *bp, *ep, *pk; 1378cf6c252SPaul Traina register struct bpf_insn *fcode; 1388cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1398cf6c252SPaul Traina register struct sb_hdr *sbp; 1408cf6c252SPaul Traina #ifdef LBL_ALIGN 1418cf6c252SPaul Traina struct sb_hdr sbhdr; 1428cf6c252SPaul Traina #endif 1438cf6c252SPaul Traina #endif 1448cf6c252SPaul Traina int flags; 1458cf6c252SPaul Traina struct strbuf data; 1468cf6c252SPaul Traina struct pcap_pkthdr pkthdr; 1478cf6c252SPaul Traina 1488cf6c252SPaul Traina flags = 0; 1498cf6c252SPaul Traina cc = p->cc; 1508cf6c252SPaul Traina if (cc == 0) { 1518cf6c252SPaul Traina data.buf = (char *)p->buffer + p->offset; 1528cf6c252SPaul Traina data.maxlen = MAXDLBUF; 1538cf6c252SPaul Traina data.len = 0; 1548cf6c252SPaul Traina do { 1558cf6c252SPaul Traina if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 1568cf6c252SPaul Traina /* Don't choke when we get ptraced */ 1578cf6c252SPaul Traina if (errno == EINTR) { 1588cf6c252SPaul Traina cc = 0; 1598cf6c252SPaul Traina continue; 1608cf6c252SPaul Traina } 1618cf6c252SPaul Traina strcpy(p->errbuf, pcap_strerror(errno)); 1628cf6c252SPaul Traina return (-1); 1638cf6c252SPaul Traina } 1648cf6c252SPaul Traina cc = data.len; 1658cf6c252SPaul Traina } while (cc == 0); 1668cf6c252SPaul Traina bp = p->buffer + p->offset; 1678cf6c252SPaul Traina } else 1688cf6c252SPaul Traina bp = p->bp; 1698cf6c252SPaul Traina 1708cf6c252SPaul Traina /* Loop through packets */ 1718cf6c252SPaul Traina fcode = p->fcode.bf_insns; 1728cf6c252SPaul Traina ep = bp + cc; 1738cf6c252SPaul Traina n = 0; 1748cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1758cf6c252SPaul Traina while (bp < ep) { 1768cf6c252SPaul Traina #ifdef LBL_ALIGN 1778cf6c252SPaul Traina if ((long)bp & 3) { 1788cf6c252SPaul Traina sbp = &sbhdr; 1798cf6c252SPaul Traina memcpy(sbp, bp, sizeof(*sbp)); 1808cf6c252SPaul Traina } else 1818cf6c252SPaul Traina #endif 1828cf6c252SPaul Traina sbp = (struct sb_hdr *)bp; 1838cf6c252SPaul Traina p->md.stat.ps_drop += sbp->sbh_drops; 1848cf6c252SPaul Traina pk = bp + sizeof(*sbp); 1858cf6c252SPaul Traina bp += sbp->sbh_totlen; 1868cf6c252SPaul Traina origlen = sbp->sbh_origlen; 1878cf6c252SPaul Traina caplen = sbp->sbh_msglen; 1888cf6c252SPaul Traina #else 1898cf6c252SPaul Traina origlen = cc; 1908cf6c252SPaul Traina caplen = min(p->snapshot, cc); 1918cf6c252SPaul Traina pk = bp; 1928cf6c252SPaul Traina bp += caplen; 1938cf6c252SPaul Traina #endif 1948cf6c252SPaul Traina ++p->md.stat.ps_recv; 1958cf6c252SPaul Traina if (bpf_filter(fcode, pk, origlen, caplen)) { 1968cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 1978cf6c252SPaul Traina pkthdr.ts = sbp->sbh_timestamp; 1988cf6c252SPaul Traina #else 1998cf6c252SPaul Traina (void)gettimeofday(&pkthdr.ts, NULL); 2008cf6c252SPaul Traina #endif 2018cf6c252SPaul Traina pkthdr.len = origlen; 2028cf6c252SPaul Traina pkthdr.caplen = caplen; 2038cf6c252SPaul Traina /* Insure caplen does not exceed snapshot */ 2048cf6c252SPaul Traina if (pkthdr.caplen > p->snapshot) 2058cf6c252SPaul Traina pkthdr.caplen = p->snapshot; 2068cf6c252SPaul Traina (*callback)(user, &pkthdr, pk); 2078cf6c252SPaul Traina if (++n >= cnt && cnt >= 0) { 2088cf6c252SPaul Traina p->cc = ep - bp; 2098cf6c252SPaul Traina p->bp = bp; 2108cf6c252SPaul Traina return (n); 2118cf6c252SPaul Traina } 2128cf6c252SPaul Traina } 2138cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2148cf6c252SPaul Traina } 2158cf6c252SPaul Traina #endif 2168cf6c252SPaul Traina p->cc = 0; 2178cf6c252SPaul Traina return (n); 2188cf6c252SPaul Traina } 2198cf6c252SPaul Traina 2208cf6c252SPaul Traina pcap_t * 2218cf6c252SPaul Traina pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 2228cf6c252SPaul Traina { 2238cf6c252SPaul Traina register char *cp; 2248cf6c252SPaul Traina char *eos; 2258cf6c252SPaul Traina register pcap_t *p; 2268cf6c252SPaul Traina register int ppa; 2278cf6c252SPaul Traina register dl_info_ack_t *infop; 2288cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 2298cf6c252SPaul Traina bpf_u_int32 ss, flag; 2308cf6c252SPaul Traina #ifdef HAVE_SOLARIS 2318cf6c252SPaul Traina register char *release; 2328cf6c252SPaul Traina bpf_u_int32 osmajor, osminor, osmicro; 2338cf6c252SPaul Traina #endif 2348cf6c252SPaul Traina #endif 2358cf6c252SPaul Traina bpf_u_int32 buf[MAXDLBUF]; 2368cf6c252SPaul Traina char dname[100]; 2378cf6c252SPaul Traina #ifndef HAVE_DEV_DLPI 2388cf6c252SPaul Traina char dname2[100]; 2398cf6c252SPaul Traina #endif 2408cf6c252SPaul Traina 2418cf6c252SPaul Traina p = (pcap_t *)malloc(sizeof(*p)); 2428cf6c252SPaul Traina if (p == NULL) { 2438cf6c252SPaul Traina strcpy(ebuf, pcap_strerror(errno)); 2448cf6c252SPaul Traina return (NULL); 2458cf6c252SPaul Traina } 2468cf6c252SPaul Traina memset(p, 0, sizeof(*p)); 2478cf6c252SPaul Traina 2488cf6c252SPaul Traina /* 2498cf6c252SPaul Traina ** Determine device and ppa 2508cf6c252SPaul Traina */ 2518cf6c252SPaul Traina cp = strpbrk(device, "0123456789"); 2528cf6c252SPaul Traina if (cp == NULL) { 2538cf6c252SPaul Traina sprintf(ebuf, "%s missing unit number", device); 2548cf6c252SPaul Traina goto bad; 2558cf6c252SPaul Traina } 2568cf6c252SPaul Traina ppa = strtol(cp, &eos, 10); 2578cf6c252SPaul Traina if (*eos != '\0') { 2588cf6c252SPaul Traina sprintf(ebuf, "%s bad unit number", device); 2598cf6c252SPaul Traina goto bad; 2608cf6c252SPaul Traina } 2618cf6c252SPaul Traina 2628cf6c252SPaul Traina if (*device == '/') 2638cf6c252SPaul Traina strcpy(dname, device); 2648cf6c252SPaul Traina else 2658cf6c252SPaul Traina sprintf(dname, "%s/%s", PCAP_DEV_PREFIX, device); 2668cf6c252SPaul Traina #ifdef HAVE_DEV_DLPI 2678cf6c252SPaul Traina /* Map network device to /dev/dlpi unit */ 2688cf6c252SPaul Traina cp = "/dev/dlpi"; 2698cf6c252SPaul Traina if ((p->fd = open(cp, O_RDWR)) < 0) { 2708cf6c252SPaul Traina sprintf(ebuf, "%s: %s", cp, pcap_strerror(errno)); 2718cf6c252SPaul Traina goto bad; 2728cf6c252SPaul Traina } 2738cf6c252SPaul Traina /* Map network interface to /dev/dlpi unit */ 2748cf6c252SPaul Traina ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); 2758cf6c252SPaul Traina if (ppa < 0) 2768cf6c252SPaul Traina goto bad; 2778cf6c252SPaul Traina #else 2788cf6c252SPaul Traina /* Try device without unit number */ 2798cf6c252SPaul Traina strcpy(dname2, dname); 2808cf6c252SPaul Traina cp = strchr(dname, *cp); 2818cf6c252SPaul Traina *cp = '\0'; 2828cf6c252SPaul Traina if ((p->fd = open(dname, O_RDWR)) < 0) { 2838cf6c252SPaul Traina if (errno != ENOENT) { 2848cf6c252SPaul Traina sprintf(ebuf, "%s: %s", dname, pcap_strerror(errno)); 2858cf6c252SPaul Traina goto bad; 2868cf6c252SPaul Traina } 2878cf6c252SPaul Traina 2888cf6c252SPaul Traina /* Try again with unit number */ 2898cf6c252SPaul Traina if ((p->fd = open(dname2, O_RDWR)) < 0) { 2908cf6c252SPaul Traina sprintf(ebuf, "%s: %s", dname2, pcap_strerror(errno)); 2918cf6c252SPaul Traina goto bad; 2928cf6c252SPaul Traina } 2938cf6c252SPaul Traina /* XXX Assume unit zero */ 2948cf6c252SPaul Traina ppa = 0; 2958cf6c252SPaul Traina } 2968cf6c252SPaul Traina #endif 2978cf6c252SPaul Traina 2988cf6c252SPaul Traina p->snapshot = snaplen; 2998cf6c252SPaul Traina 3008cf6c252SPaul Traina /* 3018cf6c252SPaul Traina ** Attach if "style 2" provider 3028cf6c252SPaul Traina */ 3038cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 3048cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 3058cf6c252SPaul Traina goto bad; 3068cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 3078cf6c252SPaul Traina if (infop->dl_provider_style == DL_STYLE2 && 3088cf6c252SPaul Traina (dlattachreq(p->fd, ppa, ebuf) < 0 || 3098cf6c252SPaul Traina dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) 3108cf6c252SPaul Traina goto bad; 3118cf6c252SPaul Traina /* 3128cf6c252SPaul Traina ** Bind (defer if using HP-UX 9, totally skip if using SINIX) 3138cf6c252SPaul Traina */ 3148cf6c252SPaul Traina #if !defined(HAVE_HPUX9) && !defined(sinix) 3158cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 3168cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 3178cf6c252SPaul Traina goto bad; 3188cf6c252SPaul Traina #endif 3198cf6c252SPaul Traina 3208cf6c252SPaul Traina if (promisc) { 3218cf6c252SPaul Traina /* 3228cf6c252SPaul Traina ** Enable promiscuous 3238cf6c252SPaul Traina */ 3248cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || 3258cf6c252SPaul Traina dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) 3268cf6c252SPaul Traina goto bad; 3278cf6c252SPaul Traina 3288cf6c252SPaul Traina /* 3298cf6c252SPaul Traina ** Try to enable multicast (you would have thought 3308cf6c252SPaul Traina ** promiscuous would be sufficient). Skip if SINIX. 3318cf6c252SPaul Traina */ 3328cf6c252SPaul Traina #ifndef sinix 3338cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || 3348cf6c252SPaul Traina dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) 3358cf6c252SPaul Traina fprintf(stderr, 3368cf6c252SPaul Traina "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); 3378cf6c252SPaul Traina #endif 3388cf6c252SPaul Traina } 3398cf6c252SPaul Traina /* 3408cf6c252SPaul Traina ** Always try to enable sap (except if SINIX) 3418cf6c252SPaul Traina */ 3428cf6c252SPaul Traina #ifndef sinix 3438cf6c252SPaul Traina if (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || 3448cf6c252SPaul Traina dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0) { 3458cf6c252SPaul Traina /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ 3468cf6c252SPaul Traina if (promisc) 3478cf6c252SPaul Traina fprintf(stderr, 3488cf6c252SPaul Traina "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); 3498cf6c252SPaul Traina else 3508cf6c252SPaul Traina goto bad; 3518cf6c252SPaul Traina } 3528cf6c252SPaul Traina #endif 3538cf6c252SPaul Traina 3548cf6c252SPaul Traina /* 3558cf6c252SPaul Traina ** Bind (HP-UX 9 must bind after setting promiscuous options) 3568cf6c252SPaul Traina */ 3578cf6c252SPaul Traina #ifdef HAVE_HPUX9 3588cf6c252SPaul Traina if (dlbindreq(p->fd, 0, ebuf) < 0 || 3598cf6c252SPaul Traina dlbindack(p->fd, (char *)buf, ebuf) < 0) 3608cf6c252SPaul Traina goto bad; 3618cf6c252SPaul Traina #endif 3628cf6c252SPaul Traina 3638cf6c252SPaul Traina /* 3648cf6c252SPaul Traina ** Determine link type 3658cf6c252SPaul Traina */ 3668cf6c252SPaul Traina if (dlinforeq(p->fd, ebuf) < 0 || 3678cf6c252SPaul Traina dlinfoack(p->fd, (char *)buf, ebuf) < 0) 3688cf6c252SPaul Traina goto bad; 3698cf6c252SPaul Traina 3708cf6c252SPaul Traina infop = &((union DL_primitives *)buf)->info_ack; 3718cf6c252SPaul Traina switch (infop->dl_mac_type) { 3728cf6c252SPaul Traina 3738cf6c252SPaul Traina case DL_CSMACD: 3748cf6c252SPaul Traina case DL_ETHER: 3758cf6c252SPaul Traina p->linktype = DLT_EN10MB; 3768cf6c252SPaul Traina p->offset = 2; 3778cf6c252SPaul Traina break; 3788cf6c252SPaul Traina 3798cf6c252SPaul Traina case DL_FDDI: 3808cf6c252SPaul Traina p->linktype = DLT_FDDI; 3818cf6c252SPaul Traina break; 3828cf6c252SPaul Traina 3838cf6c252SPaul Traina default: 3848cf6c252SPaul Traina sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type); 3858cf6c252SPaul Traina goto bad; 3868cf6c252SPaul Traina } 3878cf6c252SPaul Traina 3888cf6c252SPaul Traina #ifdef DLIOCRAW 3898cf6c252SPaul Traina /* 3908cf6c252SPaul Traina ** This is a non standard SunOS hack to get the ethernet header. 3918cf6c252SPaul Traina */ 3928cf6c252SPaul Traina if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 3938cf6c252SPaul Traina sprintf(ebuf, "DLIOCRAW: %s", pcap_strerror(errno)); 3948cf6c252SPaul Traina goto bad; 3958cf6c252SPaul Traina } 3968cf6c252SPaul Traina #endif 3978cf6c252SPaul Traina 3988cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 3998cf6c252SPaul Traina /* 4008cf6c252SPaul Traina ** Another non standard call to get the data nicely buffered 4018cf6c252SPaul Traina */ 4028cf6c252SPaul Traina if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { 4038cf6c252SPaul Traina sprintf(ebuf, "I_PUSH bufmod: %s", pcap_strerror(errno)); 4048cf6c252SPaul Traina goto bad; 4058cf6c252SPaul Traina } 4068cf6c252SPaul Traina 4078cf6c252SPaul Traina /* 4088cf6c252SPaul Traina ** Now that the bufmod is pushed lets configure it. 4098cf6c252SPaul Traina ** 4108cf6c252SPaul Traina ** There is a bug in bufmod(7). When dealing with messages of 4118cf6c252SPaul Traina ** less than snaplen size it strips data from the beginning not 4128cf6c252SPaul Traina ** the end. 4138cf6c252SPaul Traina ** 4148cf6c252SPaul Traina ** This bug is supposed to be fixed in 5.3.2. Also, there is a 4158cf6c252SPaul Traina ** patch available. Ask for bugid 1149065. 4168cf6c252SPaul Traina */ 4178cf6c252SPaul Traina ss = snaplen; 4188cf6c252SPaul Traina #ifdef HAVE_SOLARIS 4198cf6c252SPaul Traina release = get_release(&osmajor, &osminor, &osmicro); 4208cf6c252SPaul Traina if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 4218cf6c252SPaul Traina getenv("BUFMOD_FIXED") == NULL) { 4228cf6c252SPaul Traina fprintf(stderr, 4238cf6c252SPaul Traina "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", 4248cf6c252SPaul Traina release); 4258cf6c252SPaul Traina ss = 0; 4268cf6c252SPaul Traina } 4278cf6c252SPaul Traina #endif 4288cf6c252SPaul Traina if (ss > 0 && 4298cf6c252SPaul Traina strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { 4308cf6c252SPaul Traina sprintf(ebuf, "SBIOCSSNAP: %s", pcap_strerror(errno)); 4318cf6c252SPaul Traina goto bad; 4328cf6c252SPaul Traina } 4338cf6c252SPaul Traina 4348cf6c252SPaul Traina /* 4358cf6c252SPaul Traina ** Set up the bufmod flags 4368cf6c252SPaul Traina */ 4378cf6c252SPaul Traina if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) { 4388cf6c252SPaul Traina sprintf(ebuf, "SBIOCGFLAGS: %s", pcap_strerror(errno)); 4398cf6c252SPaul Traina goto bad; 4408cf6c252SPaul Traina } 4418cf6c252SPaul Traina flag |= SB_NO_DROPS; 4428cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) { 4438cf6c252SPaul Traina sprintf(ebuf, "SBIOCSFLAGS: %s", pcap_strerror(errno)); 4448cf6c252SPaul Traina goto bad; 4458cf6c252SPaul Traina } 4468cf6c252SPaul Traina /* 4478cf6c252SPaul Traina ** Set up the bufmod timeout 4488cf6c252SPaul Traina */ 4498cf6c252SPaul Traina if (to_ms != 0) { 4508cf6c252SPaul Traina struct timeval to; 4518cf6c252SPaul Traina 4528cf6c252SPaul Traina to.tv_sec = to_ms / 1000; 4538cf6c252SPaul Traina to.tv_usec = (to_ms * 1000) % 1000000; 4548cf6c252SPaul Traina if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { 4558cf6c252SPaul Traina sprintf(ebuf, "SBIOCSTIME: %s", pcap_strerror(errno)); 4568cf6c252SPaul Traina goto bad; 4578cf6c252SPaul Traina } 4588cf6c252SPaul Traina } 4598cf6c252SPaul Traina #endif 4608cf6c252SPaul Traina 4618cf6c252SPaul Traina /* 4628cf6c252SPaul Traina ** As the last operation flush the read side. 4638cf6c252SPaul Traina */ 4648cf6c252SPaul Traina if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 4658cf6c252SPaul Traina sprintf(ebuf, "FLUSHR: %s", pcap_strerror(errno)); 4668cf6c252SPaul Traina goto bad; 4678cf6c252SPaul Traina } 4688cf6c252SPaul Traina /* Allocate data buffer */ 4698cf6c252SPaul Traina p->bufsize = MAXDLBUF * sizeof(bpf_u_int32); 4708cf6c252SPaul Traina p->buffer = (u_char *)malloc(p->bufsize + p->offset); 4718cf6c252SPaul Traina 4728cf6c252SPaul Traina return (p); 4738cf6c252SPaul Traina bad: 4748cf6c252SPaul Traina free(p); 4758cf6c252SPaul Traina return (NULL); 4768cf6c252SPaul Traina } 4778cf6c252SPaul Traina 4788cf6c252SPaul Traina int 4798cf6c252SPaul Traina pcap_setfilter(pcap_t *p, struct bpf_program *fp) 4808cf6c252SPaul Traina { 4818cf6c252SPaul Traina 4828cf6c252SPaul Traina p->fcode = *fp; 4838cf6c252SPaul Traina return (0); 4848cf6c252SPaul Traina } 4858cf6c252SPaul Traina 4868cf6c252SPaul Traina static int 4878cf6c252SPaul Traina send_request(int fd, char *ptr, int len, char *what, char *ebuf) 4888cf6c252SPaul Traina { 4898cf6c252SPaul Traina struct strbuf ctl; 4908cf6c252SPaul Traina int flags; 4918cf6c252SPaul Traina 4928cf6c252SPaul Traina ctl.maxlen = 0; 4938cf6c252SPaul Traina ctl.len = len; 4948cf6c252SPaul Traina ctl.buf = ptr; 4958cf6c252SPaul Traina 4968cf6c252SPaul Traina flags = 0; 4978cf6c252SPaul Traina if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 4988cf6c252SPaul Traina sprintf(ebuf, "send_request: putmsg \"%s\": %s", 4998cf6c252SPaul Traina what, pcap_strerror(errno)); 5008cf6c252SPaul Traina return (-1); 5018cf6c252SPaul Traina } 5028cf6c252SPaul Traina return (0); 5038cf6c252SPaul Traina } 5048cf6c252SPaul Traina 5058cf6c252SPaul Traina static int 5068cf6c252SPaul Traina recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) 5078cf6c252SPaul Traina { 5088cf6c252SPaul Traina union DL_primitives *dlp; 5098cf6c252SPaul Traina struct strbuf ctl; 5108cf6c252SPaul Traina int flags; 5118cf6c252SPaul Traina 5128cf6c252SPaul Traina ctl.maxlen = MAXDLBUF; 5138cf6c252SPaul Traina ctl.len = 0; 5148cf6c252SPaul Traina ctl.buf = bufp; 5158cf6c252SPaul Traina 5168cf6c252SPaul Traina flags = 0; 5178cf6c252SPaul Traina if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 5188cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s getmsg: %s", 5198cf6c252SPaul Traina what, pcap_strerror(errno)); 5208cf6c252SPaul Traina return (-1); 5218cf6c252SPaul Traina } 5228cf6c252SPaul Traina 5238cf6c252SPaul Traina dlp = (union DL_primitives *) ctl.buf; 5248cf6c252SPaul Traina switch (dlp->dl_primitive) { 5258cf6c252SPaul Traina 5268cf6c252SPaul Traina case DL_INFO_ACK: 5278cf6c252SPaul Traina case DL_BIND_ACK: 5288cf6c252SPaul Traina case DL_OK_ACK: 5298cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK 5308cf6c252SPaul Traina case DL_HP_PPA_ACK: 5318cf6c252SPaul Traina #endif 5328cf6c252SPaul Traina 5338cf6c252SPaul Traina /* These are OK */ 5348cf6c252SPaul Traina break; 5358cf6c252SPaul Traina 5368cf6c252SPaul Traina case DL_ERROR_ACK: 5378cf6c252SPaul Traina switch (dlp->error_ack.dl_errno) { 5388cf6c252SPaul Traina 5398cf6c252SPaul Traina case DL_BADPPA: 5408cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s bad ppa (device unit)", 5418cf6c252SPaul Traina what); 5428cf6c252SPaul Traina break; 5438cf6c252SPaul Traina 5448cf6c252SPaul Traina case DL_SYSERR: 5458cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s: %s", 5468cf6c252SPaul Traina what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 5478cf6c252SPaul Traina break; 5488cf6c252SPaul Traina 5498cf6c252SPaul Traina default: 5508cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s error 0x%x", 5518cf6c252SPaul Traina what, (bpf_u_int32)dlp->error_ack.dl_errno); 5528cf6c252SPaul Traina break; 5538cf6c252SPaul Traina } 5548cf6c252SPaul Traina return (-1); 5558cf6c252SPaul Traina 5568cf6c252SPaul Traina default: 5578cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ", 5588cf6c252SPaul Traina what, (bpf_u_int32)dlp->dl_primitive); 5598cf6c252SPaul Traina return (-1); 5608cf6c252SPaul Traina } 5618cf6c252SPaul Traina 5628cf6c252SPaul Traina if (ctl.len < size) { 5638cf6c252SPaul Traina sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)", 5648cf6c252SPaul Traina what, ctl.len, size); 5658cf6c252SPaul Traina return (-1); 5668cf6c252SPaul Traina } 5678cf6c252SPaul Traina return (ctl.len); 5688cf6c252SPaul Traina } 5698cf6c252SPaul Traina 5708cf6c252SPaul Traina static int 5718cf6c252SPaul Traina dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) 5728cf6c252SPaul Traina { 5738cf6c252SPaul Traina dl_attach_req_t req; 5748cf6c252SPaul Traina 5758cf6c252SPaul Traina req.dl_primitive = DL_ATTACH_REQ; 5768cf6c252SPaul Traina req.dl_ppa = ppa; 5778cf6c252SPaul Traina 5788cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); 5798cf6c252SPaul Traina } 5808cf6c252SPaul Traina 5818cf6c252SPaul Traina static int 5828cf6c252SPaul Traina dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 5838cf6c252SPaul Traina { 5848cf6c252SPaul Traina 5858cf6c252SPaul Traina dl_bind_req_t req; 5868cf6c252SPaul Traina 5878cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 5888cf6c252SPaul Traina req.dl_primitive = DL_BIND_REQ; 5898cf6c252SPaul Traina #ifdef DL_HP_RAWDLS 5908cf6c252SPaul Traina req.dl_max_conind = 1; /* XXX magic number */ 5918cf6c252SPaul Traina /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ 5928cf6c252SPaul Traina req.dl_sap = 22; 5938cf6c252SPaul Traina req.dl_service_mode = DL_HP_RAWDLS; 5948cf6c252SPaul Traina #else 5958cf6c252SPaul Traina req.dl_sap = sap; 5968cf6c252SPaul Traina #endif 5978cf6c252SPaul Traina 5988cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 5998cf6c252SPaul Traina } 6008cf6c252SPaul Traina 6018cf6c252SPaul Traina static int 6028cf6c252SPaul Traina dlbindack(int fd, char *bufp, char *ebuf) 6038cf6c252SPaul Traina { 6048cf6c252SPaul Traina 6058cf6c252SPaul Traina return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); 6068cf6c252SPaul Traina } 6078cf6c252SPaul Traina 6088cf6c252SPaul Traina static int 6098cf6c252SPaul Traina dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) 6108cf6c252SPaul Traina { 6118cf6c252SPaul Traina dl_promiscon_req_t req; 6128cf6c252SPaul Traina 6138cf6c252SPaul Traina req.dl_primitive = DL_PROMISCON_REQ; 6148cf6c252SPaul Traina req.dl_level = level; 6158cf6c252SPaul Traina 6168cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); 6178cf6c252SPaul Traina } 6188cf6c252SPaul Traina 6198cf6c252SPaul Traina static int 6208cf6c252SPaul Traina dlokack(int fd, const char *what, char *bufp, char *ebuf) 6218cf6c252SPaul Traina { 6228cf6c252SPaul Traina 6238cf6c252SPaul Traina return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); 6248cf6c252SPaul Traina } 6258cf6c252SPaul Traina 6268cf6c252SPaul Traina 6278cf6c252SPaul Traina static int 6288cf6c252SPaul Traina dlinforeq(int fd, char *ebuf) 6298cf6c252SPaul Traina { 6308cf6c252SPaul Traina dl_info_req_t req; 6318cf6c252SPaul Traina 6328cf6c252SPaul Traina req.dl_primitive = DL_INFO_REQ; 6338cf6c252SPaul Traina 6348cf6c252SPaul Traina return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 6358cf6c252SPaul Traina } 6368cf6c252SPaul Traina 6378cf6c252SPaul Traina static int 6388cf6c252SPaul Traina dlinfoack(int fd, char *bufp, char *ebuf) 6398cf6c252SPaul Traina { 6408cf6c252SPaul Traina 6418cf6c252SPaul Traina return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); 6428cf6c252SPaul Traina } 6438cf6c252SPaul Traina 6448cf6c252SPaul Traina #ifdef HAVE_SYS_BUFMOD_H 6458cf6c252SPaul Traina static int 6468cf6c252SPaul Traina strioctl(int fd, int cmd, int len, char *dp) 6478cf6c252SPaul Traina { 6488cf6c252SPaul Traina struct strioctl str; 6498cf6c252SPaul Traina int rc; 6508cf6c252SPaul Traina 6518cf6c252SPaul Traina str.ic_cmd = cmd; 6528cf6c252SPaul Traina str.ic_timout = -1; 6538cf6c252SPaul Traina str.ic_len = len; 6548cf6c252SPaul Traina str.ic_dp = dp; 6558cf6c252SPaul Traina rc = ioctl(fd, I_STR, &str); 6568cf6c252SPaul Traina 6578cf6c252SPaul Traina if (rc < 0) 6588cf6c252SPaul Traina return (rc); 6598cf6c252SPaul Traina else 6608cf6c252SPaul Traina return (str.ic_len); 6618cf6c252SPaul Traina } 6628cf6c252SPaul Traina #endif 6638cf6c252SPaul Traina 6648cf6c252SPaul Traina #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 6658cf6c252SPaul Traina static char * 6668cf6c252SPaul Traina get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 6678cf6c252SPaul Traina { 6688cf6c252SPaul Traina char *cp; 6698cf6c252SPaul Traina static char buf[32]; 6708cf6c252SPaul Traina 6718cf6c252SPaul Traina *majorp = 0; 6728cf6c252SPaul Traina *minorp = 0; 6738cf6c252SPaul Traina *microp = 0; 6748cf6c252SPaul Traina if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 6758cf6c252SPaul Traina return ("?"); 6768cf6c252SPaul Traina cp = buf; 6778cf6c252SPaul Traina if (!isdigit(*cp)) 6788cf6c252SPaul Traina return (buf); 6798cf6c252SPaul Traina *majorp = strtol(cp, &cp, 10); 6808cf6c252SPaul Traina if (*cp++ != '.') 6818cf6c252SPaul Traina return (buf); 6828cf6c252SPaul Traina *minorp = strtol(cp, &cp, 10); 6838cf6c252SPaul Traina if (*cp++ != '.') 6848cf6c252SPaul Traina return (buf); 6858cf6c252SPaul Traina *microp = strtol(cp, &cp, 10); 6868cf6c252SPaul Traina return (buf); 6878cf6c252SPaul Traina } 6888cf6c252SPaul Traina #endif 6898cf6c252SPaul Traina 6908cf6c252SPaul Traina #ifdef DL_HP_PPA_ACK_OBS 6918cf6c252SPaul Traina /* 6928cf6c252SPaul Traina * Under HP-UX 10, we can ask for the ppa 6938cf6c252SPaul Traina */ 6948cf6c252SPaul Traina 6958cf6c252SPaul Traina 6968cf6c252SPaul Traina /* Determine ppa number that specifies ifname */ 6978cf6c252SPaul Traina static int 6988cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *device, register int unit, 6998cf6c252SPaul Traina register char *ebuf) 7008cf6c252SPaul Traina { 7018cf6c252SPaul Traina register dl_hp_ppa_ack_t *ap; 7028cf6c252SPaul Traina register dl_hp_ppa_info_t *ip; 7038cf6c252SPaul Traina register int i; 7048cf6c252SPaul Traina register u_long majdev; 7058cf6c252SPaul Traina dl_hp_ppa_req_t req; 7068cf6c252SPaul Traina struct stat statbuf; 7078cf6c252SPaul Traina bpf_u_int32 buf[MAXDLBUF]; 7088cf6c252SPaul Traina 7098cf6c252SPaul Traina if (stat(device, &statbuf) < 0) { 7108cf6c252SPaul Traina sprintf(ebuf, "stat: %s: %s", device, pcap_strerror(errno)); 7118cf6c252SPaul Traina return (-1); 7128cf6c252SPaul Traina } 7138cf6c252SPaul Traina majdev = major(statbuf.st_rdev); 7148cf6c252SPaul Traina 7158cf6c252SPaul Traina memset((char *)&req, 0, sizeof(req)); 7168cf6c252SPaul Traina req.dl_primitive = DL_HP_PPA_REQ; 7178cf6c252SPaul Traina 7188cf6c252SPaul Traina memset((char *)buf, 0, sizeof(buf)); 7198cf6c252SPaul Traina if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0 || 7208cf6c252SPaul Traina recv_ack(fd, DL_HP_PPA_ACK_SIZE, "hpppa", (char *)buf, ebuf) < 0) 7218cf6c252SPaul Traina return (-1); 7228cf6c252SPaul Traina 7238cf6c252SPaul Traina ap = (dl_hp_ppa_ack_t *)buf; 7248cf6c252SPaul Traina ip = (dl_hp_ppa_info_t *)((u_char *)ap + ap->dl_offset); 7258cf6c252SPaul Traina 7268cf6c252SPaul Traina for(i = 0; i < ap->dl_count; i++) { 7278cf6c252SPaul Traina if (ip->dl_mjr_num == majdev && ip->dl_instance_num == unit) 7288cf6c252SPaul Traina break; 7298cf6c252SPaul Traina 7308cf6c252SPaul Traina ip = (dl_hp_ppa_info_t *)((u_char *)ip + ip->dl_next_offset); 7318cf6c252SPaul Traina } 7328cf6c252SPaul Traina if (i == ap->dl_count) { 7338cf6c252SPaul Traina sprintf(ebuf, "can't find PPA for %s", device); 7348cf6c252SPaul Traina return (-1); 7358cf6c252SPaul Traina } 7368cf6c252SPaul Traina if (ip->dl_hdw_state == HDW_DEAD) { 7378cf6c252SPaul Traina sprintf(ebuf, "%s: hardware state: DOWN\n", device); 7388cf6c252SPaul Traina return (-1); 7398cf6c252SPaul Traina } 7408cf6c252SPaul Traina return ((int)ip->dl_ppa); 7418cf6c252SPaul Traina } 7428cf6c252SPaul Traina #endif 7438cf6c252SPaul Traina 7448cf6c252SPaul Traina #ifdef HAVE_HPUX9 7458cf6c252SPaul Traina /* 7468cf6c252SPaul Traina * Under HP-UX 9, there is no good way to determine the ppa. 7478cf6c252SPaul Traina * So punt and read it from /dev/kmem. 7488cf6c252SPaul Traina */ 7498cf6c252SPaul Traina static struct nlist nl[] = { 7508cf6c252SPaul Traina #define NL_IFNET 0 7518cf6c252SPaul Traina { "ifnet" }, 7528cf6c252SPaul Traina { "" } 7538cf6c252SPaul Traina }; 7548cf6c252SPaul Traina 7558cf6c252SPaul Traina static char path_vmunix[] = "/hp-ux"; 7568cf6c252SPaul Traina 7578cf6c252SPaul Traina /* Determine ppa number that specifies ifname */ 7588cf6c252SPaul Traina static int 7598cf6c252SPaul Traina get_dlpi_ppa(register int fd, register const char *ifname, register int unit, 7608cf6c252SPaul Traina register char *ebuf) 7618cf6c252SPaul Traina { 7628cf6c252SPaul Traina register const char *cp; 7638cf6c252SPaul Traina register int kd; 7648cf6c252SPaul Traina void *addr; 7658cf6c252SPaul Traina struct ifnet ifnet; 7668cf6c252SPaul Traina char if_name[sizeof(ifnet.if_name)], tifname[32]; 7678cf6c252SPaul Traina 7688cf6c252SPaul Traina cp = strrchr(ifname, '/'); 7698cf6c252SPaul Traina if (cp != NULL) 7708cf6c252SPaul Traina ifname = cp + 1; 7718cf6c252SPaul Traina if (nlist(path_vmunix, &nl) < 0) { 7728cf6c252SPaul Traina sprintf(ebuf, "nlist %s failed", path_vmunix); 7738cf6c252SPaul Traina return (-1); 7748cf6c252SPaul Traina } 7758cf6c252SPaul Traina if (nl[NL_IFNET].n_value == 0) { 7768cf6c252SPaul Traina sprintf(ebuf, "could't find %s kernel symbol", 7778cf6c252SPaul Traina nl[NL_IFNET].n_name); 7788cf6c252SPaul Traina return (-1); 7798cf6c252SPaul Traina } 7808cf6c252SPaul Traina kd = open("/dev/kmem", O_RDONLY); 7818cf6c252SPaul Traina if (kd < 0) { 7828cf6c252SPaul Traina sprintf(ebuf, "kmem open: %s", pcap_strerror(errno)); 7838cf6c252SPaul Traina return (-1); 7848cf6c252SPaul Traina } 7858cf6c252SPaul Traina if (dlpi_kread(kd, nl[NL_IFNET].n_value, 7868cf6c252SPaul Traina &addr, sizeof(addr), ebuf) < 0) { 7878cf6c252SPaul Traina close(kd); 7888cf6c252SPaul Traina return (-1); 7898cf6c252SPaul Traina } 7908cf6c252SPaul Traina for (; addr != NULL; addr = ifnet.if_next) { 7918cf6c252SPaul Traina if (dlpi_kread(kd, (off_t)addr, 7928cf6c252SPaul Traina &ifnet, sizeof(ifnet), ebuf) < 0 || 7938cf6c252SPaul Traina dlpi_kread(kd, (off_t)ifnet.if_name, 7948cf6c252SPaul Traina if_name, sizeof(if_name), ebuf) < 0) { 7958cf6c252SPaul Traina (void)close(kd); 7968cf6c252SPaul Traina return (-1); 7978cf6c252SPaul Traina } 7988cf6c252SPaul Traina sprintf(tifname, "%.*s%d", 7998cf6c252SPaul Traina (int)sizeof(if_name), if_name, ifnet.if_unit); 8008cf6c252SPaul Traina if (strcmp(tifname, ifname) == 0) 8018cf6c252SPaul Traina return (ifnet.if_index); 8028cf6c252SPaul Traina } 8038cf6c252SPaul Traina 8048cf6c252SPaul Traina sprintf(ebuf, "Can't find %s", ifname); 8058cf6c252SPaul Traina return (-1); 8068cf6c252SPaul Traina } 8078cf6c252SPaul Traina 8088cf6c252SPaul Traina static int 8098cf6c252SPaul Traina dlpi_kread(register int fd, register off_t addr, 8108cf6c252SPaul Traina register void *buf, register u_int len, register char *ebuf) 8118cf6c252SPaul Traina { 8128cf6c252SPaul Traina register int cc; 8138cf6c252SPaul Traina 8148cf6c252SPaul Traina if (lseek(fd, addr, L_SET) < 0) { 8158cf6c252SPaul Traina sprintf(ebuf, "lseek: %s", pcap_strerror(errno)); 8168cf6c252SPaul Traina return (-1); 8178cf6c252SPaul Traina } 8188cf6c252SPaul Traina cc = read(fd, buf, len); 8198cf6c252SPaul Traina if (cc < 0) { 8208cf6c252SPaul Traina sprintf(ebuf, "read: %s", pcap_strerror(errno)); 8218cf6c252SPaul Traina return (-1); 8228cf6c252SPaul Traina } else if (cc != len) { 8238cf6c252SPaul Traina sprintf(ebuf, "short read (%d != %d)", cc, len); 8248cf6c252SPaul Traina return (-1); 8258cf6c252SPaul Traina } 8268cf6c252SPaul Traina return (cc); 8278cf6c252SPaul Traina } 8288cf6c252SPaul Traina #endif 829