diff --git a/CHANGES b/CHANGES index 6fcbc8b3e2..d725a876b1 100644 --- 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] diff --git a/bin/named/control.c b/bin/named/control.c index 917784868b..0440f129fc 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -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 @@ -37,6 +37,9 @@ #include #include #include +#ifdef HAVE_LIBSCF +#include +#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 index 0000000000..cfcde5587f --- /dev/null +++ b/bin/named/include/named/ns_smf_globals.h @@ -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 + +#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 */ diff --git a/bin/named/main.c b/bin/named/main.c index 2de782540a..d78fc371b6 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -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 @@ -47,10 +47,6 @@ #include -#ifdef HAVE_LIBSCF -#include -#endif - /* * Defining NS_MAIN provides storage declarations (rather than extern) * for variables in named/globals.h. @@ -66,6 +62,9 @@ #include #include #include +#ifdef HAVE_LIBSCF +#include +#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); + *ins_name = instance; + return (ISC_R_SUCCESS); } - -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); - } -} -#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) { diff --git a/bin/named/server.c b/bin/named/server.c index 34112712c5..93515fb809 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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 @@ -82,6 +82,10 @@ #include #include #include +#ifdef HAVE_LIBSCF +#include +#include +#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 */ diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index 0a2ec0715d..c8944bf585 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -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 #include @@ -46,6 +46,9 @@ #include #include +#ifdef HAVE_LIBSCF +#include +#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 } }