summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-06-22 00:36:49 +0000
committerLennart Poettering <lennart@poettering.net>2005-06-22 00:36:49 +0000
commit6dc69c9a94e128f6703ddfcc38c253f0c8cc9d7b (patch)
treed55c5b2d5b18bb088d80d8ba5ed72c350743eb91
parent7a2a47660cceac9a053f739cf79f71d5bfb85c7c (diff)
* add support for using an avahi daemon if available
git-svn-id: file:///home/lennart/svn/public/nss-mdns/trunk@81 0ee8848e-81ea-0310-a63a-f631d1a40d77
-rw-r--r--configure.ac17
-rw-r--r--src/Makefile.am11
-rw-r--r--src/avahi-test.c48
-rw-r--r--src/avahi.c145
-rw-r--r--src/avahi.h33
-rw-r--r--src/nss.c103
-rw-r--r--src/query.c2
7 files changed, 324 insertions, 35 deletions
diff --git a/configure.ac b/configure.ac
index 2f41827..e8d42ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,5 +83,22 @@ fi
AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes])
+AC_ARG_ENABLE(avahi,
+ AC_HELP_STRING([--enable-avahi],[use Avahi (default=yes)]),
+ [case "${enableval}" in
+ yes) ENABLE_AVAHI=yes ;;
+ no) ENABLE_AVAHI=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-avahi) ;;
+ esac],
+ [ENABLE_AVAHI=yes]) dnl Default value
+
+
+AM_CONDITIONAL([ENABLE_AVAHI], [test "x$ENABLE_AVAHI" = "xyes"])
+
+if test "x$ENABLE_AVAHI" = "xyes" ; then
+ AC_DEFINE(ENABLE_AVAHI, [1], [Try to make use of a running avahi mDNS server before resolving on our own behalf])
+fi
+
+
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile doc/README.html ])
AC_OUTPUT
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
diff --git a/src/nss.c b/src/nss.c
index 7802b09..c54db7b 100644
--- a/src/nss.c
+++ b/src/nss.c
@@ -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;