]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1848. [bug] Improve SMF integration. [RT #13238]
authorMark Andrews <marka@isc.org>
Tue, 5 Apr 2005 00:58:16 +0000 (00:58 +0000)
committerMark Andrews <marka@isc.org>
Tue, 5 Apr 2005 00:58:16 +0000 (00:58 +0000)
CHANGES
bin/named/control.c
bin/named/include/named/ns_smf_globals.h [new file with mode: 0644]
bin/named/main.c
bin/named/server.c
bin/named/unix/os.c

diff --git a/CHANGES b/CHANGES
index 6fcbc8b3e248727324ca72cd0662359d6e110caf..d725a876b1a2a3dff36d8dfc4c729a6b3c395b8f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+1848.  [bug]           Improve SMF integration. [RT #13238]
+
 1847.  [bug]           isc_ondestroy_init() is called too late in
                        in dns_rbtdb_create()/dns_rbtdb_create(). 
                        [RT #13661]
index 917784868b30c9fbb034b222296866aaa87f58b7..0440f129fc48dfd072135b01d40349cbca0f14d1 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: control.c,v 1.22 2004/10/11 05:30:15 marka Exp $ */
+/* $Id: control.c,v 1.23 2005/04/05 00:58:14 marka Exp $ */
 
 #include <config.h>
 
@@ -37,6 +37,9 @@
 #include <named/log.h>
 #include <named/os.h>
 #include <named/server.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
 
 static isc_boolean_t
 command_compare(const char *text, const char *command) {
@@ -58,6 +61,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
        isccc_sexpr_t *data;
        char *command;
        isc_result_t result;
+#ifdef HAVE_LIBSCF
+       char *instance = NULL;
+#endif
 
        data = isccc_alist_lookup(message, "_data");
        if (data == NULL) {
@@ -92,11 +98,59 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
        } else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
                result = ns_server_retransfercommand(ns_g_server, command);
        } else if (command_compare(command, NS_COMMAND_HALT)) {
+#ifdef HAVE_LIBSCF
+               /*
+                * If we are managed by smf(5), AND in chroot, then
+                * we cannot connect to the smf repository, so just
+                * return with an appropriate message back to rndc.
+                */
+               if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+                       result = ns_smf_add_message(text);
+                       return (result);
+               }
+               /*
+                * If we are managed by smf(5) but not in chroot,
+                * try to disable ourselves the smf way.
+                */
+               if (ns_smf_got_instance == 1 && ns_smf_chroot == 0) {
+                       result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
+                       if (result == ISC_R_SUCCESS && instance != NULL) {
+                               ns_server_flushonshutdown(ns_g_server,
+                                       ISC_FALSE);
+                               result = ns_smf_disable(instance);
+                       }
+                       if (instance != NULL)
+                               isc_mem_free(ns_g_mctx, instance);
+                       return (result);
+               }
+               /*
+                * If ns_smf_got_instance = 0, ns_smf_chroot
+                * is not relevant and we fall through to
+                * isc_app_shutdown below.
+                */
+#endif
                ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
                ns_os_shutdownmsg(command, text);
                isc_app_shutdown();
                result = ISC_R_SUCCESS;
        } else if (command_compare(command, NS_COMMAND_STOP)) {
+#ifdef HAVE_LIBSCF
+               if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+                       result = ns_smf_add_message(text);
+                       return (result);
+               }
+               if (ns_smf_got_instance == 1 && ns_smf_chroot == 0) {
+                       result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
+                       if (result == ISC_R_SUCCESS && instance != NULL) {
+                               ns_server_flushonshutdown(ns_g_server,
+                                       ISC_TRUE);
+                               result = ns_smf_disable(instance);
+                       }
+                       if (instance != NULL)
+                               isc_mem_free(ns_g_mctx, instance);
+                       return (result);
+               }
+#endif
                ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
                ns_os_shutdownmsg(command, text);
                isc_app_shutdown();
diff --git a/bin/named/include/named/ns_smf_globals.h b/bin/named/include/named/ns_smf_globals.h
new file mode 100644 (file)
index 0000000..cfcde55
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef NS_SMF_GLOBALS_H
+#define NS_SMF_GLOBALS_H 1
+#include <libscf.h>
+#undef EXTERN
+#undef INIT
+#ifdef NS_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else
+#define EXTERN extern
+#define INIT(v)
+#endif
+                
+EXTERN unsigned int    ns_smf_got_instance     INIT(0);
+EXTERN unsigned int    ns_smf_chroot           INIT(0);
+
+isc_result_t ns_smf_add_message(isc_buffer_t *text);
+isc_result_t ns_smf_get_instance(char **name, int debug, isc_mem_t *mctx);
+isc_result_t ns_smf_disable(const char *name);
+
+#undef EXTERN
+#undef INIT
+#endif /* NS_SMF_GLOBALS_H */
index 2de782540af28bd0e96c60fd8e9f5f0b224feba7..d78fc371b65f6963edc44dd9f3abc0b96088d3c2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: main.c,v 1.140 2004/10/25 00:33:28 marka Exp $ */
+/* $Id: main.c,v 1.141 2005/04/05 00:58:14 marka Exp $ */
 
 #include <config.h>
 
 
 #include <dst/result.h>
 
-#ifdef HAVE_LIBSCF
-#include <libscf.h>
-#endif
-
 /*
  * Defining NS_MAIN provides storage declarations (rather than extern)
  * for variables in named/globals.h.
@@ -66,6 +62,9 @@
 #include <named/server.h>
 #include <named/lwresd.h>
 #include <named/main.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
 
 /*
  * Include header files for database drivers here.
@@ -540,6 +539,9 @@ destroy_managers(void) {
 static void
 setup(void) {
        isc_result_t result;
+#ifdef HAVE_LIBSCF
+       char *instance = NULL;
+#endif
 
        /*
         * Get the user and group information before changing the root
@@ -555,6 +557,18 @@ setup(void) {
 
        ns_os_opendevnull();
 
+#ifdef HAVE_LIBSCF
+       /* Check if named is under smf control, before chroot. */
+       result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
+       /* We don't care about instance, just check if we got one. */
+       if (result == ISC_R_SUCCESS)
+               ns_smf_got_instance = 1;
+       else
+               ns_smf_got_instance = 0;
+       if (instance != NULL)
+               free(instance);
+#endif /* HAVE_LIBSCF */
+
 #ifdef PATH_RANDOMDEV
        /*
         * Initialize system's random device as fallback entropy source
@@ -699,88 +713,66 @@ ns_main_setmemstats(const char *filename) {
 
 #ifdef HAVE_LIBSCF
 /*
- * Get FMRI for the current named process
+ * Get FMRI for the named process.
  */
-static char *
-scf_get_ins_name(void) {
+isc_result_t
+ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
        scf_handle_t *h = NULL;
        int namelen;
-       char *ins_name;
+       char *instance;
+
+       REQUIRE(ins_name != NULL && *ins_name == NULL);
 
        if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "scf_handle_create() failed: %s",
-                                scf_strerror(scf_error()));
-               return (NULL);
+               if (debug)
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "scf_handle_create() failed: %s",
+                                        scf_strerror(scf_error()));
+               return (ISC_R_FAILURE);
        }
 
        if (scf_handle_bind(h) == -1) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "scf_handle_bind() failed: %s",
-                                scf_strerror(scf_error()));
+               if (debug)
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "scf_handle_bind() failed: %s",
+                                        scf_strerror(scf_error()));
                scf_handle_destroy(h);
-               return (NULL);
+               return (ISC_R_FAILURE);
        }
 
        if ((namelen = scf_myname(h, NULL, 0)) == -1) {
-               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
-                             NS_LOGMODULE_MAIN, ISC_LOG_INFO,
-                             "scf_myname() failed: %s",
-                             scf_strerror(scf_error()));
+               if (debug)
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "scf_myname() failed: %s",
+                                        scf_strerror(scf_error()));
                scf_handle_destroy(h);
-               return (NULL);
+               return (ISC_R_FAILURE);
        }
 
-       if ((ins_name = malloc(namelen + 1)) == NULL) {
+       if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) {
                UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "scf_get_ins_named() memory "
+                                "ns_smf_get_instance memory "
                                 "allocation failed: %s",
                                 isc_result_totext(ISC_R_NOMEMORY));
                scf_handle_destroy(h);
-               return (NULL);
+               return (ISC_R_FAILURE);
        }
 
-       if (scf_myname(h, ins_name, namelen + 1) == -1) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "scf_myname() failed: %s",
-                                scf_strerror(scf_error()));
+       if (scf_myname(h, instance, namelen + 1) == -1) {
+               if (debug)
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "scf_myname() failed: %s",
+                                        scf_strerror(scf_error()));
                scf_handle_destroy(h);
-               free(ins_name);
-               return (NULL);
+               isc_mem_free(mctx, instance);
+               return (ISC_R_FAILURE);
        }
 
        scf_handle_destroy(h);
-       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
-                     ISC_LOG_INFO, "instance name:%s", ins_name);
-
-       return (ins_name);
-}
-
-static void
-scf_cleanup(void) {
-       char *s;
-       char *ins_name;
-
-       if ((ins_name = scf_get_ins_name()) != NULL) {
-               if ((s = smf_get_state(ins_name)) != NULL) {
-                       if ((strcmp(SCF_STATE_STRING_ONLINE, s) == 0) ||
-                           (strcmp(SCF_STATE_STRING_DEGRADED, s) == 0)) {
-                               if (smf_disable_instance(ins_name, 0) != 0) {
-                                   UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                       "smf_disable_instance() failed: %s",
-                                       scf_strerror(scf_error()));
-                               }
-                       }
-                       free(s);
-               } else {
-                       UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "smf_get_state() failed: %s",
-                                        scf_strerror(scf_error()));
-               }
-               free(ins_name);
-       }
+       *ins_name = instance;
+       return (ISC_R_SUCCESS);
 }
-#endif
+#endif /* HAVE_LIBSCF */
 
 int
 main(int argc, char *argv[]) {
@@ -855,10 +847,6 @@ main(int argc, char *argv[]) {
                }
        } while (result != ISC_R_SUCCESS);
 
-#ifdef HAVE_LIBSCF
-       scf_cleanup();
-#endif
-
        cleanup();
 
        if (want_stats) {
index 34112712c5457f7249b87fd465abe536c5761fc1..93515fb809177e77190e92a4eb545082189cb132 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.439 2005/03/14 23:55:56 marka Exp $ */
+/* $Id: server.c,v 1.440 2005/04/05 00:58:15 marka Exp $ */
 
 #include <config.h>
 
 #include <named/tkeyconf.h>
 #include <named/tsigconf.h>
 #include <named/zoneconf.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#include <stdlib.h>
+#endif
 
 /*
  * Check an operation for failure.  Assumes that the function
@@ -4215,3 +4219,36 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
        dns_zone_detach(&zone);
        return (result);
 }
+
+#ifdef HAVE_LIBSCF
+/*
+ * This function adds a message for rndc to echo if named
+ * is managed by smf and is also running chroot.
+ */
+isc_result_t
+ns_smf_add_message(isc_buffer_t *text) {
+       unsigned int n;
+
+       n = snprintf((char *)isc_buffer_used(text),
+               isc_buffer_availablelength(text),
+               "use svcadm(1M) to manage named");
+       if (n >= isc_buffer_availablelength(text))
+               return (ISC_R_NOSPACE);
+       isc_buffer_add(text, n);
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_smf_disable(const char *ins_name) {
+
+       if (ins_name == NULL)
+               return (ISC_R_UNEXPECTED);
+       if (smf_disable_instance(ins_name, 0) != 0) {
+               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                       "smf_disable_instance() failed: %s",
+                       scf_strerror(scf_error()));
+               return (ISC_R_FAILURE);
+       }
+       return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_LIBSCF */
index 0a2ec0715da91f98675f968f1e446c320ff80cfa..c8944bf5857366de858eaba4a445f9c238351caa 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: os.c,v 1.71 2004/10/07 02:33:31 marka Exp $ */
+/* $Id: os.c,v 1.72 2005/04/05 00:58:16 marka Exp $ */
 
 #include <config.h>
 #include <stdarg.h>
@@ -46,6 +46,9 @@
 
 #include <named/main.h>
 #include <named/os.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
 
 static char *pidfile = NULL;
 static int devnullfd = -1;
@@ -417,6 +420,9 @@ all_digits(const char *s) {
 void
 ns_os_chroot(const char *root) {
        char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_LIBSCF
+       ns_smf_chroot = 0;
+#endif
        if (root != NULL) {
                if (chroot(root) < 0) {
                        isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -426,6 +432,10 @@ ns_os_chroot(const char *root) {
                        isc__strerror(errno, strbuf, sizeof(strbuf));
                        ns_main_earlyfatal("chdir(/): %s", strbuf);
                }
+#ifdef HAVE_LIBSCF
+               /* Set ns_smf_chroot flag on successful chroot. */
+               ns_smf_chroot = 1;
+#endif
        }
 }