? etc/afpd/afp_avahi.c
? etc/afpd/afp_avahi.c.org
? etc/afpd/afp_avahi.h
? etc/afpd/afp_avahi.h.org
? etc/afpd/afp_bonjour.c
? etc/afpd/afp_bonjour.c.org
? etc/afpd/afp_bonjour.h
? etc/afpd/afp_bonjour.h.org
? etc/afpd/afp_howl.c
? etc/afpd/afp_howl.c.org
? etc/afpd/afp_howl.h
? etc/afpd/afp_howl.h.org
? etc/afpd/afp_zeroconf.c
? etc/afpd/afp_zeroconf.c.org
? etc/afpd/afp_zeroconf.h
? etc/afpd/afp_zeroconf.h.org
? macros/zeroconf.m4
? macros/zeroconf.m4.org
Index: configure.in
===================================================================
RCS file: /cvsroot/netatalk/netatalk/configure.in,v
retrieving revision 1.203
diff -u -r1.203 configure.in
--- configure.in	28 Apr 2005 20:49:17 -0000	1.203
+++ configure.in	5 May 2006 10:46:30 -0000
@@ -398,6 +398,9 @@
 dnl Check for optional server location protocol support (used by MacOS X)
 NETATALK_SRVLOC
 
+dnl Check for optional Zeroconf support
+NETATALK_ZEROCONF
+
 dnl Check for PAM libs
 netatalk_cv_use_pam=no
 AC_PATH_PAM([
Index: config/afpd.conf.tmpl
===================================================================
RCS file: /cvsroot/netatalk/netatalk/config/afpd.conf.tmpl,v
retrieving revision 1.16
diff -u -r1.16 afpd.conf.tmpl
--- config/afpd.conf.tmpl	28 Apr 2005 20:49:20 -0000	1.16
+++ config/afpd.conf.tmpl	5 May 2006 10:46:31 -0000
@@ -51,6 +51,8 @@
 #			  empty string.
 #     -noslp              Don't register this server with the Service
 #			  Location Protocol.
+#     -nozeroconf              Don't register this server with the Multicats
+#			  DNS Protocol.
 #
 #
 #   Authentication Methods:
Index: contrib/a2boot/Makefile.am
===================================================================
RCS file: /cvsroot/netatalk/netatalk/contrib/a2boot/Makefile.am,v
retrieving revision 1.5
diff -u -r1.5 Makefile.am
--- contrib/a2boot/Makefile.am	28 Apr 2005 20:49:21 -0000	1.5
+++ contrib/a2boot/Makefile.am	5 May 2006 10:46:32 -0000
@@ -10,7 +10,7 @@
 EXTRA_DIST = COPYRIGHT VERSION
 
 CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
-	 @CFLAGS@ @SLP_CFLAGS@ \
+	 @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
 	 -D_PATH_A_GS_BLOCKS=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Boot\ Blocks\" \
 	 -D_PATH_A_2E_BLOCKS=\"$(PKGCONFDIR)/a2boot/Apple\ :2f:2fe\ Boot\ Blocks\" \
 	 -D_PATH_P16_IMAGE=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Image\"
Index: etc/afpd/Makefile.am
===================================================================
RCS file: /cvsroot/netatalk/netatalk/etc/afpd/Makefile.am,v
retrieving revision 1.38
diff -u -r1.38 Makefile.am
--- etc/afpd/Makefile.am	30 Apr 2005 21:33:41 -0000	1.38
+++ etc/afpd/Makefile.am	5 May 2006 10:46:33 -0000
@@ -8,19 +8,21 @@
 	 file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
 	 mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c  \
 	 afp_config.c nfsquota.c quota.c uam.c afs.c uid.c afp_util.c \
-         catsearch.c afprun.c
+         catsearch.c afprun.c \
+         afp_zeroconf.c afp_avahi.c afp_bonjour.c afp_howl.c
 
 afpd_LDADD =  $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
 afpd_LDFLAGS = -export-dynamic
 
 noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
 	 filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
-	 uam_auth.h uid.h unix.h volume.h
+	 uam_auth.h uid.h unix.h volume.h \
+         afp_zeroconf.h afp_avahi.h afp_bonjour.h afp_howl.h
 
-LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@
+LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @ZEROCONF_LIBS@ @WRAP_LIBS@
 
 CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
-	 @CFLAGS@ @SLP_CFLAGS@ \
+	 @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
 	 -D_PATH_AFPDDEFVOL=\"$(pkgconfdir)/AppleVolumes.default\" \
 	 -D_PATH_AFPDSYSVOL=\"$(pkgconfdir)/AppleVolumes.system\" \
 	 -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
Index: etc/afpd/afp_config.c
===================================================================
RCS file: /cvsroot/netatalk/netatalk/etc/afpd/afp_config.c,v
retrieving revision 1.23
diff -u -r1.23 afp_config.c
--- etc/afpd/afp_config.c	28 Apr 2005 20:49:39 -0000	1.23
+++ etc/afpd/afp_config.c	5 May 2006 10:46:35 -0000
@@ -50,6 +50,9 @@
 #ifdef USE_SRVLOC
 #include <slp.h>
 #endif /* USE_SRVLOC */
+#ifdef USE_ZEROCONF
+#include "afp_zeroconf.h"
+#endif /* USE_ZEROCONF */
 
 #include "globals.h"
 #include "afp_config.h"
@@ -154,9 +157,9 @@
 }
 #endif /* USE_SRVLOC */
 
-#ifdef USE_SRVLOC
 static void dsi_cleanup(const AFPConfig *config)
 {
+#ifdef USE_SRVLOC
     SLPError err;
     SLPError callbackerr;
     SLPHandle hslp;
@@ -189,8 +192,16 @@
 srvloc_dereg_err:
     dsi->srvloc_url[0] = '\0';
     SLPClose(hslp);
-}
+#elif defined (USE_ZEROCONF)
+    DSI *dsi = (DSI *)config->obj.handle;
+
+    /*  Do nothing if we didn't register.  */
+    if (!dsi || dsi->zeroconf_registered == 0)
+        return;
+
+    zeroconf_deregister();
 #endif /* USE_SRVLOC */
+}
 
 #ifndef NO_DDP
 static void asp_cleanup(const AFPConfig *config)
@@ -355,6 +366,10 @@
     struct servent *afpovertcp;
     int afp_port = 548;
     char *srvloc_hostname, *hostname;
+#elif defined (USE_ZEROCONF)
+    struct servent *afpovertcp;
+    int afp_port = 548;
+    char *hostname = NULL;
 #endif /* USE_SRVLOC */
 
     if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
@@ -449,6 +464,36 @@
     }
 #endif /* USE_SRVLOC */
 
+#ifdef USE_ZEROCONF
+    dsi->zeroconf_registered = 0; /*  Mark that we haven't registered.  */
+
+    if (!(options->flags & OPTION_NOZEROCONF)) {
+        /* XXX We don't want to tack on the port number if we don't have to.
+    	   * Why?
+    	   * Well, this seems to break MacOS < 10.  If the user _really_ wants to
+    	   * use a non-default port, they can, but be aware, this server might
+    	   * not show up int the Network Browser.
+    	   */
+        afpovertcp = getservbyname("afpovertcp", "tcp");
+        if (afpovertcp != NULL) {
+    	      afp_port = ntohs(afpovertcp->s_port);
+        }
+
+        /* If specified use the FQDN to register with srvloc, otherwise use IP. */
+        p = NULL;
+        if (options->fqdn) {
+            hostname = options->fqdn;
+            p = strchr(hostname, ':');
+        }	
+        else 
+            hostname = inet_ntoa(dsi->server.sin_addr);
+
+        if (!(options->flags & OPTION_NOSLP)) {
+            zeroconf_register(afp_port, hostname);
+            dsi->zeroconf_registered = 1; /*  Mark that we have registered.  */
+        }
+    }
+#endif /* USE_ZEROCONF */
 
     config->fd = dsi->serversock;
     config->obj.handle = dsi;
@@ -469,6 +514,9 @@
 #ifdef USE_SRVLOC
     config->server_cleanup = dsi_cleanup;
 #endif 
+#ifdef USE_ZEROCONF
+    config->server_cleanup = dsi_cleanup;
+#endif
     return config;
 }
 
Index: etc/afpd/afp_options.c
===================================================================
RCS file: /cvsroot/netatalk/netatalk/etc/afpd/afp_options.c,v
retrieving revision 1.35
diff -u -r1.35 afp_options.c
--- etc/afpd/afp_options.c	28 Apr 2005 20:49:39 -0000	1.35
+++ etc/afpd/afp_options.c	5 May 2006 10:46:39 -0000
@@ -202,10 +202,15 @@
     /* parse toggles */
     if (strstr(buf, " -nodebug"))
         options->flags &= ~OPTION_DEBUG;
+
 #ifdef USE_SRVLOC
     if (strstr(buf, " -noslp"))
         options->flags |= OPTION_NOSLP;
 #endif /* USE_SRVLOC */
+#ifdef USE_ZEROCONF
+    if (strstr(buf, " -nozeroconf"))
+        options->flags |= OPTION_NOZEROCONF;
+#endif
 
     if (strstr(buf, " -nouservolfirst"))
         options->flags &= ~OPTION_USERVOLFIRST;
@@ -578,6 +583,12 @@
 	puts( "No" );
 #endif
 
+#ifdef USE_ZEROCONF
+	puts( "Yes" );
+#else
+	puts( "No" );
+#endif
+
 	printf( "  TCP wrappers support:\t" );
 #ifdef TCPWRAP
 	puts( "Yes" );
Index: etc/afpd/globals.h
===================================================================
RCS file: /cvsroot/netatalk/netatalk/etc/afpd/globals.h,v
retrieving revision 1.21
diff -u -r1.21 globals.h
--- etc/afpd/globals.h	28 Apr 2005 20:49:43 -0000	1.21
+++ etc/afpd/globals.h	5 May 2006 10:46:39 -0000
@@ -40,6 +40,7 @@
 #define OPTION_CUSTOMICON    (1 << 4)
 #define OPTION_NOSLP         (1 << 5)
 #define OPTION_ANNOUNCESSH   (1 << 6)
+#define OPTION_NOZEROCONF    (1 << 7)
 
 #ifdef FORCE_UIDGID
 /* set up a structure for this */
Index: include/atalk/dsi.h
===================================================================
RCS file: /cvsroot/netatalk/netatalk/include/atalk/dsi.h,v
retrieving revision 1.6
diff -u -r1.6 dsi.h
--- include/atalk/dsi.h	3 May 2005 14:55:12 -0000	1.6
+++ include/atalk/dsi.h	5 May 2006 10:46:41 -0000
@@ -85,6 +85,10 @@
   char srvloc_url[512];
 #endif 
 
+#ifdef USE_ZEROCONF
+  int zeroconf_registered;
+#endif
+
   /* buffer for OSX deadlock */
   int noblocking;
   char *buffer;
Index: macros/summary.m4
===================================================================
RCS file: /cvsroot/netatalk/netatalk/macros/summary.m4,v
retrieving revision 1.2
diff -u -r1.2 summary.m4
--- macros/summary.m4	28 Apr 2005 20:50:05 -0000	1.2
+++ macros/summary.m4	5 May 2006 10:46:46 -0000
@@ -44,6 +44,7 @@
 	AC_MSG_RESULT([    Options:])
 	AC_MSG_RESULT([         CUPS support:           $netatalk_cv_use_cups])
 	AC_MSG_RESULT([         SLP support:            $netatalk_cv_srvloc])
+	AC_MSG_RESULT([         Zeroconf support:       $netatalk_cv_zeroconf])
 	AC_MSG_RESULT([         tcp wrapper support:    $netatalk_cv_tcpwrap])
 dnl	if test x"$netatalk_cv_linux_sendfile" != x; then
 dnl		AC_MSG_RESULT([         Linux sendfile support: $netatalk_cv_linux_sendfile])
Index: man/man5/afpd.conf.5.tmpl
===================================================================
RCS file: /cvsroot/netatalk/netatalk/man/man5/afpd.conf.5.tmpl,v
retrieving revision 1.4
diff -u -r1.4 afpd.conf.5.tmpl
--- man/man5/afpd.conf.5.tmpl	28 Apr 2005 20:50:06 -0000	1.4
+++ man/man5/afpd.conf.5.tmpl	5 May 2006 10:46:48 -0000
@@ -210,6 +210,9 @@
 Protocol (if SLP support was compiled in). This is useful if you are
 running multiple servers and want one to be hidden, perhaps because
 it is advertised elsewhere, ie. by a SLP Directory Agent.
+\-noslp
+Do not register this server using the Multicast DNS
+Protocol (if Zeroconf support was compiled in).
 .SH "MISCELLANEOUS OPTIONS"
 .TP 
 \-admingroup \fI[group]\fR
--- etc/afpd/afp_avahi.c.org	2006-04-21 10:29:22.000000000 +0200
+++ etc/afpd/afp_avahi.c	2006-04-22 08:34:34.000000000 +0200
@@ -0,0 +1,500 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Avahi based Zeroconf support
+ * Docs:    http://avahi.org/download/doxygen/
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_AVAHI
+
+#include "afp_avahi.h"
+
+static void publish_reply(AvahiEntryGroup *g,
+                          AvahiEntryGroupState state,
+                          void *userdata);
+
+/*
+ * This function tries to register the AFP DNS
+ * SRV service type.
+ */
+static void register_stuff(struct context *ctx) {
+  char r[128];
+  int ret;
+
+  assert(ctx->client);
+
+  if (!ctx->group) {
+
+    if (!(ctx->group = avahi_entry_group_new(ctx->client,
+                                             publish_reply,
+                                             ctx))) {
+      LOG(log_error,
+          logtype_afpd,
+          "Failed to create entry group: %s\n",
+          avahi_strerror(avahi_client_errno(ctx->client)));
+      goto fail;
+    }
+
+  }
+
+  LOG(log_info, logtype_afpd, "Adding service '%s'\n", ctx->name);
+
+  if (avahi_entry_group_is_empty(ctx->group)) {
+    /* Register our service */
+
+    if (avahi_entry_group_add_service(ctx->group,
+                                      AVAHI_IF_UNSPEC,
+                                      AVAHI_PROTO_UNSPEC,
+                                      0,
+                                      ctx->name,
+                                      AFP_DNS_SERVICE_TYPE,
+                                      NULL,
+                                      NULL,
+                                      ctx->port,
+                                      NULL) < 0) {
+      LOG(log_error,
+          logtype_afpd,
+          "Failed to add service: %s\n",
+          avahi_strerror(avahi_client_errno(ctx->client)));
+      goto fail;
+    }
+
+    if (avahi_entry_group_commit(ctx->group) < 0) {
+      LOG(log_error,
+          logtype_afpd,
+          "Failed to commit entry group: %s\n",
+          avahi_strerror(avahi_client_errno(ctx->client)));
+      goto fail;
+    }
+  }
+
+  return;
+
+  fail:
+    avahi_client_free (ctx->client);
+#ifndef HAVE_AVAHI_THREADED_POLL
+    avahi_simple_poll_quit(ctx->simple_poll);
+#else
+    avahi_threaded_poll_quit(ctx->threaded_poll);
+#endif
+}
+
+/* Called when publishing of service data completes */
+static void publish_reply(AvahiEntryGroup *g,
+                          AvahiEntryGroupState state,
+                          AVAHI_GCC_UNUSED void *userdata)
+{
+  struct context *ctx = userdata;
+
+  assert(g == ctx->group);
+
+  switch (state) {
+
+  case AVAHI_ENTRY_GROUP_ESTABLISHED :
+    /* The entry group has been established successfully */
+    break;
+
+  case AVAHI_ENTRY_GROUP_COLLISION: {
+    char *n;
+
+    /* Pick a new name for our service */
+
+    n = avahi_alternative_service_name(ctx->name);
+    assert(n);
+
+    avahi_free(ctx->name);
+    ctx->name = n;
+
+    register_stuff(ctx);
+    break;
+  }
+
+  case AVAHI_ENTRY_GROUP_FAILURE: {
+    LOG(log_error,
+        logtype_afpd,
+        "Failed to register service: %s\n",
+        avahi_strerror(avahi_client_errno(ctx->client)));
+    avahi_client_free (avahi_entry_group_get_client(g));
+#ifndef HAVE_AVAHI_THREADED_POLL
+    avahi_simple_poll_quit(ctx->simple_poll);
+#else
+    avahi_threaded_poll_quit(ctx->threaded_poll);
+#endif
+    break;
+  }
+
+  case AVAHI_ENTRY_GROUP_UNCOMMITED:
+  case AVAHI_ENTRY_GROUP_REGISTERING:
+    ;
+  }
+}
+
+static void client_callback(AvahiClient *client,
+                            AvahiClientState state,
+                            void *userdata)
+{
+  struct context *ctx = userdata;
+
+  ctx->client = client;
+
+  switch (state) {
+
+  case AVAHI_CLIENT_S_RUNNING:
+
+    /* The server has startup successfully and registered its host
+     * name on the network, so it's time to create our services */
+    if (!ctx->group)
+      register_stuff(ctx);
+    break;
+
+  case AVAHI_CLIENT_S_COLLISION:
+
+    if (ctx->group)
+      avahi_entry_group_reset(ctx->group);
+    break;
+
+  case AVAHI_CLIENT_FAILURE: {
+
+    if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) {
+      int error;
+
+      avahi_client_free(ctx->client);
+      ctx->client = NULL;
+      ctx->group = NULL;
+
+      /* Reconnect to the server */
+
+#ifndef HAVE_AVAHI_THREADED_POLL
+      if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
+#else
+      if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
+#endif
+                                           AVAHI_CLIENT_NO_FAIL,
+                                           client_callback,
+                                           ctx,
+                                           &error))) {
+
+        LOG(log_error,
+            logtype_afpd,
+            "Failed to contact server: %s\n",
+            avahi_strerror(error));
+
+        avahi_client_free (ctx->client);
+#ifndef HAVE_AVAHI_THREADED_POLL
+        avahi_simple_poll_quit(ctx->simple_poll);
+#else
+        avahi_threaded_poll_quit(ctx->threaded_poll);
+#endif
+      }
+
+      } else {
+        LOG(log_error,
+            logtype_afpd,
+            "Client failure: %s\n",
+            avahi_strerror(avahi_client_errno(client)));
+
+        avahi_client_free (ctx->client);
+#ifndef HAVE_AVAHI_THREADED_POLL
+        avahi_simple_poll_quit(ctx->simple_poll);
+#else
+        avahi_threaded_poll_quit(ctx->threaded_poll);
+#endif
+      }
+
+    break;
+  }
+
+  case AVAHI_CLIENT_S_REGISTERING:
+  case AVAHI_CLIENT_CONNECTING:
+    ;
+  }
+}
+
+static void* thread(void *userdata) {
+#ifndef HAVE_AVAHI_THREADED_POLL
+  struct context *ctx = userdata;
+  sigset_t mask;
+  int r;
+
+  /* Make sure that signals are delivered to the main thread */
+  sigfillset(&mask);
+  pthread_sigmask(SIG_BLOCK, &mask, NULL);
+    
+  pthread_mutex_lock(&ctx->mutex);
+
+  /* Run the main loop */
+  LOG(log_info, logtype_afpd, "Starting avahi loop...");
+  r = avahi_simple_poll_loop(ctx->simple_poll);
+
+  /* Cleanup some stuff */
+  if (ctx->client)
+    avahi_client_free(ctx->client);
+  ctx->client = NULL;
+  ctx->group = NULL;
+    
+  pthread_mutex_unlock(&ctx->mutex);
+#endif    
+  return NULL;
+}
+
+static int poll_func(struct pollfd *ufds,
+                     unsigned int nfds,
+                     int timeout,
+                     void *userdata) {
+#ifndef HAVE_AVAHI_THREADED_POLL
+  pthread_mutex_t *mutex = userdata;
+  int r;
+
+  /* Before entering poll() we unlock the mutex, so that
+   * avahi_simple_poll_quit() can succeed from another thread. */
+    
+  pthread_mutex_unlock(mutex);
+  r = poll(ufds, nfds, timeout);
+  pthread_mutex_lock(mutex);
+
+  return r;
+#else
+  return 0;
+#endif
+}
+
+/*
+ * Tries to setup the Zeroconf thread and any
+ * neccessary config setting.
+ */
+void* av_zeroconf_setup(unsigned long port, const char *name) {
+  struct context *ctx = NULL;
+
+  /* default service name, if there's none in
+   * the config file.
+   */
+  char service[256] = "AFP Server on ";
+  int error, ret;
+
+  /* initialize the struct that holds our
+   * config settings.
+   */
+  ctx = malloc(sizeof(struct context));
+  assert(ctx);
+  ctx->client = NULL;
+  ctx->group = NULL;
+#ifndef HAVE_AVAHI_THREADED_POLL
+  ctx->simple_poll = NULL;
+  pthread_mutex_init(&ctx->mutex, NULL);
+#else
+  ctx->threaded_poll = NULL;
+#endif
+  ctx->thread_running = 0;
+
+  LOG(log_info,
+      logtype_afpd,
+      "Setting port for Zeroconf service to: %i.\n",
+      port);  
+  ctx->port = port;
+
+  /* Prepare service name */
+  if (!name) {
+    LOG(log_info,
+        logtype_afpd,
+        "Assigning default service name.\n");
+    gethostname(service+14, sizeof(service)-15);
+    service[sizeof(service)-1] = 0;
+
+    ctx->name = strdup(service);
+  }
+  else {
+    ctx->name = strdup(name);
+  }
+
+  assert(ctx->name);
+
+/* first of all we need to initialize our threading env */
+#ifdef HAVE_AVAHI_THREADED_POLL
+  if (!(ctx->threaded_poll = avahi_threaded_poll_new())) {
+     goto fail;
+  }
+#else
+  if (!(ctx->simple_poll = avahi_simple_poll_new())) {
+      LOG(log_error,
+          logtype_afpd,
+          "Failed to create event loop object.\n");
+      goto fail;
+  }
+
+  avahi_simple_poll_set_func(ctx->simple_poll, poll_func, &ctx->mutex);
+#endif
+
+/* now we need to acquire a client */
+#ifdef HAVE_AVAHI_THREADED_POLL
+  if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
+                                       AVAHI_CLIENT_NO_FAIL,
+                                       client_callback,
+                                       ctx,
+                                       &error))) {
+    LOG(log_error,
+        logtype_afpd,
+        "Failed to create client object: %s\n",
+        avahi_strerror(avahi_client_errno(ctx->client)));
+    goto fail;
+  }
+#else
+  if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
+                                       AVAHI_CLIENT_NO_FAIL,
+                                       client_callback,
+                                       ctx,
+                                       &error))) {
+    LOG(log_error,
+        logtype_afpd,
+        "Failed to create client object: %s\n",
+        avahi_strerror(avahi_client_errno(ctx->client)));
+    goto fail;
+  }
+#endif
+
+  return ctx;
+
+fail:
+
+  if (ctx)
+    av_zeroconf_unregister(ctx);
+
+  return NULL;
+}
+
+/*
+ * This function finally runs the loop impl.
+ */
+int av_zeroconf_run(void *u) {
+  struct context *ctx = u;
+  int ret;
+
+#ifdef HAVE_AVAHI_THREADED_POLL
+  /* Finally, start the event loop thread */
+  if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) {
+    LOG(log_error,
+        logtype_afpd,
+        "Failed to create thread: %s\n",
+        avahi_strerror(avahi_client_errno(ctx->client)));
+    goto fail;
+  } else {
+    LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
+  }
+#else
+  /* Create the mDNS event handler */
+  if ((ret = pthread_create(&ctx->thread_id, NULL, thread, ctx)) < 0) {
+    LOG(log_error,
+        logtype_afpd,
+        "Failed to create thread: %s\n", strerror(ret));
+    goto fail;
+  } else {
+    LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
+  }
+#endif
+
+  ctx->thread_running = 1;
+
+  return 0;
+
+fail:
+
+  if (ctx)
+    av_zeroconf_unregister(ctx);
+
+  return -1;
+}
+
+/*
+ * Used to lock access to the loop.
+ * Currently unused.
+ */
+void av_zeroconf_lock(void *u) {
+#ifdef HAVE_AVAHI_THREADED_POLL
+  struct context *ctx = u;
+
+  avahi_threaded_poll_lock(ctx->threaded_poll);
+#endif
+}
+
+/*
+ * Used to unlock access to the loop.
+ * Currently unused.
+ */
+void av_zeroconf_unlock(void *u) {
+#ifdef HAVE_AVAHI_THREADED_POLL
+  struct context *ctx = u;
+
+  avahi_threaded_poll_unlock(ctx->threaded_poll);
+#endif
+}
+
+/*
+ * Tries to shutdown this loop impl.
+ * Call this function from outside this thread.
+ */
+void av_zeroconf_shutdown(void *u) {
+  struct context *ctx = u;
+
+  /* Call this when the app shuts down */
+#ifdef HAVE_AVAHI_THREADED_POLL
+  avahi_threaded_poll_stop(ctx->threaded_poll);
+  avahi_free(ctx->name);
+  avahi_client_free(ctx->client);
+  avahi_threaded_poll_free(ctx->threaded_poll);
+#else
+  av_zeroconf_unregister(ctx);
+#endif
+}
+
+/*
+ * Tries to shutdown this loop impl.
+ * Call this function from inside this thread.
+ */
+int av_zeroconf_unregister(void *u) {
+  struct context *ctx = u;
+
+  if (ctx->thread_running) {
+#ifndef HAVE_AVAHI_THREADED_POLL
+    pthread_mutex_lock(&ctx->mutex);
+    avahi_simple_poll_quit(ctx->simple_poll);
+    pthread_mutex_unlock(&ctx->mutex);
+
+    pthread_join(ctx->thread_id, NULL);
+#else
+    /* First, block the event loop */
+    avahi_threaded_poll_lock(ctx->threaded_poll);
+
+    /* Than, do your stuff */
+    avahi_threaded_poll_quit(ctx->threaded_poll);
+
+    /* Finally, unblock the event loop */
+    avahi_threaded_poll_unlock(ctx->threaded_poll);
+#endif
+    ctx->thread_running = 0;
+  }
+
+  avahi_free(ctx->name);
+
+  if (ctx->client)
+    avahi_client_free(ctx->client);
+
+#ifndef HAVE_AVAHI_THREADED_POLL
+  if (ctx->simple_poll)
+    avahi_simple_poll_free(ctx->simple_poll);
+
+  pthread_mutex_destroy(&ctx->mutex);
+#else
+  if (ctx->threaded_poll)
+    avahi_threaded_poll_free(ctx->threaded_poll);
+#endif
+
+  free(ctx);
+
+  return 0;
+}
+
+#endif /* USE_AVAHI */
--- etc/afpd/afp_avahi.h.org	2006-04-21 10:29:23.000000000 +0200
+++ etc/afpd/afp_avahi.h	2006-04-22 07:40:05.000000000 +0200
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Avahi based Zeroconf support
+ * Docs:    http://avahi.org/download/doxygen/
+ *
+ */
+
+#ifndef AFPD_AVAHI_H
+#define AFPD_AVAHI_H
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+
+#include <avahi-common/alternative.h>
+
+#ifndef HAVE_AVAHI_THREADED_POLL
+#include <avahi-common/simple-watch.h>
+#include <signal.h> /* SIG_BLOCK */
+#else
+#include <avahi-common/thread-watch.h>
+#endif
+
+#include <avahi-common/malloc.h>
+#include <avahi-common/error.h>
+
+#include <atalk/logger.h>
+
+#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
+
+struct context {
+  int thread_running;
+  pthread_t thread_id;
+  pthread_mutex_t mutex;
+  char *name;
+#ifndef HAVE_AVAHI_THREADED_POLL
+  AvahiSimplePoll   *simple_poll;
+#else
+  AvahiThreadedPoll *threaded_poll;
+#endif
+  AvahiClient       *client;
+  AvahiEntryGroup   *group;
+  unsigned long     port;
+};
+
+/* prototype definitions */
+void* av_zeroconf_setup(unsigned long, const char *);
+int av_zeroconf_run(void*);
+int av_zeroconf_unregister(void*);
+void av_zeroconf_shutdown(void*);
+void av_zeroconf_lock(void *);
+void av_zeroconf_unlock(void *);
+
+#endif   /* AFPD_AVAHI_H */
--- etc/afpd/afp_bonjour.h.org	2006-04-21 10:29:30.000000000 +0200
+++ etc/afpd/afp_bonjour.h	2006-04-21 07:37:05.000000000 +0200
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Bonjour based Zeroconf support
+ * Docs:    http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
+ *
+ */
+
+#ifndef AFPD_BONJOUR_H
+#define AFPD_BONJOUR_H
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <dns_sd.h>     /* DNSServiceRegister(), DNSServiceDiscoveryDeallocate() */
+
+#include <atalk/logger.h>
+
+#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
+
+/* prototype definitions */
+void* bo_zeroconf_setup(unsigned long, const char *);
+int bo_zeroconf_unregister(void);
+int bo_zeroconf_run(void);
+
+#endif   /* AFPD_BONJOUR_H */
--- etc/afpd/afp_bonjour.c.org	2006-04-21 10:29:28.000000000 +0200
+++ etc/afpd/afp_bonjour.c	2006-04-21 09:45:13.000000000 +0200
@@ -0,0 +1,112 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Bonjour based Zeroconf support
+ * Docs:    http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_BONJOUR
+
+#include "afp_bonjour.h"
+
+DNSServiceRef publish_session = NULL;
+
+static void DNSSD_API
+publish_reply(DNSServiceRef,
+              const DNSServiceFlags,
+              DNSServiceErrorType,
+              const char *,
+              const char *,
+              const char *,
+              void *);
+
+static void DNSSD_API
+publish_reply (DNSServiceRef sdRef,
+         const DNSServiceFlags flags,
+         DNSServiceErrorType errorCode,
+         const char *name,
+         const char *regtype,
+         const char *domain,
+         void *context)
+{
+}
+
+void* bo_zeroconf_setup(unsigned long port, const char *name) {
+  DNSServiceErrorType err;
+  char service[256] = "AFP Server on ";
+
+  /* Prepare service name */
+  if (!name) {
+    LOG(log_info, logtype_afpd,, "Assigning default service name.\n");
+    gethostname(service+14, sizeof(service)-15);
+    service[sizeof(service)-1] = 0;
+
+    name = strdup(service);
+  }
+
+  assert(name);
+  assert(port);
+
+  err = DNSServiceRegister (&publish_session,
+                            0,                    /* flags */
+                            0,                    /* interface; 0 for all */
+                            name,                 /* name */
+                            AFP_DNS_SERVICE_TYPE, /* type */
+                            NULL,                 /* domain */
+                            NULL,                 /* hostname */
+                            htons (port),         /* port in network byte order */
+                            0,                    /* text record length */
+                            NULL,                 /* text record */
+                            publish_reply,        /* callback */
+                            NULL);                /* context */
+
+  if (err == kDNSServiceErr_NoError) {
+    LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
+  } else {
+    LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
+    bo_zeroconf_unregister();
+  }
+}
+
+int bo_zeroconf_run(void) {
+  fd_set set;
+  int fd;
+  struct timeval timeout;
+
+  /* Initialize the file descriptor set. */
+  FD_ZERO (&set);
+  FD_SET (fd, &set);
+
+  /* Initialize the timeout data structure. */
+  /* TODO: Should the value for sec be configurable? */
+  timeout.tv_sec = 10;
+  timeout.tv_usec = 0;
+
+  if (publish_session != NULL) {
+    fd = DNSServiceRefSockFD(publish_session);
+
+    if (select(FD_SETSIZE,
+                  &set, NULL, NULL,
+                  &timeout) > 0) {
+      DNSServiceProcessResult(publish_session);
+    }
+  }
+
+  return 0;
+}
+
+int bo_zeroconf_unregister(void) {
+  if (publish_session != NULL) {
+    DNSServiceRefDeallocate(publish_session);
+    publish_session = NULL;
+  }
+
+  return 0;
+}
+
+#endif /* HAVE_BONJOUR */
--- etc/afpd/afp_howl.c.org	2006-04-21 10:29:34.000000000 +0200
+++ etc/afpd/afp_howl.c	2006-04-21 09:46:11.000000000 +0200
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Howl based Zeroconf support
+ * Doc:     http://www.porchdogsoft.com/products/howl/docs/
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_HOWL
+
+#include "afp_howl.h"
+
+sw_discovery discovery = NULL;
+
+static sw_result HOWL_API publish_reply(sw_discovery,
+                                        sw_discovery_oid,
+                                        sw_discovery_publish_status,
+                                        sw_opaque);
+
+static sw_result HOWL_API publish_reply(sw_discovery discovery,
+                                        sw_discovery_oid oid,
+                                        sw_discovery_publish_status status,
+                                        sw_opaque extra) {
+  static sw_string
+    status_text[] =
+    {
+      "Started",
+      "Stopped",
+      "Name Collision",
+      "Invalid"
+    };
+
+  LOG(log_info, logtype_afpd, "publish reply: %s\n", status_text[status]);
+  return SW_OKAY;
+}
+
+void* ho_zeroconf_setup(unsigned long port, const char *name) {
+  sw_result result;
+  sw_discovery_publish_id id;
+  char service[256] = "AFP Server on ";
+
+  if (sw_discovery_init (&discovery) != SW_OKAY) {
+    LOG(log_error,
+        logtype_afpd,
+        "AFPD could not be started. \nTry running mDNSResponder.");
+    return;
+  }
+
+  /* Prepare service name */
+  if (!name) {
+    LOG(log_info, logtype_afpd, "Assigning default service name.\n");
+    gethostname(service+14, sizeof(service)-15);
+    service[sizeof(service)-1] = 0;
+
+    name = strdup(service);
+  }
+
+  assert(name);
+
+  if (!(result = sw_discovery_publish (discovery,
+                                       0,
+                                       name,
+                                       AFP_DNS_SERVICE_TYPE,
+                                       NULL,
+                                       NULL,
+                                       port,
+                                       NULL,
+                                       0,
+                                       publish_reply,
+                                       NULL,
+                                       &id)) != SW_OKAY) {
+    LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
+  } else {
+    LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
+    ho_zeroconf_unregister();
+  }
+}
+
+void* ho_zeroconf_run(void) {
+  sw_discovery_run(discovery);
+}
+
+void* ho_zeroconf_unregister(void) {
+  sw_discovery_stop_run(discovery);
+  sw_discovery_fina(discovery);
+}
+
+#endif /* USE_HOWL */
--- etc/afpd/afp_howl.h.org	2006-04-21 10:29:33.000000000 +0200
+++ etc/afpd/afp_howl.h	2006-04-21 07:37:11.000000000 +0200
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Howl based Zeroconf support
+ * Doc:     http://www.porchdogsoft.com/products/howl/docs/
+ *
+ */
+
+#ifndef AFPD_HOWL_H
+#define AFPD_HOWL_H
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <howl.h>
+
+#include <atalk/logger.h>
+
+#define NTP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
+
+/* prototype definitions */
+void* ho_zeroconf_setup(unsigned long, const char *);
+void* ho_zeroconf_unregister(void);
+void* ho_zeroconf_run(void);
+
+#endif   /* AFPD_HOWL_H */
--- etc/afpd/afp_zeroconf.h.org	2006-04-21 10:29:39.000000000 +0200
+++ etc/afpd/afp_zeroconf.h	2006-04-21 11:39:20.000000000 +0200
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Zeroconf facade, that abstracts access to a
+ *          particular Zeroconf implementation
+ * Doc:     http://www.dns-sd.org/
+ *
+ */
+
+#ifndef AFPD_ZEROCONF_H
+#define AFPD_ZEROCONF_H
+
+#include <netinet/in.h> /* htons() */
+#include <atalk/logger.h>
+
+# ifdef HAVE_BONJOUR
+# include "afp_bonjour.h"
+# elif defined (HAVE_HOWL)
+# include "afp_howl.h"
+# elif defined (HAVE_AVAHI)
+# include "afp_avahi.h"
+# endif
+
+#define AFP_PORT 548
+
+/*
+ * Prototype Definitions
+ */
+
+/*
+ * registers the ntpd service with a particular Zerconf implemenation.
+ */
+void zeroconf_register(int port, char *hostname);
+
+/*
+ * de-registers the ntpd service with a particular Zerconf implemenation.
+ */
+void zeroconf_deregister(void);
+
+#endif AFPD_ZEROCONF_H
--- etc/afpd/afp_zeroconf.c.org	2006-04-21 10:29:38.000000000 +0200
+++ etc/afpd/afp_zeroconf.c	2006-04-21 13:12:38.000000000 +0200
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+/*
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
+ * Purpose: Zeroconf facade, that abstracts access to a
+ *          particular Zeroconf implementation
+ * Doc:     http://www.dns-sd.org/
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "afp_zeroconf.h"
+
+/*
+ * Global Definitions
+ */
+#ifdef HAVE_AVAHI
+struct context *ctx = NULL;
+#endif
+
+/*
+ * Functions (actually they are just facades)
+ */
+void zeroconf_register(int port, char *hostname)
+{
+#ifdef HAVE_BONJOUR
+  LOG(log_info,
+      logtype_afpd,
+      "Attempting to register with mDNS using Apple's Bonjour\n");
+  if (hostname && strlen(hostname) > 0 && port)
+  {
+    bo_zeroconf_setup(port, hostname);
+  }
+  else if (hostname && strlen(hostname) > 0)
+  {
+    bo_zeroconf_setup(AFP_PORT, hostname);
+  }
+  else
+  {
+    bo_zeroconf_setup(AFP_PORT, NULL);
+  }
+  bo_zeroconf_run();
+#elif defined (HAVE_HOWL)
+  LOG(log_info,
+      logtype_afpd,
+      "Attempting to register with mDNS using Porchdog's Howl\n");
+  if (hostname && strlen(hostname) > 0 && port)
+  {
+    ho_zeroconf_setup(port, hostname);
+  }
+  else if (hostname && strlen(hostname) > 0)
+  {
+    ho_zeroconf_setup(AFP_PORT, hostname);
+  }
+  else
+  {
+    ho_zeroconf_setup(AFP_PORT, NULL);
+  }
+  bo_zeroconf_run();
+#elif defined (HAVE_AVAHI)
+  LOG(log_info, logtype_afpd, "Attempting to register with mDNS using Avahi\n");
+  if (hostname && strlen(hostname) > 0 && port)
+  {
+    ctx = av_zeroconf_setup(port, hostname);
+  }
+  else if (hostname && strlen(hostname) > 0)
+  {
+    ctx = av_zeroconf_setup(AFP_PORT, hostname);
+  }
+  else
+  {
+    ctx = av_zeroconf_setup(AFP_PORT, NULL);
+  }
+  av_zeroconf_run(ctx);
+#endif
+}
+
+void zeroconf_deregister(void)
+{
+#ifdef HAVE_BONJOUR
+  LOG(log_error,
+      logtype_afpd,
+      "Attempting to de-register mDNS using Apple's Bonjour\n");
+  bo_zeroconf_unregister();
+#elif defined (HAVE_HOWL)
+  LOG(log_error,
+      logtype_afpd,
+      "Attempting to de-register mDNS using Porchdog's Howl\n");
+  ho_zeroconf_unregister();
+#elif defined (HAVE_AVAHI)
+  LOG(log_error, logtype_afpd, "Attempting to de-register mDNS using Avahi\n");
+  if (ctx)
+    av_zeroconf_shutdown(ctx);
+#endif
+}
--- macros/zeroconf.m4.org	2006-04-21 10:29:51.000000000 +0200
+++ macros/zeroconf.m4	2006-04-22 07:26:56.000000000 +0200
@@ -0,0 +1,101 @@
+dnl Check for optional Zeroconf support
+
+dnl $Id$
+
+AC_DEFUN([NETATALK_ZEROCONF], [
+
+	ZEROCONF_LIBS=""
+	ZEROCONF_CFLAGS=""
+	found_zeroconf=no
+	zeroconf_dir=""
+
+	AC_ARG_ENABLE(zeroconf,
+		[  --enable-zeroconf[[=DIR]]   enable Zeroconf support [[auto]]],
+		[zeroconf=$enableval],
+		[zeroconf=try]
+	)
+
+    dnl make sure atalk_libname is defined beforehand
+    [[ -n "$atalk_libname" ]] || AC_MSG_ERROR([internal error, atalk_libname undefined])
+
+	if test "x$zeroconf" != "xno"; then
+
+		savedcppflags="$CPPFLAGS"
+		savedldflags="$LDFLAGS"
+
+		if test "x$zeroconf" = "xyes" -o "x$zeroconf" = "xtry"; then
+			zeroconf_dir="/usr"
+		else
+			zeroconf_dir="$zeroconf"
+		fi
+
+		# mDNS support using Apple's Bonjour
+		AC_CHECK_HEADER(dns_sd.h,
+		  [AC_CHECK_LIB(dns_sd,
+		    DNSServiceRegister,
+				  [AC_DEFINE(USE_ZEROCONF, 1,
+				  	[Use DNS-SD registration])])])
+  	case "$ac_cv_lib_dns_sd_DNSServiceRegister" in
+      yes)
+      ZEROCONF_LIBS="-L$zeroconf_dir/lib -ldns_sd"
+      ZEROCONF_LIBS="-I$zeroconf_dir/include"
+      AC_DEFINE(HAVE_BONJOUR, 1, [Use Bonjour/DNS-SD registration])
+      found_zeroconf=yes
+      ;;
+    esac
+    # mDNS support using Porchdog's Howl
+    AC_CHECK_HEADER(howl.h,
+      [AC_CHECK_LIB(howl,
+        sw_discovery_publish,
+        [AC_DEFINE(USE_ZEROCONF, 1,
+          [Use DNS-SD registration])])])
+    case "$ac_cv_lib_howl_sw_discovery_publish" in
+      yes)
+      PKG_CHECK_MODULES(HOWL, [ howl >= 1.0.0 ])
+      ZEROCONF_LIBS="$HOWL_LIBS"
+      ZEROCONF_CFLAGS="$HOWL_CFLAGS"
+      AC_DEFINE(HAVE_HOWL, 1, [Use Howl/DNS-SD registration])
+      found_zeroconf=yes
+      ;;
+    esac
+    # mDNS support using Avahi
+    AC_CHECK_HEADER(avahi-client/client.h,
+      [AC_CHECK_LIB(avahi-client,
+        avahi_client_new,
+				[AC_DEFINE(USE_ZEROCONF, 1,
+          [Use DNS-SD registration])])])
+    case "$ac_cv_lib_avahi_client_avahi_client_new" in
+      yes)
+      PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6 ])
+      PKG_CHECK_MODULES(AVAHI_TPOLL, [ avahi-client >= 0.6.4 ],
+        [AC_DEFINE(HAVE_AVAHI_THREADED_POLL, 1, [Uses Avahis threaded poll implementation])],
+        [AC_MSG_WARN(This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want.)])
+      ZEROCONF_LIBS="$AVAHI_LIBS"
+      ZEROCONF_CFLAGS="$AVAHI_CFLAGS"
+      AC_DEFINE(HAVE_AVAHI, 1, [Use Avahi/DNS-SD registration])
+      found_zeroconf=yes
+      ;;
+    esac
+
+		CPPFLAGS="$savedcppflags"
+		LDFLAGS="$savedldflags"
+	fi
+	
+	netatalk_cv_zeroconf=no
+	AC_MSG_CHECKING([whether to enable Zerconf support])
+	if test "x$found_zeroconf" = "xyes"; then
+		AC_MSG_RESULT([yes])
+		AC_DEFINE(USE_ZEROCONF, 1, [Define to enable Zeroconf support])
+		netatalk_cv_zeroconf=yes
+	else
+		AC_MSG_RESULT([no])
+		if test "x$zeroconf" != "xno" -a "x$zeroconf" != "xtry"; then
+			AC_MSG_ERROR([Zeroconf installation not found])
+		fi
+	fi
+
+	LIB_REMOVE_USR_LIB(ZEROCONF_LIBS)
+	CFLAGS_REMOVE_USR_INCLUDE(ZEROCONF_CFLAGS)
+	AC_SUBST(ZEROCONF_LIBS)
+	AC_SUBST(ZEROCONF_CFLAGS)
+])