[Iftop-users] [PATCH] options: select interface that is IPv4 default route (Closes: #644998)
Paul Warren
pdw at ex-parrot.com
Mon Jun 11 10:18:16 BST 2018
Hi Shawn,
Thanks for this. Unfortunately, it doesn't work:
r = read(fds[1], &buf, sizeof(buf));
fds[1] is the write end of the pipe, so reading from it doesn't work.
This highlights another problem:
fprintf(stderr, "get_interface_for_default_ipv4_route: read() failed: %s, continuing...", strerror(r));
vs.
"On error, -1 is returned, and errno is set appropriately."
Paul
On 11/06/18 02:40, Shawn Landden wrote:
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=644998
> ---
> options.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 76 insertions(+), 1 deletion(-)
>
> diff --git a/options.c b/options.c
> index a075357..efff2c7 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,72 @@ 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_ipv4_route(void) {
> +#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);
> + }
> +
> + execlp("ip", /* add "-6", here to make default IPv6 route */ "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 +194,13 @@ static char *get_first_interface(void) {
>
> void options_set_defaults() {
> char *s;
> +
> + if (!options.interface)
> + options.interface = get_interface_for_default_ipv4_route();
> /* 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";
>
More information about the iftop-users
mailing list