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

Reply via email to