strlst-test \
avahi-test \
alternative-test \
- conformance-test
+ conformance-test \
+ avahi-reflector
libavahi_core_la_SOURCES = \
timeeventq.c timeeventq.h\
conformance_test_CFLAGS = $(AM_CFLAGS)
conformance_test_LDADD = $(AM_LDADD)
+avahi_reflector_SOURCES = \
+ avahi-reflector.c \
+ $(libavahi_core_la_SOURCES)
+avahi_reflector_CFLAGS = $(AM_CFLAGS)
+avahi_reflector_LDADD = $(AM_LDADD)
+
valgrind: avahi-test
libtool --mode=execute valgrind ./avahi-test
--- /dev/null
+/* $Id$ */
+
+/***
+ This file is part of avahi.
+
+ avahi 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.
+
+ avahi 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 avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#include <avahi-core/core.h>
+#include <avahi-core/alternative.h>
+
+int main(int argc, char*argv[]) {
+ AvahiServer *server;
+ AvahiServerConfig config;
+ GMainLoop *loop;
+
+
+ avahi_server_config_init(&config);
+ config.register_hinfo = FALSE;
+ config.register_addresses = FALSE;
+ config.announce_domain = FALSE;
+ config.use_ipv6 = FALSE;
+ config.enable_reflector = TRUE;
+
+ server = avahi_server_new(NULL, &config, NULL, NULL);
+ avahi_server_config_free(&config);
+
+ loop = g_main_loop_new(NULL, FALSE);
+
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+
+ avahi_server_free(server);
+}
#include <arpa/inet.h>
#include <stdlib.h>
-#include "core.h"
-#include "alternative.h"
+#include <avahi-core/core.h>
+#include <avahi-core/alternative.h>
static AvahiEntryGroup *group = NULL;
static AvahiServer *server = NULL;
gboolean check_response_ttl; /**< If enabled the server ignores all incoming responses with IP TTL != 255 */
gboolean announce_domain; /**< Announce the local domain for browsing */
gboolean use_iff_running; /**< Require IFF_RUNNING on local network interfaces. This is the official way to check for link beat. Unfortunately this doesn't work with all drivers. So bettere leave this off. */
+ gboolean enable_reflector; /**< Reflect incoming mDNS traffic to all local networks. This allows mDNS based network browsing beyond ethernet borders */
} AvahiServerConfig;
/** Allocate a new mDNS responder object. */
AvahiServer *avahi_server_new(
GMainContext *c, /**< The GLIB main loop context to attach to */
- const AvahiServerConfig *sc, /**< If non-NULL a pointer to a configuration structure for the server */
+ const AvahiServerConfig *sc, /**< If non-NULL a pointer to a configuration structure for the server. The server makes an internal deep copy of this structure, so you may free it using avahi_server_config_done() immediately after calling this function. */
AvahiServerCallback callback, /**< A callback which is called whenever the state of the server changes */
gpointer userdata /**< An opaque pointer which is passed to the callback function */);
/** Free an mDNS responder object */
void avahi_server_free(AvahiServer* s);
-AvahiServerConfig* avahi_server_config_init(AvahiServerConfig *c);
-AvahiServerConfig* avahi_server_config_copy(AvahiServerConfig *ret, const AvahiServerConfig *c);
+/** Fill in default values for a server configuration structure. If you
+ * make use of an AvahiServerConfig structure be sure to initialize
+ * it with this function for the sake of upwards library
+ * compatibility. This call may allocate strings on the heap. To
+ * release this memory make sure to call
+ * avahi_server_config_done(). If you want to replace any strings in
+ * the structure be sure to free the strings filled in by this
+ * function with g_free() first and allocate the replacements with
+ * g_malloc() (or g_strdup()).*/
+AvahiServerConfig* avahi_server_config_init(
+ AvahiServerConfig *c /**< A structure which shall be filled in */ );
+
+/** Make a deep copy of the configuration structure *c to *ret. */
+AvahiServerConfig* avahi_server_config_copy(
+ AvahiServerConfig *ret /**< destination */,
+ const AvahiServerConfig *c /**< source */);
+
+/** Free the data in a server configuration structure. */
void avahi_server_config_free(AvahiServerConfig *c);
-
+
+/** Return the currently chosen domain name of the server object. The
+ * return value points to an internally allocated string. Be sure to
+ * make a copy of the string before calling any other library
+ * functions. */
const gchar* avahi_server_get_domain_name(AvahiServer *s);
+
+/** Return the currently chosen host name. The return value points to a internally allocated string. */
const gchar* avahi_server_get_host_name(AvahiServer *s);
+
+/** Return the currently chosen host name as a FQDN ("fully qualified
+ * domain name", i.e. the concatenation of the host and domain
+ * name). The return value points to a internally allocated string. */
const gchar* avahi_server_get_host_name_fqdn(AvahiServer *s);
void avahi_server_set_host_name(AvahiServer *s, const gchar *host_name);
avahi_record_list_flush(s->record_list);
}
+
+static void reflect_response(AvahiServer *s, AvahiInterface *i, AvahiRecord *r, gboolean flush_cache) {
+ AvahiInterface *j;
+
+ g_assert(s);
+ g_assert(i);
+ g_assert(r);
+
+ if (!s->config.enable_reflector)
+ return;
+
+ for (j = s->monitor->interfaces; j; j = j->interface_next)
+ if (j != i)
+ avahi_interface_post_response(j, r, flush_cache, NULL, TRUE);
+}
+
+static void reflect_query(AvahiServer *s, AvahiInterface *i, AvahiKey *k) {
+ AvahiInterface *j;
+
+ g_assert(s);
+ g_assert(i);
+ g_assert(k);
+
+ if (!s->config.enable_reflector)
+ return;
+
+ for (j = s->monitor->interfaces; j; j = j->interface_next)
+ if (j != i)
+ avahi_interface_post_query(j, k, TRUE);
+}
+
+static void reflect_probe(AvahiServer *s, AvahiInterface *i, AvahiRecord *r) {
+ AvahiInterface *j;
+
+ g_assert(s);
+ g_assert(i);
+ g_assert(r);
+
+ if (!s->config.enable_reflector)
+ return;
+
+ for (j = s->monitor->interfaces; j; j = j->interface_next)
+ if (j != i)
+ avahi_interface_post_probe(j, r, TRUE);
+}
+
static void handle_query(AvahiServer *s, AvahiDnsPacket *p, AvahiInterface *i, const AvahiAddress *a, guint16 port, gboolean legacy_unicast) {
guint n;
goto fail;
}
+ reflect_query(s, i, key);
avahi_query_scheduler_incoming(i->query_scheduler, key);
avahi_server_prepare_matching_responses(s, i, key, unicast_response);
avahi_key_unref(key);
goto fail;
}
- if (record->key->type != AVAHI_DNS_TYPE_ANY)
+ if (record->key->type != AVAHI_DNS_TYPE_ANY) {
+ reflect_probe(s, i, record);
incoming_probe(s, record, i);
+ }
avahi_record_unref(record);
}
/* g_free(txt); */
if (handle_conflict(s, i, record, cache_flush, a)) {
+ reflect_response(s, i, record, cache_flush);
avahi_cache_update(i->cache, record, cache_flush, a);
avahi_response_scheduler_incoming(i->response_scheduler, record, cache_flush);
}
c->check_response_ttl = TRUE;
c->announce_domain = TRUE;
c->use_iff_running = FALSE;
+ c->enable_reflector = FALSE;
return c;
}
if (ret_sa->sin_addr.s_addr == INADDR_ANY) {
/* Linux 2.4 behaves very strangely sometimes! */
+
+ avahi_hexdump(AVAHI_DNS_PACKET_DATA(p), l);
+
+
goto fail;
}
todo:
-* Add some APIs to get the clean service name from RR for browsing
+* reflector:
+ - handle legacy unicast
+ - handle unicast reply
+ - handle known answer
+
+* debug linux 2.4 spurious packet
* test against apple test suite