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 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <locale.h>
27#include <unistd.h>
28#include <string.h>
29#include <time.h>
30#include "nscd_common.h"
31#include "nscd_config.h"
32#include "nscd_log.h"
33#include "nscd_switch.h"
34#include "nscd_frontend.h"
35
36static char	*cfgfile_save = NULL;
37static mutex_t	time_mutex = DEFAULTMUTEX;
38static time_t	start_time = 0;
39
40void
41_nscd_set_start_time(int reset)
42{
43	(void) mutex_lock(&time_mutex);
44	if (start_time == 0 || reset == 1)
45		start_time = time(NULL);
46	(void) mutex_unlock(&time_mutex);
47}
48
49time_t
50_nscd_get_start_time()
51{
52	return (start_time);
53}
54
55nscd_rc_t
56_nscd_init(
57	char			*cfgfile)
58{
59	char			*me = "nscd_init";
60	nscd_rc_t		rc;
61	nscd_cfg_error_t	*err;
62
63	/*
64	 * remember when main or forker nscd starts.
65	 */
66	_nscd_set_start_time(0);
67
68	/*
69	 * allocate the space for tables
70	 */
71	if ((rc = _nscd_alloc_nsw_config()) != NSCD_SUCCESS ||
72	    (rc = _nscd_alloc_service_state_table()) != NSCD_SUCCESS ||
73	    (rc = _nscd_alloc_nsw_state_base()) != NSCD_SUCCESS ||
74	    (rc = _nscd_alloc_nsw_be_info_db()) != NSCD_SUCCESS ||
75	    (rc = _nscd_alloc_getent_ctx_base()) != NSCD_SUCCESS)
76		return (rc);
77
78	/*
79	 * allocate the space for local configuration
80	 * and statistics
81	 */
82	if ((rc = _nscd_alloc_switch_cfg()) != NSCD_SUCCESS ||
83	    (rc = _nscd_alloc_frontend_cfg()) != NSCD_SUCCESS ||
84	    (rc = _nscd_alloc_switch_stats()) != NSCD_SUCCESS)
85		return (rc);
86
87	/*
88	 * Create and init the internal address database to keep
89	 * track of the memory allocated by _nscd_alloc
90	 */
91	if (_nscd_create_int_addrDB() == NULL) {
92		_NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_ERROR)
93		(me, "_nscd_create_int_addrDB failed\n");
94		return (NSCD_NO_MEMORY);
95	}
96
97	/*
98	 * Create and init the internal context database to keep
99	 * track of the getent context currently being used
100	 */
101	if (_nscd_create_getent_ctxDB() == NULL) {
102		_NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
103		(me, "_nscd_create_getent_ctx_addrDB failed\n");
104		return (NSCD_NO_MEMORY);
105	}
106
107	/*
108	 * Create the backend info database for each possible source
109	 */
110	if ((rc = _nscd_init_all_nsw_be_info_db()) != NSCD_SUCCESS) {
111		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
112		(me, "_nscd_init_all_nsw_be_info_db failed (rc = %d)\n",
113		    rc);
114		return (rc);
115	}
116
117	/*
118	 * Create the nscd_nsw_config_t for each possible nss database
119	 */
120	if ((rc = _nscd_init_all_nsw_config()) != NSCD_SUCCESS) {
121		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
122		(me, "_nscd_init_all_nsw_config failed (rc = %d)\n", rc);
123		return (rc);
124	}
125
126	/*
127	 * initialize config/stats management
128	 */
129	rc = _nscd_cfg_init(&err);
130	if (rc != NSCD_SUCCESS) {
131		if (err != NULL)
132			_nscd_cfg_free_error(err);
133		return (rc);
134	}
135
136	/*
137	 * read in the nsswitch configuration
138	 */
139	rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err);
140	if (rc != NSCD_SUCCESS) {
141		(void) printf(
142		gettext("reading config file %s failed with rc = %d, %s\n"),
143		    "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err));
144		if (err != NULL)
145			_nscd_cfg_free_error(err);
146
147		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
148	(me, "unable to read /etc/nsswitch.conf (rc = %d)\n", rc);
149		return (rc);
150	}
151	/*
152	 * remember which version of /etc/nsswitch.conf that was read
153	 */
154	_nscd_restart_if_cfgfile_changed();
155
156	/*
157	 * read in the nscd configuration
158	 */
159	if (cfgfile == NULL) {
160		cfgfile = "/etc/nscd.conf";
161		if (access(cfgfile, R_OK) != 0) {
162			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
163		(me, "unable to read /etc/nscd.conf (rc = %d)\n", rc);
164
165			return (NSCD_CFG_FILE_ACCESS_ERROR);
166		}
167	}
168	rc = _nscd_cfg_read_file(cfgfile, &err);
169	if (rc != NSCD_SUCCESS) {
170		(void) printf(
171		gettext("reading config file %s failed with rc = %d, %s\n"),
172		    cfgfile, rc, NSCD_ERR2MSG(err));
173		if (err != NULL)
174			_nscd_cfg_free_error(err);
175
176		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
177		(me, "unable to read configuration from %s (rc = %d)\n",
178		    cfgfile, rc);
179
180		return (rc);
181	}
182	/*
183	 * remember the name of the config file
184	 * in case refresh is requested later
185	 */
186	if (cfgfile != NULL) {
187		cfgfile_save = strdup(cfgfile);
188		if (cfgfile_save == NULL)
189			return (NSCD_NO_MEMORY);
190	}
191
192	return (NSCD_SUCCESS);
193}
194
195nscd_rc_t
196_nscd_refresh()
197{
198	char			*me = "nscd_refresh";
199	char			*cfgfile;
200	nscd_rc_t		rc;
201	nscd_cfg_error_t	*err;
202	char			errmsg[1024];
203
204	/*
205	 * re-read the nscd configuration
206	 */
207	if (cfgfile_save == NULL)
208		cfgfile = "/etc/nscd.conf";
209	else
210		cfgfile = cfgfile_save;
211
212	if (access(cfgfile, R_OK) != 0) {
213		(void) snprintf(errmsg, sizeof (errmsg),
214		"unable to read the config file %s (rc = %d), %s\n",
215		    cfgfile, NSCD_CFG_FILE_ACCESS_ERROR,
216		    strerror(errno));
217
218		goto error_exit;
219	}
220
221	rc = _nscd_cfg_read_file(cfgfile, &err);
222	if (rc != NSCD_SUCCESS) {
223		(void) snprintf(errmsg, sizeof (errmsg),
224		    "unable to parse the config file %s (rc = %d), %s\n",
225		    cfgfile, rc, NSCD_ERR2MSG(err));
226
227		goto error_exit;
228	}
229
230	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ALL)
231	(me, "nscd configuration refreshed successfully\n");
232
233	return (NSCD_SUCCESS);
234
235	error_exit:
236
237	if (err != NULL)
238		_nscd_cfg_free_error(err);
239
240	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
241	(me, "%s\n", errmsg);
242
243	return (rc);
244}
245