[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