~ubuntu-branches/debian/wheezy/netatalk/wheezy

« back to all changes in this revision

Viewing changes to debian/patches/107_afpd-zeroconf.patch

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2011-06-05 21:04:21 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110605210421-19gag2srevj0ocxh
Tags: 2.2~beta4-1
* New upstream release.
  + Fixes "Internal Error" after ad_open on sparc.
    Closes: bug#606005. Thanks to Alfredo Sola.
* Adjust references to unofficial packages in README.Debian.
* Use dversionmangle (not uversionmangle) in watch file. Fix add
  leading dash (-) to upstream version in mangling.
* Update patches:
  + Drop patches 107 and 294 (Zeroconf support): Implemented
    (differently) upstream now.
  + Drop patches 109 and 112 (avoid broken XFS linkage) obsolete.
  + Drop patch 200 (hostname resolving): adopted upstream.
  + Refresh patch 205.
* Rewrite copyright file using draft 174 of DEP-5 format.
* Build-depend on and recommend unversioned (i.e. default) BerkeleyDB
  packages.
  Closes: bug#621413. Thanks to Ondřej Surý.
  Simplify suggestions on older versioned BerkeleyDB packages.
* Stop installing some documentation dropped upstream, and let CDBS
  automagically handle some of the remains.
* Update control file:
  + Bump policy compliance to standards-version 3.9.2.
  + Shorten Vcs-* URLs.
* Add patches 115 and (for automade file) 214 to avoid installing
  unneeded /default dir.
  Closes: bug#628119. Thanks to Russell Muetzelfeldt and Luk Claes.
* Don't ship .la files. Closes: bug#621849. Thanks to Andreas Metzler
  and Luk Claes.
* Stop renaming afile and achfile, dropped upstream.
* Explicitly enable DDP (AppleTalk), now disabled by default.
* Enable Zeroconf, should be stable now.
* Simplify package relations:
  + Drop (build-)dependency fallback unneeded even for oldstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
--- a/configure.in
2
 
+++ b/configure.in
3
 
@@ -386,6 +386,9 @@
4
 
 dnl Check for optional server location protocol support (used by MacOS X)
5
 
 NETATALK_SRVLOC
6
 
 
7
 
+dnl Check for optional Zeroconf support
8
 
+NETATALK_ZEROCONF
9
 
+
10
 
 dnl Check for PAM libs
11
 
 netatalk_cv_use_pam=no
12
 
 AC_PATH_PAM([
13
 
--- a/config/afpd.conf.tmpl
14
 
+++ b/config/afpd.conf.tmpl
15
 
@@ -51,6 +51,8 @@
16
 
 #                        empty string.
17
 
 #     -noslp              Don't register this server with the Service
18
 
 #                        Location Protocol.
19
 
+#     -nozeroconf         Don't register this server with the Multicast
20
 
+#                        DNS Protocol.
21
 
 #
22
 
 #
23
 
 #   Authentication Methods:
24
 
--- a/contrib/a2boot/Makefile.am
25
 
+++ b/contrib/a2boot/Makefile.am
26
 
@@ -10,7 +10,7 @@
27
 
 EXTRA_DIST = COPYRIGHT VERSION
28
 
 
29
 
 CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
30
 
-        @CFLAGS@ @SLP_CFLAGS@ \
31
 
+        @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
32
 
         -D_PATH_A_GS_BLOCKS=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Boot\ Blocks\" \
33
 
         -D_PATH_A_2E_BLOCKS=\"$(PKGCONFDIR)/a2boot/Apple\ :2f:2fe\ Boot\ Blocks\" \
34
 
         -D_PATH_P16_IMAGE=\"$(PKGCONFDIR)/a2boot/ProDOS16\ Image\"
35
 
--- a/etc/afpd/Makefile.am
36
 
+++ b/etc/afpd/Makefile.am
37
 
@@ -8,19 +8,21 @@
38
 
         file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
39
 
         mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c  \
40
 
         afp_config.c nfsquota.c quota.c uam.c afs.c uid.c afp_util.c \
41
 
-         catsearch.c afprun.c
42
 
+         catsearch.c afprun.c \
43
 
+         afp_zeroconf.c afp_avahi.c afp_bonjour.c afp_howl.c
44
 
 
45
 
 afpd_LDADD =  $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
46
 
 afpd_LDFLAGS = -export-dynamic
47
 
 
48
 
 noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
49
 
         filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
50
 
-        uam_auth.h uid.h unix.h volume.h
51
 
+        uam_auth.h uid.h unix.h volume.h \
52
 
+         afp_zeroconf.h afp_avahi.h afp_bonjour.h afp_howl.h
53
 
 
54
 
-LIBS = @LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@
55
 
+LIBS = @LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @ZEROCONF_LIBS@ @WRAP_LIBS@ @LIBADD_DL@
56
 
 
57
 
 CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/sys \
58
 
-        @CFLAGS@ @SLP_CFLAGS@ \
59
 
+        @CFLAGS@ @SLP_CFLAGS@ @ZEROCONF_CFLAGS@ \
60
 
         -D_PATH_AFPDDEFVOL=\"$(pkgconfdir)/AppleVolumes.default\" \
61
 
         -D_PATH_AFPDSYSVOL=\"$(pkgconfdir)/AppleVolumes.system\" \
62
 
         -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
63
 
--- a/etc/afpd/afp_config.c
64
 
+++ b/etc/afpd/afp_config.c
65
 
@@ -50,6 +50,9 @@
66
 
 #ifdef USE_SRVLOC
67
 
 #include <slp.h>
68
 
 #endif /* USE_SRVLOC */
69
 
+#ifdef USE_ZEROCONF
70
 
+#include "afp_zeroconf.h"
71
 
+#endif /* USE_ZEROCONF */
72
 
 
73
 
 #include "globals.h"
74
 
 #include "afp_config.h"
75
 
@@ -154,9 +157,9 @@
76
 
 }
77
 
 #endif /* USE_SRVLOC */
78
 
 
79
 
-#ifdef USE_SRVLOC
80
 
 static void dsi_cleanup(const AFPConfig *config)
81
 
 {
82
 
+#ifdef USE_SRVLOC
83
 
     SLPError err;
84
 
     SLPError callbackerr;
85
 
     SLPHandle hslp;
86
 
@@ -189,8 +192,16 @@
87
 
 srvloc_dereg_err:
88
 
     dsi->srvloc_url[0] = '\0';
89
 
     SLPClose(hslp);
90
 
-}
91
 
+#elif defined (USE_ZEROCONF)
92
 
+    DSI *dsi = (DSI *)config->obj.handle;
93
 
+
94
 
+    /*  Do nothing if we didn't register.  */
95
 
+    if (!dsi || dsi->zeroconf_registered == 0)
96
 
+        return;
97
 
+
98
 
+    zeroconf_deregister();
99
 
 #endif /* USE_SRVLOC */
100
 
+}
101
 
 
102
 
 #ifndef NO_DDP
103
 
 static void asp_cleanup(const AFPConfig *config)
104
 
@@ -355,6 +366,10 @@
105
 
     struct servent *afpovertcp;
106
 
     int afp_port = 548;
107
 
     char *srvloc_hostname, *hostname;
108
 
+#elif defined (USE_ZEROCONF)
109
 
+    struct servent *afpovertcp;
110
 
+    int afp_port = 548;
111
 
+    char *hostname = NULL;
112
 
 #endif /* USE_SRVLOC */
113
 
 
114
 
     if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) {
115
 
@@ -449,6 +464,36 @@
116
 
     }
117
 
 #endif /* USE_SRVLOC */
118
 
 
119
 
+#ifdef USE_ZEROCONF
120
 
+    dsi->zeroconf_registered = 0; /*  Mark that we haven't registered.  */
121
 
+
122
 
+    if (!(options->flags & OPTION_NOZEROCONF)) {
123
 
+        /* XXX We don't want to tack on the port number if we don't have to.
124
 
+          * Why?
125
 
+          * Well, this seems to break MacOS < 10.  If the user _really_ wants to
126
 
+          * use a non-default port, they can, but be aware, this server might
127
 
+          * not show up int the Network Browser.
128
 
+          */
129
 
+        afpovertcp = getservbyname("afpovertcp", "tcp");
130
 
+        if (afpovertcp != NULL) {
131
 
+             afp_port = ntohs(afpovertcp->s_port);
132
 
+        }
133
 
+
134
 
+        /* If specified use the FQDN to register with srvloc, otherwise use IP. */
135
 
+        p = NULL;
136
 
+        if (options->fqdn) {
137
 
+            hostname = options->fqdn;
138
 
+            p = strchr(hostname, ':');
139
 
+        }      
140
 
+        else 
141
 
+            hostname = inet_ntoa(dsi->server.sin_addr);
142
 
+
143
 
+        if (!(options->flags & OPTION_NOSLP)) {
144
 
+            zeroconf_register(afp_port, hostname);
145
 
+            dsi->zeroconf_registered = 1; /*  Mark that we have registered.  */
146
 
+        }
147
 
+    }
148
 
+#endif /* USE_ZEROCONF */
149
 
 
150
 
     config->fd = dsi->serversock;
151
 
     config->obj.handle = dsi;
152
 
@@ -469,6 +514,9 @@
153
 
 #ifdef USE_SRVLOC
154
 
     config->server_cleanup = dsi_cleanup;
155
 
 #endif 
156
 
+#ifdef USE_ZEROCONF
157
 
+    config->server_cleanup = dsi_cleanup;
158
 
+#endif
159
 
     return config;
160
 
 }
161
 
 
162
 
--- a/etc/afpd/afp_options.c
163
 
+++ b/etc/afpd/afp_options.c
164
 
@@ -202,10 +202,15 @@
165
 
     /* parse toggles */
166
 
     if (strstr(buf, " -nodebug"))
167
 
         options->flags &= ~OPTION_DEBUG;
168
 
+
169
 
 #ifdef USE_SRVLOC
170
 
     if (strstr(buf, " -noslp"))
171
 
         options->flags |= OPTION_NOSLP;
172
 
 #endif /* USE_SRVLOC */
173
 
+#ifdef USE_ZEROCONF
174
 
+    if (strstr(buf, " -nozeroconf"))
175
 
+        options->flags |= OPTION_NOZEROCONF;
176
 
+#endif
177
 
 
178
 
     if (strstr(buf, " -nouservolfirst"))
179
 
         options->flags &= ~OPTION_USERVOLFIRST;
180
 
@@ -578,6 +583,12 @@
181
 
        puts( "No" );
182
 
 #endif
183
 
 
184
 
+#ifdef USE_ZEROCONF
185
 
+       puts( "Yes" );
186
 
+#else
187
 
+       puts( "No" );
188
 
+#endif
189
 
+
190
 
        printf( "  TCP wrappers support:\t" );
191
 
 #ifdef TCPWRAP
192
 
        puts( "Yes" );
193
 
--- a/etc/afpd/globals.h
194
 
+++ b/etc/afpd/globals.h
195
 
@@ -35,6 +35,7 @@
196
 
 #define OPTION_CUSTOMICON    (1 << 4)
197
 
 #define OPTION_NOSLP         (1 << 5)
198
 
 #define OPTION_ANNOUNCESSH   (1 << 6)
199
 
+#define OPTION_NOZEROCONF    (1 << 7)
200
 
 
201
 
 #ifdef FORCE_UIDGID
202
 
 /* set up a structure for this */
203
 
--- a/include/atalk/dsi.h
204
 
+++ b/include/atalk/dsi.h
205
 
@@ -86,6 +86,10 @@
206
 
   char srvloc_url[512];
207
 
 #endif 
208
 
 
209
 
+#ifdef USE_ZEROCONF
210
 
+  int zeroconf_registered;
211
 
+#endif
212
 
+
213
 
   /* buffer for OSX deadlock */
214
 
   int noblocking;
215
 
   char *buffer;
216
 
--- a/macros/summary.m4
217
 
+++ b/macros/summary.m4
218
 
@@ -49,6 +49,7 @@
219
 
        AC_MSG_RESULT([    Options:])
220
 
        AC_MSG_RESULT([         CUPS support:           $netatalk_cv_use_cups])
221
 
        AC_MSG_RESULT([         SLP support:            $netatalk_cv_srvloc])
222
 
+       AC_MSG_RESULT([         Zeroconf support:       $netatalk_cv_zeroconf])
223
 
        AC_MSG_RESULT([         tcp wrapper support:    $netatalk_cv_tcpwrap])
224
 
 dnl    if test x"$netatalk_cv_linux_sendfile" != x; then
225
 
 dnl            AC_MSG_RESULT([         Linux sendfile support: $netatalk_cv_linux_sendfile])
226
 
--- a/man/man5/afpd.conf.5.tmpl
227
 
+++ b/man/man5/afpd.conf.5.tmpl
228
 
@@ -269,6 +269,12 @@
229
 
 Do not register this server using the Service Location Protocol (if SLP
230
 
 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\&.
231
 
 .RE
232
 
+.PP
233
 
+\-nozeroconf
234
 
+.RS 4
235
 
+Do not register this server using the Multicast DNS Protocol (if Zeroconf
236
 
+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\&.
237
 
+.RE
238
 
 .SH "MISCELLANEOUS OPTIONS"
239
 
 .PP
240
 
 \-admingroup \fI[group]\fR
241
 
--- a/etc/afpd/afp_avahi.c
242
 
+++ b/etc/afpd/afp_avahi.c
243
 
@@ -0,0 +1,500 @@
244
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
245
 
+/*
246
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
247
 
+ * Purpose: Avahi based Zeroconf support
248
 
+ * Docs:    http://avahi.org/download/doxygen/
249
 
+ *
250
 
+ */
251
 
+
252
 
+#ifdef HAVE_CONFIG_H
253
 
+#include <config.h>
254
 
+#endif
255
 
+
256
 
+#ifdef HAVE_AVAHI
257
 
+
258
 
+#include "afp_avahi.h"
259
 
+
260
 
+static void publish_reply(AvahiEntryGroup *g,
261
 
+                          AvahiEntryGroupState state,
262
 
+                          void *userdata);
263
 
+
264
 
+/*
265
 
+ * This function tries to register the AFP DNS
266
 
+ * SRV service type.
267
 
+ */
268
 
+static void register_stuff(struct context *ctx) {
269
 
+  char r[128];
270
 
+  int ret;
271
 
+
272
 
+  assert(ctx->client);
273
 
+
274
 
+  if (!ctx->group) {
275
 
+
276
 
+    if (!(ctx->group = avahi_entry_group_new(ctx->client,
277
 
+                                             publish_reply,
278
 
+                                             ctx))) {
279
 
+      LOG(log_error,
280
 
+          logtype_afpd,
281
 
+          "Failed to create entry group: %s\n",
282
 
+          avahi_strerror(avahi_client_errno(ctx->client)));
283
 
+      goto fail;
284
 
+    }
285
 
+
286
 
+  }
287
 
+
288
 
+  LOG(log_info, logtype_afpd, "Adding service '%s'\n", ctx->name);
289
 
+
290
 
+  if (avahi_entry_group_is_empty(ctx->group)) {
291
 
+    /* Register our service */
292
 
+
293
 
+    if (avahi_entry_group_add_service(ctx->group,
294
 
+                                      AVAHI_IF_UNSPEC,
295
 
+                                      AVAHI_PROTO_UNSPEC,
296
 
+                                      0,
297
 
+                                      ctx->name,
298
 
+                                      AFP_DNS_SERVICE_TYPE,
299
 
+                                      NULL,
300
 
+                                      NULL,
301
 
+                                      ctx->port,
302
 
+                                      NULL) < 0) {
303
 
+      LOG(log_error,
304
 
+          logtype_afpd,
305
 
+          "Failed to add service: %s\n",
306
 
+          avahi_strerror(avahi_client_errno(ctx->client)));
307
 
+      goto fail;
308
 
+    }
309
 
+
310
 
+    if (avahi_entry_group_commit(ctx->group) < 0) {
311
 
+      LOG(log_error,
312
 
+          logtype_afpd,
313
 
+          "Failed to commit entry group: %s\n",
314
 
+          avahi_strerror(avahi_client_errno(ctx->client)));
315
 
+      goto fail;
316
 
+    }
317
 
+  }
318
 
+
319
 
+  return;
320
 
+
321
 
+  fail:
322
 
+    avahi_client_free (ctx->client);
323
 
+#ifndef HAVE_AVAHI_THREADED_POLL
324
 
+    avahi_simple_poll_quit(ctx->simple_poll);
325
 
+#else
326
 
+    avahi_threaded_poll_quit(ctx->threaded_poll);
327
 
+#endif
328
 
+}
329
 
+
330
 
+/* Called when publishing of service data completes */
331
 
+static void publish_reply(AvahiEntryGroup *g,
332
 
+                          AvahiEntryGroupState state,
333
 
+                          AVAHI_GCC_UNUSED void *userdata)
334
 
+{
335
 
+  struct context *ctx = userdata;
336
 
+
337
 
+  assert(g == ctx->group);
338
 
+
339
 
+  switch (state) {
340
 
+
341
 
+  case AVAHI_ENTRY_GROUP_ESTABLISHED :
342
 
+    /* The entry group has been established successfully */
343
 
+    break;
344
 
+
345
 
+  case AVAHI_ENTRY_GROUP_COLLISION: {
346
 
+    char *n;
347
 
+
348
 
+    /* Pick a new name for our service */
349
 
+
350
 
+    n = avahi_alternative_service_name(ctx->name);
351
 
+    assert(n);
352
 
+
353
 
+    avahi_free(ctx->name);
354
 
+    ctx->name = n;
355
 
+
356
 
+    register_stuff(ctx);
357
 
+    break;
358
 
+  }
359
 
+
360
 
+  case AVAHI_ENTRY_GROUP_FAILURE: {
361
 
+    LOG(log_error,
362
 
+        logtype_afpd,
363
 
+        "Failed to register service: %s\n",
364
 
+        avahi_strerror(avahi_client_errno(ctx->client)));
365
 
+    avahi_client_free (avahi_entry_group_get_client(g));
366
 
+#ifndef HAVE_AVAHI_THREADED_POLL
367
 
+    avahi_simple_poll_quit(ctx->simple_poll);
368
 
+#else
369
 
+    avahi_threaded_poll_quit(ctx->threaded_poll);
370
 
+#endif
371
 
+    break;
372
 
+  }
373
 
+
374
 
+  case AVAHI_ENTRY_GROUP_UNCOMMITED:
375
 
+  case AVAHI_ENTRY_GROUP_REGISTERING:
376
 
+    ;
377
 
+  }
378
 
+}
379
 
+
380
 
+static void client_callback(AvahiClient *client,
381
 
+                            AvahiClientState state,
382
 
+                            void *userdata)
383
 
+{
384
 
+  struct context *ctx = userdata;
385
 
+
386
 
+  ctx->client = client;
387
 
+
388
 
+  switch (state) {
389
 
+
390
 
+  case AVAHI_CLIENT_S_RUNNING:
391
 
+
392
 
+    /* The server has startup successfully and registered its host
393
 
+     * name on the network, so it's time to create our services */
394
 
+    if (!ctx->group)
395
 
+      register_stuff(ctx);
396
 
+    break;
397
 
+
398
 
+  case AVAHI_CLIENT_S_COLLISION:
399
 
+
400
 
+    if (ctx->group)
401
 
+      avahi_entry_group_reset(ctx->group);
402
 
+    break;
403
 
+
404
 
+  case AVAHI_CLIENT_FAILURE: {
405
 
+
406
 
+    if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) {
407
 
+      int error;
408
 
+
409
 
+      avahi_client_free(ctx->client);
410
 
+      ctx->client = NULL;
411
 
+      ctx->group = NULL;
412
 
+
413
 
+      /* Reconnect to the server */
414
 
+
415
 
+#ifndef HAVE_AVAHI_THREADED_POLL
416
 
+      if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
417
 
+#else
418
 
+      if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
419
 
+#endif
420
 
+                                           AVAHI_CLIENT_NO_FAIL,
421
 
+                                           client_callback,
422
 
+                                           ctx,
423
 
+                                           &error))) {
424
 
+
425
 
+        LOG(log_error,
426
 
+            logtype_afpd,
427
 
+            "Failed to contact server: %s\n",
428
 
+            avahi_strerror(error));
429
 
+
430
 
+        avahi_client_free (ctx->client);
431
 
+#ifndef HAVE_AVAHI_THREADED_POLL
432
 
+        avahi_simple_poll_quit(ctx->simple_poll);
433
 
+#else
434
 
+        avahi_threaded_poll_quit(ctx->threaded_poll);
435
 
+#endif
436
 
+      }
437
 
+
438
 
+      } else {
439
 
+        LOG(log_error,
440
 
+            logtype_afpd,
441
 
+            "Client failure: %s\n",
442
 
+            avahi_strerror(avahi_client_errno(client)));
443
 
+
444
 
+        avahi_client_free (ctx->client);
445
 
+#ifndef HAVE_AVAHI_THREADED_POLL
446
 
+        avahi_simple_poll_quit(ctx->simple_poll);
447
 
+#else
448
 
+        avahi_threaded_poll_quit(ctx->threaded_poll);
449
 
+#endif
450
 
+      }
451
 
+
452
 
+    break;
453
 
+  }
454
 
+
455
 
+  case AVAHI_CLIENT_S_REGISTERING:
456
 
+  case AVAHI_CLIENT_CONNECTING:
457
 
+    ;
458
 
+  }
459
 
+}
460
 
+
461
 
+static void* thread(void *userdata) {
462
 
+#ifndef HAVE_AVAHI_THREADED_POLL
463
 
+  struct context *ctx = userdata;
464
 
+  sigset_t mask;
465
 
+  int r;
466
 
+
467
 
+  /* Make sure that signals are delivered to the main thread */
468
 
+  sigfillset(&mask);
469
 
+  pthread_sigmask(SIG_BLOCK, &mask, NULL);
470
 
+    
471
 
+  pthread_mutex_lock(&ctx->mutex);
472
 
+
473
 
+  /* Run the main loop */
474
 
+  LOG(log_info, logtype_afpd, "Starting avahi loop...");
475
 
+  r = avahi_simple_poll_loop(ctx->simple_poll);
476
 
+
477
 
+  /* Cleanup some stuff */
478
 
+  if (ctx->client)
479
 
+    avahi_client_free(ctx->client);
480
 
+  ctx->client = NULL;
481
 
+  ctx->group = NULL;
482
 
+    
483
 
+  pthread_mutex_unlock(&ctx->mutex);
484
 
+#endif    
485
 
+  return NULL;
486
 
+}
487
 
+
488
 
+static int poll_func(struct pollfd *ufds,
489
 
+                     unsigned int nfds,
490
 
+                     int timeout,
491
 
+                     void *userdata) {
492
 
+#ifndef HAVE_AVAHI_THREADED_POLL
493
 
+  pthread_mutex_t *mutex = userdata;
494
 
+  int r;
495
 
+
496
 
+  /* Before entering poll() we unlock the mutex, so that
497
 
+   * avahi_simple_poll_quit() can succeed from another thread. */
498
 
+    
499
 
+  pthread_mutex_unlock(mutex);
500
 
+  r = poll(ufds, nfds, timeout);
501
 
+  pthread_mutex_lock(mutex);
502
 
+
503
 
+  return r;
504
 
+#else
505
 
+  return 0;
506
 
+#endif
507
 
+}
508
 
+
509
 
+/*
510
 
+ * Tries to setup the Zeroconf thread and any
511
 
+ * neccessary config setting.
512
 
+ */
513
 
+void* av_zeroconf_setup(unsigned long port, const char *name) {
514
 
+  struct context *ctx = NULL;
515
 
+
516
 
+  /* default service name, if there's none in
517
 
+   * the config file.
518
 
+   */
519
 
+  char service[256] = "AFP Server on ";
520
 
+  int error, ret;
521
 
+
522
 
+  /* initialize the struct that holds our
523
 
+   * config settings.
524
 
+   */
525
 
+  ctx = malloc(sizeof(struct context));
526
 
+  assert(ctx);
527
 
+  ctx->client = NULL;
528
 
+  ctx->group = NULL;
529
 
+#ifndef HAVE_AVAHI_THREADED_POLL
530
 
+  ctx->simple_poll = NULL;
531
 
+  pthread_mutex_init(&ctx->mutex, NULL);
532
 
+#else
533
 
+  ctx->threaded_poll = NULL;
534
 
+#endif
535
 
+  ctx->thread_running = 0;
536
 
+
537
 
+  LOG(log_info,
538
 
+      logtype_afpd,
539
 
+      "Setting port for Zeroconf service to: %i.\n",
540
 
+      port);  
541
 
+  ctx->port = port;
542
 
+
543
 
+  /* Prepare service name */
544
 
+  if (!name) {
545
 
+    LOG(log_info,
546
 
+        logtype_afpd,
547
 
+        "Assigning default service name.\n");
548
 
+    gethostname(service+14, sizeof(service)-15);
549
 
+    service[sizeof(service)-1] = 0;
550
 
+
551
 
+    ctx->name = strdup(service);
552
 
+  }
553
 
+  else {
554
 
+    ctx->name = strdup(name);
555
 
+  }
556
 
+
557
 
+  assert(ctx->name);
558
 
+
559
 
+/* first of all we need to initialize our threading env */
560
 
+#ifdef HAVE_AVAHI_THREADED_POLL
561
 
+  if (!(ctx->threaded_poll = avahi_threaded_poll_new())) {
562
 
+     goto fail;
563
 
+  }
564
 
+#else
565
 
+  if (!(ctx->simple_poll = avahi_simple_poll_new())) {
566
 
+      LOG(log_error,
567
 
+          logtype_afpd,
568
 
+          "Failed to create event loop object.\n");
569
 
+      goto fail;
570
 
+  }
571
 
+
572
 
+  avahi_simple_poll_set_func(ctx->simple_poll, poll_func, &ctx->mutex);
573
 
+#endif
574
 
+
575
 
+/* now we need to acquire a client */
576
 
+#ifdef HAVE_AVAHI_THREADED_POLL
577
 
+  if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll),
578
 
+                                       AVAHI_CLIENT_NO_FAIL,
579
 
+                                       client_callback,
580
 
+                                       ctx,
581
 
+                                       &error))) {
582
 
+    LOG(log_error,
583
 
+        logtype_afpd,
584
 
+        "Failed to create client object: %s\n",
585
 
+        avahi_strerror(avahi_client_errno(ctx->client)));
586
 
+    goto fail;
587
 
+  }
588
 
+#else
589
 
+  if (!(ctx->client = avahi_client_new(avahi_simple_poll_get(ctx->simple_poll),
590
 
+                                       AVAHI_CLIENT_NO_FAIL,
591
 
+                                       client_callback,
592
 
+                                       ctx,
593
 
+                                       &error))) {
594
 
+    LOG(log_error,
595
 
+        logtype_afpd,
596
 
+        "Failed to create client object: %s\n",
597
 
+        avahi_strerror(avahi_client_errno(ctx->client)));
598
 
+    goto fail;
599
 
+  }
600
 
+#endif
601
 
+
602
 
+  return ctx;
603
 
+
604
 
+fail:
605
 
+
606
 
+  if (ctx)
607
 
+    av_zeroconf_unregister(ctx);
608
 
+
609
 
+  return NULL;
610
 
+}
611
 
+
612
 
+/*
613
 
+ * This function finally runs the loop impl.
614
 
+ */
615
 
+int av_zeroconf_run(void *u) {
616
 
+  struct context *ctx = u;
617
 
+  int ret;
618
 
+
619
 
+#ifdef HAVE_AVAHI_THREADED_POLL
620
 
+  /* Finally, start the event loop thread */
621
 
+  if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) {
622
 
+    LOG(log_error,
623
 
+        logtype_afpd,
624
 
+        "Failed to create thread: %s\n",
625
 
+        avahi_strerror(avahi_client_errno(ctx->client)));
626
 
+    goto fail;
627
 
+  } else {
628
 
+    LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
629
 
+  }
630
 
+#else
631
 
+  /* Create the mDNS event handler */
632
 
+  if ((ret = pthread_create(&ctx->thread_id, NULL, thread, ctx)) < 0) {
633
 
+    LOG(log_error,
634
 
+        logtype_afpd,
635
 
+        "Failed to create thread: %s\n", strerror(ret));
636
 
+    goto fail;
637
 
+  } else {
638
 
+    LOG(log_info, logtype_afpd, "Successfully started avahi loop.\n");
639
 
+  }
640
 
+#endif
641
 
+
642
 
+  ctx->thread_running = 1;
643
 
+
644
 
+  return 0;
645
 
+
646
 
+fail:
647
 
+
648
 
+  if (ctx)
649
 
+    av_zeroconf_unregister(ctx);
650
 
+
651
 
+  return -1;
652
 
+}
653
 
+
654
 
+/*
655
 
+ * Used to lock access to the loop.
656
 
+ * Currently unused.
657
 
+ */
658
 
+void av_zeroconf_lock(void *u) {
659
 
+#ifdef HAVE_AVAHI_THREADED_POLL
660
 
+  struct context *ctx = u;
661
 
+
662
 
+  avahi_threaded_poll_lock(ctx->threaded_poll);
663
 
+#endif
664
 
+}
665
 
+
666
 
+/*
667
 
+ * Used to unlock access to the loop.
668
 
+ * Currently unused.
669
 
+ */
670
 
+void av_zeroconf_unlock(void *u) {
671
 
+#ifdef HAVE_AVAHI_THREADED_POLL
672
 
+  struct context *ctx = u;
673
 
+
674
 
+  avahi_threaded_poll_unlock(ctx->threaded_poll);
675
 
+#endif
676
 
+}
677
 
+
678
 
+/*
679
 
+ * Tries to shutdown this loop impl.
680
 
+ * Call this function from outside this thread.
681
 
+ */
682
 
+void av_zeroconf_shutdown(void *u) {
683
 
+  struct context *ctx = u;
684
 
+
685
 
+  /* Call this when the app shuts down */
686
 
+#ifdef HAVE_AVAHI_THREADED_POLL
687
 
+  avahi_threaded_poll_stop(ctx->threaded_poll);
688
 
+  avahi_free(ctx->name);
689
 
+  avahi_client_free(ctx->client);
690
 
+  avahi_threaded_poll_free(ctx->threaded_poll);
691
 
+#else
692
 
+  av_zeroconf_unregister(ctx);
693
 
+#endif
694
 
+}
695
 
+
696
 
+/*
697
 
+ * Tries to shutdown this loop impl.
698
 
+ * Call this function from inside this thread.
699
 
+ */
700
 
+int av_zeroconf_unregister(void *u) {
701
 
+  struct context *ctx = u;
702
 
+
703
 
+  if (ctx->thread_running) {
704
 
+#ifndef HAVE_AVAHI_THREADED_POLL
705
 
+    pthread_mutex_lock(&ctx->mutex);
706
 
+    avahi_simple_poll_quit(ctx->simple_poll);
707
 
+    pthread_mutex_unlock(&ctx->mutex);
708
 
+
709
 
+    pthread_join(ctx->thread_id, NULL);
710
 
+#else
711
 
+    /* First, block the event loop */
712
 
+    avahi_threaded_poll_lock(ctx->threaded_poll);
713
 
+
714
 
+    /* Than, do your stuff */
715
 
+    avahi_threaded_poll_quit(ctx->threaded_poll);
716
 
+
717
 
+    /* Finally, unblock the event loop */
718
 
+    avahi_threaded_poll_unlock(ctx->threaded_poll);
719
 
+#endif
720
 
+    ctx->thread_running = 0;
721
 
+  }
722
 
+
723
 
+  avahi_free(ctx->name);
724
 
+
725
 
+  if (ctx->client)
726
 
+    avahi_client_free(ctx->client);
727
 
+
728
 
+#ifndef HAVE_AVAHI_THREADED_POLL
729
 
+  if (ctx->simple_poll)
730
 
+    avahi_simple_poll_free(ctx->simple_poll);
731
 
+
732
 
+  pthread_mutex_destroy(&ctx->mutex);
733
 
+#else
734
 
+  if (ctx->threaded_poll)
735
 
+    avahi_threaded_poll_free(ctx->threaded_poll);
736
 
+#endif
737
 
+
738
 
+  free(ctx);
739
 
+
740
 
+  return 0;
741
 
+}
742
 
+
743
 
+#endif /* USE_AVAHI */
744
 
--- a/etc/afpd/afp_avahi.h
745
 
+++ b/etc/afpd/afp_avahi.h
746
 
@@ -0,0 +1,58 @@
747
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
748
 
+/*
749
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
750
 
+ * Purpose: Avahi based Zeroconf support
751
 
+ * Docs:    http://avahi.org/download/doxygen/
752
 
+ *
753
 
+ */
754
 
+
755
 
+#ifndef AFPD_AVAHI_H
756
 
+#define AFPD_AVAHI_H
757
 
+
758
 
+#include <stdlib.h>
759
 
+#include <assert.h>
760
 
+#include <string.h>
761
 
+
762
 
+#include <avahi-client/client.h>
763
 
+#include <avahi-client/publish.h>
764
 
+
765
 
+#include <avahi-common/alternative.h>
766
 
+
767
 
+#ifndef HAVE_AVAHI_THREADED_POLL
768
 
+#include <avahi-common/simple-watch.h>
769
 
+#include <signal.h> /* SIG_BLOCK */
770
 
+#else
771
 
+#include <avahi-common/thread-watch.h>
772
 
+#endif
773
 
+
774
 
+#include <avahi-common/malloc.h>
775
 
+#include <avahi-common/error.h>
776
 
+
777
 
+#include <atalk/logger.h>
778
 
+
779
 
+#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
780
 
+
781
 
+struct context {
782
 
+  int thread_running;
783
 
+  pthread_t thread_id;
784
 
+  pthread_mutex_t mutex;
785
 
+  char *name;
786
 
+#ifndef HAVE_AVAHI_THREADED_POLL
787
 
+  AvahiSimplePoll   *simple_poll;
788
 
+#else
789
 
+  AvahiThreadedPoll *threaded_poll;
790
 
+#endif
791
 
+  AvahiClient       *client;
792
 
+  AvahiEntryGroup   *group;
793
 
+  unsigned long     port;
794
 
+};
795
 
+
796
 
+/* prototype definitions */
797
 
+void* av_zeroconf_setup(unsigned long, const char *);
798
 
+int av_zeroconf_run(void*);
799
 
+int av_zeroconf_unregister(void*);
800
 
+void av_zeroconf_shutdown(void*);
801
 
+void av_zeroconf_lock(void *);
802
 
+void av_zeroconf_unlock(void *);
803
 
+
804
 
+#endif   /* AFPD_AVAHI_H */
805
 
--- a/etc/afpd/afp_bonjour.h
806
 
+++ b/etc/afpd/afp_bonjour.h
807
 
@@ -0,0 +1,27 @@
808
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
809
 
+/*
810
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
811
 
+ * Purpose: Bonjour based Zeroconf support
812
 
+ * Docs:    http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
813
 
+ *
814
 
+ */
815
 
+
816
 
+#ifndef AFPD_BONJOUR_H
817
 
+#define AFPD_BONJOUR_H
818
 
+
819
 
+#include <stdlib.h>
820
 
+#include <assert.h>
821
 
+#include <string.h>
822
 
+
823
 
+#include <dns_sd.h>     /* DNSServiceRegister(), DNSServiceDiscoveryDeallocate() */
824
 
+
825
 
+#include <atalk/logger.h>
826
 
+
827
 
+#define AFP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
828
 
+
829
 
+/* prototype definitions */
830
 
+void* bo_zeroconf_setup(unsigned long, const char *);
831
 
+int bo_zeroconf_unregister(void);
832
 
+int bo_zeroconf_run(void);
833
 
+
834
 
+#endif   /* AFPD_BONJOUR_H */
835
 
--- a/etc/afpd/afp_bonjour.c
836
 
+++ b/etc/afpd/afp_bonjour.c
837
 
@@ -0,0 +1,112 @@
838
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
839
 
+/*
840
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
841
 
+ * Purpose: Bonjour based Zeroconf support
842
 
+ * Docs:    http://developer.apple.com/documentation/Networking/Reference/DNSServiceDiscovery_CRef/dns_sd/
843
 
+ *
844
 
+ */
845
 
+
846
 
+#ifdef HAVE_CONFIG_H
847
 
+#include <config.h>
848
 
+#endif
849
 
+
850
 
+#ifdef HAVE_BONJOUR
851
 
+
852
 
+#include "afp_bonjour.h"
853
 
+
854
 
+DNSServiceRef publish_session = NULL;
855
 
+
856
 
+static void DNSSD_API
857
 
+publish_reply(DNSServiceRef,
858
 
+              const DNSServiceFlags,
859
 
+              DNSServiceErrorType,
860
 
+              const char *,
861
 
+              const char *,
862
 
+              const char *,
863
 
+              void *);
864
 
+
865
 
+static void DNSSD_API
866
 
+publish_reply (DNSServiceRef sdRef,
867
 
+         const DNSServiceFlags flags,
868
 
+         DNSServiceErrorType errorCode,
869
 
+         const char *name,
870
 
+         const char *regtype,
871
 
+         const char *domain,
872
 
+         void *context)
873
 
+{
874
 
+}
875
 
+
876
 
+void* bo_zeroconf_setup(unsigned long port, const char *name) {
877
 
+  DNSServiceErrorType err;
878
 
+  char service[256] = "AFP Server on ";
879
 
+
880
 
+  /* Prepare service name */
881
 
+  if (!name) {
882
 
+    LOG(log_info, logtype_afpd,, "Assigning default service name.\n");
883
 
+    gethostname(service+14, sizeof(service)-15);
884
 
+    service[sizeof(service)-1] = 0;
885
 
+
886
 
+    name = strdup(service);
887
 
+  }
888
 
+
889
 
+  assert(name);
890
 
+  assert(port);
891
 
+
892
 
+  err = DNSServiceRegister (&publish_session,
893
 
+                            0,                    /* flags */
894
 
+                            0,                    /* interface; 0 for all */
895
 
+                            name,                 /* name */
896
 
+                            AFP_DNS_SERVICE_TYPE, /* type */
897
 
+                            NULL,                 /* domain */
898
 
+                            NULL,                 /* hostname */
899
 
+                            htons (port),         /* port in network byte order */
900
 
+                            0,                    /* text record length */
901
 
+                            NULL,                 /* text record */
902
 
+                            publish_reply,        /* callback */
903
 
+                            NULL);                /* context */
904
 
+
905
 
+  if (err == kDNSServiceErr_NoError) {
906
 
+    LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
907
 
+  } else {
908
 
+    LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
909
 
+    bo_zeroconf_unregister();
910
 
+  }
911
 
+}
912
 
+
913
 
+int bo_zeroconf_run(void) {
914
 
+  fd_set set;
915
 
+  int fd;
916
 
+  struct timeval timeout;
917
 
+
918
 
+  /* Initialize the file descriptor set. */
919
 
+  FD_ZERO (&set);
920
 
+  FD_SET (fd, &set);
921
 
+
922
 
+  /* Initialize the timeout data structure. */
923
 
+  /* TODO: Should the value for sec be configurable? */
924
 
+  timeout.tv_sec = 10;
925
 
+  timeout.tv_usec = 0;
926
 
+
927
 
+  if (publish_session != NULL) {
928
 
+    fd = DNSServiceRefSockFD(publish_session);
929
 
+
930
 
+    if (select(FD_SETSIZE,
931
 
+                  &set, NULL, NULL,
932
 
+                  &timeout) > 0) {
933
 
+      DNSServiceProcessResult(publish_session);
934
 
+    }
935
 
+  }
936
 
+
937
 
+  return 0;
938
 
+}
939
 
+
940
 
+int bo_zeroconf_unregister(void) {
941
 
+  if (publish_session != NULL) {
942
 
+    DNSServiceRefDeallocate(publish_session);
943
 
+    publish_session = NULL;
944
 
+  }
945
 
+
946
 
+  return 0;
947
 
+}
948
 
+
949
 
+#endif /* HAVE_BONJOUR */
950
 
--- a/etc/afpd/afp_howl.c
951
 
+++ b/etc/afpd/afp_howl.c
952
 
@@ -0,0 +1,92 @@
953
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
954
 
+/*
955
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
956
 
+ * Purpose: Howl based Zeroconf support
957
 
+ * Doc:     http://www.porchdogsoft.com/products/howl/docs/
958
 
+ *
959
 
+ */
960
 
+
961
 
+#ifdef HAVE_CONFIG_H
962
 
+#include <config.h>
963
 
+#endif
964
 
+
965
 
+#ifdef HAVE_HOWL
966
 
+
967
 
+#include "afp_howl.h"
968
 
+
969
 
+sw_discovery discovery = NULL;
970
 
+
971
 
+static sw_result HOWL_API publish_reply(sw_discovery,
972
 
+                                        sw_discovery_oid,
973
 
+                                        sw_discovery_publish_status,
974
 
+                                        sw_opaque);
975
 
+
976
 
+static sw_result HOWL_API publish_reply(sw_discovery discovery,
977
 
+                                        sw_discovery_oid oid,
978
 
+                                        sw_discovery_publish_status status,
979
 
+                                        sw_opaque extra) {
980
 
+  static sw_string
981
 
+    status_text[] =
982
 
+    {
983
 
+      "Started",
984
 
+      "Stopped",
985
 
+      "Name Collision",
986
 
+      "Invalid"
987
 
+    };
988
 
+
989
 
+  LOG(log_info, logtype_afpd, "publish reply: %s\n", status_text[status]);
990
 
+  return SW_OKAY;
991
 
+}
992
 
+
993
 
+void* ho_zeroconf_setup(unsigned long port, const char *name) {
994
 
+  sw_result result;
995
 
+  sw_discovery_publish_id id;
996
 
+  char service[256] = "AFP Server on ";
997
 
+
998
 
+  if (sw_discovery_init (&discovery) != SW_OKAY) {
999
 
+    LOG(log_error,
1000
 
+        logtype_afpd,
1001
 
+        "AFPD could not be started. \nTry running mDNSResponder.");
1002
 
+    return;
1003
 
+  }
1004
 
+
1005
 
+  /* Prepare service name */
1006
 
+  if (!name) {
1007
 
+    LOG(log_info, logtype_afpd, "Assigning default service name.\n");
1008
 
+    gethostname(service+14, sizeof(service)-15);
1009
 
+    service[sizeof(service)-1] = 0;
1010
 
+
1011
 
+    name = strdup(service);
1012
 
+  }
1013
 
+
1014
 
+  assert(name);
1015
 
+
1016
 
+  if (!(result = sw_discovery_publish (discovery,
1017
 
+                                       0,
1018
 
+                                       name,
1019
 
+                                       AFP_DNS_SERVICE_TYPE,
1020
 
+                                       NULL,
1021
 
+                                       NULL,
1022
 
+                                       port,
1023
 
+                                       NULL,
1024
 
+                                       0,
1025
 
+                                       publish_reply,
1026
 
+                                       NULL,
1027
 
+                                       &id)) != SW_OKAY) {
1028
 
+    LOG(log_info, logtype_afpd, "Adding service '%s'\n", name);
1029
 
+  } else {
1030
 
+    LOG(log_error, logtype_afpd, "Adding service '%s' failed\n", name);
1031
 
+    ho_zeroconf_unregister();
1032
 
+  }
1033
 
+}
1034
 
+
1035
 
+void* ho_zeroconf_run(void) {
1036
 
+  sw_discovery_run(discovery);
1037
 
+}
1038
 
+
1039
 
+void* ho_zeroconf_unregister(void) {
1040
 
+  sw_discovery_stop_run(discovery);
1041
 
+  sw_discovery_fina(discovery);
1042
 
+}
1043
 
+
1044
 
+#endif /* USE_HOWL */
1045
 
--- a/etc/afpd/afp_howl.h
1046
 
+++ b/etc/afpd/afp_howl.h
1047
 
@@ -0,0 +1,27 @@
1048
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
1049
 
+/*
1050
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
1051
 
+ * Purpose: Howl based Zeroconf support
1052
 
+ * Doc:     http://www.porchdogsoft.com/products/howl/docs/
1053
 
+ *
1054
 
+ */
1055
 
+
1056
 
+#ifndef AFPD_HOWL_H
1057
 
+#define AFPD_HOWL_H
1058
 
+
1059
 
+#include <stdlib.h>
1060
 
+#include <assert.h>
1061
 
+#include <string.h>
1062
 
+
1063
 
+#include <howl.h>
1064
 
+
1065
 
+#include <atalk/logger.h>
1066
 
+
1067
 
+#define NTP_DNS_SERVICE_TYPE "_afpovertcp._tcp"
1068
 
+
1069
 
+/* prototype definitions */
1070
 
+void* ho_zeroconf_setup(unsigned long, const char *);
1071
 
+void* ho_zeroconf_unregister(void);
1072
 
+void* ho_zeroconf_run(void);
1073
 
+
1074
 
+#endif   /* AFPD_HOWL_H */
1075
 
--- a/etc/afpd/afp_zeroconf.h
1076
 
+++ b/etc/afpd/afp_zeroconf.h
1077
 
@@ -0,0 +1,40 @@
1078
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
1079
 
+/*
1080
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
1081
 
+ * Purpose: Zeroconf facade, that abstracts access to a
1082
 
+ *          particular Zeroconf implementation
1083
 
+ * Doc:     http://www.dns-sd.org/
1084
 
+ *
1085
 
+ */
1086
 
+
1087
 
+#ifndef AFPD_ZEROCONF_H
1088
 
+#define AFPD_ZEROCONF_H
1089
 
+
1090
 
+#include <netinet/in.h> /* htons() */
1091
 
+#include <atalk/logger.h>
1092
 
+
1093
 
+# ifdef HAVE_BONJOUR
1094
 
+# include "afp_bonjour.h"
1095
 
+# elif defined (HAVE_HOWL)
1096
 
+# include "afp_howl.h"
1097
 
+# elif defined (HAVE_AVAHI)
1098
 
+# include "afp_avahi.h"
1099
 
+# endif
1100
 
+
1101
 
+#define AFP_PORT 548
1102
 
+
1103
 
+/*
1104
 
+ * Prototype Definitions
1105
 
+ */
1106
 
+
1107
 
+/*
1108
 
+ * registers the ntpd service with a particular Zerconf implemenation.
1109
 
+ */
1110
 
+void zeroconf_register(int port, char *hostname);
1111
 
+
1112
 
+/*
1113
 
+ * de-registers the ntpd service with a particular Zerconf implemenation.
1114
 
+ */
1115
 
+void zeroconf_deregister(void);
1116
 
+
1117
 
+#endif AFPD_ZEROCONF_H
1118
 
--- a/etc/afpd/afp_zeroconf.c
1119
 
+++ b/etc/afpd/afp_zeroconf.c
1120
 
@@ -0,0 +1,97 @@
1121
 
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
1122
 
+/*
1123
 
+ * Author:  Daniel S. Haischt <me@daniel.stefan.haischt.name>
1124
 
+ * Purpose: Zeroconf facade, that abstracts access to a
1125
 
+ *          particular Zeroconf implementation
1126
 
+ * Doc:     http://www.dns-sd.org/
1127
 
+ *
1128
 
+ */
1129
 
+
1130
 
+#ifdef HAVE_CONFIG_H
1131
 
+#include <config.h>
1132
 
+#endif
1133
 
+
1134
 
+#include "afp_zeroconf.h"
1135
 
+
1136
 
+/*
1137
 
+ * Global Definitions
1138
 
+ */
1139
 
+#ifdef HAVE_AVAHI
1140
 
+struct context *ctx = NULL;
1141
 
+#endif
1142
 
+
1143
 
+/*
1144
 
+ * Functions (actually they are just facades)
1145
 
+ */
1146
 
+void zeroconf_register(int port, char *hostname)
1147
 
+{
1148
 
+#ifdef HAVE_BONJOUR
1149
 
+  LOG(log_info,
1150
 
+      logtype_afpd,
1151
 
+      "Attempting to register with mDNS using Apple's Bonjour\n");
1152
 
+  if (hostname && strlen(hostname) > 0 && port)
1153
 
+  {
1154
 
+    bo_zeroconf_setup(port, hostname);
1155
 
+  }
1156
 
+  else if (hostname && strlen(hostname) > 0)
1157
 
+  {
1158
 
+    bo_zeroconf_setup(AFP_PORT, hostname);
1159
 
+  }
1160
 
+  else
1161
 
+  {
1162
 
+    bo_zeroconf_setup(AFP_PORT, NULL);
1163
 
+  }
1164
 
+  bo_zeroconf_run();
1165
 
+#elif defined (HAVE_HOWL)
1166
 
+  LOG(log_info,
1167
 
+      logtype_afpd,
1168
 
+      "Attempting to register with mDNS using Porchdog's Howl\n");
1169
 
+  if (hostname && strlen(hostname) > 0 && port)
1170
 
+  {
1171
 
+    ho_zeroconf_setup(port, hostname);
1172
 
+  }
1173
 
+  else if (hostname && strlen(hostname) > 0)
1174
 
+  {
1175
 
+    ho_zeroconf_setup(AFP_PORT, hostname);
1176
 
+  }
1177
 
+  else
1178
 
+  {
1179
 
+    ho_zeroconf_setup(AFP_PORT, NULL);
1180
 
+  }
1181
 
+  bo_zeroconf_run();
1182
 
+#elif defined (HAVE_AVAHI)
1183
 
+  LOG(log_info, logtype_afpd, "Attempting to register with mDNS using Avahi\n");
1184
 
+  if (hostname && strlen(hostname) > 0 && port)
1185
 
+  {
1186
 
+    ctx = av_zeroconf_setup(port, hostname);
1187
 
+  }
1188
 
+  else if (hostname && strlen(hostname) > 0)
1189
 
+  {
1190
 
+    ctx = av_zeroconf_setup(AFP_PORT, hostname);
1191
 
+  }
1192
 
+  else
1193
 
+  {
1194
 
+    ctx = av_zeroconf_setup(AFP_PORT, NULL);
1195
 
+  }
1196
 
+  av_zeroconf_run(ctx);
1197
 
+#endif
1198
 
+}
1199
 
+
1200
 
+void zeroconf_deregister(void)
1201
 
+{
1202
 
+#ifdef HAVE_BONJOUR
1203
 
+  LOG(log_error,
1204
 
+      logtype_afpd,
1205
 
+      "Attempting to de-register mDNS using Apple's Bonjour\n");
1206
 
+  bo_zeroconf_unregister();
1207
 
+#elif defined (HAVE_HOWL)
1208
 
+  LOG(log_error,
1209
 
+      logtype_afpd,
1210
 
+      "Attempting to de-register mDNS using Porchdog's Howl\n");
1211
 
+  ho_zeroconf_unregister();
1212
 
+#elif defined (HAVE_AVAHI)
1213
 
+  LOG(log_error, logtype_afpd, "Attempting to de-register mDNS using Avahi\n");
1214
 
+  if (ctx)
1215
 
+    av_zeroconf_shutdown(ctx);
1216
 
+#endif
1217
 
+}
1218
 
--- a/macros/zeroconf.m4
1219
 
+++ b/macros/zeroconf.m4
1220
 
@@ -0,0 +1,101 @@
1221
 
+dnl Check for optional Zeroconf support
1222
 
+
1223
 
+dnl $Id: $
1224
 
+
1225
 
+AC_DEFUN([NETATALK_ZEROCONF], [
1226
 
+
1227
 
+       ZEROCONF_LIBS=""
1228
 
+       ZEROCONF_CFLAGS=""
1229
 
+       found_zeroconf=no
1230
 
+       zeroconf_dir=""
1231
 
+
1232
 
+       AC_ARG_ENABLE(zeroconf,
1233
 
+               [  --enable-zeroconf[[=DIR]]   enable Zeroconf support [[auto]]],
1234
 
+               [zeroconf=$enableval],
1235
 
+               [zeroconf=try]
1236
 
+       )
1237
 
+
1238
 
+    dnl make sure atalk_libname is defined beforehand
1239
 
+    [[ -n "$atalk_libname" ]] || AC_MSG_ERROR([internal error, atalk_libname undefined])
1240
 
+
1241
 
+       if test "x$zeroconf" != "xno"; then
1242
 
+
1243
 
+               savedcppflags="$CPPFLAGS"
1244
 
+               savedldflags="$LDFLAGS"
1245
 
+
1246
 
+               if test "x$zeroconf" = "xyes" -o "x$zeroconf" = "xtry"; then
1247
 
+                       zeroconf_dir="/usr"
1248
 
+               else
1249
 
+                       zeroconf_dir="$zeroconf"
1250
 
+               fi
1251
 
+
1252
 
+               # mDNS support using Apple's Bonjour
1253
 
+               AC_CHECK_HEADER(dns_sd.h,
1254
 
+                 [AC_CHECK_LIB(dns_sd,
1255
 
+                   DNSServiceRegister,
1256
 
+                                 [AC_DEFINE(USE_ZEROCONF, 1,
1257
 
+                                       [Use DNS-SD registration])])])
1258
 
+       case "$ac_cv_lib_dns_sd_DNSServiceRegister" in
1259
 
+      yes)
1260
 
+      ZEROCONF_LIBS="-L$zeroconf_dir/lib -ldns_sd"
1261
 
+      ZEROCONF_LIBS="-I$zeroconf_dir/include"
1262
 
+      AC_DEFINE(HAVE_BONJOUR, 1, [Use Bonjour/DNS-SD registration])
1263
 
+      found_zeroconf=yes
1264
 
+      ;;
1265
 
+    esac
1266
 
+    # mDNS support using Porchdog's Howl
1267
 
+    AC_CHECK_HEADER(howl.h,
1268
 
+      [AC_CHECK_LIB(howl,
1269
 
+        sw_discovery_publish,
1270
 
+        [AC_DEFINE(USE_ZEROCONF, 1,
1271
 
+          [Use DNS-SD registration])])])
1272
 
+    case "$ac_cv_lib_howl_sw_discovery_publish" in
1273
 
+      yes)
1274
 
+      PKG_CHECK_MODULES(HOWL, [ howl >= 1.0.0 ])
1275
 
+      ZEROCONF_LIBS="$HOWL_LIBS"
1276
 
+      ZEROCONF_CFLAGS="$HOWL_CFLAGS"
1277
 
+      AC_DEFINE(HAVE_HOWL, 1, [Use Howl/DNS-SD registration])
1278
 
+      found_zeroconf=yes
1279
 
+      ;;
1280
 
+    esac
1281
 
+    # mDNS support using Avahi
1282
 
+    AC_CHECK_HEADER(avahi-client/client.h,
1283
 
+      [AC_CHECK_LIB(avahi-client,
1284
 
+        avahi_client_new,
1285
 
+                               [AC_DEFINE(USE_ZEROCONF, 1,
1286
 
+          [Use DNS-SD registration])])])
1287
 
+    case "$ac_cv_lib_avahi_client_avahi_client_new" in
1288
 
+      yes)
1289
 
+      PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6 ])
1290
 
+      PKG_CHECK_MODULES(AVAHI_TPOLL, [ avahi-client >= 0.6.4 ],
1291
 
+        [AC_DEFINE(HAVE_AVAHI_THREADED_POLL, 1, [Uses Avahis threaded poll implementation])],
1292
 
+        [AC_MSG_WARN(This Avahi implementation is not supporting threaded poll objects. Maybe this is not what you want.)])
1293
 
+      ZEROCONF_LIBS="$AVAHI_LIBS"
1294
 
+      ZEROCONF_CFLAGS="$AVAHI_CFLAGS"
1295
 
+      AC_DEFINE(HAVE_AVAHI, 1, [Use Avahi/DNS-SD registration])
1296
 
+      found_zeroconf=yes
1297
 
+      ;;
1298
 
+    esac
1299
 
+
1300
 
+               CPPFLAGS="$savedcppflags"
1301
 
+               LDFLAGS="$savedldflags"
1302
 
+       fi
1303
 
+       
1304
 
+       netatalk_cv_zeroconf=no
1305
 
+       AC_MSG_CHECKING([whether to enable Zerconf support])
1306
 
+       if test "x$found_zeroconf" = "xyes"; then
1307
 
+               AC_MSG_RESULT([yes])
1308
 
+               AC_DEFINE(USE_ZEROCONF, 1, [Define to enable Zeroconf support])
1309
 
+               netatalk_cv_zeroconf=yes
1310
 
+       else
1311
 
+               AC_MSG_RESULT([no])
1312
 
+               if test "x$zeroconf" != "xno" -a "x$zeroconf" != "xtry"; then
1313
 
+                       AC_MSG_ERROR([Zeroconf installation not found])
1314
 
+               fi
1315
 
+       fi
1316
 
+
1317
 
+       LIB_REMOVE_USR_LIB(ZEROCONF_LIBS)
1318
 
+       CFLAGS_REMOVE_USR_INCLUDE(ZEROCONF_CFLAGS)
1319
 
+       AC_SUBST(ZEROCONF_LIBS)
1320
 
+       AC_SUBST(ZEROCONF_CFLAGS)
1321
 
+])