Package: iftop Version: 1.0~pre4-4 Followup-For: Bug #644998 New version of the patch that supports ipv6-only hosts -- System Information: Debian Release: 9.4 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: amd64 (x86_64)
Kernel: Linux 4.9.0-6-amd64 (SMP w/1 CPU core) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages iftop depends on: ii libc6 2.24-11+deb9u3 ii libncurses5 6.0+20161126-1+deb9u2 ii libpcap0.8 1.8.1-3 ii libtinfo5 6.0+20161126-1+deb9u2 iftop recommends no packages. iftop suggests no packages. -- no debconf information
>From 90ce46be76f1ed558a88448d730a47ad31a18b92 Mon Sep 17 00:00:00 2001 From: Shawn Landden <sh...@git.icu> Date: Sun, 10 Jun 2018 18:33:56 -0700 Subject: [PATCH] options: select interface that is default route (Closes: #644998) https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644998 IPv4 detection first, cause iftop does not work with v4tunnel --- options.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/options.c b/options.c index a075357..0654d46 100644 --- a/options.c +++ b/options.c @@ -6,8 +6,13 @@ #include "config.h" +#ifdef __linux__ +#define _GNU_SOURCE +#endif + #include <sys/types.h> +#include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -90,6 +95,75 @@ static int is_bad_interface_name(char *i) { return 0; } +/* none of these errors are expected, so I think it is OK to print them */ +static char *get_interface_for_default_route(int ipv6) { +#ifdef __linux__ + pid_t pid; + int fds[2]; + int r; + char buf[4096]; + char *p, *q; + + r = pipe2(fds, O_CLOEXEC); + if (r < 0) { + fprintf(stderr, "get_interface_for_default_ipv4_route: pipe() failed: %s, continuing...", strerror(r)); + return NULL; + } + pid = fork(); + if (pid < 0) { + fprintf(stderr, "get_interface_for_default_ipv4_route: fork() failed: %s, continuing...", strerror(r)); + return NULL; + } else if (pid == 0) { + /* child */ + r = dup2(fds[0], STDOUT_FILENO); + if (r < 0) { + char buf[1] = {'\n'}; + + /* we have to write something as the other end is expecting something */ + r = write(fds[0], &buf, sizeof(buf)); + _exit(EXIT_FAILURE); + } + + if (ipv6) + execlp("ip", "-6", "route", NULL); + else + execlp("ip", "route", NULL); + char buf[1] = {'\n'}; + + /* we have to write something as the other end is expecting something */ + r = write(fds[0], &buf, sizeof(buf)); + _exit(EXIT_FAILURE); + } + /* parent */ + close(fds[1]); + r = read(fds[1], &buf, sizeof(buf)); + if (r < 0) { + fprintf(stderr, "get_interface_for_default_ipv4_route: read() failed: %s, continuing...", strerror(r)); + return NULL; + } + + p = strstr((char *)&buf, "default via "); + if (!p) + return NULL; + p += strlen("default via "); + q = p; + for (;*p != '\n' && *p; p++) + ; + *p = '\0'; + p = strstr(q, " dev "); + if (!p) + return NULL; + p += strlen(" dev "); + q = p; + for (;*p != ' ' && *p; p++) + ; + *p = '\0'; + return xstrdup(q); +#else + return NULL; +#endif +} + /* This finds the first interface which is up and is not the loopback * interface or one of the interface types listed in bad_interface_names. */ static char *get_first_interface(void) { @@ -123,9 +197,16 @@ static char *get_first_interface(void) { void options_set_defaults() { char *s; + + if (!options.interface) /* IPv4. Must come first because iftop does not work with v4tunnels. + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901283 */ + options.interface = get_interface_for_default_route(0); + if (!options.interface) /* IPv6*/ + options.interface = get_interface_for_default_route(1); /* Should go through the list of interfaces, and find the first one which * is up and is not lo or dummy*. */ - options.interface = get_first_interface(); + if (!options.interface) + options.interface = get_first_interface(); if (!options.interface) options.interface = "eth0"; -- 2.17.1