Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Tue, 17 Nov 2015 11:33:48 +0100
From: Jo-Philipp Wich <jow@...nwrt.org>
To: musl@...ts.openwall.com
Subject: Fix handling of peer-to-peer interfaces in getifaddrs()

properly handle point-to-point interfaces in getifaddrs()

With point-to-point interfaces, the IFA_ADDRESS netlink attribute contains
the peer address while an extra attribute IFA_LOCAL carries the actual local
interface address.

Currently musl lacks any treatment of IFA_LOCAL leading to bogus results
when using getifaddrs() to obtain the local and remote IP addresses of
point-to-point interfaces like ppp ones.

The following test case illustrates the problem:

-- 8< --
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <stdio.h>
 
int main(int argc, char **argv) {
        struct ifaddrs *ifa, *ifap;
        char local[32];
        char remote[32];
 
        if (!getifaddrs(&ifa)) {
                for (ifap = ifa; ifap; ifap = ifap->ifa_next) {
                        if (!ifap->ifa_name || strcmp(ifap->ifa_name, argv[1]) ||
                            !ifap->ifa_addr || ifap->ifa_addr->sa_family != AF_INET)
                                continue;
 
                        inet_ntop(AF_INET, &((struct sockaddr_in *)ifap->ifa_addr)->sin_addr, local, sizeof(local));
 
                        if (ifap->ifa_dstaddr)
                                inet_ntop(AF_INET, &((struct sockaddr_in *)ifap->ifa_dstaddr)->sin_addr, remote, sizeof(remote));
                        else
                                strcpy(remote, "(null)");
 
                        printf("local addr = %s / remote addr = %s\n", local, remote);
                        break;
                }
 
                freeifaddrs(ifa);
        }
 
        return 0;
}
-- >8 --

I used the following command sequence to assert the results:

$ gcc -o /tmp/ifa /tmp/ifa.c
$ ip link add name dummy0 type dummy
$ ip addr add 1.1.1.1 peer 2.2.2.2 dev dummy0
$ /tmp/ifa dummy0

That led to the following result on musl:

  local addr = 2.2.2.2 / remote addr = (null)

Note that the local address is unexpectedly 2.2.2.2 while it should be 1.1.1.1
and the remote address is not set at all.

Running the same test on an ordinary glibc system (Debian) and on an uclibc
based OpenWrt gives the correct result:

  local addr = 1.1.1.1 / remote addr = 2.2.2.2


The proposed change adds special treatment of IFA_LOCAL to getifaddrs(),
following the logic used in uclibc and glibc implementations.

Reagrds,
Jo-Philipp

Powered by blists - more mailing lists

Your e-mail address:

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.