diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/avahi-test.c | 48 | ||||
-rw-r--r-- | src/avahi.c | 145 | ||||
-rw-r--r-- | src/avahi.h | 33 | ||||
-rw-r--r-- | src/nss.c | 103 | ||||
-rw-r--r-- | src/query.c | 2 |
6 files changed, 307 insertions, 35 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 032ee3f..ac24af2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,6 @@ AM_CFLAGS=-D_GNU_SOURCE -DMDNS_ALLOW_FILE=\"$(sysconfdir)/mdns.allow\" AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' noinst_PROGRAMS = nss-test mdns-test - lib_LTLIBRARIES = libnss_mdns.la libnss_mdns4.la libnss_mdns6.la mdns_test_SOURCES = query.c dns.c util.c mdns-test.c \ @@ -32,12 +31,16 @@ mdns_test_SOURCES = query.c dns.c util.c mdns-test.c \ nss_test_SOURCES = nss-test.c -libnss_mdns_la_SOURCES = query.c dns.c util.c nss.c \ - query.h dns.h util.h - +libnss_mdns_la_SOURCES = query.c dns.c util.c nss.c query.h dns.h util.h libnss_mdns_la_CFLAGS=$(AM_CFLAGS) libnss_mdns_la_LDFLAGS=-avoid-version -module -export-dynamic -shrext .so.2 +if ENABLE_AVAHI +noinst_PROGRAMS += avahi-test +avahi_test_SOURCES = avahi.c util.c avahi.h util.h avahi-test.c +libnss_mdns_la_SOURCES += avahi.c avahi.h +endif + libnss_mdns4_la_SOURCES=$(libnss_mdns_la_SOURCES) libnss_mdns4_la_CFLAGS=$(libnss_mdns_la_CFLAGS) -DNSS_IPV4_ONLY=1 libnss_mdns4_la_LDFLAGS=$(libnss_mdns_la_LDFLAGS) diff --git a/src/avahi-test.c b/src/avahi-test.c new file mode 100644 index 0000000..e66421e --- /dev/null +++ b/src/avahi-test.c @@ -0,0 +1,48 @@ +/* $Id$ */ + +/*** + This file is part of nss-mdns. + + nss-mdns 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 of the + License, or (at your option) any later version. + + nss-mdns 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 + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with nss-mdns; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include <arpa/inet.h> +#include <stdio.h> + +#include "avahi.h" + +int main(int argc, char *argv[]) { + uint8_t data[64]; + char t[256]; + int r; + + if ((r = avahi_resolve_name(AF_INET, argc >= 2 ? argv[1] : "whiskey.local", data)) == 0) + printf("AF_INET: %s\n", inet_ntop(AF_INET, data, t, sizeof(t))); + else + printf("AF_INET: failed (%i).\n", r); + + if ((r = avahi_resolve_name(AF_INET6, argc >= 2 ? argv[1] : "whiskey.local", data)) == 0) + printf("AF_INET6: %s\n", inet_ntop(AF_INET6, data, t, sizeof(t))); + else + printf("AF_INET6: failed (%i).\n", r); + + if ((r = avahi_resolve_address(AF_INET6, data, t, sizeof(t))) == 0) + printf("REVERSE: %s\n", t); + else + printf("REVERSE: failed (%i).\n", r); + + return 0; +} diff --git a/src/avahi.c b/src/avahi.c new file mode 100644 index 0000000..cd4db00 --- /dev/null +++ b/src/avahi.c @@ -0,0 +1,145 @@ +/* $Id$ */ + +/*** + This file is part of nss-mdns. + + nss-mdns 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 of the + License, or (at your option) any later version. + + nss-mdns 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 + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with nss-mdns; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + + +#include <sys/socket.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <arpa/inet.h> +#include <sys/un.h> +#include <assert.h> +#include <unistd.h> + +#include "avahi.h" +#include "util.h" + +#define AVAHI_SOCKET "/var/run/avahi/socket" + +static FILE *open_socket(void) { + int fd = -1; + struct sockaddr_un sa; + FILE *f; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + goto fail; + + set_cloexec(fd); + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + strncpy(sa.sun_path, AVAHI_SOCKET, sizeof(sa.sun_path)-1); + sa.sun_path[sizeof(sa.sun_path)-1] = 0; + + if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) + goto fail; + + if (!(f = fdopen(fd, "r+"))) + goto fail; + + return f; + +fail: + if (fd >= 0) + close(fd); + + return NULL; + +} + +int avahi_resolve_name(int af, const char* name, void* data) { + FILE *f; + char *e, *p; + int ret = -1; + char ln[256]; + + assert(af == AF_INET || af == AF_INET6); + + if (!(f = open_socket())) + goto finish; + + fprintf(f, "RESOLVE-HOSTNAME%s %s\n", af == AF_INET ? "-IPV4" : "-IPV6", name); + fflush(f); + + if (!(fgets(ln, sizeof(ln), f))) + goto finish; + + if (ln[0] != '+') { + ret = 1; + goto finish; + } + + p = ln+1; + p += strspn(p, "\t "); + e = p + strcspn(p, "\n\r\t "); + *e = 0; + + if (inet_pton(af, p, data) <= 0) + goto finish; + + ret = 0; + +finish: + + if (f) + fclose(f); + + return ret; +} + +int avahi_resolve_address(int af, const void *data, char* name, size_t name_len) { + FILE *f; + char *e, *p; + int ret = -1; + char a[256], ln[256]; + + assert(af == AF_INET || af == AF_INET6); + + if (!(f = open_socket())) + goto finish; + + fprintf(f, "RESOLVE-ADDRESS %s\n", inet_ntop(af, data, a, sizeof(a))); + + if (!(fgets(ln, sizeof(ln), f))) + goto finish; + + if (ln[0] != '+') { + ret = 1; + goto finish; + } + + p = ln+1; + p += strspn(p, "\t "); + e = p + strcspn(p, "\n\r\t "); + *e = 0; + + strncpy(name, p, name_len-1); + name[name_len-1] = 0; + + ret = 0; + +finish: + + if (f) + fclose(f); + + return ret; +} diff --git a/src/avahi.h b/src/avahi.h new file mode 100644 index 0000000..79d1c86 --- /dev/null +++ b/src/avahi.h @@ -0,0 +1,33 @@ +#ifndef fooavahihfoo +#define fooavahihfoo + +/* $Id$ */ + +/*** + This file is part of nss-mdns. + + nss-mdns 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 of the + License, or (at your option) any later version. + + nss-mdns 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 + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with nss-mdns; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + + +#include <inttypes.h> +#include <sys/types.h> + +int avahi_resolve_name(int af, const char* name, void* data); + +int avahi_resolve_address(int af, const void *data, char* name, size_t name_len); + +#endif @@ -34,6 +34,10 @@ #include "query.h" +#ifdef ENABLE_AVAHI +#include "avahi.h" +#endif + #define MAX_ENTRIES 16 #ifdef NSS_IPV4_ONLY @@ -161,6 +165,10 @@ enum nss_status _nss_mdns_gethostbyname2_r( void (*ipv4_func)(const ipv4_address_t *ipv4, void *userdata); void (*ipv6_func)(const ipv6_address_t *ipv6, void *userdata); +#ifdef ENABLE_AVAHI + uint8_t data[128]; +#endif + /* DEBUG_TRAP; */ #ifdef NSS_IPV4_ONLY @@ -195,39 +203,56 @@ enum nss_status _nss_mdns_gethostbyname2_r( goto finish; } - if ((fd = mdns_open_socket()) < 0) { - - *errnop = errno; - *h_errnop = NO_RECOVERY; - goto finish; - } - u.count = 0; u.data_len = 0; -#ifndef NSS_IPV6_ONLY - ipv4_func = af == AF_INET ? ipv4_callback : NULL; -#else +#ifdef NSS_IPV6_ONLY ipv4_func = NULL; +#else + ipv4_func = af == AF_INET ? ipv4_callback : NULL; #endif -#ifndef NSS_IPV4_ONLY - ipv6_func = af == AF_INET6 ? ipv6_callback : NULL; -#else +#ifdef NSS_IPV4_ONLY ipv6_func = NULL; +#else + ipv6_func = af == AF_INET6 ? ipv6_callback : NULL; #endif - - if ((r = mdns_query_name(fd, name, ipv4_func, ipv6_func, &u)) < 0) { + +#ifdef ENABLE_AVAHI + + if ((r = avahi_resolve_name(af, name, data)) == 0) { + if (af == AF_INET && ipv4_func) + ipv4_func((ipv4_address_t*) data, &u); + if (af == AF_INET6 && ipv4_func) + ipv6_func((ipv6_address_t*)data, &u); + } else if (r > 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; goto finish; } + +#endif + if (u.count == 0) { + if ((fd = mdns_open_socket()) < 0) { + + *errnop = errno; + *h_errnop = NO_RECOVERY; + goto finish; + } + + if ((r = mdns_query_name(fd, name, ipv4_func, ipv6_func, &u)) < 0) { + *errnop = ETIMEDOUT; + *h_errnop = HOST_NOT_FOUND; + goto finish; + } + } + /* Alias names */ *((char**) buffer) = NULL; result->h_aliases = (char**) buffer; index = sizeof(char*); - + /* Official name */ strcpy(buffer+index, name); result->h_name = buffer+index; @@ -235,7 +260,7 @@ enum nss_status _nss_mdns_gethostbyname2_r( result->h_addrtype = af; result->h_length = address_length; - + /* Check if there's enough space for the addresses */ if (buflen < index+u.data_len+sizeof(char*)*(u.count+1)) { *errnop = ERANGE; @@ -302,6 +327,9 @@ enum nss_status _nss_mdns_gethostbyaddr_r( enum nss_status status = NSS_STATUS_UNAVAIL; int fd = -1, r; size_t address_length, index, astart; +#ifdef ENABLE_AVAHI + char t[256]; +#endif *errnop = EINVAL; *h_errnop = NO_RECOVERY; @@ -335,31 +363,46 @@ enum nss_status _nss_mdns_gethostbyaddr_r( goto finish; } - - if ((fd = mdns_open_socket()) < 0) { - *errnop = errno; - *h_errnop = NO_RECOVERY; +#ifdef ENABLE_AVAHI + + if ((r = avahi_resolve_address(af, addr, t, sizeof(t))) == 0) { + name_callback(t, &u); + } else if (r > 0) { + *errnop = ETIMEDOUT; + *h_errnop = HOST_NOT_FOUND; goto finish; } +#endif + + if (u.count == 0) { + + if ((fd = mdns_open_socket()) < 0) { + + *errnop = errno; + *h_errnop = NO_RECOVERY; + goto finish; + } + #if ! defined(NSS_IPV6_ONLY) && ! defined(NSS_IPV4_ONLY) - if (af == AF_INET) + if (af == AF_INET) #endif #ifndef NSS_IPV6_ONLY - r = mdns_query_ipv4(fd, (ipv4_address_t*) addr, name_callback, &u); + r = mdns_query_ipv4(fd, (ipv4_address_t*) addr, name_callback, &u); #endif #if ! defined(NSS_IPV6_ONLY) && ! defined(NSS_IPV4_ONLY) - else + else #endif #ifndef NSS_IPV4_ONLY - r = mdns_query_ipv6(fd, (ipv6_address_t*) addr, name_callback, &u); + r = mdns_query_ipv6(fd, (ipv6_address_t*) addr, name_callback, &u); #endif - - if (r < 0) { - *errnop = ETIMEDOUT; - *h_errnop = HOST_NOT_FOUND; - goto finish; + + if (r < 0) { + *errnop = ETIMEDOUT; + *h_errnop = HOST_NOT_FOUND; + goto finish; + } } /* Alias names */ diff --git a/src/query.c b/src/query.c index b59513e..32401fc 100644 --- a/src/query.c +++ b/src/query.c @@ -220,7 +220,7 @@ static int send_dns_packet(int fd, struct dns_packet *p) { return n_sent; } -static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t* ret_ttl, struct timeval *end) { +static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t *ret_ttl, struct timeval *end) { struct dns_packet *p= NULL; struct msghdr msg; struct iovec io; |