1511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 2511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 1993, 1994, 1995, 1996, 1997 3511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * The Regents of the University of California. All rights reserved. 4511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 5511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Redistribution and use in source and binary forms, with or without 6511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * modification, are permitted provided that: (1) source code distributions 7511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * retain the above copyright notice and this paragraph in its entirety, (2) 8511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * distributions including binary code include the above copyright notice and 9511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * this paragraph in its entirety in the documentation or other materials 10511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * provided with the distribution, and (3) all advertising materials mentioning 11511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * features or use of this software display the following acknowledgement: 12511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * ``This product includes software developed by the University of California, 13511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the University nor the names of its contributors may be used to endorse 15511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * or promote products derived from this software without specific prior 16511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * written permission. 17511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 21511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * This code contributed by Sagun Shakya (sagun.shakya@sun.com) 22511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 23511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 24511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Packet capture routines for DLPI using libdlpi under SunOS 5.11. 25511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 26511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 27511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_CONFIG_H 28511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "config.h" 29511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif 30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/types.h> 32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/time.h> 33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/bufmod.h> 34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/stream.h> 35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <libdlpi.h> 36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <errno.h> 37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <memory.h> 38511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stropts.h> 39511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdio.h> 40511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdlib.h> 41511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <string.h> 42511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 43511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-int.h" 44511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "dlpisubs.h" 45511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* Forwards. */ 47511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int dlpromiscon(pcap_t *, bpf_u_int32); 48511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *); 49511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_inject_libdlpi(pcap_t *, const void *, size_t); 50511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_libdlpi_err(const char *, const char *, int, char *); 51511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_cleanup_libdlpi(pcap_t *); 52511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 53511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 54511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * list_interfaces() will list all the network links that are 55511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * available on a system. 56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 57511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic boolean_t list_interfaces(const char *, void *); 58511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 59511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralltypedef struct linknamelist { 60511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall char linkname[DLPI_LINKNAME_MAX]; 61511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct linknamelist *lnl_next; 62511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} linknamelist_t; 63511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 64511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralltypedef struct linkwalk { 65511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall linknamelist_t *lw_list; 66511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int lw_err; 67511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} linkwalk_t; 68511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 69511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 70511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * The caller of this function should free the memory allocated 71511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * for each linknamelist_t "entry" allocated. 72511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 73511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic boolean_t 74511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralllist_interfaces(const char *linkname, void *arg) 75511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 76511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall linkwalk_t *lwp = arg; 77511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall linknamelist_t *entry; 78511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 79511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) { 80511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall lwp->lw_err = ENOMEM; 81511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (B_TRUE); 82511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 83511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall (void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX); 84511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 85511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (lwp->lw_list == NULL) { 86511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall lwp->lw_list = entry; 87511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else { 88511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall entry->lnl_next = lwp->lw_list; 89511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall lwp->lw_list = entry; 90511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 91511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 92511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (B_FALSE); 93511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 94511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 95511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 96511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_activate_libdlpi(pcap_t *p) 97511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 98511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_dlpi *pd = p->priv; 99d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes int status = 0; 100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int retv; 101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dlpi_handle_t dh; 102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dlpi_info_t dlinfo; 103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Enable Solaris raw and passive DLPI extensions; 106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * dlpi_open() will not fail if the underlying link does not support 107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * passive mode. See dlpi(7P) for details. 108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 109965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE); 110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv != DLPI_SUCCESS) { 111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) 112d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR_NO_SUCH_DEVICE; 113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall else if (retv == DL_SYSERR && 114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall (errno == EPERM || errno == EACCES)) 115d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR_PERM_DENIED; 116d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes else 117d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 118965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_libdlpi_err(p->opt.device, "dlpi_open", retv, 119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->errbuf); 120d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes return (status); 121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pd->dlpi_hd = dh; 123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p->opt.rfmon) { 125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * This device exists, but we don't support monitor mode 127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * any platforms that support DLPI. 128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 129d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR_RFMON_NOTSUP; 130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Bind with DLPI_ANY_SAP. */ 134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { 135d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 136965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_libdlpi_err(p->opt.device, "dlpi_bind", retv, p->errbuf); 137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Enable promiscuous mode. */ 141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p->opt.promisc) { 142d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes retv = dlpromiscon(p, DL_PROMISC_PHYS); 143d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (retv < 0) { 144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "You don't have permission to capture on 146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * this device" and "you don't have permission 147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * to capture in promiscuous mode on this 148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * device" are different; let the user know, 149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * so if they can't get permission to 150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * capture in promiscuous mode, they can at 151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * least try to capture in non-promiscuous 152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * mode. 153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * XXX - you might have to capture in 155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * promiscuous mode to see outgoing packets. 156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 157d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (retv == PCAP_ERROR_PERM_DENIED) 158d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR_PROMISC_PERM_DENIED; 159d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes else 160d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = retv; 161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } else { 164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Try to enable multicast. */ 165d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes retv = dlpromiscon(p, DL_PROMISC_MULTI); 166d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (retv < 0) { 167d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = retv; 168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 169d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes } 170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Try to enable SAP promiscuity. */ 173d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes retv = dlpromiscon(p, DL_PROMISC_SAP); 174d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (retv < 0) { 175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Not fatal, since the DL_PROMISC_PHYS mode worked. 177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Report it as a warning, however. 178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p->opt.promisc) 180d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_WARNING; 181d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes else { 182d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = retv; 183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 184d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes } 185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Determine link type. */ 188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { 189d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 190965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_libdlpi_err(p->opt.device, "dlpi_info", retv, p->errbuf); 191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 194d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) { 195d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 197d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes } 198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->fd = dlpi_fd(pd->dlpi_hd); 200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Push and configure bufmod. */ 202d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (pcap_conf_bufmod(p, p->snapshot) != 0) { 203d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 205d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes } 206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Flush the read side. 209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 211d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 212965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_strerror(errno)); 214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Allocate data buffer. */ 218d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes if (pcap_alloc_databuf(p) != 0) { 219d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes status = PCAP_ERROR; 220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto bad; 221d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes } 222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "p->fd" is a FD for a STREAMS device, so "select()" and 225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "poll()" should work on it. 226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->selectable_fd = p->fd; 228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->read_op = pcap_read_libdlpi; 230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->inject_op = pcap_inject_libdlpi; 231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->setfilter_op = install_bpf_program; /* No kernel filtering */ 232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->setdirection_op = NULL; /* Not implemented */ 233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->set_datalink_op = NULL; /* Can't change data link type */ 234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->getnonblock_op = pcap_getnonblock_fd; 235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->setnonblock_op = pcap_setnonblock_fd; 236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->stats_op = pcap_stats_dlpi; 237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->cleanup_op = pcap_cleanup_libdlpi; 238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 239d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes return (status); 240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallbad: 241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_cleanup_libdlpi(p); 242d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes return (status); 243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define STRINGIFY(n) #n 246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralldlpromiscon(pcap_t *p, bpf_u_int32 level) 249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_dlpi *pd = p->priv; 251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int retv; 252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int err; 253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv = dlpi_promiscon(pd->dlpi_hd, level); 255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv != DLPI_SUCCESS) { 256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv == DL_SYSERR && 257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall (errno == EPERM || errno == EACCES)) 258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall err = PCAP_ERROR_PERM_DENIED; 259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall else 260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall err = PCAP_ERROR; 261965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_libdlpi_err(p->opt.device, "dlpi_promiscon" STRINGIFY(level), 262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv, p->errbuf); 263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (err); 264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (0); 266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 269965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes * Presumably everything returned by dlpi_walk() is a DLPI device, 270965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes * so there's no work to be done here to check whether name refers 271965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes * to a DLPI device. 272965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes */ 273965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughesstatic int 274965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughesis_dlpi_interface(const char *name _U_) 275965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes{ 276965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes return (1); 277965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes} 278965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes 279965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes/* 280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find 281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * network links that are plumbed and are up. dlpi_walk(3DLPI) will find 282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * additional network links present in the system. 283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint 285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int retv = 0; 288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall linknamelist_t *entry, *next; 290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall linkwalk_t lw = {NULL, 0}; 291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int save_errno; 292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 293965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes /* 294965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes * Get the list of regular interfaces first. 295965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes */ 296965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1) 297965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes return (-1); /* failure */ 298965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes 299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* dlpi_walk() for loopback will be added here. */ 300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dlpi_walk(list_interfaces, &lw, 0); 302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (lw.lw_err != 0) { 304965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall "dlpi_walk: %s", pcap_strerror(lw.lw_err)); 306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv = -1; 307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto done; 308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Add linkname if it does not exist on the list. */ 311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) { 312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0) 313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv = -1; 314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralldone: 316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall save_errno = errno; 317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall for (entry = lw.lw_list; entry != NULL; entry = next) { 318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall next = entry->lnl_next; 319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall free(entry); 320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall errno = save_errno; 322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (retv); 324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Read data received on DLPI handle. Returns -2 if told to terminate, else 328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * returns the number of packets read. 329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) 332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_dlpi *pd = p->priv; 334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int len; 335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall u_char *bufp; 336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall size_t msglen; 337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int retv; 338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len = p->cc; 340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (len != 0) { 341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall bufp = p->bp; 342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall goto process_pkts; 343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall do { 345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* Has "pcap_breakloop()" been called? */ 346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p->break_loop) { 347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Yes - clear the flag that indicates that it has, 349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * and return -2 to indicate that we were told to 350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * break out of the loop. 351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->break_loop = 0; 353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (-2); 354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall msglen = p->bufsize; 357965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes bufp = (u_char *)p->buffer + p->offset; 358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp, 360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall &msglen, -1, NULL); 361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv != DLPI_SUCCESS) { 362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * This is most likely a call to terminate out of the 364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * loop. So, do not return an error message, instead 365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * check if "pcap_breakloop()" has been called above. 366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv == DL_SYSERR && errno == EINTR) { 368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len = 0; 369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall continue; 370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), 372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall "dlpi_recv", retv, p->errbuf); 373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (-1); 374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall len = msglen; 376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } while (len == 0); 377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallprocess_pkts: 379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (pcap_process_pkts(p, callback, user, count, bufp, len)); 380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int 383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size) 384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_dlpi *pd = p->priv; 386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall int retv; 387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL); 389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (retv != DLPI_SUCCESS) { 390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv, 391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->errbuf); 392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (-1); 393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* 395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * dlpi_send(3DLPI) does not provide a way to return the number of 396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was 397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * returned we are assuming 'size' bytes were sent. 398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (size); 400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Close dlpi handle. 404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void 406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_cleanup_libdlpi(pcap_t *p) 407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall struct pcap_dlpi *pd = p->priv; 409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (pd->dlpi_hd != NULL) { 411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall dlpi_close(pd->dlpi_hd); 412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pd->dlpi_hd = NULL; 413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->fd = -1; 414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall } 415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_cleanup_live_common(p); 416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* 419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Write error message to buffer. 420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */ 421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void 422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf) 423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 424965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s", 425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall func, linkname, dlpi_strerror(err)); 426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_t * 429965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughespcap_create_interface(const char *device _U_, char *ebuf) 430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{ 431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall pcap_t *p; 432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 433965a4b5291eead2d8f826d2c87e58a12bb56a214Elliott Hughes p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi)); 434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall if (p == NULL) 435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (NULL); 436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall 437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall p->activate_op = pcap_activate_libdlpi; 438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall return (p); 439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} 440