[Iftop-users] [PATCH] options: select interface that is default route (Closes: #644998)
Shawn Landden
shawn at git.icu
Mon Jun 11 13:05:35 BST 2018
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644998
IPv4 detection first, cause iftop does not work with v4tunnel
---
options.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/options.c b/options.c
index a075357..1363597 100644
--- a/options.c
+++ b/options.c
@@ -6,8 +6,14 @@
#include "config.h"
+#ifdef __linux__
+#define _GNU_SOURCE
+#endif
+
#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -90,6 +96,76 @@ 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) {
+ (void)fprintf(stderr, "%s: %s() failed: %s, continuing...", __PRETTY_FUNCTION__, "pipe2", strerror(errno));
+ return NULL;
+ }
+ pid = fork();
+ if (pid < 0) {
+ (void)fprintf(stderr, "%s: %s() failed: %s, continuing...", __PRETTY_FUNCTION__, "fork", strerror(errno));
+ return NULL;
+ } else if (pid == 0) {
+ /* child */
+ r = dup2(fds[1], STDOUT_FILENO);
+ if (r < 0) {
+ char buf[1] = {'\n'};
+
+ /* we have to write something as the other end is expecting something */
+ r = write(fds[1], &buf, sizeof(buf));
+ _exit(EXIT_FAILURE);
+ }
+
+ if (ipv6)
+ execlp("ip", "ip", "-6", "route", NULL);
+ else
+ execlp("ip", "ip", "route", NULL);
+ char buf[1] = {'\n'};
+
+ /* we have to write something as the other end is expecting something */
+ r = write(fds[1], &buf, sizeof(buf));
+ _exit(EXIT_FAILURE);
+ }
+ /* parent */
+ close(fds[1]);
+ r = read(fds[0], &buf, sizeof(buf));
+ if (r < 0) {
+ (void)fprintf(stderr, "%s: %s() failed: %s, continuing...", __PRETTY_FUNCTION__, "read", strerror(errno));
+ 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 +199,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
More information about the iftop-users
mailing list