xref: /illumos-gate/usr/src/cmd/nscd/nscd_smfmonitor.c (revision 71269a2275bf5a143dad6461eee2710a344e7261)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <libscf.h>
28 #include <string.h>
29 #include "nscd_switch.h"
30 #include "nscd_log.h"
31 #include "nscd_door.h"
32 
33 extern int	_whoami;
34 
35 /*
36  * Service states monitored by nscd. Protected by
37  * readers/writer lock nscd_smf_service_state_lock
38  */
39 nscd_smf_state_t *nscd_smf_service_state;
40 static rwlock_t nscd_smf_service_state_lock = DEFAULTRWLOCK;
41 /*
42  * init service state table
43  */
44 nscd_rc_t
45 _nscd_alloc_service_state_table()
46 {
47 	int i;
48 
49 	nscd_smf_service_state = calloc(NSCD_NUM_SMF_FMRI,
50 	    sizeof (nscd_smf_state_t));
51 
52 	if (nscd_smf_service_state == NULL)
53 		return (NSCD_NO_MEMORY);
54 
55 	for (i = 1; i < NSCD_NUM_SMF_FMRI; i++)
56 		NSCD_SMF_SVC_STATE(i) = NSCD_SVC_STATE_UNINITED;
57 
58 	return (NSCD_SUCCESS);
59 }
60 
61 static int
62 query_smf_state(int srci)
63 {
64 
65 	int	ret = NSCD_SVC_STATE_UNINITED;
66 	char	*state = NULL;
67 	char	*me = "query_smf_state";
68 
69 	state = smf_get_state(NSCD_SMF_SVC_FMRI(srci));
70 	if (state == NULL)
71 		return (ret);
72 
73 	_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
74 		(me, "%s -- %s\n", state, NSCD_SMF_SVC_FMRI(srci));
75 
76 	(void) rw_wrlock(&nscd_smf_service_state_lock);
77 
78 	if (nscd_smf_service_state[srci].src_name == NULL)
79 		nscd_smf_service_state[srci].src_name =
80 		    NSCD_NSW_SRC_NAME(srci);
81 
82 	if (strcmp(state, SCF_STATE_STRING_UNINIT) == 0)
83 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_UNINIT;
84 	else if (strcmp(state, SCF_STATE_STRING_MAINT) == 0)
85 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_MAINT;
86 	else if (strcmp(state, SCF_STATE_STRING_OFFLINE) == 0)
87 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_OFFLINE;
88 	else if (strcmp(state, SCF_STATE_STRING_DISABLED) == 0)
89 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DISABLED;
90 	else if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0)
91 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_ONLINE;
92 	else if (strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)
93 		NSCD_SMF_SVC_STATE(srci) = SCF_STATE_DEGRADED;
94 
95 	ret = NSCD_SMF_SVC_STATE(srci);
96 	(void) rw_unlock(&nscd_smf_service_state_lock);
97 
98 	free(state);
99 	return (ret);
100 }
101 
102 /* ARGSUSED */
103 static void *
104 set_smf_state(void *arg)
105 {
106 
107 	int	i;
108 	int	st;
109 
110 	/*
111 	 * the forker nscd needs not monitor the state
112 	 * of the client services
113 	 */
114 	if (_whoami == NSCD_FORKER)
115 		thr_exit(0);
116 
117 	/*CONSTCOND*/
118 	while (1) {
119 
120 		/* skip the first service which is nscd */
121 		for (i = 1; i < NSCD_NUM_SMF_FMRI; i++) {
122 			st = query_smf_state(i);
123 			if (st == NSCD_SVC_STATE_UNINITED)
124 				break;
125 		}
126 
127 		(void) sleep(NSCD_SW_CFG_G.check_smf_state_interval_g);
128 	}
129 	/* NOTREACHED */
130 	/*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
131 }
132 
133 nscd_rc_t
134 _nscd_init_smf_monitor() {
135 
136 	int	errnum;
137 	char	*me = "_nscd_init_smf_monitor";
138 
139 	_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_DEBUG)
140 	(me, "initializing the smf monitor\n");
141 
142 	/*
143 	 * start a thread to check the state of the client services
144 	 */
145 	if (thr_create(NULL, NULL, set_smf_state,
146 		NULL, THR_DETACHED, NULL) != 0) {
147 		errnum = errno;
148 		_NSCD_LOG(NSCD_LOG_SMF_MONITOR, NSCD_LOG_LEVEL_ERROR)
149 		(me, "thr_create: %s\n", strerror(errnum));
150 		return (NSCD_THREAD_CREATE_ERROR);
151 	}
152 
153 	return (NSCD_SUCCESS);
154 }
155 
156 int
157 _nscd_get_smf_state(int srci, int dbi, int recheck)
158 {
159 	int	s;
160 	char	*n;
161 
162 	n = NSCD_NSW_SRC_NAME(srci);
163 
164 	/* the files, compat, and dns backends are always available */
165 	if ((*n == 'f' || *n == 'c' || *n == 'd' || *n == 'a') &&
166 	    (strcmp(NSCD_NSW_SRC_NAME(srci), "files") == 0 ||
167 	    strcmp(NSCD_NSW_SRC_NAME(srci), "compat") == 0 ||
168 	    strcmp(NSCD_NSW_SRC_NAME(srci), "ad") == 0 ||
169 	    strcmp(NSCD_NSW_SRC_NAME(srci), "dns") == 0)) {
170 		return (SCF_STATE_ONLINE);
171 	}
172 
173 	/*
174 	 * for the printer database and user backend, treat the
175 	 * backend as a unsupported one, as nscd can not access
176 	 * the home directory of the user
177 	 */
178 	if (*n == 'u' && strcmp(NSCD_NSW_SRC_NAME(srci), "user") == 0) {
179 		if (strcmp(NSCD_NSW_DB_NAME(dbi), NSS_DBNAM_PRINTERS) == 0)
180 			return (NSCD_SVC_STATE_UNSUPPORTED_SRC);
181 		else
182 			return (SCF_STATE_ONLINE);
183 	}
184 
185 	/*
186 	 * Foreign backend is not supported by nscd unless
187 	 * the backend supports the nss2 interface (global
188 	 * symbol _nss_<backname name>_version is present),
189 	 * tell the switch engine to return NSS_TRYLOCAL
190 	 * if needed via rc NSCD_SVC_STATE_FOREIGN_SRC.
191 	 */
192 	if (srci >= _nscd_cfg_num_nsw_src)
193 		return (NSCD_SVC_STATE_FOREIGN_SRC);
194 
195 	if (recheck == 1)
196 		return (query_smf_state(srci));
197 
198 	(void) rw_rdlock(&nscd_smf_service_state_lock);
199 	s = NSCD_SMF_SVC_STATE(srci);
200 	(void) rw_unlock(&nscd_smf_service_state_lock);
201 
202 	/*
203 	 * if the state has been queried at least once but is
204 	 * still not online, query one more time
205 	 */
206 	if (s != NSCD_SVC_STATE_UNINITED && s < SCF_STATE_ONLINE)
207 		s = query_smf_state(srci);
208 
209 	return (s);
210 }
211