From 26516fb613fd1ae8373c0620af7bce563bc9d678 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Mar 2009 15:59:33 +0100 Subject: [PATCH] Use avahi to register _smb._tcp in smbd (cherry picked from commit b0ad52693d4ee548a2d3870e28f6499f827bed31) --- source/configure.in | 2 +- source/include/proto.h | 5 ++ source/smbd/avahi_register.c | 170 +++++++++++++++++++++++++++++++++++ source/smbd/server.c | 23 +++-- 4 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 source/smbd/avahi_register.c diff --git a/source/configure.in b/source/configure.in index 6905203fa82..8a1f7fc70c9 100644 --- a/source/configure.in +++ b/source/configure.in @@ -6227,7 +6227,7 @@ if test x"$enable_avahi" != x"no"; then if test x"$have_avahi_support" = x"yes"; then AC_DEFINE(WITH_AVAHI_SUPPORT, 1, [Whether to enable avahi support]) - AC_SUBST(AVAHI_OBJ, lib/avahi.o) + AC_SUBST(AVAHI_OBJ, "lib/avahi.o smbd/avahi_register.o") else if test x"$enable_avahi" = x"yes"; then AC_MSG_ERROR(avahi support not available) diff --git a/source/include/proto.h b/source/include/proto.h index e7cb2ca83e7..794742ce402 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -9756,4 +9756,9 @@ NTSTATUS nss_info_template_init( void ); struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx, struct event_context *ev); +/* The following definitions come from smbd/avahi_register.c */ + +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct event_context *ev, + uint16_t port); + #endif /* _PROTO_H_ */ diff --git a/source/smbd/avahi_register.c b/source/smbd/avahi_register.c new file mode 100644 index 00000000000..95cb6d11c0b --- /dev/null +++ b/source/smbd/avahi_register.c @@ -0,0 +1,170 @@ +/* + * Unix SMB/CIFS implementation. + * Register _smb._tcp with avahi + * + * Copyright (C) Volker Lendecke 2009 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" + +#include +#include +#include + +struct avahi_state_struct { + struct AvahiPoll *poll; + AvahiClient *client; + AvahiEntryGroup *entry_group; + uint16_t port; +}; + +static void avahi_entry_group_callback(AvahiEntryGroup *g, + AvahiEntryGroupState status, + void *userdata) +{ + struct avahi_state_struct *state = talloc_get_type_abort( + userdata, struct avahi_state_struct); + int error; + + switch (status) { + case AVAHI_ENTRY_GROUP_ESTABLISHED: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_ESTABLISHED\n")); + break; + case AVAHI_ENTRY_GROUP_FAILURE: + error = avahi_client_errno(state->client); + + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_FAILURE: %s\n", + avahi_strerror(error))); + break; + case AVAHI_ENTRY_GROUP_COLLISION: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_COLLISION\n")); + break; + case AVAHI_ENTRY_GROUP_UNCOMMITED: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_UNCOMMITED\n")); + break; + case AVAHI_ENTRY_GROUP_REGISTERING: + DEBUG(10, ("avahi_entry_group_callback: " + "AVAHI_ENTRY_GROUP_REGISTERING\n")); + break; + } +} + +static void avahi_client_callback(AvahiClient *c, AvahiClientState status, + void *userdata) +{ + struct avahi_state_struct *state = talloc_get_type_abort( + userdata, struct avahi_state_struct); + int error; + + switch (status) { + case AVAHI_CLIENT_S_RUNNING: + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_S_RUNNING\n")); + + state->entry_group = avahi_entry_group_new( + c, avahi_entry_group_callback, state); + if (state->entry_group == NULL) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_new failed: %s\n", + avahi_strerror(error))); + break; + } + if (avahi_entry_group_add_service( + state->entry_group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, global_myname(), + "_smb._tcp", NULL, NULL, state->port, NULL) < 0) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_add_service failed: " + "%s\n", avahi_strerror(error))); + avahi_entry_group_free(state->entry_group); + state->entry_group = NULL; + break; + } + if (avahi_entry_group_commit(state->entry_group) < 0) { + error = avahi_client_errno(c); + DEBUG(10, ("avahi_entry_group_commit failed: " + "%s\n", avahi_strerror(error))); + avahi_entry_group_free(state->entry_group); + state->entry_group = NULL; + break; + } + break; + case AVAHI_CLIENT_FAILURE: + error = avahi_client_errno(c); + + DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_FAILURE: %s\n", + avahi_strerror(error))); + + if (error != AVAHI_ERR_DISCONNECTED) { + break; + } + avahi_client_free(c); + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL, + avahi_client_callback, state, + &error); + if (state->client == NULL) { + DEBUG(10, ("avahi_client_new failed: %s\n", + avahi_strerror(error))); + break; + } + break; + case AVAHI_CLIENT_S_COLLISION: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_S_COLLISION\n")); + break; + case AVAHI_CLIENT_S_REGISTERING: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_S_REGISTERING\n")); + break; + case AVAHI_CLIENT_CONNECTING: + DEBUG(10, ("avahi_client_callback: " + "AVAHI_CLIENT_CONNECTING\n")); + break; + } +} + +void *avahi_start_register(TALLOC_CTX *mem_ctx, struct event_context *ev, + uint16_t port) +{ + struct avahi_state_struct *state; + int error; + + state = talloc(mem_ctx, struct avahi_state_struct); + if (state == NULL) { + return state; + } + state->port = port; + state->poll = tevent_avahi_poll(state, ev); + if (state->poll == NULL) { + goto fail; + } + state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL, + avahi_client_callback, state, + &error); + if (state->client == NULL) { + DEBUG(10, ("avahi_client_new failed: %s\n", + avahi_strerror(error))); + goto fail; + } + return state; + + fail: + TALLOC_FREE(state); + return NULL; +} diff --git a/source/smbd/server.c b/source/smbd/server.c index 00a2cd4c756..b05758ea4eb 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -588,6 +588,23 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif + /* Kick off our mDNS registration. */ + if (dns_port != 0) { +#ifdef WITH_DNSSD_SUPPORT + dns_register_smbd(&dns_reg, dns_port, &maxfd, + &r_fds, &idle_timeout); +#endif +#ifdef WITH_AVAHI_SUPPORT + void *avahi_conn; + avahi_conn = avahi_start_register( + smbd_event_context(), smbd_event_context(), + dns_port); + if (avahi_conn == NULL) { + DEBUG(10, ("avahi_start_register failed\n")); + } +#endif + } + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -632,12 +649,6 @@ static bool open_sockets_smbd(bool is_daemon, bool interactive, const char *smb_ FD_ZERO(&w_fds); GetTimeOfDay(&now); - /* Kick off our mDNS registration. */ - if (dns_port != 0) { - dns_register_smbd(&dns_reg, dns_port, &maxfd, - &r_fds, &idle_timeout); - } - event_add_to_select_args(smbd_event_context(), &now, &r_fds, &w_fds, &idle_timeout, &maxfd); -- 2.34.1