#include <string.h>
#include <unistd.h>
-#ifdef HAVE_NET_IF_MEDIA_H
+#ifdef SIOCGIFMEDIA
# include <net/if_media.h>
#endif
}
#endif
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+#ifdef SIOCGIFMEDIA
+int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ int sock;
+ struct ifmediareq req;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "Can't create socket to get media information for %s",
+ name);
+ return (-1);
+ }
+ memset(&req, 0, sizeof(req));
+ strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ if (errno == EOPNOTSUPP) {
+ /*
+ * Not supported, so we can't provide any
+ * additional information. Assume that
+ * this means that "connected" vs.
+ * "disconnected" doesn't apply.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ close(sock);
+ return (0);
+ }
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFMEDIA on %s failed", name);
+ close(sock);
+ return (-1);
+ }
+ close(sock);
+
+ /*
+ * OK, what type of network is this?
+ */
+ switch (IFM_TYPE(req.ifm_active)) {
+
+ case IFM_IEEE80211:
+ /*
+ * Wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+
+ /*
+ * Do we know whether it's connected?
+ */
+ if (req.ifm_status & IFM_AVALID) {
+ /*
+ * Yes.
+ */
+ if (req.ifm_status & IFM_ACTIVE) {
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ } else {
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ }
+ }
+ return (0);
+}
+#else
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ */
+ return (0);
+}
+#endif
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
pcap_snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
pcap_snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
- if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
+ /*
+ * Bluetooth is a wireless technology.
+ * XXX - if there's the notion of associating with a
+ * network, and we can determine whether the interface
+ * is associated with a network, check that and set
+ * the status to PCAP_IF_CONNECTION_STATUS_CONNECTED
+ * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+ */
+ if (add_dev(devlistp, dev_name, PCAP_IF_WIRELESS, dev_descr, err_str) == NULL)
{
ret = -1;
break;
}
-
}
free:
dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
{
char name[12]; /* XXX - pick a size */
- int ret = 0;
int c;
char dagname[DAGNAME_BUFSIZE];
int dagstream;
{
(void) pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"dag: device name %s can't be parsed", name);
- return -1;
+ return (-1);
}
if ( (dagfd = dag_open(dagname)) >= 0 ) {
description = NULL;
if ((inf = dag_pciinfo(dagfd)))
description = dag_device_name(inf->device_code, 1);
+ /*
+ * XXX - is there a way to determine whether
+ * the card is plugged into a network or not?
+ * If so, we should check that and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+ *
+ * Also, are there notions of "up" and "running"?
+ */
if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
/*
* Failure.
*/
- ret = -1;
+ return (-1);
}
rxstreams = dag_rx_get_stream_count(dagfd);
for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
/*
* Failure.
*/
- ret = -1;
+ return (-1);
}
rxstreams--;
}
}
- return (ret);
+ return (0);
}
/*
int
dbus_findalldevs(pcap_if_list_t *devlistp, char *err_str)
{
- if (add_dev(devlistp, "dbus-system", 0, "D-Bus system bus", err_str) == NULL)
+ /*
+ * The notion of "connected" vs. "disconnected" doesn't apply.
+ * XXX - what about the notions of "up" and "running"?
+ */
+ if (add_dev(devlistp, "dbus-system",
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus system bus",
+ err_str) == NULL)
return -1;
- if (add_dev(devlistp, "dbus-session", 0, "D-Bus session bus", err_str) == NULL)
+ if (add_dev(devlistp, "dbus-session",
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus session bus",
+ err_str) == NULL)
return -1;
return 0;
}
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
}
for (i = 0; i < buf.nunits; i++) {
pcap_snprintf(baname, sizeof baname, "ba%u", i);
+ /*
+ * XXX - is there a notion of "up" and "running"?
+ * And is there a way to determine whether the
+ * interface is plugged into a network?
+ */
if (add_dev(devlistp, baname, 0, NULL, errbuf) == NULL)
return (-1);
}
/*
* XXX - find out whether it's up or running? Does that apply here?
+ * Can we find out if anything's plugged into the adapter, if it's
+ * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
+ * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
*/
if ((curdev = add_dev(devlistp, dev->name, 0,
dev->long_name, errbuf)) == NULL)
*
* "find_or_add_dev()" checks whether a device is already in a pcap_if_list_t
* and, if not, adds an entry for it.
+ *
+ * "get_if_flags()" is the platform-dependent routine to get additional
+ * pcap flags for an interface.
*/
struct pcap_if_list;
typedef struct pcap_if_list pcap_if_list_t;
int pcap_platform_finddevs(pcap_if_list_t *, char *);
+int get_if_flags(const char *name, bpf_u_int32 *, char *);
#if !defined(_WIN32) && !defined(MSDOS)
int pcap_findalldevs_interfaces(pcap_if_list_t *, char *,
int (*)(const char *));
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
/*
* In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
* network links that are plumbed and are up. dlpi_walk(3DLPI) will find
return (1);
}
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ int sock;
+ char *pathstr;
+ FILE *fh;
+ unsigned int arptype;
+ struct ifreq ifr;
+ struct ethtool_value info;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "Can't create socket to get ethtool information for %s",
+ name);
+ return -1;
+ }
+
+ /*
+ * OK, what type of network is this?
+ * In particular, is it wired or wireless?
+ */
+ if (is_wifi(sock, name)) {
+ /*
+ * Wi-Fi, hence wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ } else {
+ /*
+ * OK, what does /sys/class/net/{if}/type contain?
+ * (We don't use that for Wi-Fi, as it'll report
+ * "Ethernet", i.e. ARPHRD_ETHER, for non-monitor-
+ * mode devices.)
+ */
+ if (asprintf(&pathstr, "/sys/class/net/%s/type", name) == -1) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Can't generate path name string for /sys/class/net device",
+ device);
+ close(sock);
+ return -1;
+ }
+ fh = fopen(pathstr, "r");
+ if (fh != NULL) {
+ if (scanf(fh, "%u", &arptype) == 1) {
+ /*
+ * OK, we got an ARPHRD_ type; what is it?
+ */
+ switch (arptype) {
+
+ case ARPHRD_LOOPBACK;
+ /*
+ * These are types to which
+ * "connected" and "disconnected"
+ * don't apply, so don't bother
+ * asking about it.
+ *
+ * XXX - add other types?
+ */
+ close(sock);
+ return 0;
+
+ case ARPHRD_IRDA:
+ case ARPHRD_IEEE80211:
+ case ARPHRD_IEEE80211_PRISM:
+ case ARPHRD_IEEE80211_RADIOTAP:
+ case ARPHRD_IEEE802154:
+ case ARPHRD_IEEE802154_MONITOR:
+ case ARPHRD_6LOWPAN:
+ /*
+ * Various wireless types.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+ }
+ fclose(fh);
+ }
+ }
+ free(pathstr);
+
+#ifdef ETHTOOL_GLINK
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ info.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (caddr_t)&info;
+ if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) {
+ int save_errno = errno;
+
+ switch (save_errno) {
+
+ case EOPNOTSUPP:
+ case EINVAL:
+ /*
+ * OK, this OS version or driver doesn't support
+ * asking for this information.
+ * XXX - distinguish between "this doesn't
+ * support ethtool at all because it's not
+ * that type of device" vs. "this doesn't
+ * support ethtool even though it's that
+ * type of device", and return "unknown".
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ close(sock);
+ return 0;
+
+ case ENODEV:
+ /*
+ * OK, no such device.
+ * The user will find that out when they try to
+ * activate the device; just say "OK" and
+ * don't set anything.
+ */
+ close(sock);
+ return 0;
+
+ default:
+ /*
+ * Other error.
+ */
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ save_errno,
+ "%s: SIOCETHTOOL(ETHTOOL_GLINK) ioctl failed",
+ device);
+ close(sock);
+ return -1;
+ }
+ }
+
+ /*
+ * Is it connected?
+ */
+ if (info.data) {
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ } else {
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ }
+#endif
+
+ close(sock);
+ return 0;
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
/*
* Add the "any" device.
+ * As it refers to all network devices, not to any particular
+ * network device, the notion of "connected" vs. "disconnected"
+ * doesn't apply.
*/
- if (add_dev(devlistp, "any", PCAP_IF_UP|PCAP_IF_RUNNING,
+ if (add_dev(devlistp, "any",
+ PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
any_descr, errbuf) == NULL)
return (-1);
}
close(sock);
- if (add_dev(devlistp, NFLOG_IFACE, 0, "Linux netfilter log (NFLOG) interface", err_str) == NULL)
+ /*
+ * The notion of "connected" vs. "disconnected" doesn't apply.
+ * XXX - what about "up" and "running"?
+ */
+ if (add_dev(devlistp, NFLOG_IFACE,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Linux netfilter log (NFLOG) interface", err_str) == NULL)
return -1;
- if (add_dev(devlistp, NFQUEUE_IFACE, 0, "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL)
+ if (add_dev(devlistp, NFQUEUE_IFACE,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL)
return -1;
return 0;
}
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
}
#endif
+static int
+oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
+ char *errbuf)
+{
+ PACKET_OID_DATA *oid_data_arg;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+
+ /*
+ * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+ * It should be big enough to hold "*lenp" bytes of data; it
+ * will actually be slightly larger, as PACKET_OID_DATA has a
+ * 1-byte data array at the end, standing in for the variable-length
+ * data that's actually there.
+ */
+ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+ if (oid_data_arg == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Couldn't allocate argument buffer for PacketRequest");
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * No need to copy the data - we're doing a fetch.
+ */
+ oid_data_arg->Oid = oid;
+ oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
+ if (!PacketRequest(adapter, FALSE, oid_data_arg)) {
+ int status;
+ DWORD request_error;
+
+ request_error = GetLastError();
+ if (request_error == NDIS_STATUS_INVALID_OID ||
+ request_error == NDIS_STATUS_NOT_SUPPORTED ||
+ request_error == NDIS_STATUS_NOT_RECOGNIZED)
+ status = PCAP_ERROR_OPERATION_NOTSUP;
+ else
+ status = PCAP_ERROR;
+ pcap_win32_err_to_str(request_error, errbuf);
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Error calling PacketRequest: %s", errbuf);
+ free(oid_data_arg);
+ return (status);
+ }
+
+ /*
+ * Get the length actually supplied.
+ */
+ *lenp = oid_data_arg->Length;
+
+ /*
+ * Copy back the data we fetched.
+ */
+ memcpy(data, oid_data_arg->Data, *lenp);
+ free(oid_data_arg);
+ return (0);
+}
+
static int
pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
{
pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
{
struct pcap_win *pw = p->priv;
- PACKET_OID_DATA *oid_data_arg;
- char errbuf[PCAP_ERRBUF_SIZE+1];
- /*
- * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
- * It should be big enough to hold "*lenp" bytes of data; it
- * will actually be slightly larger, as PACKET_OID_DATA has a
- * 1-byte data array at the end, standing in for the variable-length
- * data that's actually there.
- */
- oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
- if (oid_data_arg == NULL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "Couldn't allocate argument buffer for PacketRequest");
- return (PCAP_ERROR);
- }
-
- /*
- * No need to copy the data - we're doing a fetch.
- */
- oid_data_arg->Oid = oid;
- oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
- if (!PacketRequest(pw->adapter, FALSE, oid_data_arg)) {
- pcap_win32_err_to_str(GetLastError(), errbuf);
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "Error calling PacketRequest: %s", errbuf);
- free(oid_data_arg);
- return (PCAP_ERROR);
- }
-
- /*
- * Get the length actually supplied.
- */
- *lenp = oid_data_arg->Length;
-
- /*
- * Copy back the data we fetched.
- */
- memcpy(data, oid_data_arg->Data, *lenp);
- free(oid_data_arg);
- return (0);
+ return (oid_get_request(pw->adapter, oid, data, lenp, p->errbuf));
}
static int
return (res);
}
+int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ ADAPTER *adapter;
+ int status;
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+ NDIS_PHYSICAL_MEDIUM phys_medium;
+ bpf_u_int32 gen_physical_medium_oids[] = {
+ #ifdef OID_GEN_PHYSICAL_MEDIUM_EX
+ OID_GEN_PHYSICAL_MEDIUM_EX,
+ #endif
+ OID_GEN_PHYSICAL_MEDIUM
+ };
+#define N_GEN_PHYSICAL_MEDIUM_OIDS (sizeof gen_physical_medium_oids / sizeof gen_physical_medium_oids[0])
+#endif /* OID_GEN_PHYSICAL_MEDIUM */
+#ifdef OID_GEN_MEDIA_CONNECT_STATUS_EX
+ NET_IF_MEDIA_CONNECT_STATE connect_state_ex;
+#endif
+ int connect_state;
+
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback interface, so the connection status doesn't
+ * apply. and it's not wireless (or wired, for that
+ * matter...).
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+
+ /*
+ * We need to open the adapter to get this information.
+ */
+ adapter = PacketOpenAdapter(name);
+ if (adapter == NULL) {
+ /*
+ * Give up; if they try to open this device, it'll fail.
+ */
+ return (0);
+ }
+
+ /*
+ * Get the network type.
+ */
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+ /*
+ * Try the OIDs we have for this, in order.
+ */
+ for (i = 0; i < N_GEN_PHYSICAL_MEDIUM_OIDS; i++) {
+ len = sizeof (phys_medium);
+ status = oid_get_request(adapter, gen_physical_medium_oids[i],
+ &phys_medium, &len, errbuf);
+ if (status == PCAP_ERROR) {
+ /*
+ * Failed with a hard error.
+ */
+ PacketCloseAdapter(adapter);
+ return (-1);
+ }
+ if (status == 0) {
+ /*
+ * Success.
+ */
+ break;
+ }
+ /*
+ * Failed with "I don't support that OID", so try the
+ * next one, if we have a next one.
+ */
+ }
+ if (status == 0) {
+ /*
+ * We got the physical medium.
+ */
+ switch (phys_medium) {
+
+ case NdisPhysicalMediumWirelessLan:
+ case NdisPhysicalMediumWirelessWan:
+ case NdisPhysicalMediumNative802_11:
+ case NdisPhysicalMediumBluetooth:
+ case NdisPhysicalMediumUWB:
+ case NdisPhysicalMediumIrda:
+ /*
+ * Wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+ }
+#endif
+
+ /*
+ * Get the connection status.
+ */
+#ifdef OID_GEN_MEDIA_CONNECT_STATUS_EX
+ len = sizeof(connect_state_ex);
+ status = oid_get_request(adapter, OID_GEN_MEDIA_CONNECT_STATUS_EX,
+ &connect_state_ex, &len, errbuf);
+ if (status == PCAP_ERROR) {
+ /*
+ * Fatal error.
+ */
+ PacketCloseAdapter(adapter);
+ return (-1);
+ }
+ if (status == 0) {
+ switch (connect_state_ex) {
+
+ case MediaConnectStateConnected:
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ break;
+
+ case MediaConnectStateDisconnected:
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ break;
+ }
+ }
+#else
+ /*
+ * OID_GEN_MEDIA_CONNECT_STATUS_EX isn't supported because it's
+ * not in our SDK.
+ */
+ status = PCAP_ERROR_OPERATION_NOTSUP;
+#endif
+ if (status == PCAP_ERROR_OPERATION_NOTSUP) {
+ /*
+ * OK, OID_GEN_MEDIA_CONNECT_STATUS_EX isn't supported,
+ * try OID_GEN_MEDIA_CONNECT_STATUS.
+ */
+ status = oid_get_request(adapter, OID_GEN_MEDIA_CONNECT_STATUS,
+ &connect_state, &len, errbuf);
+ if (status == PCAP_ERROR) {
+ /*
+ * Fatal error.
+ */
+ PacketCloseAdapter(adapter);
+ return (-1);
+ }
+ if (status == 0) {
+ switch (connect_state) {
+
+ case NdisMediaStateConnected:
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ break;
+
+ case NdisMediaStateDisconnected:
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ break;
+ }
+ }
+ }
+ PacketCloseAdapter(adapter);
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
}
#endif
+ /*
+ * XXX - get the link state here.
+ * Does the OID we want depend on NDIS 5 vs. NDIS 6?
+ * If so, that means that there should be a packet.dll
+ * API for this.
+ * Set the appropriate bits in flags.
+ */
+
/*
* Add an entry for this interface.
*/
return (NULL);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
}
for (i = 0; i < numdev; ++i) {
+ /*
+ * XXX - do the notions of "up", "running", or
+ * "connected" apply here?
+ */
if (!add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) {
ret = -1;
goto out;
int
septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
{
+ /*
+ * XXX - do the notions of "up", "running", or "connected" apply here?
+ */
if (add_dev(devlistp,"septel",0,"Intel/Septel device",errbuf) == NULL)
return -1;
return 0;
} else {
/*
* No. Add an entry for it.
+ *
+ * XXX - is there a notion of "up" or "running",
+ * and can we determine whether something's
+ * plugged into the adapter and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
*/
dev = add_dev(devlistp, ifa->snf_ifa_name, 0, desc,
errbuf);
(void)pcap_snprintf(name,MAX_DESC_LENGTH,"snf%d",allports);
(void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom Merge Bitmask All Ports snf%d",
allports);
- if (add_dev(devlistp, name, 0, desc, errbuf) == NULL)
+ /*
+ * XXX - is there any notion of "up" and "running" that
+ * would apply to this device, given that it handles
+ * multiple ports?
+ *
+ * Presumably, there's no notion of "connected" vs.
+ * "disconnected", as "is this plugged into a network?"
+ * would be a per-port property.
+ */
+ if (add_dev(devlistp, name,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, desc,
+ errbuf) == NULL)
return (-1);
/*
* XXX - should we give it a list of addresses with all
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
return (1);
}
+int
+get_if_flags(const char *name _U_, bpf_u_int32 flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
char dev_name[10];
char dev_descr[30];
pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
- if (n == 0)
- pcap_snprintf(dev_descr, 30, "All USB buses");
- else
+ /*
+ * XXX - is there any notion of "up" and "running"?
+ */
+ if (n == 0) {
+ /*
+ * As this refers to all buses, there's no notion of
+ * "connected" vs. "disconnected", as that's a property
+ * that would apply to a particular USB interface.
+ */
+ if (add_dev(devlistp, dev_name,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "All USB buses", err_str) == NULL)
+ return -1;
+ } else {
+ /*
+ * XXX - is there a way to determine whether anything's
+ * plugged into this bus interface or not, and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+ */
pcap_snprintf(dev_descr, 30, "USB bus number %d", n);
+ if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
+ return -1;
+ }
- if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
- return -1;
return 0;
}
n |= 0x80000000;
if (!(dev->flags & PCAP_IF_UP))
n |= 0x40000000;
- if (dev->flags & PCAP_IF_LOOPBACK)
+
+ /*
+ * Give non-wireless interfaces that aren't disconnected a better
+ * figure of merit than interfaces that are disconnected, as
+ * "disconnected" should indicate that the interface isn't
+ * plugged into a network and thus won't give you any traffic.
+ *
+ * For wireless interfaces, it means "associated with a network",
+ * which we presume not to necessarily prevent capture, as you
+ * might run the adapter in some flavor of monitor mode.
+ */
+ if (!(dev->flags & PCAP_IF_WIRELESS) &&
+ (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
n |= 0x20000000;
+
+ /*
+ * Sort loopback devices after non-loopback devices, *except* for
+ * disconnected devices.
+ */
+ if (dev->flags & PCAP_IF_LOOPBACK)
+ n |= 0x10000000;
+
return (n);
}
}
/*
- * No, we didn't find it. Try to add it to the list of devices.
+ * No, we didn't find it.
+ */
+
+ /*
+ * Try to get additional flags for the device.
+ */
+ if (get_if_flags(name, &flags, errbuf) == -1) {
+ /*
+ * Failed.
+ */
+ return (NULL);
+ }
+
+ /*
+ * Now, try to add it to the list of devices.
*/
return (add_dev(devlistp, name, flags, description, errbuf));
}
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
return ("That device doesn't support that time stamp precision");
+
+ case PCAP_ERROR_OPERATION_NOTSUP:
+ return ("That device doesn't support that operation");
}
(void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
return(ebuf);
bpf_u_int32 flags; /* PCAP_IF_ interface flags */
};
-#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
-#define PCAP_IF_UP 0x00000002 /* interface is up */
-#define PCAP_IF_RUNNING 0x00000004 /* interface is running */
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+#define PCAP_IF_UP 0x00000002 /* interface is up */
+#define PCAP_IF_RUNNING 0x00000004 /* interface is running */
+#define PCAP_IF_WIRELESS 0x00000008 /* interface is wireless (*NOT* necessarily Wi-Fi!) */
+#define PCAP_IF_CONNECTION_STATUS 0x00000030 /* connection status: */
+#define PCAP_IF_CONNECTION_STATUS_UNKNOWN 0x00000000 /* unknown */
+#define PCAP_IF_CONNECTION_STATUS_CONNECTED 0x00000010 /* connected */
+#define PCAP_IF_CONNECTION_STATUS_DISCONNECTED 0x00000020 /* disconnected */
+#define PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE 0x00000030 /* not applicable */
/*
* Representation of an interface address.
#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
+#define PCAP_ERROR_OPERATION_NOTSUP -13 /* OID operation not supported by adapter */
/*
* Warning codes for the pcap API.
.TP
.B PCAP_IF_RUNNING
set if the device is running
+.TP
+.B PCAP_IF_WIRELESS
+set if the device is a wireless interface; this includes IrDA as well as
+radio-based networks such as IEEE 802.15.4 and IEEE 802.11, so it
+doesn't just mean Wi-Fi
+.TP
+.B PCAP_IF_CONNECTION_STATUS
+a bitmask for an indication of whether the adapter is connected or not;
+for wireless interfaces, "connected" means "associated with a network"
+.TP
+The possible values for the connection status bits are:
+.TP
+.B PCAP_IF_CONNECTION_STATUS_UNKNOWN
+it's unknown whether the adapter is connected or not
+.TP
+.B PCAP_IF_CONNECTION_STATUS_CONNECTED
+the adapter is connected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_DISCONNECTED
+the adapter is disconnected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+the notion of "connected" and "disconnected" don't apply to this
+interface; for example, it doesn't apply to a loopback device
.RE
.RE
.PP
printf("%sLOOPBACK", sep);
sep = ", ";
}
+ if (d->flags & PCAP_IF_WIRELESS) {
+ printf("%sWIRELESS", sep);
+ switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(" (association unknown)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(" (associated)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(" (not associated)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ } else {
+ switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(" (connection status unknown)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(" (connected)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(" (disconnectted)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ }
+ sep = ", ";
printf("\n");
for(a=d->addresses;a;a=a->next) {