1 diff --git a/source/Makefile.in b/source/Makefile.in
2 index ee22703..0500d73 100644
3 --- a/source/Makefile.in
4 +++ b/source/Makefile.in
5 @@ -69,6 +69,7 @@ WINBIND_NSS_EXTRA_LIBS=@WINBIND_NSS_EXTRA_LIBS@
6 WINBIND_NSS_PTHREAD=@WINBIND_NSS_PTHREAD@
7 PAM_WINBIND_EXTRA_LIBS=@PAM_WINBIND_EXTRA_LIBS@
8 DNSSD_LIBS=@DNSSD_LIBS@
9 +AVAHI_LIBS=@AVAHI_LIBS@
11 LIBTALLOC_LIBS=@LIBTALLOC_LIBS@
12 LIBTDB_LIBS=@LIBTDB_LIBS@
13 @@ -250,6 +251,8 @@ AFS_OBJ = lib/afs.o
15 AFS_SETTOKEN_OBJ = lib/afs_settoken.o
17 +AVAHI_OBJ = @AVAHI_OBJ@
19 SERVER_MUTEX_OBJ = lib/server_mutex.o
21 PASSCHANGE_OBJ = libsmb/passchange.o
22 @@ -688,7 +691,7 @@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
23 $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
24 $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \
25 $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
26 - $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) \
27 + $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(AVAHI_OBJ) \
28 $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
29 $(REG_FULL_OBJ) $(POPT_LIB_OBJ) $(BUILDOPT_OBJ) \
30 $(SMBLDAP_OBJ) $(LDB_OBJ) $(LIBNET_OBJ) @LIBWBCLIENT_STATIC@ \
31 @@ -1328,7 +1331,7 @@ bin/smbd@EXEEXT@: $(BINARY_PREREQS) $(SMBD_OBJ) @LIBTALLOC_SHARED@ @LIBTDB_SHARE
33 @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
34 $(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \
35 - $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) \
36 + $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) $(DNSSD_LIBS) $(AVAHI_LIBS) \
37 $(POPT_LIBS) @SMBD_LIBS@ $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \
40 @@ -1513,7 +1516,7 @@ bin/pdbtest@EXEEXT@: $(BINARY_PREREQS) $(PDBTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SH
42 bin/vfstest@EXEEXT@: $(BINARY_PREREQS) $(VFSTEST_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@
44 - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) \
45 + @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(AVAHI_LIBS) \
46 $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(DNSSD_LIBS) \
47 $(ACL_LIBS) $(LIBS) $(POPT_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \
48 @SMBD_LIBS@ $(NSCD_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \
49 diff --git a/source/configure.in b/source/configure.in
50 index 95dd67d..8a1f7fc 100644
51 --- a/source/configure.in
52 +++ b/source/configure.in
53 @@ -6168,10 +6168,10 @@ AC_SUBST(FLAGS1)
54 # Check if user wants DNS service discovery support
57 -[AS_HELP_STRING([--enable-dnssd], [Enable DNS service discovery support (default=auto)])])
58 +[AS_HELP_STRING([--enable-dnssd], [Enable DNS service discovery support (default=no)])])
61 -if test x"$enable_dnssd" != x"no"; then
62 +if test x"$enable_dnssd" == x"yes"; then
63 have_dnssd_support=yes
65 AC_CHECK_HEADERS(dns_sd.h)
66 @@ -6200,6 +6200,42 @@ if test x"$enable_dnssd" != x"no"; then
69 #################################################
70 +# Check if user wants avahi support
73 +[AS_HELP_STRING([--enable-avahi], [Enable Avahi support (default=auto)])])
76 +if test x"$enable_avahi" != x"no"; then
77 + have_avahi_support=yes
79 + AC_CHECK_HEADERS(avahi-common/watch.h)
80 + if test x"$ac_cv_header_avahi_common_watch_h" != x"yes"; then
81 + have_avahi_support=no
84 + AC_CHECK_HEADERS(avahi-client/client.h)
85 + if test x"$ac_cv_header_avahi_common_watch_h" != x"yes"; then
86 + have_avahi_support=no
89 + AC_CHECK_LIB_EXT(avahi-client, AVAHI_LIBS, avahi_client_new)
90 + if test x"$ac_cv_lib_ext_avahi_client_avahi_client_new" != x"yes"; then
91 + have_avahi_support=no
94 + if test x"$have_avahi_support" = x"yes"; then
95 + AC_DEFINE(WITH_AVAHI_SUPPORT, 1,
96 + [Whether to enable avahi support])
97 + AC_SUBST(AVAHI_OBJ, "lib/avahi.o smbd/avahi_register.o")
99 + if test x"$enable_avahi" = x"yes"; then
100 + AC_MSG_ERROR(avahi support not available)
105 +#################################################
106 # Check to see if we should use the included iniparser
108 AC_ARG_WITH(included-iniparser,
109 diff --git a/source/include/proto.h b/source/include/proto.h
110 index c2b318e..794742c 100644
111 --- a/source/include/proto.h
112 +++ b/source/include/proto.h
113 @@ -9751,4 +9751,14 @@ NTSTATUS idmap_sid_to_gid(const char *domname, DOM_SID *sid, gid_t *gid);
115 NTSTATUS nss_info_template_init( void );
117 +/* The following definitions come from lib/avahi.c */
119 +struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
120 + struct event_context *ev);
122 +/* The following definitions come from smbd/avahi_register.c */
124 +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct event_context *ev,
127 #endif /* _PROTO_H_ */
128 diff --git a/source/lib/avahi.c b/source/lib/avahi.c
130 index 0000000..bdc58cb
132 +++ b/source/lib/avahi.c
135 + Unix SMB/CIFS implementation.
136 + Connect avahi to lib/tevents
137 + Copyright (C) Volker Lendecke 2009
139 + This program is free software; you can redistribute it and/or modify
140 + it under the terms of the GNU General Public License as published by
141 + the Free Software Foundation; either version 3 of the License, or
142 + (at your option) any later version.
144 + This program is distributed in the hope that it will be useful,
145 + but WITHOUT ANY WARRANTY; without even the implied warranty of
146 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147 + GNU General Public License for more details.
149 + You should have received a copy of the GNU General Public License
150 + along with this program. If not, see <http://www.gnu.org/licenses/>.
153 +#include "includes.h"
155 +#include <avahi-common/watch.h>
157 +struct avahi_poll_context {
158 + struct event_context *ev;
159 + AvahiWatch **watches;
160 + AvahiTimeout **timeouts;
164 + struct avahi_poll_context *ctx;
165 + struct fd_event *fde;
167 + AvahiWatchEvent latest_event;
168 + AvahiWatchCallback callback;
172 +struct AvahiTimeout {
173 + struct avahi_poll_context *ctx;
174 + struct timed_event *te;
175 + AvahiTimeoutCallback callback;
179 +static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
181 + return ((event & AVAHI_WATCH_IN) ? EVENT_FD_READ : 0)
182 + | ((event & AVAHI_WATCH_OUT) ? EVENT_FD_WRITE : 0);
185 +static void avahi_fd_handler(struct event_context *ev,
186 + struct fd_event *fde, uint16_t flags,
187 + void *private_data);
189 +static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd,
190 + AvahiWatchEvent event,
191 + AvahiWatchCallback callback,
194 + struct avahi_poll_context *ctx = talloc_get_type_abort(
195 + api->userdata, struct avahi_poll_context);
196 + int num_watches = talloc_get_size(ctx->watches)/sizeof(*ctx->watches);
197 + AvahiWatch **tmp, *watch_ctx;
199 + tmp = talloc_realloc(ctx, ctx->watches, AvahiWatch *, num_watches + 1);
203 + ctx->watches = tmp;
205 + watch_ctx = talloc(tmp, AvahiWatch);
206 + if (watch_ctx == NULL) {
209 + ctx->watches[num_watches] = watch_ctx;
211 + watch_ctx->ctx = ctx;
212 + watch_ctx->fde = event_add_fd(ctx->ev, watch_ctx, fd,
213 + avahi_flags_map_to_tevent(event),
214 + avahi_fd_handler, watch_ctx);
215 + if (watch_ctx->fde == NULL) {
218 + watch_ctx->callback = callback;
219 + watch_ctx->userdata = userdata;
223 + TALLOC_FREE(watch_ctx);
224 + ctx->watches = talloc_realloc(ctx, ctx->watches, AvahiWatch *,
229 +static void avahi_fd_handler(struct event_context *ev,
230 + struct fd_event *fde, uint16_t flags,
231 + void *private_data)
233 + AvahiWatch *watch_ctx = talloc_get_type_abort(private_data, AvahiWatch);
235 + watch_ctx->latest_event =
236 + ((flags & EVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
237 + | ((flags & EVENT_FD_WRITE) ? AVAHI_WATCH_OUT : 0);
239 + watch_ctx->callback(watch_ctx, watch_ctx->fd, watch_ctx->latest_event,
240 + watch_ctx->userdata);
243 +static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
245 + if (event & AVAHI_WATCH_IN) {
246 + event_fd_set_readable(w->fde);
248 + event_fd_set_not_readable(w->fde);
250 + if (event & AVAHI_WATCH_OUT) {
251 + event_fd_set_writeable(w->fde);
253 + event_fd_set_not_writeable(w->fde);
257 +static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
259 + return w->latest_event;
262 +static void avahi_watch_free(AvahiWatch *w)
264 + int i, num_watches;
265 + AvahiWatch **watches = w->ctx->watches;
266 + struct avahi_poll_context *ctx;
268 + num_watches = talloc_get_size(watches) / sizeof(*watches);
270 + for (i=0; i<num_watches; i++) {
271 + if (w == watches[i]) {
275 + if (i == num_watches) {
280 + memmove(&watches[i], &watches[i+1],
281 + sizeof(*watches) * (num_watches - i - 1));
282 + ctx->watches = talloc_realloc(ctx, watches, AvahiWatch *,
286 +static void avahi_timeout_handler(struct event_context *ev,
287 + struct timed_event *te,
288 + struct timeval current_time,
289 + void *private_data);
291 +static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
292 + const struct timeval *tv,
293 + AvahiTimeoutCallback callback,
296 + struct avahi_poll_context *ctx = talloc_get_type_abort(
297 + api->userdata, struct avahi_poll_context);
298 + int num_timeouts = talloc_get_size(ctx->timeouts)/sizeof(*ctx->timeouts);
299 + AvahiTimeout **tmp, *timeout_ctx;
301 + tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
306 + ctx->timeouts = tmp;
308 + timeout_ctx = talloc(tmp, AvahiTimeout);
309 + if (timeout_ctx == NULL) {
312 + ctx->timeouts[num_timeouts] = timeout_ctx;
314 + timeout_ctx->ctx = ctx;
316 + timeout_ctx->te = NULL;
318 + timeout_ctx->te = event_add_timed(ctx->ev, timeout_ctx,
319 + *tv, avahi_timeout_handler,
321 + if (timeout_ctx->te == NULL) {
325 + timeout_ctx->callback = callback;
326 + timeout_ctx->userdata = userdata;
327 + return timeout_ctx;
330 + TALLOC_FREE(timeout_ctx);
331 + ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
336 +static void avahi_timeout_handler(struct event_context *ev,
337 + struct timed_event *te,
338 + struct timeval current_time,
339 + void *private_data)
341 + AvahiTimeout *timeout_ctx = talloc_get_type_abort(
342 + private_data, AvahiTimeout);
344 + TALLOC_FREE(timeout_ctx->te);
345 + timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
348 +static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
350 + TALLOC_FREE(t->te);
352 + t->te = event_add_timed(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
354 + * No failure mode defined here
356 + SMB_ASSERT(t->te != NULL);
359 +static void avahi_timeout_free(AvahiTimeout *t)
361 + int i, num_timeouts;
362 + AvahiTimeout **timeouts = t->ctx->timeouts;
363 + struct avahi_poll_context *ctx;
365 + num_timeouts = talloc_get_size(timeouts)/sizeof(*timeouts);
367 + for (i=0; i<num_timeouts; i++) {
368 + if (t == timeouts[i]) {
372 + if (i == num_timeouts) {
377 + memmove(&timeouts[i], &timeouts[i+1],
378 + sizeof(*timeouts) * (num_timeouts - i - 1));
379 + ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *,
383 +struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
384 + struct event_context *ev)
386 + struct AvahiPoll *result;
387 + struct avahi_poll_context *ctx;
389 + result = talloc(mem_ctx, struct AvahiPoll);
390 + if (result == NULL) {
393 + ctx = talloc_zero(result, struct avahi_poll_context);
395 + TALLOC_FREE(result);
400 + result->watch_new = avahi_watch_new;
401 + result->watch_update = avahi_watch_update;
402 + result->watch_get_events = avahi_watch_get_events;
403 + result->watch_free = avahi_watch_free;
404 + result->timeout_new = avahi_timeout_new;
405 + result->timeout_update = avahi_timeout_update;
406 + result->timeout_free = avahi_timeout_free;
407 + result->userdata = ctx;
411 diff --git a/source/smbd/avahi_register.c b/source/smbd/avahi_register.c
413 index 0000000..95cb6d1
415 +++ b/source/smbd/avahi_register.c
418 + * Unix SMB/CIFS implementation.
419 + * Register _smb._tcp with avahi
421 + * Copyright (C) Volker Lendecke 2009
423 + * This program is free software; you can redistribute it and/or modify
424 + * it under the terms of the GNU General Public License as published by
425 + * the Free Software Foundation; either version 3 of the License, or
426 + * (at your option) any later version.
428 + * This program is distributed in the hope that it will be useful,
429 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
430 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
431 + * GNU General Public License for more details.
433 + * You should have received a copy of the GNU General Public License
434 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
437 +#include "includes.h"
439 +#include <avahi-client/client.h>
440 +#include <avahi-client/publish.h>
441 +#include <avahi-common/error.h>
443 +struct avahi_state_struct {
444 + struct AvahiPoll *poll;
445 + AvahiClient *client;
446 + AvahiEntryGroup *entry_group;
450 +static void avahi_entry_group_callback(AvahiEntryGroup *g,
451 + AvahiEntryGroupState status,
454 + struct avahi_state_struct *state = talloc_get_type_abort(
455 + userdata, struct avahi_state_struct);
459 + case AVAHI_ENTRY_GROUP_ESTABLISHED:
460 + DEBUG(10, ("avahi_entry_group_callback: "
461 + "AVAHI_ENTRY_GROUP_ESTABLISHED\n"));
463 + case AVAHI_ENTRY_GROUP_FAILURE:
464 + error = avahi_client_errno(state->client);
466 + DEBUG(10, ("avahi_entry_group_callback: "
467 + "AVAHI_ENTRY_GROUP_FAILURE: %s\n",
468 + avahi_strerror(error)));
470 + case AVAHI_ENTRY_GROUP_COLLISION:
471 + DEBUG(10, ("avahi_entry_group_callback: "
472 + "AVAHI_ENTRY_GROUP_COLLISION\n"));
474 + case AVAHI_ENTRY_GROUP_UNCOMMITED:
475 + DEBUG(10, ("avahi_entry_group_callback: "
476 + "AVAHI_ENTRY_GROUP_UNCOMMITED\n"));
478 + case AVAHI_ENTRY_GROUP_REGISTERING:
479 + DEBUG(10, ("avahi_entry_group_callback: "
480 + "AVAHI_ENTRY_GROUP_REGISTERING\n"));
485 +static void avahi_client_callback(AvahiClient *c, AvahiClientState status,
488 + struct avahi_state_struct *state = talloc_get_type_abort(
489 + userdata, struct avahi_state_struct);
493 + case AVAHI_CLIENT_S_RUNNING:
494 + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_S_RUNNING\n"));
496 + state->entry_group = avahi_entry_group_new(
497 + c, avahi_entry_group_callback, state);
498 + if (state->entry_group == NULL) {
499 + error = avahi_client_errno(c);
500 + DEBUG(10, ("avahi_entry_group_new failed: %s\n",
501 + avahi_strerror(error)));
504 + if (avahi_entry_group_add_service(
505 + state->entry_group, AVAHI_IF_UNSPEC,
506 + AVAHI_PROTO_UNSPEC, 0, global_myname(),
507 + "_smb._tcp", NULL, NULL, state->port, NULL) < 0) {
508 + error = avahi_client_errno(c);
509 + DEBUG(10, ("avahi_entry_group_add_service failed: "
510 + "%s\n", avahi_strerror(error)));
511 + avahi_entry_group_free(state->entry_group);
512 + state->entry_group = NULL;
515 + if (avahi_entry_group_commit(state->entry_group) < 0) {
516 + error = avahi_client_errno(c);
517 + DEBUG(10, ("avahi_entry_group_commit failed: "
518 + "%s\n", avahi_strerror(error)));
519 + avahi_entry_group_free(state->entry_group);
520 + state->entry_group = NULL;
524 + case AVAHI_CLIENT_FAILURE:
525 + error = avahi_client_errno(c);
527 + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_FAILURE: %s\n",
528 + avahi_strerror(error)));
530 + if (error != AVAHI_ERR_DISCONNECTED) {
533 + avahi_client_free(c);
534 + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
535 + avahi_client_callback, state,
537 + if (state->client == NULL) {
538 + DEBUG(10, ("avahi_client_new failed: %s\n",
539 + avahi_strerror(error)));
543 + case AVAHI_CLIENT_S_COLLISION:
544 + DEBUG(10, ("avahi_client_callback: "
545 + "AVAHI_CLIENT_S_COLLISION\n"));
547 + case AVAHI_CLIENT_S_REGISTERING:
548 + DEBUG(10, ("avahi_client_callback: "
549 + "AVAHI_CLIENT_S_REGISTERING\n"));
551 + case AVAHI_CLIENT_CONNECTING:
552 + DEBUG(10, ("avahi_client_callback: "
553 + "AVAHI_CLIENT_CONNECTING\n"));
558 +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct event_context *ev,
561 + struct avahi_state_struct *state;
564 + state = talloc(mem_ctx, struct avahi_state_struct);
565 + if (state == NULL) {
568 + state->port = port;
569 + state->poll = tevent_avahi_poll(state, ev);
570 + if (state->poll == NULL) {
573 + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
574 + avahi_client_callback, state,
576 + if (state->client == NULL) {
577 + DEBUG(10, ("avahi_client_new failed: %s\n",
578 + avahi_strerror(error)));
584 + TALLOC_FREE(state);
587 diff --git a/source/smbd/server.c b/source/smbd/server.c
588 index 00a2cd4..b05758e 100644
589 --- a/source/smbd/server.c
590 +++ b/source/smbd/server.c
591 @@ -588,6 +588,23 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_
592 MSG_SMB_INJECT_FAULT, msg_inject_fault);
595 + /* Kick off our mDNS registration. */
596 + if (dns_port != 0) {
597 +#ifdef WITH_DNSSD_SUPPORT
598 + dns_register_smbd(&dns_reg, dns_port, &maxfd,
599 + &r_fds, &idle_timeout);
601 +#ifdef WITH_AVAHI_SUPPORT
603 + avahi_conn = avahi_start_register(
604 + smbd_event_context(), smbd_event_context(),
606 + if (avahi_conn == NULL) {
607 + DEBUG(10, ("avahi_start_register failed\n"));
612 /* now accept incoming connections - forking a new process
613 for each incoming connection */
614 DEBUG(2,("waiting for a connection\n"));
615 @@ -632,12 +649,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_
619 - /* Kick off our mDNS registration. */
620 - if (dns_port != 0) {
621 - dns_register_smbd(&dns_reg, dns_port, &maxfd,
622 - &r_fds, &idle_timeout);
625 event_add_to_select_args(smbd_event_context(), &now,
626 &r_fds, &w_fds, &idle_timeout,