aboutsummaryrefslogtreecommitdiff
path: root/pcap-linux.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2019-11-08 19:56:53 -0800
committerGitHub <noreply@github.com>2019-11-08 19:56:53 -0800
commitca73e1eb38426d78f72a574774008f9d9fc179aa (patch)
tree95ee96d564cd70437cab8cf7fc5ab1f1c3512150 /pcap-linux.c
parent108b0eecc5c876c4ce93e60207146add85fc978e (diff)
parent1548ff3a6af09e4abfc91900bacb3d278530ae7e (diff)
Merge pull request #880 from Oppen/linux-simplify_dev_detection
Linux: remove procfs and sysfs crawling for interface detection.
Diffstat (limited to 'pcap-linux.c')
-rw-r--r--pcap-linux.c255
1 files changed, 1 insertions, 254 deletions
diff --git a/pcap-linux.c b/pcap-linux.c
index 004bc91b..444d509c 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -2284,220 +2284,6 @@ add_linux_if(pcap_if_list_t *devlistp, const char *ifname, int fd, char *errbuf)
}
/*
- * Get from "/sys/class/net" all interfaces listed there; if they're
- * already in the list of interfaces we have, that won't add another
- * instance, but if they're not, that'll add them.
- *
- * We don't bother getting any addresses for them; it appears you can't
- * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
- * although some other types of addresses can be fetched with SIOCGIFADDR,
- * we don't bother with them for now.
- *
- * We also don't fail if we couldn't open "/sys/class/net"; we just leave
- * the list of interfaces as is, and return 0, so that we can try
- * scanning /proc/net/dev.
- *
- * Otherwise, we return 1 if we don't get an error and -1 if we do.
- */
-static int
-scan_sys_class_net(pcap_if_list_t *devlistp, char *errbuf)
-{
- DIR *sys_class_net_d;
- int fd;
- struct dirent *ent;
- char subsystem_path[PATH_MAX+1];
- struct stat statb;
- int ret = 1;
-
- sys_class_net_d = opendir("/sys/class/net");
- if (sys_class_net_d == NULL) {
- /*
- * Don't fail if it doesn't exist at all.
- */
- if (errno == ENOENT)
- return (0);
-
- /*
- * Fail if we got some other error.
- */
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "Can't open /sys/class/net");
- return (-1);
- }
-
- /*
- * Create a socket from which to fetch interface information.
- */
- fd = socket(PF_UNIX, SOCK_RAW, 0);
- if (fd < 0) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "socket");
- (void)closedir(sys_class_net_d);
- return (-1);
- }
-
- for (;;) {
- errno = 0;
- ent = readdir(sys_class_net_d);
- if (ent == NULL) {
- /*
- * Error or EOF; if errno != 0, it's an error.
- */
- break;
- }
-
- /*
- * Ignore "." and "..".
- */
- if (strcmp(ent->d_name, ".") == 0 ||
- strcmp(ent->d_name, "..") == 0)
- continue;
-
- /*
- * Ignore plain files; they do not have subdirectories
- * and thus have no attributes.
- */
- if (ent->d_type == DT_REG)
- continue;
-
- /*
- * Is there an "ifindex" file under that name?
- * (We don't care whether it's a directory or
- * a symlink; older kernels have directories
- * for devices, newer kernels have symlinks to
- * directories.)
- */
- snprintf(subsystem_path, sizeof subsystem_path,
- "/sys/class/net/%s/ifindex", ent->d_name);
- if (lstat(subsystem_path, &statb) != 0) {
- /*
- * Stat failed. Either there was an error
- * other than ENOENT, and we don't know if
- * this is an interface, or it's ENOENT,
- * and either some part of "/sys/class/net/{if_name}"
- * disappeared, in which case it probably means
- * the interface disappeared, or there's no
- * "ifindex" file, which means it's not a
- * network interface.
- */
- continue;
- }
-
- /*
- * Attempt to add the interface.
- */
- if (add_linux_if(devlistp, &ent->d_name[0], fd, errbuf) == -1) {
- /* Fail. */
- ret = -1;
- break;
- }
- }
- if (ret != -1) {
- /*
- * Well, we didn't fail for any other reason; did we
- * fail due to an error reading the directory?
- */
- if (errno != 0) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "Error reading /sys/class/net");
- ret = -1;
- }
- }
-
- (void)close(fd);
- (void)closedir(sys_class_net_d);
- return (ret);
-}
-
-/*
- * Get from "/proc/net/dev" all interfaces listed there; if they're
- * already in the list of interfaces we have, that won't add another
- * instance, but if they're not, that'll add them.
- *
- * See comments from scan_sys_class_net().
- */
-static int
-scan_proc_net_dev(pcap_if_list_t *devlistp, char *errbuf)
-{
- FILE *proc_net_f;
- int fd;
- char linebuf[512];
- int linenum;
- char *p;
- int ret = 0;
-
- proc_net_f = fopen("/proc/net/dev", "r");
- if (proc_net_f == NULL) {
- /*
- * Don't fail if it doesn't exist at all.
- */
- if (errno == ENOENT)
- return (0);
-
- /*
- * Fail if we got some other error.
- */
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "Can't open /proc/net/dev");
- return (-1);
- }
-
- /*
- * Create a socket from which to fetch interface information.
- */
- fd = socket(PF_UNIX, SOCK_RAW, 0);
- if (fd < 0) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "socket");
- (void)fclose(proc_net_f);
- return (-1);
- }
-
- for (linenum = 1;
- fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
- /*
- * Skip the first two lines - they're headers.
- */
- if (linenum <= 2)
- continue;
-
- p = &linebuf[0];
-
- /*
- * Skip leading white space.
- */
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '\0' || *p == '\n')
- continue; /* blank line */
-
- /*
- * Attempt to add the interface.
- */
- if (add_linux_if(devlistp, p, fd, errbuf) == -1) {
- /* Fail. */
- ret = -1;
- break;
- }
- }
- if (ret != -1) {
- /*
- * Well, we didn't fail for any other reason; did we
- * fail due to an error reading the file?
- */
- if (ferror(proc_net_f)) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "Error reading /proc/net/dev");
- ret = -1;
- }
- }
-
- (void)close(fd);
- (void)fclose(proc_net_f);
- return (ret);
-}
-
-/*
* Description string for the "any" device.
*/
static const char any_descr[] = "Pseudo-device that captures on all interfaces";
@@ -2685,46 +2471,7 @@ get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
int
pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
- int ret;
-
- /*
- * Get the list of regular interfaces first.
- */
- if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
- get_if_flags) == -1)
- return (-1); /* failure */
-
- /*
- * Read "/sys/class/net", and add to the list of interfaces all
- * interfaces listed there that we don't already have, because,
- * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
- * and even getifaddrs() won't return information about
- * interfaces with no addresses, so you need to read "/sys/class/net"
- * to get the names of the rest of the interfaces.
- */
- ret = scan_sys_class_net(devlistp, errbuf);
- if (ret == -1)
- return (-1); /* failed */
- if (ret == 0) {
- /*
- * No /sys/class/net; try reading /proc/net/dev instead.
- */
- if (scan_proc_net_dev(devlistp, errbuf) == -1)
- return (-1);
- }
-
- /*
- * 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|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
- any_descr, errbuf) == NULL)
- return (-1);
-
- return (0);
+ return pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound, get_if_flags);
}
/*