summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-12-17 01:20:43 +0000
committerLennart Poettering <lennart@poettering.net>2004-12-17 01:20:43 +0000
commite0d7d87d0a583785385478617ff2ff4a34ba007e (patch)
treec6ad95b6b1ff459af4c7f029c5411988d7308c73
parent1440ff002fb551eec469170476e25658c494e12a (diff)
* bump version number
* update README * send mDNS queries on all local interfaces that support multicasts git-svn-id: file:///home/lennart/svn/public/nss-mdns/trunk@64 0ee8848e-81ea-0310-a63a-f631d1a40d77
-rw-r--r--configure.ac2
-rw-r--r--doc/README.html.in14
-rw-r--r--src/query.c118
3 files changed, 110 insertions, 24 deletions
diff --git a/configure.ac b/configure.ac
index 65ae43c..848645e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@
# USA.
AC_PREREQ(2.57)
-AC_INIT([nss-mdns],[0.1],[mzaffzqaf (at) 0pointer (dot) de])
+AC_INIT([nss-mdns],[0.2],[mzaffzqaf (at) 0pointer (dot) de])
AC_CONFIG_SRCDIR([src/query.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign -Wall])
diff --git a/doc/README.html.in b/doc/README.html.in
index 532b508..c9d1493 100644
--- a/doc/README.html.in
+++ b/doc/README.html.in
@@ -42,6 +42,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</p>
<h2><a name="news">News</a></h2>
+<div class="news-date">Mon Dec 17 2004: </div> <p class="news-text"><a
+href="@PACKAGE_URL@nss-mdns-0.2.tar.gz">Version 0.2</a>
+released. Changes include: send mDNS queries on every interface that
+supports multicasts, instead of only the one with the default route,
+making <tt>nss-mdns</tt> more robust on multi-homed hosts; gcc 2.95
+compatiblity.</p>
+
<div class="news-date">Mon Dec 6 2004: </div> <p class="news-text"><a
href="@PACKAGE_URL@nss-mdns-0.1.tar.gz">Version 0.1</a> released</p>
@@ -59,8 +66,8 @@ means that you have to run a mDNS responder daemon seperately
from <tt>nss-mdns</tt> if you want to register the local host name via
mDNS (e.g. <a href="http://www.porchdogsoft.com/products/howl/">HOWL</a>).</p>
-<p><tt>nss-mdns</tt> is very lightweight (18 KByte stripped binary <tt>.so</tt> compiled with
-<tt>-DNDEBUG=1</tt>), has no dependencies besides the <tt>glibc</tt> and requires only minimal
+<p><tt>nss-mdns</tt> is very lightweight (22 KByte stripped binary <tt>.so</tt> compiled with
+<tt>-DNDEBUG=1</tt> on i386, <tt>gcc</tt> 3.3), has no dependencies besides the <tt>glibc</tt> and requires only minimal
configuration.</p>
<h2><a name="status">Status</a></h2>
@@ -120,6 +127,9 @@ use <tt>glibc</tt>'s <tt>getent</tt> tool:
repeated mDNS resolutions are slowed down. Consider installing <tt>glibc</tt>'s name
service cache daemon <tt>nscd</tt> to work around this limitation.</p>
+<p>When doing troubleshooting for <tt>nss-mdns</tt>, don't forget to
+disable <tt>nscd</tt> for getting sensible results.</p>
+
<h2><a name="requirements">Requirements</a></h2>
<p>Currently, <tt>nss-mdns</tt> is tested on Linux only. A fairly modern <tt>glibc</tt> installation with development headers (2.0 or newer) is required. Not
diff --git a/src/query.c b/src/query.c
index b534433..6f5900c 100644
--- a/src/query.c
+++ b/src/query.c
@@ -34,6 +34,8 @@
#include <fcntl.h>
#include <assert.h>
#include <sys/time.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
#include "dns.h"
#include "util.h"
@@ -89,7 +91,12 @@ int mdns_open_socket(void) {
}
if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
- fprintf(stderr, "O_RECVTTL failed: %s\n", strerror(errno));
+ fprintf(stderr, "IP_RECVTTL failed: %s\n", strerror(errno));
+ goto fail;
+ }
+
+ if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
+ fprintf(stderr, "IP_PKTINFO failed: %s\n", strerror(errno));
goto fail;
}
@@ -114,24 +121,99 @@ fail:
static int send_dns_packet(int fd, struct dns_packet *p) {
struct sockaddr_in sa;
- assert(fd >= 0 && p);
+ struct msghdr msg;
+ struct iovec io;
+ struct cmsghdr *cmsg;
+ struct in_pktinfo *pkti;
+ uint8_t cmsg_data[sizeof(struct cmsghdr) + sizeof(struct in_pktinfo)];
+ int i, n;
+ struct ifreq ifreq[32];
+ struct ifconf ifconf;
+ int n_sent = 0;
+ assert(fd >= 0 && p);
assert(dns_packet_check_valid(p) >= 0);
mdns_mcast_group(&sa);
- for (;;) {
- if (sendto(fd, p->data, p->size, 0, (struct sockaddr*) &sa, sizeof(sa)) >= 0)
- return 0;
+ memset(&io, 0, sizeof(io));
+ io.iov_base = p->data;
+ io.iov_len = p->size;
- if (errno != EAGAIN) {
- fprintf(stderr, "sendto() failed: %s\n", strerror(errno));
- return -1;
- }
+ memset(cmsg_data, 0, sizeof(cmsg_data));
+ cmsg = (struct cmsghdr*) cmsg_data;
+ cmsg->cmsg_len = sizeof(cmsg_data);
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+
+ pkti = (struct in_pktinfo*) (cmsg_data + sizeof(struct cmsghdr));
+ pkti->ipi_ifindex = 0;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = &sa;
+ msg.msg_namelen = sizeof(sa);
+ msg.msg_iov = &io;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg_data;
+ msg.msg_controllen = sizeof(cmsg_data);
+ msg.msg_flags = 0;
+
+ ifconf.ifc_req = ifreq;
+ ifconf.ifc_len = sizeof(ifreq);
+
+ if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0) {
+ fprintf(stderr, "SIOCGIFCONF failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ for (i = 0, n = ifconf.ifc_len/sizeof(struct ifreq); i < n; i++) {
+ struct sockaddr_in *sa;
+ u_int32_t s_addr;
+
+ /* Check if this is the loopback device or any other invalid interface */
+ sa = (struct sockaddr_in*) &ifreq[i].ifr_addr;
+ s_addr = htonl(sa->sin_addr.s_addr);
+ if (sa->sin_family != AF_INET ||
+ s_addr == INADDR_LOOPBACK ||
+ s_addr == INADDR_ANY ||
+ s_addr == INADDR_BROADCAST)
+ continue;
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifreq[i]) < 0)
+ continue; /* Since SIOCGIFCONF and this call is not
+ * issued in a transaction, we ignore errors
+ * here, since the interface may have vanished
+ * since that call */
+
+ /* Check whether this network interface supports multicasts and is up and running */
+ if (!(ifreq[i].ifr_flags & IFF_MULTICAST) ||
+ !(ifreq[i].ifr_flags & IFF_UP) ||
+ !(ifreq[i].ifr_flags & IFF_RUNNING))
+ continue;
+
+ if (ioctl(fd, SIOCGIFINDEX, &ifreq[i]) < 0)
+ continue; /* See above why we ignore this error */
+
+ pkti->ipi_ifindex = ifreq[i].ifr_ifindex;
+
+ for (;;) {
- if (wait_for_write(fd, NULL) < 0)
- return -1;
+ if (sendmsg(fd, &msg, MSG_DONTROUTE) >= 0)
+ break;
+
+ if (errno != EAGAIN) {
+ fprintf(stderr, "sendmsg() failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (wait_for_write(fd, NULL) < 0)
+ return -1;
+ }
+
+ n_sent++;
}
+
+ return n_sent;
}
static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t* ret_ttl, struct timeval *end) {
@@ -139,7 +221,7 @@ static int recv_dns_packet(int fd, struct dns_packet **ret_packet, uint8_t* ret_
struct msghdr msg;
struct iovec io;
int ret = -1;
- uint8_t aux[16];
+ uint8_t aux[64];
assert(fd >= 0);
p = dns_packet_new();
@@ -245,10 +327,7 @@ static int send_name_query(int fd, const char *name, int query_ipv4, int query_i
dns_packet_set_field(p, DNS_FIELD_QDCOUNT, qdcount);
- if (send_dns_packet(fd, p) < 0)
- goto finish;
-
- ret = 0;
+ ret = send_dns_packet(fd, p);
finish:
if (p)
@@ -418,10 +497,7 @@ static int send_reverse_query(int fd, const char *name) {
dns_packet_set_field(p, DNS_FIELD_QDCOUNT, 1);
- if (send_dns_packet(fd, p) < 0)
- goto finish;
-
- ret = 0;
+ ret = send_dns_packet(fd, p);
finish:
if (p)
@@ -509,7 +585,7 @@ static int query_reverse(int fd, const char *name, void (*name_func)(const char
while (*timeout > 0) {
int n;
- if (send_reverse_query(fd, name) < 0)
+ if (send_reverse_query(fd, name) <= 0) /* error or no interface to send data on */
return -1;
if ((n = process_reverse_response(fd, name, *timeout, name_func, userdata)) < 0)