* could be opened.
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
struct ifaddrs *ifap, *ifa;
return (-1);
}
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, we assume it's a logical interface. Those
+ * are just the way you assign multiple IP addresses to
+ * a real interface on Linux, so an entry for a logical
+ * interface should be treated like the entry for the
+ * real interface; we do that by stripping off the ":"
+ * and the number.
+ *
+ * XXX - should we do this only on Linux?
+ */
+ p = strchr(ifa->ifa_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifa->ifa_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
/*
* "ifa_addr" was apparently null on at least one
* interface on some system. Therefore, we supply
dstaddr_size = 0;
}
- /*
- * If this entry has a colon followed by a number at
- * the end, we assume it's a logical interface. Those
- * are just the way you assign multiple IP addresses to
- * a real interface on Linux, so an entry for a logical
- * interface should be treated like the entry for the
- * real interface; we do that by stripping off the ":"
- * and the number.
- *
- * XXX - should we do this only on Linux?
- */
- p = strchr(ifa->ifa_name, ':');
- if (p != NULL) {
- /*
- * We have a ":"; is it followed by a number?
- */
- q = p + 1;
- while (isdigit((unsigned char)*q))
- q++;
- if (*q == '\0') {
- /*
- * All digits after the ":" until the end.
- * Strip off the ":" and everything after
- * it.
- */
- *p = '\0';
- }
- }
-
/*
* Add information for this address to the list.
*/
* we already have that.
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
register int fd;
if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
continue;
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifrp->ifr_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
/*
* Get the flags for this interface.
*/
* SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
*/
int
-pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
+pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf,
+ int (*check_usable)(const char *))
{
pcap_if_t *devlist = NULL;
register int fd4, fd6, fd;
ifend = (struct lifreq *)(buf + ifc.lifc_len);
for (; ifrp < ifend; ifrp++) {
- /*
- * IPv6 or not?
- */
- if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
- fd = fd6;
- else
- fd = fd4;
-
/*
* Skip entries that begin with "dummy".
* XXX - what are these? Is this Linux-specific?
}
#endif
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifrp->lifr_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
+ * IPv6 or not?
+ */
+ if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
+ fd = fd6;
+ else
+ fd = fd4;
+
/*
* Get the flags for this interface.
*/
* On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
*/
static int
-bpf_open(pcap_t *p)
+bpf_open(char *errbuf)
{
int fd;
#ifdef HAVE_CLONING_BPF
* and create the BPF device entries, if they don't
* already exist.
*/
- if (bpf_load(p->errbuf) == PCAP_ERROR)
+ if (bpf_load(errbuf) == PCAP_ERROR)
return (PCAP_ERROR);
#endif
fd = PCAP_ERROR_PERM_DENIED;
else
fd = PCAP_ERROR;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open device) %s: %s", device, pcap_strerror(errno));
}
#else
* means we probably have no BPF
* devices.
*/
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(there are no BPF devices)");
} else {
/*
* devices, but all the ones
* that exist are busy.
*/
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(all BPF devices are busy)");
}
break;
* if any.
*/
fd = PCAP_ERROR_PERM_DENIED;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
* Some other problem.
*/
fd = PCAP_ERROR;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
return (fd);
}
+/*
+ * Open and bind to a device; used if we're not actually going to use
+ * the device, but are just testing whether it can be opened, or opening
+ * it to get information about it.
+ *
+ * Returns an error code on failure (always negative), and an FD for
+ * the now-bound BPF device on success (always non-negative).
+ */
+static int
+bpf_open_and_bind(const char *name, char *errbuf)
+{
+ int fd;
+ struct ifreq ifr;
+
+ fd = bpf_open(errbuf);
+ if (fd < 0)
+ return (fd); /* fd is the appropriate error code */
+
+ /*
+ * Now bind to the device.
+ */
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(fd);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case ENETDOWN:
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * Success.
+ */
+ return (fd);
+}
+
#ifdef BIOCGDLTLIST
static int
get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
*
* First, open a BPF device.
*/
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0)
return (fd); /* fd is the appropriate error code */
u_int bufmode, zbufmax;
#endif
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0) {
status = fd;
goto bad;
}
/*
- * We might have USB sniffing support, so try looking for USB interfaces.
+ * Not all interfaces can be bound to by BPF, so try to bind to
+ * the specified interface; return 0 if we fail with
+ * PCAP_ERROR_NO_SUCH_DEVICE (which means we got an ENXIO when we tried
+ * to bind, which means this interface isn't in the list of interfaces
+ * attached to BPF) and 1 otherwise.
*/
+static int
+check_bpf_bindable(const char *name)
+{
+ int fd;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = bpf_open_and_bind(name, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't bind to this because it's
+ * not something supported by BPF.
+ */
+ return (0);
+ }
+ /*
+ * No, so we don't know whether it's supported or not;
+ * say it is, so that the user can at least try to
+ * open it and report the error (which is probably
+ * "you don't have permission to open BPF devices";
+ * reporting those interfaces means users will ask
+ * "why am I getting a permissions error when I try
+ * to capture" rather than "why am I not seeing any
+ * interfaces", making the underlying problem clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
/*
* Get the list of regular interfaces first.
*/
- if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, check_bpf_bindable) == -1)
return (-1); /* failure */
#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
/*
+ * We might have USB sniffing support, so try looking for USB
+ * interfaces.
+ *
* We want to report a usbusN device for each USB bus, but
* usbusN interfaces might, or might not, exist for them -
* we create one if there isn't already one.
}
static int
-pcap_activate_dlpi(pcap_t *p)
+open_dlpi_device(const char *name, int *ppa, char *errbuf)
{
-#ifdef DL_HP_RAWDLS
- struct pcap_dlpi *pd = p->priv;
-#endif
- int status = 0;
- int retv;
- register char *cp;
- int ppa;
-#ifdef HAVE_SOLARIS
- int isatm = 0;
-#endif
- register dl_info_ack_t *infop;
-#ifdef HAVE_SYS_BUFMOD_H
- bpf_u_int32 ss;
-#ifdef HAVE_SOLARIS
- register char *release;
- bpf_u_int32 osmajor, osminor, osmicro;
-#endif
-#endif
- bpf_u_int32 buf[MAXDLBUF];
+ int status;
char dname[100];
+ char *cp;
+ int fd;
#ifndef HAVE_DEV_DLPI
char dname2[100];
#endif
/*
** Remove any "/dev/" on the front of the device.
*/
- cp = strrchr(p->opt.source, '/');
+ cp = strrchr(name, '/');
if (cp == NULL)
- strlcpy(dname, p->opt.source, sizeof(dname));
+ strlcpy(dname, name, sizeof(dname));
else
strlcpy(dname, cp + 1, sizeof(dname));
* Split the device name into a device type name and a unit number;
* chop off the unit number, so "dname" is just a device type name.
*/
- cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL) {
- status = PCAP_ERROR_NO_SUCH_DEVICE;
- goto bad;
- }
+ cp = split_dname(dname, ppa, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
*cp = '\0';
/*
* device number, rather than hardwiring "/dev/dlpi".
*/
cp = "/dev/dlpi";
- if ((p->fd = open(cp, O_RDWR)) < 0) {
+ if ((fd = open(cp, O_RDWR)) < 0) {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"%s: %s", cp, pcap_strerror(errno));
- goto bad;
+ return (status);
}
-#ifdef DL_HP_RAWDLS
- /*
- * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
- * receiving packets on the same descriptor - you need separate
- * descriptors for sending and receiving, bound to different SAPs.
- *
- * If the open fails, we just leave -1 in "pd->send_fd" and reject
- * attempts to send packets, just as if, in pcap-bpf.c, we fail
- * to open the BPF device for reading and writing, we just try
- * to open it for reading only and, if that succeeds, just let
- * the send attempts fail.
- */
- pd->send_fd = open(cp, O_RDWR);
-#endif
-
/*
* Get a table of all PPAs for that device, and search that
* table for the specified device type name and unit number.
*/
- ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
+ *ppa = get_dlpi_ppa(fd, dname, *ppa, errbuf);
if (ppa < 0) {
- status = ppa;
- goto bad;
+ close(fd);
+ return (ppa);
}
#else
/*
* otherwise, concatenate the device directory name and the
* device name.
*/
- if (*p->opt.source == '/')
- strlcpy(dname, p->opt.source, sizeof(dname));
+ if (*name == '/')
+ strlcpy(dname, name, sizeof(dname));
else
pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
- p->opt.source);
+ name);
/*
* Get the unit number, and a pointer to the end of the device
* type name.
*/
- cp = split_dname(dname, &ppa, p->errbuf);
- if (cp == NULL) {
- status = PCAP_ERROR_NO_SUCH_DEVICE;
- goto bad;
- }
+ cp = split_dname(dname, ppa, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
/*
* Make a copy of the device pathname, and then remove the unit
*cp = '\0';
/* Try device without unit number */
- if ((p->fd = open(dname, O_RDWR)) < 0) {
+ if ((fd = open(dname, O_RDWR)) < 0) {
if (errno != ENOENT) {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
pcap_strerror(errno));
- goto bad;
+ return (status);
}
/* Try again with unit number */
- if ((p->fd = open(dname2, O_RDWR)) < 0) {
+ if ((fd = open(dname2, O_RDWR)) < 0) {
if (errno == ENOENT) {
status = PCAP_ERROR_NO_SUCH_DEVICE;
* found" with the device name, so people
* don't get confused and think, for example,
* that if they can't capture on "lo0"
- * on Solaris the fix is to change libpcap
- * (or the application that uses it) to
- * look for something other than "/dev/lo0",
- * as the fix is to look for an operating
- * system other than Solaris - you just
- * *can't* capture on a loopback interface
- * on Solaris, the lack of a DLPI device
- * for the loopback interface is just a
- * symptom of that inability.
+ * on Solaris prior to Solaris 11 the fix
+ * is to change libpcap (or the application
+ * that uses it) to look for something other
+ * than "/dev/lo0", as the fix is to use
+ * Solaris 11 or some operating system
+ * other than Solaris - you just *can't*
+ * capture on a loopback interface
+ * on Solaris prior to Solaris 11, the lack
+ * of a DLPI device for the loopback
+ * interface is just a symptom of that
+ * inability.
*/
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "%s: No DLPI device found", p->opt.source);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No DLPI device found", name);
} else {
if (errno == EPERM || errno == EACCES)
status = PCAP_ERROR_PERM_DENIED;
else
status = PCAP_ERROR;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
dname2, pcap_strerror(errno));
}
- goto bad;
+ return (status);
}
/* XXX Assume unit zero */
- ppa = 0;
+ *ppa = 0;
}
#endif
+ return (fd);
+}
+
+static int
+pcap_activate_dlpi(pcap_t *p)
+{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+#endif
+ int status = 0;
+ int retv;
+ int ppa;
+#ifdef HAVE_SOLARIS
+ int isatm = 0;
+#endif
+ register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+ bpf_u_int32 ss;
+#ifdef HAVE_SOLARIS
+ register char *release;
+ bpf_u_int32 osmajor, osminor, osmicro;
+#endif
+#endif
+ bpf_u_int32 buf[MAXDLBUF];
+
+ p->fd = open_dlpi_device(p->opt.source, &ppa, p->errbuf);
+ if (p->fd < 0) {
+ status = p->fd;
+ goto bad;
+ }
+
+#ifdef DL_HP_RAWDLS
+ /*
+ * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
+ * receiving packets on the same descriptor - you need separate
+ * descriptors for sending and receiving, bound to different SAPs.
+ *
+ * If the open fails, we just leave -1 in "pd->send_fd" and reject
+ * attempts to send packets, just as if, in pcap-bpf.c, we fail
+ * to open the BPF device for reading and writing, we just try
+ * to open it for reading only and, if that succeeds, just let
+ * the send attempts fail.
+ */
+ pd->send_fd = open("/dev/dlpi", O_RDWR);
+#endif
/*
** Attach if "style 2" provider
return (0);
}
+/*
+ * Not all interfaces are DLPI interfaces, and thus not all interfaces
+ * can be opened with DLPI (for example, the loopback interface is not
+ * a DLPI interface on Solaris prior to Solaris 11), so try to open
+ * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
+ * and 1 otherwise.
+ */
+static int
+is_dlpi_interface(const char *name)
+{
+ int fd;
+ int ppa;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = open_dlpi_device(name, &ppa, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't open this because it's
+ * not a DLPI interface.
+ */
+ return (0);
+ }
+ /*
+ * No, so, in the case where there's a single DLPI
+ * device for all interfaces of this type ("style
+ * 2" providers?), we don't know whether it's a DLPI
+ * interface or not, as we didn't try an attach.
+ * Say it is a DLPI device, so that the user can at
+ * least try to open it and report the error (which
+ * is probably "you don't have permission to open that
+ * DLPI device"; reporting those interfaces means
+ * users will ask "why am I getting a permissions error
+ * when I try to capture" rather than "why am I not
+ * seeing any interfaces", making the underlying problem
+ * clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
/*
* Get the list of regular interfaces first.
*/
- if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
return (-1); /* failure */
#ifdef HAVE_SOLARIS
*/
int pcap_platform_finddevs(pcap_if_t **, char *);
#if !defined(_WIN32) && !defined(MSDOS)
-int pcap_findalldevs_interfaces(pcap_if_t **, char *);
+int pcap_findalldevs_interfaces(pcap_if_t **, char *,
+ int (*)(const char *));
#endif
int add_addr_to_iflist(pcap_if_t **, const char *, bpf_u_int32,
struct sockaddr *, size_t, struct sockaddr *, size_t,
return (0);
}
+/*
+ * Presumably everything returned by dlpi_walk() is a DLPI device,
+ * so there's no work to be done here to check whether name refers
+ * to a DLPI device.
+ */
+static int
+is_dlpi_interface(const char *name _U_)
+{
+ return (1);
+}
+
/*
* In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
* network links that are plumbed and are up. dlpi_walk(3DLPI) will find
/*
* Get the list of regular interfaces first.
*/
- if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, is_dlpi_interface) == -1)
return (-1); /* failure */
/* dlpi_walk() for loopback will be added here. */
*/
static const char any_descr[] = "Pseudo-device that captures on all interfaces";
+/*
+ * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
/*
* Get the list of regular interfaces first.
*/
- if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound) == -1)
return (-1); /* failure */
/*
(void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ);
if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support NIT";
+ * they might be the same error, if they both end up
+ * meaning "NIT doesn't know about that device".
+ */
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
goto bad;
return (p);
}
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support NIT"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (pcap_findalldevs_interfaces(alldevsp, errbuf));
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
* its argument, even though it takes a "char *" rather than a
* "const char *" as its first argument. That appears to be
* the case, at least on Digital UNIX 4.0.
+ *
+ * XXX - is there an error that means "no such device"? Is
+ * there one that means "that device doesn't support pf"?
*/
p->fd = pfopen(p->opt.source, O_RDWR);
if (p->fd == -1 && errno == EACCES)
return (p);
}
+/*
+ * XXX - is there an error from pfopen() that means "no such device"?
+ * Is there one that means "that device doesn't support pf"?
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (pcap_findalldevs_interfaces(alldevsp, errbuf));
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
static int
si.ic_len = sizeof(ifr);
si.ic_dp = (char *)𝔦
if (ioctl(fd, I_STR, (char *)&si) < 0) {
+ /*
+ * XXX - is there an error that means "no such device"?
+ * Is there one that means "that device doesn't support
+ * STREAMS NIT"?
+ */
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
ifr.ifr_name, pcap_strerror(errno));
goto bad;
return (p);
}
+/*
+ * XXX - there's probably a NIOCBIND error that means "that device
+ * doesn't support NIT"; if so, we should try an NIOCBIND and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (pcap_findalldevs_interfaces(alldevsp, errbuf));
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}
sr.sr_family = AF_RAW;
(void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support snoop";
+ * they might be the same error, if they both end up
+ * meaning "snoop doesn't know about that device".
+ */
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
pcap_strerror(errno));
goto bad;
return (p);
}
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support snoop"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- return (pcap_findalldevs_interfaces(alldevsp, errbuf));
+ return (pcap_findalldevs_interfaces(alldevsp, errbuf, can_be_bound));
}