aboutsummaryrefslogtreecommitdiffstats
path: root/util.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2000-01-16 02:48:12 +0000
committerGuy Harris <guy@alum.mit.edu>2000-01-16 02:48:12 +0000
commit7f30e566a0257e7319a2e6a052476afd46924b12 (patch)
treeebe8cc252f6efe9166f3a6a14517cfd937290a17 /util.c
parent66a0ac1ca116c350549aa006772c67c891602b8f (diff)
Move the routine to get a list of the network interfaces on the system
to "util.c", and provide a routine to free that list as well. When picking an interface on which to do a capture (if no "-i" flag was specified), use that routine, and pick the first interface on the list. svn path=/trunk/; revision=1495
Diffstat (limited to 'util.c')
-rw-r--r--util.c210
1 files changed, 209 insertions, 1 deletions
diff --git a/util.c b/util.c
index 6d3b5cf81e..676b055fc7 100644
--- a/util.c
+++ b/util.c
@@ -1,7 +1,7 @@
/* util.c
* Utility routines
*
- * $Id: util.c,v 1.26 2000/01/15 00:22:34 gram Exp $
+ * $Id: util.c,v 1.27 2000/01/16 02:47:47 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -66,6 +66,28 @@
typedef int mode_t; /* for win32 */
#endif
+#ifdef HAVE_LIBPCAP
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#include "globals.h"
+
+#endif
+
static char *
setup_tmpdir(char *dir)
{
@@ -276,3 +298,189 @@ EBCDIC_to_ASCII1(guint8 c)
{
return EBCDIC_translate_ASCII[c];
}
+
+#ifdef HAVE_LIBPCAP
+
+/*
+ * If the ability to capture packets is added to Wiretap, these
+ * routines should be moved to the Wiretap source (with
+ * "get_interface_list()" and "free_interface_list()" renamed to
+ * "wtap_get_interface_list()" and "wtap_free_interface_list()",
+ * and modified to use Wiretap routines to attempt to open the
+ * interface.
+ */
+
+struct search_user_data {
+ char *name;
+ int found;
+};
+
+static void
+search_for_if_cb(gpointer data, gpointer user_data);
+
+static void
+free_if_cb(gpointer data, gpointer user_data);
+
+GList *
+get_interface_list(int *err, char *err_str)
+{
+ GList *il = NULL;
+ gint nonloopback_pos = 0;
+ struct ifreq *ifr, *last;
+ struct ifconf ifc;
+ struct ifreq ifrflags;
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ struct search_user_data user_data;
+ pcap_t *pch;
+
+ if (sock < 0) {
+ sprintf(err_str, "Error opening socket: %s",
+ strerror(errno));
+ return NULL;
+ }
+
+ /*
+ * Since we have to grab the interface list all at once, we'll
+ * make plenty of room.
+ */
+ ifc.ifc_len = 1024 * sizeof(struct ifreq);
+ ifc.ifc_buf = malloc(ifc.ifc_len);
+
+ if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
+ ifc.ifc_len < sizeof(struct ifreq)) {
+ sprintf(err_str, "SIOCGIFCONF error getting list of interfaces: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ ifr = (struct ifreq *) ifc.ifc_req;
+ last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
+ while (ifr < last) {
+ /*
+ * Skip addresses that begin with "dummy", or that include
+ * a ":" (the latter are Solaris virtuals).
+ */
+ if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
+ strchr(ifr->ifr_name, ':') != NULL)
+ goto next;
+
+ /*
+ * If we already have this interface name on the list,
+ * don't add it (SIOCGIFCONF returns, at least on
+ * BSD-flavored systems, one entry per interface *address*;
+ * if an interface has multiple addresses, we get multiple
+ * entries for it).
+ */
+ user_data.name = ifr->ifr_name;
+ user_data.found = FALSE;
+ g_list_foreach(il, search_for_if_cb, &user_data);
+ if (user_data.found)
+ goto next;
+
+ /*
+ * Get the interface flags.
+ */
+ memset(&ifrflags, 0, sizeof ifrflags);
+ strncpy(ifrflags.ifr_name, ifr->ifr_name,
+ sizeof ifrflags.ifr_name);
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+ if (errno == ENXIO)
+ goto next;
+ sprintf(err_str, "SIOCGIFFLAGS error getting flags for interface %s: %s",
+ ifr->ifr_name, strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * Skip interfaces that aren't up.
+ */
+ if (!(ifrflags.ifr_flags & IFF_UP))
+ goto next;
+
+ /*
+ * Skip interfaces that we can't open with "libpcap".
+ * Open with the minimum packet size - it appears that the
+ * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
+ * supplied is too large, rather than just truncating it.
+ */
+ pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0,
+ err_str);
+ if (pch == NULL)
+ goto next;
+ pcap_close(pch);
+
+ /*
+ * If it's a loopback interface, add it at the end of the
+ * list, otherwise add it after the last non-loopback
+ * interface, so all loopback interfaces go at the end - we
+ * don't want a loopback interface to be the default capture
+ * device unless there are no non-loopback devices.
+ */
+ if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
+ strncmp(ifr->ifr_name, "lo", 2) == 0)
+ il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
+ else {
+ il = g_list_insert(il, g_strdup(ifr->ifr_name),
+ nonloopback_pos);
+ /*
+ * Insert the next non-loopback interface after this
+ * one.
+ */
+ nonloopback_pos++;
+ }
+
+ next:
+#ifdef HAVE_SA_LEN
+ ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
+#else
+ ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
+#endif
+ }
+
+ free(ifc.ifc_buf);
+ close(sock);
+
+ if (il == NULL) {
+ /*
+ * No interfaces found.
+ */
+ *err = NO_INTERFACES_FOUND;
+ }
+ return il;
+
+fail:
+ if (il != NULL) {
+ g_list_foreach(il, free_if_cb, NULL);
+ g_list_free(il);
+ }
+ free(ifc.ifc_buf);
+ close(sock);
+ *err = CANT_GET_INTERFACE_LIST;
+ return NULL;
+}
+
+static void
+search_for_if_cb(gpointer data, gpointer user_data)
+{
+ struct search_user_data *search_user_data = user_data;
+
+ if (strcmp((char *)data, search_user_data->name) == 0)
+ search_user_data->found = TRUE;
+}
+
+static void
+free_if_cb(gpointer data, gpointer user_data)
+{
+ g_free(data);
+}
+
+void
+free_interface_list(GList *if_list)
+{
+ while (if_list != NULL) {
+ g_free(if_list->data);
+ if_list = g_list_remove_link(if_list, if_list);
+ }
+}
+
+#endif /* HAVE_LIBPCAP */