Use avahi to register _smb._tcp in smbd
authorVolker Lendecke <vl@samba.org>
Sun, 22 Mar 2009 14:59:33 +0000 (15:59 +0100)
committerVolker Lendecke <vl@samba.org>
Mon, 23 Mar 2009 16:09:53 +0000 (17:09 +0100)
source3/configure.in
source3/include/proto.h
source3/smbd/avahi_register.c [new file with mode: 0644]
source3/smbd/server.c

index 103edaf3690e36dadfee5e9377b906db3c71be2f..1cf8d9ca4a45d1b73fe750e053b872e977fb7748 100644 (file)
@@ -6032,7 +6032,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 a8c4b14fff8ef0e451bab08240303408d5e65a8e..c8dce139161ee3fbed634c57d2c44fcffba1c098 100644 (file)
@@ -7235,6 +7235,11 @@ NTSTATUS nss_info_template_init( void );
 struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev);
 
+/* The following definitions come from smbd/avahi_register.c */
+
+void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                          uint16_t port);
+
 /* Misc protos */
 
 #endif /*  _PROTO_H_  */
diff --git a/source3/smbd/avahi_register.c b/source3/smbd/avahi_register.c
new file mode 100644 (file)
index 0000000..1903b0e
--- /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 tevent_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 d27f98281b388c527638eef087137a9be55f7731..67836f785b489c8e022d10e1aa8ded2f78a8dd15 100644 (file)
@@ -643,8 +643,19 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 #endif
 
        if (dns_port != 0) {
+#ifdef WITH_DNSSD_SUPPORT
                smbd_setup_mdns_registration(smbd_event_context(),
                                             parent, dns_port);
+#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
        }
 
        return true;