Use avahi to register _smb._tcp in smbd
authorVolker Lendecke <vl@samba.org>
Sun, 22 Mar 2009 14:59:33 +0000 (15:59 +0100)
committerKarolin Seeger <kseeger@samba.org>
Fri, 27 Mar 2009 13:15:52 +0000 (14:15 +0100)
(cherry picked from commit b0ad52693d4ee548a2d3870e28f6499f827bed31)

source/configure.in
source/include/proto.h
source/smbd/avahi_register.c [new file with mode: 0644]
source/smbd/server.c

index 6905203fa82a5413b9eb407e8f079c8e4082c5d6..8a1f7fc70c9dca1b8d8a993f8417b9f3db541c52 100644 (file)
@@ -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)
index e7cb2ca83e7f732fc0956df4320aa7ba007246e1..794742ce4021d52d0f5d1e9062624026a15d2fa1 100644 (file)
@@ -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 (file)
index 0000000..95cb6d1
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-common/error.h>
+
+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;
+}
index 00a2cd4c756d5a20e68660001599a83ff6fe3561..b05758ea4ebba1b5b70f36fda4b2778a75864948 100644 (file)
@@ -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);