diff options
author | Robert Millan <rmh@debian.org> | 2011-06-15 16:49:24 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2011-06-15 16:49:56 +0200 |
commit | 1df2a0fce427fab7754f6ac572cf68cef2e95696 (patch) | |
tree | 3a4fcc5f1e9a3cad3d4c875564b48afed73ae926 | |
parent | 87a477c74e2478e94e89e7026cf7207fcdc2dffc (diff) |
Use legacy getifaddrs() on GNU/kFreeBSD
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | ifconf.h (renamed from netlink.h) | 32 | ||||
-rw-r--r-- | legacy.c | 92 | ||||
-rw-r--r-- | netlink.c | 27 | ||||
-rw-r--r-- | nss-myhostname.c | 8 |
6 files changed, 141 insertions, 34 deletions
diff --git a/Makefile.am b/Makefile.am index 7f2f3a39c..f82b8d46e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,14 +40,19 @@ homepage: all dist ln -sf README.html $$HOME/homepage/private/projects/nss-myhostname/index.html .PHONY: homepage libnss_myhostname_la_SOURCES = \ nss-myhostname.c \ - netlink.c \ - netlink.h + ifconf.h + +if LEGACY +libnss_myhostname_la_SOURCES += legacy.c +else +libnss_myhostname_la_SOURCES += netlink.c +endif libnss_myhostname_la_LDFLAGS = \ -avoid-version \ -module \ -export-dynamic \ -shrext .so.2 diff --git a/configure.ac b/configure.ac index 38cd58fb4..30ebc44a8 100644 --- a/configure.ac +++ b/configure.ac @@ -30,12 +30,19 @@ AC_SYS_LARGEFILE AM_INIT_AUTOMAKE([foreign 1.9 -Wall -Wno-portability silent-rules tar-pax subdir-objects dist-bzip2]) AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/nss-myhostname/]) ac_default_prefix="/" +AC_CANONICAL_HOST +case "$host_os" in + linux*) legacy=false ;; + *) legacy=true ;; +esac +AM_CONDITIONAL([LEGACY], [test x$legacy = xtrue]) + # Checks for programs. AC_PROG_CC AC_PROG_CC_C99 AC_PROG_CPP AC_PROG_INSTALL @@ -1,10 +1,12 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foonetlinkhfoo -#define foonetlinkhfoo +#ifndef fooifconfhfoo +#define fooifconfhfoo + +#include <sys/socket.h> /*** This file is part of nss-myhostname. Copyright 2008-2011 Lennart Poettering @@ -34,15 +36,39 @@ struct address { int ifindex; }; #define _public_ __attribute__ ((visibility("default"))) #define _hidden_ __attribute__ ((visibility("hidden"))) -int netlink_acquire_addresses(struct address **_list, unsigned *_n_list) _hidden_; +int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) _hidden_; static inline size_t PROTO_ADDRESS_SIZE(int proto) { assert(proto == AF_INET || proto == AF_INET6); return proto == AF_INET6 ? 16 : 4; } +static inline int address_compare(const void *_a, const void *_b) { + const struct address *a = _a, *b = _b; + + /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */ + + if (a->scope < b->scope) + return -1; + if (a->scope > b->scope) + return 1; + + if (a->family == AF_INET && b->family == AF_INET6) + return -1; + if (a->family == AF_INET6 && b->family == AF_INET) + return 1; + + if (a->ifindex < b->ifindex) + return -1; + if (a->ifindex > b->ifindex) + return 1; + + return 0; +} + + #endif diff --git a/legacy.c b/legacy.c new file mode 100644 index 000000000..9c0bcadb6 --- /dev/null +++ b/legacy.c @@ -0,0 +1,92 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of nss-myhostname. + + Copyright 2008-2011 Lennart Poettering + Copyright 2011 Robert millan + + nss-myhostname is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + nss-myhostname is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with nss-myhostname; If not, see + <http://www.gnu.org/licenses/>. +***/ + +#include <sys/types.h> +#include <errno.h> +#include <ifaddrs.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> + +#include "ifconf.h" + +int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) { + struct address *list = NULL; + unsigned n_list = 0; + struct ifaddrs *ifa = NULL; + int r = 1; + struct ifaddrs *i; + int ifindex = 0; + + if (getifaddrs(&ifa) == -1) { + r = -errno; + goto finish; + } + + for (i = ifa; i != NULL; i = i->ifa_next) { + int af; + const void *cp; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) i->ifa_addr; + struct sockaddr_in *in = (struct sockaddr_in *) i->ifa_addr; + + if (! i->ifa_addr) + continue; + + af = i->ifa_addr->sa_family; + + if (af != AF_INET && af != AF_INET6) + continue; + + list = realloc(list, (n_list+1) * sizeof(struct address)); + if (!list) { + r = -ENOMEM; + goto finish; + } + + if (af == AF_INET6) + cp = &in6->sin6_addr; + else + cp = &in->sin_addr; + + list[n_list].family = af; + list[n_list].scope = 0; + memcpy(list[n_list].address, cp, PROTO_ADDRESS_SIZE(af)); + list[n_list].ifindex = ifindex++; + n_list++; + } + +finish: + if (ifa) + freeifaddrs(ifa); + + if (r < 0) + free(list); + else { + qsort(list, n_list, sizeof(struct address), address_compare); + + *_list = list; + *_n_list = n_list; + } + + return r; +} @@ -32,38 +32,15 @@ #include <limits.h> #include <arpa/inet.h> #include <unistd.h> #include <inttypes.h> #include <stdlib.h> -#include "netlink.h" +#include "ifconf.h" -static int address_compare(const void *_a, const void *_b) { - const struct address *a = _a, *b = _b; - - /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */ - - if (a->scope < b->scope) - return -1; - if (a->scope > b->scope) - return 1; - - if (a->family == AF_INET && b->family == AF_INET6) - return -1; - if (a->family == AF_INET6 && b->family == AF_INET) - return 1; - - if (a->ifindex < b->ifindex) - return -1; - if (a->ifindex > b->ifindex) - return 1; - - return 0; -} - -int netlink_acquire_addresses(struct address **_list, unsigned *_n_list) { +int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) { struct { struct nlmsghdr hdr; struct rtgenmsg gen; } req; struct rtgenmsg *gen; diff --git a/nss-myhostname.c b/nss-myhostname.c index 293166c49..83180ad80 100644 --- a/nss-myhostname.c +++ b/nss-myhostname.c @@ -29,13 +29,13 @@ #include <assert.h> #include <unistd.h> #include <net/if.h> #include <stdlib.h> #include <arpa/inet.h> -#include "netlink.h" +#include "ifconf.h" /* We use 127.0.0.2 as IPv4 address. This has the advantage over * 127.0.0.1 that it can be translated back to the local hostname. For * IPv6 we use ::1 which unfortunately will not translate back to the * hostname but instead something like "localhost6" or so. */ @@ -115,13 +115,13 @@ enum nss_status _nss_myhostname_gethostbyname4_r( *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } /* If this fails, n_addresses is 0. Which is fine */ - netlink_acquire_addresses(&addresses, &n_addresses); + ifconf_acquire_addresses(&addresses, &n_addresses); /* If this call fails we fill in 0 as scope. Which is fine */ lo_ifi = if_nametoindex(LOOPBACK_INTERFACE); l = strlen(hn); ms = ALIGN(l+1)+ALIGN(sizeof(struct gaih_addrtuple))*(n_addresses > 0 ? n_addresses : 2); @@ -201,13 +201,13 @@ static enum nss_status fill_in_hostent( size_t alen; struct address *addresses = NULL, *a; unsigned n_addresses = 0, n, c; alen = PROTO_ADDRESS_SIZE(af); - netlink_acquire_addresses(&addresses, &n_addresses); + ifconf_acquire_addresses(&addresses, &n_addresses); for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) if (af == a->family) c++; l = strlen(hn); @@ -400,13 +400,13 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( } else { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } - netlink_acquire_addresses(&addresses, &n_addresses); + ifconf_acquire_addresses(&addresses, &n_addresses); for (a = addresses, n = 0; n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, a->address, PROTO_ADDRESS_SIZE(af)) == 0) |