xref: /titanic_53/usr/src/cmd/nscd/nscd_frontend.c (revision cb5caa98562cf06753163f558cbcfe30b8f4673a)
1*cb5caa98Sdjl /*
2*cb5caa98Sdjl  * CDDL HEADER START
3*cb5caa98Sdjl  *
4*cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5*cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6*cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7*cb5caa98Sdjl  *
8*cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10*cb5caa98Sdjl  * See the License for the specific language governing permissions
11*cb5caa98Sdjl  * and limitations under the License.
12*cb5caa98Sdjl  *
13*cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14*cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16*cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17*cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18*cb5caa98Sdjl  *
19*cb5caa98Sdjl  * CDDL HEADER END
20*cb5caa98Sdjl  */
21*cb5caa98Sdjl /*
22*cb5caa98Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*cb5caa98Sdjl  * Use is subject to license terms.
24*cb5caa98Sdjl  */
25*cb5caa98Sdjl 
26*cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*cb5caa98Sdjl 
28*cb5caa98Sdjl #include <stdlib.h>
29*cb5caa98Sdjl #include <alloca.h>
30*cb5caa98Sdjl #include <signal.h>
31*cb5caa98Sdjl #include <sys/stat.h>
32*cb5caa98Sdjl #include <unistd.h>
33*cb5caa98Sdjl #include <pthread.h>
34*cb5caa98Sdjl #include <time.h>
35*cb5caa98Sdjl #include <errno.h>
36*cb5caa98Sdjl #include <door.h>
37*cb5caa98Sdjl #include <zone.h>
38*cb5caa98Sdjl #include <resolv.h>
39*cb5caa98Sdjl #include <sys/socket.h>
40*cb5caa98Sdjl #include <net/route.h>
41*cb5caa98Sdjl #include <string.h>
42*cb5caa98Sdjl #include <net/if.h>
43*cb5caa98Sdjl #include <sys/stat.h>
44*cb5caa98Sdjl #include <fcntl.h>
45*cb5caa98Sdjl #include "nscd_common.h"
46*cb5caa98Sdjl #include "nscd_door.h"
47*cb5caa98Sdjl #include "nscd_config.h"
48*cb5caa98Sdjl #include "nscd_switch.h"
49*cb5caa98Sdjl #include "nscd_log.h"
50*cb5caa98Sdjl #include "nscd_selfcred.h"
51*cb5caa98Sdjl #include "nscd_frontend.h"
52*cb5caa98Sdjl #include "nscd_admin.h"
53*cb5caa98Sdjl 
54*cb5caa98Sdjl static void rts_mon(void);
55*cb5caa98Sdjl static void keep_open_dns_socket(void);
56*cb5caa98Sdjl 
57*cb5caa98Sdjl extern nsc_ctx_t *cache_ctx_p[];
58*cb5caa98Sdjl 
59*cb5caa98Sdjl /*
60*cb5caa98Sdjl  * Current active Configuration data for the frontend component
61*cb5caa98Sdjl  */
62*cb5caa98Sdjl static nscd_cfg_global_frontend_t	frontend_cfg_g;
63*cb5caa98Sdjl static nscd_cfg_frontend_t		*frontend_cfg;
64*cb5caa98Sdjl 
65*cb5caa98Sdjl static int	max_servers = 0;
66*cb5caa98Sdjl static int	max_servers_set = 0;
67*cb5caa98Sdjl static int	per_user_is_on = 1;
68*cb5caa98Sdjl 
69*cb5caa98Sdjl static char	*main_execname;
70*cb5caa98Sdjl static char	**main_argv;
71*cb5caa98Sdjl extern int	_whoami;
72*cb5caa98Sdjl extern long	activity;
73*cb5caa98Sdjl extern mutex_t	activity_lock;
74*cb5caa98Sdjl 
75*cb5caa98Sdjl static sema_t	common_sema;
76*cb5caa98Sdjl 
77*cb5caa98Sdjl static thread_key_t	lookup_state_key;
78*cb5caa98Sdjl static mutex_t		create_lock = DEFAULTMUTEX;
79*cb5caa98Sdjl static int		num_servers = 0;
80*cb5caa98Sdjl static thread_key_t	server_key;
81*cb5caa98Sdjl 
82*cb5caa98Sdjl /*
83*cb5caa98Sdjl  * Bind a TSD value to a server thread. This enables the destructor to
84*cb5caa98Sdjl  * be called if/when this thread exits.  This would be a programming
85*cb5caa98Sdjl  * error, but better safe than sorry.
86*cb5caa98Sdjl  */
87*cb5caa98Sdjl /*ARGSUSED*/
88*cb5caa98Sdjl static void *
89*cb5caa98Sdjl server_tsd_bind(void *arg)
90*cb5caa98Sdjl {
91*cb5caa98Sdjl 	static void *value = 0;
92*cb5caa98Sdjl 
93*cb5caa98Sdjl 	/* disable cancellation to avoid hangs if server threads disappear */
94*cb5caa98Sdjl 	(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
95*cb5caa98Sdjl 	(void) thr_setspecific(server_key, value);
96*cb5caa98Sdjl 	(void) door_return(NULL, 0, NULL, 0);
97*cb5caa98Sdjl 
98*cb5caa98Sdjl 	/* make lint happy */
99*cb5caa98Sdjl 	return (NULL);
100*cb5caa98Sdjl }
101*cb5caa98Sdjl 
102*cb5caa98Sdjl /*
103*cb5caa98Sdjl  * Server threads are created here.
104*cb5caa98Sdjl  */
105*cb5caa98Sdjl /*ARGSUSED*/
106*cb5caa98Sdjl static void
107*cb5caa98Sdjl server_create(door_info_t *dip)
108*cb5caa98Sdjl {
109*cb5caa98Sdjl 	(void) mutex_lock(&create_lock);
110*cb5caa98Sdjl 	if (++num_servers > max_servers) {
111*cb5caa98Sdjl 		num_servers--;
112*cb5caa98Sdjl 		(void) mutex_unlock(&create_lock);
113*cb5caa98Sdjl 		return;
114*cb5caa98Sdjl 	}
115*cb5caa98Sdjl 	(void) mutex_unlock(&create_lock);
116*cb5caa98Sdjl 	(void) thr_create(NULL, 0, server_tsd_bind, NULL,
117*cb5caa98Sdjl 			THR_BOUND|THR_DETACHED, NULL);
118*cb5caa98Sdjl }
119*cb5caa98Sdjl 
120*cb5caa98Sdjl /*
121*cb5caa98Sdjl  * Server thread are destroyed here
122*cb5caa98Sdjl  */
123*cb5caa98Sdjl /*ARGSUSED*/
124*cb5caa98Sdjl static void
125*cb5caa98Sdjl server_destroy(void *arg)
126*cb5caa98Sdjl {
127*cb5caa98Sdjl 	(void) mutex_lock(&create_lock);
128*cb5caa98Sdjl 	num_servers--;
129*cb5caa98Sdjl 	(void) mutex_unlock(&create_lock);
130*cb5caa98Sdjl }
131*cb5caa98Sdjl 
132*cb5caa98Sdjl /*
133*cb5caa98Sdjl  * get clearance
134*cb5caa98Sdjl  */
135*cb5caa98Sdjl int
136*cb5caa98Sdjl _nscd_get_clearance(sema_t *sema) {
137*cb5caa98Sdjl 	if (sema_trywait(&common_sema) == 0) {
138*cb5caa98Sdjl 		(void) thr_setspecific(lookup_state_key, NULL);
139*cb5caa98Sdjl 		return (0);
140*cb5caa98Sdjl 	}
141*cb5caa98Sdjl 
142*cb5caa98Sdjl 	if (sema_trywait(sema) == 0) {
143*cb5caa98Sdjl 		(void) thr_setspecific(lookup_state_key, (void*)1);
144*cb5caa98Sdjl 		return (0);
145*cb5caa98Sdjl 	}
146*cb5caa98Sdjl 
147*cb5caa98Sdjl 	return (1);
148*cb5caa98Sdjl }
149*cb5caa98Sdjl 
150*cb5caa98Sdjl 
151*cb5caa98Sdjl /*
152*cb5caa98Sdjl  * release clearance
153*cb5caa98Sdjl  */
154*cb5caa98Sdjl int
155*cb5caa98Sdjl _nscd_release_clearance(sema_t *sema) {
156*cb5caa98Sdjl 	int	which;
157*cb5caa98Sdjl 
158*cb5caa98Sdjl 	(void) thr_getspecific(lookup_state_key, (void**)&which);
159*cb5caa98Sdjl 	if (which == 0) /* from common pool */ {
160*cb5caa98Sdjl 		(void) sema_post(&common_sema);
161*cb5caa98Sdjl 		return (0);
162*cb5caa98Sdjl 	}
163*cb5caa98Sdjl 
164*cb5caa98Sdjl 	(void) sema_post(sema);
165*cb5caa98Sdjl 	return (1);
166*cb5caa98Sdjl }
167*cb5caa98Sdjl 
168*cb5caa98Sdjl static void
169*cb5caa98Sdjl dozip(void)
170*cb5caa98Sdjl {
171*cb5caa98Sdjl 	/* not much here */
172*cb5caa98Sdjl }
173*cb5caa98Sdjl 
174*cb5caa98Sdjl static void
175*cb5caa98Sdjl restart_if_cfgfile_changed()
176*cb5caa98Sdjl {
177*cb5caa98Sdjl 
178*cb5caa98Sdjl 	static mutex_t	nsswitch_lock = DEFAULTMUTEX;
179*cb5caa98Sdjl 	static time_t	last_nsswitch_check = 0;
180*cb5caa98Sdjl 	static time_t	last_nsswitch_modified = 0;
181*cb5caa98Sdjl 	static time_t	last_resolv_modified = 0;
182*cb5caa98Sdjl 	time_t		now = time(NULL);
183*cb5caa98Sdjl 	char		*me = "restart_if_cfgfile_changed";
184*cb5caa98Sdjl 
185*cb5caa98Sdjl 	if (now - last_nsswitch_check <= _NSC_FILE_CHECK_TIME)
186*cb5caa98Sdjl 		return;
187*cb5caa98Sdjl 
188*cb5caa98Sdjl 	(void) mutex_lock(&nsswitch_lock);
189*cb5caa98Sdjl 
190*cb5caa98Sdjl 	if (now - last_nsswitch_check > _NSC_FILE_CHECK_TIME) {
191*cb5caa98Sdjl 		struct stat nss_buf;
192*cb5caa98Sdjl 		struct stat res_buf;
193*cb5caa98Sdjl 
194*cb5caa98Sdjl 		last_nsswitch_check = now;
195*cb5caa98Sdjl 
196*cb5caa98Sdjl 		(void) mutex_unlock(&nsswitch_lock); /* let others continue */
197*cb5caa98Sdjl 
198*cb5caa98Sdjl 		/*
199*cb5caa98Sdjl 		 *  This code keeps us from statting resolv.conf
200*cb5caa98Sdjl 		 *  if it doesn't exist, yet prevents us from ignoring
201*cb5caa98Sdjl 		 *  it if it happens to disappear later on for a bit.
202*cb5caa98Sdjl 		 */
203*cb5caa98Sdjl 
204*cb5caa98Sdjl 		if (last_resolv_modified >= 0) {
205*cb5caa98Sdjl 			if (stat("/etc/resolv.conf", &res_buf) < 0) {
206*cb5caa98Sdjl 				if (last_resolv_modified == 0)
207*cb5caa98Sdjl 				    last_resolv_modified = -1;
208*cb5caa98Sdjl 				else
209*cb5caa98Sdjl 				    res_buf.st_mtime = last_resolv_modified;
210*cb5caa98Sdjl 			} else if (last_resolv_modified == 0) {
211*cb5caa98Sdjl 			    last_resolv_modified = res_buf.st_mtime;
212*cb5caa98Sdjl 			}
213*cb5caa98Sdjl 		}
214*cb5caa98Sdjl 
215*cb5caa98Sdjl 		if (stat("/etc/nsswitch.conf", &nss_buf) < 0) {
216*cb5caa98Sdjl 
217*cb5caa98Sdjl 			/*EMPTY*/;
218*cb5caa98Sdjl 
219*cb5caa98Sdjl 		} else if (last_nsswitch_modified == 0) {
220*cb5caa98Sdjl 
221*cb5caa98Sdjl 			last_nsswitch_modified = nss_buf.st_mtime;
222*cb5caa98Sdjl 
223*cb5caa98Sdjl 		} else if ((last_nsswitch_modified < nss_buf.st_mtime) ||
224*cb5caa98Sdjl 		    ((last_resolv_modified > 0) &&
225*cb5caa98Sdjl 		    (last_resolv_modified < res_buf.st_mtime))) {
226*cb5caa98Sdjl 			static mutex_t exit_lock = DEFAULTMUTEX;
227*cb5caa98Sdjl 			char *fmri;
228*cb5caa98Sdjl 
229*cb5caa98Sdjl 			/*
230*cb5caa98Sdjl 			 * if in self cred mode, kill the forker and
231*cb5caa98Sdjl 			 * child nscds
232*cb5caa98Sdjl 			 */
233*cb5caa98Sdjl 			if (_nscd_is_self_cred_on(0, NULL)) {
234*cb5caa98Sdjl 				_nscd_kill_forker();
235*cb5caa98Sdjl 				_nscd_kill_all_children();
236*cb5caa98Sdjl 			}
237*cb5caa98Sdjl 
238*cb5caa98Sdjl 			/*
239*cb5caa98Sdjl 			 * time for restart
240*cb5caa98Sdjl 			 */
241*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO)
242*cb5caa98Sdjl 			(me, "nscd restart due to %s or %s change\n",
243*cb5caa98Sdjl 				"/etc/nsswitch.conf", "resolv.conf");
244*cb5caa98Sdjl 			/*
245*cb5caa98Sdjl 			 * try to restart under smf
246*cb5caa98Sdjl 			 */
247*cb5caa98Sdjl 			if ((fmri = getenv("SMF_FMRI")) == NULL) {
248*cb5caa98Sdjl 				/* not running under smf - reexec */
249*cb5caa98Sdjl 				(void) execv(main_execname, main_argv);
250*cb5caa98Sdjl 				exit(1); /* just in case */
251*cb5caa98Sdjl 			}
252*cb5caa98Sdjl 
253*cb5caa98Sdjl 			/* prevent multiple restarts */
254*cb5caa98Sdjl 			(void) mutex_lock(&exit_lock);
255*cb5caa98Sdjl 
256*cb5caa98Sdjl 			if (smf_restart_instance(fmri) == 0)
257*cb5caa98Sdjl 				(void) sleep(10); /* wait a bit */
258*cb5caa98Sdjl 			exit(1); /* give up waiting for resurrection */
259*cb5caa98Sdjl 		}
260*cb5caa98Sdjl 
261*cb5caa98Sdjl 	} else
262*cb5caa98Sdjl 	    (void) mutex_unlock(&nsswitch_lock);
263*cb5caa98Sdjl }
264*cb5caa98Sdjl 
265*cb5caa98Sdjl uid_t
266*cb5caa98Sdjl _nscd_get_client_euid()
267*cb5caa98Sdjl {
268*cb5caa98Sdjl 	ucred_t	*uc = NULL;
269*cb5caa98Sdjl 	uid_t	id;
270*cb5caa98Sdjl 	char	*me = "get_client_euid";
271*cb5caa98Sdjl 
272*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
273*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
274*cb5caa98Sdjl 		(me, "door_ucred: %s\n", strerror(errno));
275*cb5caa98Sdjl 		return ((uid_t)-1);
276*cb5caa98Sdjl 	}
277*cb5caa98Sdjl 
278*cb5caa98Sdjl 	id = ucred_geteuid(uc);
279*cb5caa98Sdjl 	ucred_free(uc);
280*cb5caa98Sdjl 	return (id);
281*cb5caa98Sdjl }
282*cb5caa98Sdjl 
283*cb5caa98Sdjl static void
284*cb5caa98Sdjl N2N_check_priv(
285*cb5caa98Sdjl 	void			*buf,
286*cb5caa98Sdjl 	char			*dc_str)
287*cb5caa98Sdjl {
288*cb5caa98Sdjl 	nss_pheader_t		*phdr = (nss_pheader_t *)buf;
289*cb5caa98Sdjl 	ucred_t			*uc = NULL;
290*cb5caa98Sdjl 	const priv_set_t	*eset;
291*cb5caa98Sdjl 	zoneid_t		zoneid;
292*cb5caa98Sdjl 	int			errnum;
293*cb5caa98Sdjl 	char			*me = "N2N_check_priv";
294*cb5caa98Sdjl 
295*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
296*cb5caa98Sdjl 		errnum = errno;
297*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
298*cb5caa98Sdjl 		(me, "door_ucred: %s\n", strerror(errno));
299*cb5caa98Sdjl 
300*cb5caa98Sdjl 		NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
301*cb5caa98Sdjl 	}
302*cb5caa98Sdjl 
303*cb5caa98Sdjl 	eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
304*cb5caa98Sdjl 	zoneid = ucred_getzoneid(uc);
305*cb5caa98Sdjl 
306*cb5caa98Sdjl 	if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) ||
307*cb5caa98Sdjl 		eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) :
308*cb5caa98Sdjl 		ucred_geteuid(uc) != 0) {
309*cb5caa98Sdjl 
310*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
311*cb5caa98Sdjl 		(me, "%s call failed(cred): caller pid %d, uid %d, "
312*cb5caa98Sdjl 		"euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
313*cb5caa98Sdjl 		ucred_getruid(uc), ucred_geteuid(uc), zoneid);
314*cb5caa98Sdjl 		ucred_free(uc);
315*cb5caa98Sdjl 
316*cb5caa98Sdjl 		NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES);
317*cb5caa98Sdjl 	}
318*cb5caa98Sdjl 
319*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
320*cb5caa98Sdjl 	(me, "nscd received %s cmd from pid %d, uid %d, "
321*cb5caa98Sdjl 	"euid %d, zoneid %d\n", dc_str, ucred_getpid(uc),
322*cb5caa98Sdjl 	ucred_getruid(uc), ucred_geteuid(uc), zoneid);
323*cb5caa98Sdjl 
324*cb5caa98Sdjl 	ucred_free(uc);
325*cb5caa98Sdjl 
326*cb5caa98Sdjl 	NSCD_RETURN_STATUS_SUCCESS(phdr);
327*cb5caa98Sdjl }
328*cb5caa98Sdjl 
329*cb5caa98Sdjl static void
330*cb5caa98Sdjl APP_check_cred(
331*cb5caa98Sdjl 	void		*buf,
332*cb5caa98Sdjl 	pid_t		*pidp,
333*cb5caa98Sdjl 	char		*dc_str)
334*cb5caa98Sdjl {
335*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
336*cb5caa98Sdjl 	ucred_t		*uc = NULL;
337*cb5caa98Sdjl 	uid_t		ruid;
338*cb5caa98Sdjl 	uid_t		euid;
339*cb5caa98Sdjl 	int		errnum;
340*cb5caa98Sdjl 	char		*me = "APP_check_cred";
341*cb5caa98Sdjl 
342*cb5caa98Sdjl 	if (door_ucred(&uc) != 0) {
343*cb5caa98Sdjl 		errnum = errno;
344*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
345*cb5caa98Sdjl 		(me, "door_ucred: %s\n", strerror(errno));
346*cb5caa98Sdjl 
347*cb5caa98Sdjl 		NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum);
348*cb5caa98Sdjl 	}
349*cb5caa98Sdjl 
350*cb5caa98Sdjl 	if (NSS_PACKED_CRED_CHECK(buf, ruid = ucred_getruid(uc),
351*cb5caa98Sdjl 		euid = ucred_geteuid(uc))) {
352*cb5caa98Sdjl 		if (pidp != NULL)
353*cb5caa98Sdjl 			*pidp = ucred_getpid(uc);
354*cb5caa98Sdjl 		ucred_free(uc);
355*cb5caa98Sdjl 
356*cb5caa98Sdjl 		NSCD_RETURN_STATUS_SUCCESS(phdr);
357*cb5caa98Sdjl 	}
358*cb5caa98Sdjl 
359*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT)
360*cb5caa98Sdjl 	(me, "%s call failed: caller pid %d, ruid %d, "
361*cb5caa98Sdjl 	"euid %d, header ruid %d, header euid %d\n", dc_str,
362*cb5caa98Sdjl 	(pidp != NULL) ? *pidp : -1, ruid, euid,
363*cb5caa98Sdjl 	((nss_pheader_t *)(buf))->p_ruid, ((nss_pheader_t *)(buf))->p_euid);
364*cb5caa98Sdjl 
365*cb5caa98Sdjl 
366*cb5caa98Sdjl 	ucred_free(uc);
367*cb5caa98Sdjl 
368*cb5caa98Sdjl 	NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES);
369*cb5caa98Sdjl }
370*cb5caa98Sdjl 
371*cb5caa98Sdjl static void
372*cb5caa98Sdjl lookup(char *argp, size_t arg_size)
373*cb5caa98Sdjl {
374*cb5caa98Sdjl 	nsc_lookup_args_t	largs;
375*cb5caa98Sdjl 	char			space[NSCD_LOOKUP_BUFSIZE];
376*cb5caa98Sdjl 	nss_pheader_t		*phdr = (nss_pheader_t *)(void *)argp;
377*cb5caa98Sdjl 
378*cb5caa98Sdjl 	NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space,
379*cb5caa98Sdjl 		sizeof (space));
380*cb5caa98Sdjl 
381*cb5caa98Sdjl 	(void) memset(&largs, 0, sizeof (largs));
382*cb5caa98Sdjl 	largs.buffer = argp;
383*cb5caa98Sdjl 	largs.bufsize = arg_size;
384*cb5caa98Sdjl 	nsc_lookup(&largs, 0);
385*cb5caa98Sdjl 
386*cb5caa98Sdjl 	/*
387*cb5caa98Sdjl 	 * only the PUN needs to keep track of the
388*cb5caa98Sdjl 	 * activity count to determine when to
389*cb5caa98Sdjl 	 * terminate itself
390*cb5caa98Sdjl 	 */
391*cb5caa98Sdjl 	if (_whoami == NSCD_CHILD) {
392*cb5caa98Sdjl 		(void) mutex_lock(&activity_lock);
393*cb5caa98Sdjl 		++activity;
394*cb5caa98Sdjl 		(void) mutex_unlock(&activity_lock);
395*cb5caa98Sdjl 	}
396*cb5caa98Sdjl 
397*cb5caa98Sdjl 	NSCD_SET_RETURN_ARG(phdr, arg_size);
398*cb5caa98Sdjl 	(void) door_return(argp, arg_size, NULL, 0);
399*cb5caa98Sdjl }
400*cb5caa98Sdjl 
401*cb5caa98Sdjl static void
402*cb5caa98Sdjl getent(char *argp, size_t arg_size)
403*cb5caa98Sdjl {
404*cb5caa98Sdjl 	char			space[NSCD_LOOKUP_BUFSIZE];
405*cb5caa98Sdjl 	nss_pheader_t		*phdr = (nss_pheader_t *)(void *)argp;
406*cb5caa98Sdjl 
407*cb5caa98Sdjl 	NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr,
408*cb5caa98Sdjl 		space, sizeof (space));
409*cb5caa98Sdjl 
410*cb5caa98Sdjl 	nss_pgetent(argp, arg_size);
411*cb5caa98Sdjl 
412*cb5caa98Sdjl 	NSCD_SET_RETURN_ARG(phdr, arg_size);
413*cb5caa98Sdjl 	(void) door_return(argp, arg_size, NULL, 0);
414*cb5caa98Sdjl }
415*cb5caa98Sdjl 
416*cb5caa98Sdjl static int
417*cb5caa98Sdjl is_db_per_user(void *buf, char *dblist)
418*cb5caa98Sdjl {
419*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
420*cb5caa98Sdjl 	nss_dbd_t	*pdbd;
421*cb5caa98Sdjl 	char		*dbname, *dbn;
422*cb5caa98Sdjl 	int		len;
423*cb5caa98Sdjl 
424*cb5caa98Sdjl 	/* copy db name into a temp buffer */
425*cb5caa98Sdjl 	pdbd = (nss_dbd_t *)((void *)((char *)buf + phdr->dbd_off));
426*cb5caa98Sdjl 	dbname = (char *)pdbd + pdbd->o_name;
427*cb5caa98Sdjl 	len = strlen(dbname);
428*cb5caa98Sdjl 	dbn = alloca(len + 2);
429*cb5caa98Sdjl 	(void) memcpy(dbn, dbname, len);
430*cb5caa98Sdjl 
431*cb5caa98Sdjl 	/* check if <dbname> + ',' can be found in the dblist string */
432*cb5caa98Sdjl 	dbn[len] = ',';
433*cb5caa98Sdjl 	dbn[len + 1] = '\0';
434*cb5caa98Sdjl 	if (strstr(dblist, dbn) != NULL)
435*cb5caa98Sdjl 		return (1);
436*cb5caa98Sdjl 
437*cb5caa98Sdjl 	/*
438*cb5caa98Sdjl 	 * check if <dbname> can be found in the last part
439*cb5caa98Sdjl 	 * of the dblist string
440*cb5caa98Sdjl 	 */
441*cb5caa98Sdjl 	dbn[len] = '\0';
442*cb5caa98Sdjl 	if (strstr(dblist, dbn) != NULL)
443*cb5caa98Sdjl 		return (1);
444*cb5caa98Sdjl 
445*cb5caa98Sdjl 	return (0);
446*cb5caa98Sdjl }
447*cb5caa98Sdjl 
448*cb5caa98Sdjl /*
449*cb5caa98Sdjl  * Check to see if all conditions are met for processing per-user
450*cb5caa98Sdjl  * requests. Returns 1 if yes, -1 if backend is not configured,
451*cb5caa98Sdjl  * 0 otherwise.
452*cb5caa98Sdjl  */
453*cb5caa98Sdjl static int
454*cb5caa98Sdjl need_per_user_door(void *buf, int whoami, uid_t uid, char **dblist)
455*cb5caa98Sdjl {
456*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
457*cb5caa98Sdjl 
458*cb5caa98Sdjl 	NSCD_SET_STATUS_SUCCESS(phdr);
459*cb5caa98Sdjl 
460*cb5caa98Sdjl 	/* if already a per-user nscd, no need to get per-user door */
461*cb5caa98Sdjl 	if (whoami == NSCD_CHILD)
462*cb5caa98Sdjl 		return (0);
463*cb5caa98Sdjl 
464*cb5caa98Sdjl 	/* forker shouldn't be asked */
465*cb5caa98Sdjl 	if (whoami == NSCD_FORKER) {
466*cb5caa98Sdjl 		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
467*cb5caa98Sdjl 		return (0);
468*cb5caa98Sdjl 	}
469*cb5caa98Sdjl 
470*cb5caa98Sdjl 	/* if door client is root, no need for a per-user door */
471*cb5caa98Sdjl 	if (uid == 0)
472*cb5caa98Sdjl 		return (0);
473*cb5caa98Sdjl 
474*cb5caa98Sdjl 	/*
475*cb5caa98Sdjl 	 * if per-user lookup is not configured, no per-user
476*cb5caa98Sdjl 	 * door available
477*cb5caa98Sdjl 	 */
478*cb5caa98Sdjl 	if (_nscd_is_self_cred_on(0, dblist) == 0)
479*cb5caa98Sdjl 		return (-1);
480*cb5caa98Sdjl 
481*cb5caa98Sdjl 	/*
482*cb5caa98Sdjl 	 * if per-user lookup is not configured for the db,
483*cb5caa98Sdjl 	 * don't bother
484*cb5caa98Sdjl 	 */
485*cb5caa98Sdjl 	if (is_db_per_user(phdr, *dblist) == 0)
486*cb5caa98Sdjl 		return (0);
487*cb5caa98Sdjl 
488*cb5caa98Sdjl 	return (1);
489*cb5caa98Sdjl }
490*cb5caa98Sdjl 
491*cb5caa98Sdjl static void
492*cb5caa98Sdjl if_selfcred_return_per_user_door(char *argp, size_t arg_size,
493*cb5caa98Sdjl 	door_desc_t *dp, int whoami)
494*cb5caa98Sdjl {
495*cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)((void *)argp);
496*cb5caa98Sdjl 	char		*dblist;
497*cb5caa98Sdjl 	int		door = -1;
498*cb5caa98Sdjl 	int		rc = 0;
499*cb5caa98Sdjl 	door_desc_t	desc;
500*cb5caa98Sdjl 	char		space[1024*4];
501*cb5caa98Sdjl 
502*cb5caa98Sdjl 	/*
503*cb5caa98Sdjl 	 * check to see if self-cred is configured and
504*cb5caa98Sdjl 	 * need to return an alternate PUN door
505*cb5caa98Sdjl 	 */
506*cb5caa98Sdjl 	if (per_user_is_on == 1) {
507*cb5caa98Sdjl 		rc = need_per_user_door(argp, whoami,
508*cb5caa98Sdjl 			_nscd_get_client_euid(), &dblist);
509*cb5caa98Sdjl 		if (rc == -1)
510*cb5caa98Sdjl 			per_user_is_on = 0;
511*cb5caa98Sdjl 	}
512*cb5caa98Sdjl 	if (rc <= 0) {
513*cb5caa98Sdjl 		/*
514*cb5caa98Sdjl 		 * self-cred not configured, and no error detected,
515*cb5caa98Sdjl 		 * return to continue the door call processing
516*cb5caa98Sdjl 		 */
517*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr))
518*cb5caa98Sdjl 			return;
519*cb5caa98Sdjl 		else
520*cb5caa98Sdjl 			/*
521*cb5caa98Sdjl 			 * configured but error detected,
522*cb5caa98Sdjl 			 * stop the door call processing
523*cb5caa98Sdjl 			 */
524*cb5caa98Sdjl 			(void) door_return(argp, phdr->data_off, NULL, 0);
525*cb5caa98Sdjl 	}
526*cb5caa98Sdjl 
527*cb5caa98Sdjl 	/* get the alternate PUN door */
528*cb5caa98Sdjl 	_nscd_proc_alt_get(argp, &door);
529*cb5caa98Sdjl 	if (NSCD_GET_STATUS(phdr) != NSS_ALTRETRY) {
530*cb5caa98Sdjl 		(void) door_return(argp, phdr->data_off, NULL, 0);
531*cb5caa98Sdjl 	}
532*cb5caa98Sdjl 
533*cb5caa98Sdjl 	/* return the alternate door descriptor */
534*cb5caa98Sdjl 	(void) memcpy(space, phdr, NSCD_PHDR_LEN(phdr));
535*cb5caa98Sdjl 	argp = space;
536*cb5caa98Sdjl 	phdr = (nss_pheader_t *)(void *)space;
537*cb5caa98Sdjl 	dp = &desc;
538*cb5caa98Sdjl 	dp->d_attributes = DOOR_DESCRIPTOR;
539*cb5caa98Sdjl 	dp->d_data.d_desc.d_descriptor = door;
540*cb5caa98Sdjl 	phdr->data_len = strlen(dblist) + 1;
541*cb5caa98Sdjl 	(void) strcpy(((char *)phdr) + NSCD_PHDR_LEN(phdr), dblist);
542*cb5caa98Sdjl 
543*cb5caa98Sdjl 	arg_size = NSCD_PHDR_LEN(phdr) + NSCD_DATA_LEN(phdr);
544*cb5caa98Sdjl 	(void) door_return(argp, arg_size, dp, 1);
545*cb5caa98Sdjl }
546*cb5caa98Sdjl 
547*cb5caa98Sdjl /*ARGSUSED*/
548*cb5caa98Sdjl static void
549*cb5caa98Sdjl switcher(void *cookie, char *argp, size_t arg_size,
550*cb5caa98Sdjl     door_desc_t *dp, uint_t n_desc)
551*cb5caa98Sdjl {
552*cb5caa98Sdjl 	int			iam;
553*cb5caa98Sdjl 	pid_t			ent_pid = -1;
554*cb5caa98Sdjl 	nss_pheader_t		*phdr = (nss_pheader_t *)((void *)argp);
555*cb5caa98Sdjl 	void			*uptr;
556*cb5caa98Sdjl 	int			buflen, len;
557*cb5caa98Sdjl 	int			callnum;
558*cb5caa98Sdjl 	char			*me = "switcher";
559*cb5caa98Sdjl 
560*cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
561*cb5caa98Sdjl 	(me, "switcher ...\n");
562*cb5caa98Sdjl 
563*cb5caa98Sdjl 	if (argp == DOOR_UNREF_DATA) {
564*cb5caa98Sdjl 		(void) printf("Door Slam... exiting\n");
565*cb5caa98Sdjl 		exit(0);
566*cb5caa98Sdjl 	}
567*cb5caa98Sdjl 
568*cb5caa98Sdjl 	if (argp == NULL) { /* empty door call */
569*cb5caa98Sdjl 		(void) door_return(NULL, 0, 0, 0); /* return the favor */
570*cb5caa98Sdjl 	}
571*cb5caa98Sdjl 
572*cb5caa98Sdjl 	/*
573*cb5caa98Sdjl 	 *  need to restart if main nscd and config file(s) changed
574*cb5caa98Sdjl 	 */
575*cb5caa98Sdjl 	if (_whoami == NSCD_MAIN)
576*cb5caa98Sdjl 		restart_if_cfgfile_changed();
577*cb5caa98Sdjl 
578*cb5caa98Sdjl 	if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) {
579*cb5caa98Sdjl 		switch (phdr->nsc_callnumber) {
580*cb5caa98Sdjl 		case NSCD_SEARCH:
581*cb5caa98Sdjl 
582*cb5caa98Sdjl 		/* if a fallback to main nscd, skip per-user setup */
583*cb5caa98Sdjl 		if (phdr->p_status != NSS_ALTRETRY)
584*cb5caa98Sdjl 			if_selfcred_return_per_user_door(argp, arg_size,
585*cb5caa98Sdjl 				dp, _whoami);
586*cb5caa98Sdjl 		lookup(argp, arg_size);
587*cb5caa98Sdjl 
588*cb5caa98Sdjl 		break;
589*cb5caa98Sdjl 
590*cb5caa98Sdjl 		case NSCD_SETENT:
591*cb5caa98Sdjl 
592*cb5caa98Sdjl 		APP_check_cred(argp, &ent_pid, "NSCD_SETENT");
593*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr)) {
594*cb5caa98Sdjl 			if_selfcred_return_per_user_door(argp, arg_size,
595*cb5caa98Sdjl 				dp, _whoami);
596*cb5caa98Sdjl 			nss_psetent(argp, arg_size, ent_pid);
597*cb5caa98Sdjl 		}
598*cb5caa98Sdjl 		break;
599*cb5caa98Sdjl 
600*cb5caa98Sdjl 		case NSCD_GETENT:
601*cb5caa98Sdjl 
602*cb5caa98Sdjl 		getent(argp, arg_size);
603*cb5caa98Sdjl 		break;
604*cb5caa98Sdjl 
605*cb5caa98Sdjl 		case NSCD_ENDENT:
606*cb5caa98Sdjl 
607*cb5caa98Sdjl 		nss_pendent(argp, arg_size);
608*cb5caa98Sdjl 		break;
609*cb5caa98Sdjl 
610*cb5caa98Sdjl 		case NSCD_PUT:
611*cb5caa98Sdjl 
612*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
613*cb5caa98Sdjl 		(me, "door call NSCD_PUT not supported yet\n");
614*cb5caa98Sdjl 
615*cb5caa98Sdjl 		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
616*cb5caa98Sdjl 		break;
617*cb5caa98Sdjl 
618*cb5caa98Sdjl 		case NSCD_GETHINTS:
619*cb5caa98Sdjl 
620*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
621*cb5caa98Sdjl 		(me, "door call NSCD_GETHINTS not supported yet\n");
622*cb5caa98Sdjl 
623*cb5caa98Sdjl 		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP);
624*cb5caa98Sdjl 		break;
625*cb5caa98Sdjl 
626*cb5caa98Sdjl 		default:
627*cb5caa98Sdjl 
628*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
629*cb5caa98Sdjl 		(me, "Unknown name service door call op %x\n",
630*cb5caa98Sdjl 		phdr->nsc_callnumber);
631*cb5caa98Sdjl 
632*cb5caa98Sdjl 		NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
633*cb5caa98Sdjl 		break;
634*cb5caa98Sdjl 		}
635*cb5caa98Sdjl 
636*cb5caa98Sdjl 		(void) door_return(argp, arg_size, NULL, 0);
637*cb5caa98Sdjl 	}
638*cb5caa98Sdjl 
639*cb5caa98Sdjl 	iam = NSCD_MAIN;
640*cb5caa98Sdjl 	callnum = phdr->nsc_callnumber & ~NSCD_WHOAMI;
641*cb5caa98Sdjl 	if (callnum == NSCD_IMHERE ||
642*cb5caa98Sdjl 		callnum == NSCD_PULSE || callnum == NSCD_FORK)
643*cb5caa98Sdjl 		iam = phdr->nsc_callnumber & NSCD_WHOAMI;
644*cb5caa98Sdjl 	else
645*cb5caa98Sdjl 		callnum = phdr->nsc_callnumber;
646*cb5caa98Sdjl 
647*cb5caa98Sdjl 	/* nscd -> nscd v2 calls */
648*cb5caa98Sdjl 	switch (callnum) {
649*cb5caa98Sdjl 
650*cb5caa98Sdjl 	case NSCD_PING:
651*cb5caa98Sdjl 		NSCD_SET_STATUS_SUCCESS(phdr);
652*cb5caa98Sdjl 		break;
653*cb5caa98Sdjl 
654*cb5caa98Sdjl 	case NSCD_IMHERE:
655*cb5caa98Sdjl 		_nscd_proc_iamhere(argp, dp, n_desc, iam);
656*cb5caa98Sdjl 		break;
657*cb5caa98Sdjl 
658*cb5caa98Sdjl 	case NSCD_PULSE:
659*cb5caa98Sdjl 		N2N_check_priv(argp, "NSCD_PULSE");
660*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr))
661*cb5caa98Sdjl 			_nscd_proc_pulse(argp, iam);
662*cb5caa98Sdjl 		break;
663*cb5caa98Sdjl 
664*cb5caa98Sdjl 	case NSCD_FORK:
665*cb5caa98Sdjl 		N2N_check_priv(argp, "NSCD_FORK");
666*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr))
667*cb5caa98Sdjl 			_nscd_proc_fork(argp, iam);
668*cb5caa98Sdjl 		break;
669*cb5caa98Sdjl 
670*cb5caa98Sdjl 	case NSCD_KILL:
671*cb5caa98Sdjl 		N2N_check_priv(argp, "NSCD_KILL");
672*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr))
673*cb5caa98Sdjl 			exit(0);
674*cb5caa98Sdjl 		break;
675*cb5caa98Sdjl 
676*cb5caa98Sdjl 	case NSCD_REFRESH:
677*cb5caa98Sdjl 		if (_nscd_refresh() != NSCD_SUCCESS)
678*cb5caa98Sdjl 			exit(1);
679*cb5caa98Sdjl 		NSCD_SET_STATUS_SUCCESS(phdr);
680*cb5caa98Sdjl 		break;
681*cb5caa98Sdjl 
682*cb5caa98Sdjl 	case NSCD_GETPUADMIN:
683*cb5caa98Sdjl 
684*cb5caa98Sdjl 		if (_nscd_is_self_cred_on(0, NULL)) {
685*cb5caa98Sdjl 			_nscd_peruser_getadmin(argp, sizeof (nscd_admin_t));
686*cb5caa98Sdjl 		} else {
687*cb5caa98Sdjl 			NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
688*cb5caa98Sdjl 				NSCD_SELF_CRED_NOT_CONFIGURED);
689*cb5caa98Sdjl 		}
690*cb5caa98Sdjl 		break;
691*cb5caa98Sdjl 
692*cb5caa98Sdjl 	case NSCD_GETADMIN:
693*cb5caa98Sdjl 
694*cb5caa98Sdjl 		len = _nscd_door_getadmin((void *)argp);
695*cb5caa98Sdjl 		if (len == 0)
696*cb5caa98Sdjl 			break;
697*cb5caa98Sdjl 
698*cb5caa98Sdjl 		/* size of door buffer not big enough, allocate one */
699*cb5caa98Sdjl 		NSCD_ALLOC_DOORBUF(NSCD_GETADMIN, len, uptr, buflen);
700*cb5caa98Sdjl 
701*cb5caa98Sdjl 		/* copy packed header */
702*cb5caa98Sdjl 		*(nss_pheader_t *)uptr = *(nss_pheader_t *)((void *)argp);
703*cb5caa98Sdjl 
704*cb5caa98Sdjl 		/* set new buffer size */
705*cb5caa98Sdjl 		((nss_pheader_t *)uptr)->pbufsiz = buflen;
706*cb5caa98Sdjl 
707*cb5caa98Sdjl 		/* try one more time */
708*cb5caa98Sdjl 		(void) _nscd_door_getadmin((void *)uptr);
709*cb5caa98Sdjl 		(void) door_return(uptr, buflen, NULL, 0);
710*cb5caa98Sdjl 		break;
711*cb5caa98Sdjl 
712*cb5caa98Sdjl 	case NSCD_SETADMIN:
713*cb5caa98Sdjl 		N2N_check_priv(argp, "NSCD_SETADMIN");
714*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr))
715*cb5caa98Sdjl 			_nscd_door_setadmin(argp);
716*cb5caa98Sdjl 		break;
717*cb5caa98Sdjl 
718*cb5caa98Sdjl 	case NSCD_KILLSERVER:
719*cb5caa98Sdjl 		N2N_check_priv(argp, "NSCD_KILLSERVER");
720*cb5caa98Sdjl 		if (NSCD_STATUS_IS_OK(phdr)) {
721*cb5caa98Sdjl 			/* also kill the forker nscd if one is running */
722*cb5caa98Sdjl 			_nscd_kill_forker();
723*cb5caa98Sdjl 			exit(0);
724*cb5caa98Sdjl 		}
725*cb5caa98Sdjl 		break;
726*cb5caa98Sdjl 
727*cb5caa98Sdjl 	default:
728*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
729*cb5caa98Sdjl 		(me, "Unknown name service door call op %d\n",
730*cb5caa98Sdjl 			phdr->nsc_callnumber);
731*cb5caa98Sdjl 
732*cb5caa98Sdjl 		NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL);
733*cb5caa98Sdjl 
734*cb5caa98Sdjl 		(void) door_return(argp, arg_size, NULL, 0);
735*cb5caa98Sdjl 		break;
736*cb5caa98Sdjl 
737*cb5caa98Sdjl 	}
738*cb5caa98Sdjl 	(void) door_return(argp, arg_size, NULL, 0);
739*cb5caa98Sdjl }
740*cb5caa98Sdjl 
741*cb5caa98Sdjl int
742*cb5caa98Sdjl _nscd_setup_server(char *execname, char **argv)
743*cb5caa98Sdjl {
744*cb5caa98Sdjl 
745*cb5caa98Sdjl 	int		fd;
746*cb5caa98Sdjl 	int		errnum;
747*cb5caa98Sdjl 	int		bind_failed = 0;
748*cb5caa98Sdjl 	struct stat	buf;
749*cb5caa98Sdjl 	sigset_t	myset;
750*cb5caa98Sdjl 	struct sigaction action;
751*cb5caa98Sdjl 	char		*me = "_nscd_setup_server";
752*cb5caa98Sdjl 
753*cb5caa98Sdjl 	main_execname = execname;
754*cb5caa98Sdjl 	main_argv = argv;
755*cb5caa98Sdjl 
756*cb5caa98Sdjl 	keep_open_dns_socket();
757*cb5caa98Sdjl 
758*cb5caa98Sdjl 	/*
759*cb5caa98Sdjl 	 * the max number of server threads should be fixed now, so
760*cb5caa98Sdjl 	 * set flag to indicate that no in-flight change is allowed
761*cb5caa98Sdjl 	 */
762*cb5caa98Sdjl 	max_servers_set = 1;
763*cb5caa98Sdjl 
764*cb5caa98Sdjl 	(void) thr_keycreate(&lookup_state_key, NULL);
765*cb5caa98Sdjl 	(void) sema_init(&common_sema,
766*cb5caa98Sdjl 			frontend_cfg_g.common_worker_threads,
767*cb5caa98Sdjl 			USYNC_THREAD, 0);
768*cb5caa98Sdjl 
769*cb5caa98Sdjl 	/* Establish server thread pool */
770*cb5caa98Sdjl 	(void) door_server_create(server_create);
771*cb5caa98Sdjl 	if (thr_keycreate(&server_key, server_destroy) != 0) {
772*cb5caa98Sdjl 		errnum = errno;
773*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
774*cb5caa98Sdjl 		(me, "thr_keycreate (server thread): %s\n",
775*cb5caa98Sdjl 			strerror(errnum));
776*cb5caa98Sdjl 		return (-1);
777*cb5caa98Sdjl 	}
778*cb5caa98Sdjl 
779*cb5caa98Sdjl 	/* Create a door */
780*cb5caa98Sdjl 	if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE,
781*cb5caa98Sdjl 	    DOOR_UNREF | DOOR_NO_CANCEL)) < 0) {
782*cb5caa98Sdjl 		errnum = errno;
783*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
784*cb5caa98Sdjl 		(me, "door_create: %s\n", strerror(errnum));
785*cb5caa98Sdjl 		return (-1);
786*cb5caa98Sdjl 	}
787*cb5caa98Sdjl 
788*cb5caa98Sdjl 	/* if not main nscd, no more setup to do */
789*cb5caa98Sdjl 	if (_whoami != NSCD_MAIN)
790*cb5caa98Sdjl 		return (fd);
791*cb5caa98Sdjl 
792*cb5caa98Sdjl 	/* bind to file system */
793*cb5caa98Sdjl 	if (is_system_labeled()) {
794*cb5caa98Sdjl 		if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) {
795*cb5caa98Sdjl 			int newfd;
796*cb5caa98Sdjl 			if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) {
797*cb5caa98Sdjl 				errnum = errno;
798*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_FRONT_END,
799*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
800*cb5caa98Sdjl 				(me, "Cannot create %s: %s\n",
801*cb5caa98Sdjl 					TSOL_NAME_SERVICE_DOOR,
802*cb5caa98Sdjl 					strerror(errnum));
803*cb5caa98Sdjl 				bind_failed = 1;
804*cb5caa98Sdjl 			}
805*cb5caa98Sdjl 			(void) close(newfd);
806*cb5caa98Sdjl 		}
807*cb5caa98Sdjl 		if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) {
808*cb5caa98Sdjl 			if (errno != EEXIST) {
809*cb5caa98Sdjl 				errnum = errno;
810*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_FRONT_END,
811*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
812*cb5caa98Sdjl 				(me, "Cannot symlink %s: %s\n",
813*cb5caa98Sdjl 					NAME_SERVICE_DOOR,
814*cb5caa98Sdjl 					strerror(errnum));
815*cb5caa98Sdjl 				bind_failed = 1;
816*cb5caa98Sdjl 			}
817*cb5caa98Sdjl 		}
818*cb5caa98Sdjl 	} else if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
819*cb5caa98Sdjl 		int newfd;
820*cb5caa98Sdjl 		if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) {
821*cb5caa98Sdjl 			errnum = errno;
822*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
823*cb5caa98Sdjl 			(me, "Cannot create %s: %s\n", NAME_SERVICE_DOOR,
824*cb5caa98Sdjl 				strerror(errnum));
825*cb5caa98Sdjl 			bind_failed = 1;
826*cb5caa98Sdjl 		}
827*cb5caa98Sdjl 		(void) close(newfd);
828*cb5caa98Sdjl 	}
829*cb5caa98Sdjl 
830*cb5caa98Sdjl 	if (bind_failed == 1) {
831*cb5caa98Sdjl 		(void) door_revoke(fd);
832*cb5caa98Sdjl 		return (-1);
833*cb5caa98Sdjl 	}
834*cb5caa98Sdjl 
835*cb5caa98Sdjl 	if (fattach(fd, NAME_SERVICE_DOOR) < 0) {
836*cb5caa98Sdjl 		if ((errno != EBUSY) ||
837*cb5caa98Sdjl 		(fdetach(NAME_SERVICE_DOOR) <  0) ||
838*cb5caa98Sdjl 		(fattach(fd, NAME_SERVICE_DOOR) < 0)) {
839*cb5caa98Sdjl 			errnum = errno;
840*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_FRONT_END,
841*cb5caa98Sdjl 				NSCD_LOG_LEVEL_ERROR)
842*cb5caa98Sdjl 			(me, "fattach: %s\n", strerror(errnum));
843*cb5caa98Sdjl 			(void) door_revoke(fd);
844*cb5caa98Sdjl 			return (-1);
845*cb5caa98Sdjl 		}
846*cb5caa98Sdjl 	}
847*cb5caa98Sdjl 
848*cb5caa98Sdjl 	/*
849*cb5caa98Sdjl 	 * kick off routing socket monitor thread
850*cb5caa98Sdjl 	 */
851*cb5caa98Sdjl 	if (thr_create(NULL, NULL,
852*cb5caa98Sdjl 		(void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
853*cb5caa98Sdjl 		errnum = errno;
854*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
855*cb5caa98Sdjl 		(me, "thr_create (routing socket monitor): %s\n",
856*cb5caa98Sdjl 			strerror(errnum));
857*cb5caa98Sdjl 
858*cb5caa98Sdjl 		(void) door_revoke(fd);
859*cb5caa98Sdjl 		return (-1);
860*cb5caa98Sdjl 	}
861*cb5caa98Sdjl 
862*cb5caa98Sdjl 	/*
863*cb5caa98Sdjl 	 * set up signal handler for SIGHUP
864*cb5caa98Sdjl 	 */
865*cb5caa98Sdjl 	action.sa_handler = dozip;
866*cb5caa98Sdjl 	action.sa_flags = 0;
867*cb5caa98Sdjl 	(void) sigemptyset(&action.sa_mask);
868*cb5caa98Sdjl 	(void) sigemptyset(&myset);
869*cb5caa98Sdjl 	(void) sigaddset(&myset, SIGHUP);
870*cb5caa98Sdjl 
871*cb5caa98Sdjl 	if (sigaction(SIGHUP, &action, NULL) < 0) {
872*cb5caa98Sdjl 		errnum = errno;
873*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
874*cb5caa98Sdjl 		(me, "sigaction (SIGHUP): %s\n", strerror(errnum));
875*cb5caa98Sdjl 
876*cb5caa98Sdjl 		(void) door_revoke(fd);
877*cb5caa98Sdjl 		return (-1);
878*cb5caa98Sdjl 	}
879*cb5caa98Sdjl 
880*cb5caa98Sdjl 	return (fd);
881*cb5caa98Sdjl }
882*cb5caa98Sdjl 
883*cb5caa98Sdjl int
884*cb5caa98Sdjl _nscd_setup_child_server(int did)
885*cb5caa98Sdjl {
886*cb5caa98Sdjl 
887*cb5caa98Sdjl 	int		errnum;
888*cb5caa98Sdjl 	int		fd;
889*cb5caa98Sdjl 	nscd_rc_t	rc;
890*cb5caa98Sdjl 	char		*me = "_nscd_setup_child_server";
891*cb5caa98Sdjl 
892*cb5caa98Sdjl 	/* Re-establish our own server thread pool */
893*cb5caa98Sdjl 	(void) door_server_create(server_create);
894*cb5caa98Sdjl 	if (thr_keycreate(&server_key, server_destroy) != 0) {
895*cb5caa98Sdjl 		errnum = errno;
896*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
897*cb5caa98Sdjl 		(me, "thr_keycreate failed: %s", strerror(errnum));
898*cb5caa98Sdjl 		return (-1);
899*cb5caa98Sdjl 	}
900*cb5caa98Sdjl 
901*cb5caa98Sdjl 	/*
902*cb5caa98Sdjl 	 * Create a new door.
903*cb5caa98Sdjl 	 * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork)
904*cb5caa98Sdjl 	 */
905*cb5caa98Sdjl 	(void) close(did);
906*cb5caa98Sdjl 	if ((fd = door_create(switcher,
907*cb5caa98Sdjl 		NAME_SERVICE_DOOR_COOKIE,
908*cb5caa98Sdjl 		DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) {
909*cb5caa98Sdjl 		errnum = errno;
910*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
911*cb5caa98Sdjl 		(me, "door_create failed: %s", strerror(errnum));
912*cb5caa98Sdjl 		return (-1);
913*cb5caa98Sdjl 	}
914*cb5caa98Sdjl 
915*cb5caa98Sdjl 	/*
916*cb5caa98Sdjl 	 * kick off routing socket monitor thread
917*cb5caa98Sdjl 	 */
918*cb5caa98Sdjl 	if (thr_create(NULL, NULL,
919*cb5caa98Sdjl 		(void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
920*cb5caa98Sdjl 		errnum = errno;
921*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
922*cb5caa98Sdjl 		(me, "thr_create (routing socket monitor): %s\n",
923*cb5caa98Sdjl 			strerror(errnum));
924*cb5caa98Sdjl 		(void) door_revoke(fd);
925*cb5caa98Sdjl 		return (-1);
926*cb5caa98Sdjl 	}
927*cb5caa98Sdjl 
928*cb5caa98Sdjl 	/*
929*cb5caa98Sdjl 	 * start monitoring the states of the name service clients
930*cb5caa98Sdjl 	 */
931*cb5caa98Sdjl 	rc = _nscd_init_smf_monitor();
932*cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
933*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
934*cb5caa98Sdjl 	(me, "unable to start the SMF monitor (rc = %d)\n", rc);
935*cb5caa98Sdjl 
936*cb5caa98Sdjl 		(void) door_revoke(fd);
937*cb5caa98Sdjl 		return (-1);
938*cb5caa98Sdjl 	}
939*cb5caa98Sdjl 
940*cb5caa98Sdjl 	return (fd);
941*cb5caa98Sdjl }
942*cb5caa98Sdjl 
943*cb5caa98Sdjl nscd_rc_t
944*cb5caa98Sdjl _nscd_alloc_frontend_cfg()
945*cb5caa98Sdjl {
946*cb5caa98Sdjl 	frontend_cfg  = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_frontend_t));
947*cb5caa98Sdjl 	if (frontend_cfg == NULL)
948*cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
949*cb5caa98Sdjl 
950*cb5caa98Sdjl 	return (NSCD_SUCCESS);
951*cb5caa98Sdjl }
952*cb5caa98Sdjl 
953*cb5caa98Sdjl 
954*cb5caa98Sdjl /* ARGSUSED */
955*cb5caa98Sdjl nscd_rc_t
956*cb5caa98Sdjl _nscd_cfg_frontend_notify(
957*cb5caa98Sdjl 	void				*data,
958*cb5caa98Sdjl 	struct nscd_cfg_param_desc	*pdesc,
959*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
960*cb5caa98Sdjl 	nscd_cfg_flag_t			dflag,
961*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp,
962*cb5caa98Sdjl 	void				*cookie)
963*cb5caa98Sdjl {
964*cb5caa98Sdjl 	void				*dp;
965*cb5caa98Sdjl 
966*cb5caa98Sdjl 	/*
967*cb5caa98Sdjl 	 * At init time, the whole group of config params are received.
968*cb5caa98Sdjl 	 * At update time, group or individual parameter value could
969*cb5caa98Sdjl 	 * be received.
970*cb5caa98Sdjl 	 */
971*cb5caa98Sdjl 
972*cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) ||
973*cb5caa98Sdjl 		_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) {
974*cb5caa98Sdjl 		/*
975*cb5caa98Sdjl 		 * group data is received, copy in the
976*cb5caa98Sdjl 		 * entire strcture
977*cb5caa98Sdjl 		 */
978*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(pdesc->pflag,
979*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GLOBAL))
980*cb5caa98Sdjl 			frontend_cfg_g =
981*cb5caa98Sdjl 				*(nscd_cfg_global_frontend_t *)data;
982*cb5caa98Sdjl 		else
983*cb5caa98Sdjl 			frontend_cfg[nswdb->index] =
984*cb5caa98Sdjl 				*(nscd_cfg_frontend_t *)data;
985*cb5caa98Sdjl 
986*cb5caa98Sdjl 	} else {
987*cb5caa98Sdjl 		/*
988*cb5caa98Sdjl 		 * individual paramater is received: copy in the
989*cb5caa98Sdjl 		 * parameter value.
990*cb5caa98Sdjl 		 */
991*cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(pdesc->pflag,
992*cb5caa98Sdjl 			NSCD_CFG_PFLAG_GLOBAL))
993*cb5caa98Sdjl 			dp = (char *)&frontend_cfg_g + pdesc->p_offset;
994*cb5caa98Sdjl 		else
995*cb5caa98Sdjl 			dp = (char *)&frontend_cfg[nswdb->index] +
996*cb5caa98Sdjl 				pdesc->p_offset;
997*cb5caa98Sdjl 		(void) memcpy(dp, data, pdesc->p_size);
998*cb5caa98Sdjl 	}
999*cb5caa98Sdjl 
1000*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1001*cb5caa98Sdjl }
1002*cb5caa98Sdjl 
1003*cb5caa98Sdjl /* ARGSUSED */
1004*cb5caa98Sdjl nscd_rc_t
1005*cb5caa98Sdjl _nscd_cfg_frontend_verify(
1006*cb5caa98Sdjl 	void				*data,
1007*cb5caa98Sdjl 	struct	nscd_cfg_param_desc	*pdesc,
1008*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
1009*cb5caa98Sdjl 	nscd_cfg_flag_t			dflag,
1010*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp,
1011*cb5caa98Sdjl 	void				**cookie)
1012*cb5caa98Sdjl {
1013*cb5caa98Sdjl 
1014*cb5caa98Sdjl 	char				*me = "_nscd_cfg_frontend_verify";
1015*cb5caa98Sdjl 
1016*cb5caa98Sdjl 	/*
1017*cb5caa98Sdjl 	 * if max. number of server threads is set and in effect,
1018*cb5caa98Sdjl 	 * don't allow changing of the frontend configuration
1019*cb5caa98Sdjl 	 */
1020*cb5caa98Sdjl 	if (max_servers_set) {
1021*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO)
1022*cb5caa98Sdjl 	(me, "changing of the frontend configuration not allowed now");
1023*cb5caa98Sdjl 
1024*cb5caa98Sdjl 		return (NSCD_CFG_CHANGE_NOT_ALLOWED);
1025*cb5caa98Sdjl 	}
1026*cb5caa98Sdjl 
1027*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1028*cb5caa98Sdjl }
1029*cb5caa98Sdjl 
1030*cb5caa98Sdjl /* ARGSUSED */
1031*cb5caa98Sdjl nscd_rc_t
1032*cb5caa98Sdjl _nscd_cfg_frontend_get_stat(
1033*cb5caa98Sdjl 	void				**stat,
1034*cb5caa98Sdjl 	struct nscd_cfg_stat_desc	*sdesc,
1035*cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb,
1036*cb5caa98Sdjl 	nscd_cfg_flag_t			*dflag,
1037*cb5caa98Sdjl 	void				(**free_stat)(void *stat),
1038*cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
1039*cb5caa98Sdjl {
1040*cb5caa98Sdjl 	return (NSCD_SUCCESS);
1041*cb5caa98Sdjl }
1042*cb5caa98Sdjl 
1043*cb5caa98Sdjl void
1044*cb5caa98Sdjl _nscd_init_cache_sema(sema_t *sema, char *cache_name)
1045*cb5caa98Sdjl {
1046*cb5caa98Sdjl 	int	i, j;
1047*cb5caa98Sdjl 	char	*dbn;
1048*cb5caa98Sdjl 
1049*cb5caa98Sdjl 	if (max_servers == 0)
1050*cb5caa98Sdjl 		max_servers = frontend_cfg_g.common_worker_threads +
1051*cb5caa98Sdjl 		frontend_cfg_g.cache_hit_threads;
1052*cb5caa98Sdjl 
1053*cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
1054*cb5caa98Sdjl 
1055*cb5caa98Sdjl 		dbn = NSCD_NSW_DB_NAME(i);
1056*cb5caa98Sdjl 		if (strcasecmp(dbn, cache_name) == 0) {
1057*cb5caa98Sdjl 			j = frontend_cfg[i].worker_thread_per_nsw_db;
1058*cb5caa98Sdjl 			(void) sema_init(sema, j, USYNC_THREAD, 0);
1059*cb5caa98Sdjl 			max_servers += j;
1060*cb5caa98Sdjl 			break;
1061*cb5caa98Sdjl 		}
1062*cb5caa98Sdjl 	}
1063*cb5caa98Sdjl }
1064*cb5caa98Sdjl 
1065*cb5caa98Sdjl /*
1066*cb5caa98Sdjl  * Monitor the routing socket.  Address lists stored in the ipnodes
1067*cb5caa98Sdjl  * cache are sorted based on destination address selection rules,
1068*cb5caa98Sdjl  * so when things change that could affect that sorting (interfaces
1069*cb5caa98Sdjl  * go up or down, flags change, etc.), we clear that cache so the
1070*cb5caa98Sdjl  * list will be re-ordered the next time the hostname is resolved.
1071*cb5caa98Sdjl  */
1072*cb5caa98Sdjl static void
1073*cb5caa98Sdjl rts_mon(void)
1074*cb5caa98Sdjl {
1075*cb5caa98Sdjl 	int	rt_sock, rdlen, idx;
1076*cb5caa98Sdjl 	union {
1077*cb5caa98Sdjl 		struct {
1078*cb5caa98Sdjl 			struct rt_msghdr rtm;
1079*cb5caa98Sdjl 			struct sockaddr_storage addrs[RTA_NUMBITS];
1080*cb5caa98Sdjl 		} r;
1081*cb5caa98Sdjl 		struct if_msghdr ifm;
1082*cb5caa98Sdjl 		struct ifa_msghdr ifam;
1083*cb5caa98Sdjl 	} mbuf;
1084*cb5caa98Sdjl 	struct ifa_msghdr *ifam = &mbuf.ifam;
1085*cb5caa98Sdjl 	char	*me = "rts_mon";
1086*cb5caa98Sdjl 
1087*cb5caa98Sdjl 	rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
1088*cb5caa98Sdjl 	if (rt_sock < 0) {
1089*cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
1090*cb5caa98Sdjl 		(me, "Failed to open routing socket: %s\n", strerror(errno));
1091*cb5caa98Sdjl 		thr_exit(0);
1092*cb5caa98Sdjl 	}
1093*cb5caa98Sdjl 
1094*cb5caa98Sdjl 	for (;;) {
1095*cb5caa98Sdjl 		rdlen = read(rt_sock, &mbuf, sizeof (mbuf));
1096*cb5caa98Sdjl 		if (rdlen <= 0) {
1097*cb5caa98Sdjl 			if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) {
1098*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_FRONT_END,
1099*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
1100*cb5caa98Sdjl 				(me, "routing socket read: %s\n",
1101*cb5caa98Sdjl 					strerror(errno));
1102*cb5caa98Sdjl 				thr_exit(0);
1103*cb5caa98Sdjl 			}
1104*cb5caa98Sdjl 			continue;
1105*cb5caa98Sdjl 		}
1106*cb5caa98Sdjl 		if (ifam->ifam_version != RTM_VERSION) {
1107*cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_FRONT_END,
1108*cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
1109*cb5caa98Sdjl 				(me, "rx unknown version (%d) on "
1110*cb5caa98Sdjl 					"routing socket.\n",
1111*cb5caa98Sdjl 					ifam->ifam_version);
1112*cb5caa98Sdjl 			continue;
1113*cb5caa98Sdjl 		}
1114*cb5caa98Sdjl 		switch (ifam->ifam_type) {
1115*cb5caa98Sdjl 		case RTM_NEWADDR:
1116*cb5caa98Sdjl 		case RTM_DELADDR:
1117*cb5caa98Sdjl 			/* if no ipnodes cache, then nothing to do */
1118*cb5caa98Sdjl 			idx = get_cache_idx("ipnodes");
1119*cb5caa98Sdjl 			if (cache_ctx_p[idx] == NULL ||
1120*cb5caa98Sdjl 				cache_ctx_p[idx]->reaper_on != nscd_true)
1121*cb5caa98Sdjl 				break;
1122*cb5caa98Sdjl 			nsc_invalidate(cache_ctx_p[idx], NULL, NULL);
1123*cb5caa98Sdjl 			break;
1124*cb5caa98Sdjl 		case RTM_ADD:
1125*cb5caa98Sdjl 		case RTM_DELETE:
1126*cb5caa98Sdjl 		case RTM_CHANGE:
1127*cb5caa98Sdjl 		case RTM_GET:
1128*cb5caa98Sdjl 		case RTM_LOSING:
1129*cb5caa98Sdjl 		case RTM_REDIRECT:
1130*cb5caa98Sdjl 		case RTM_MISS:
1131*cb5caa98Sdjl 		case RTM_LOCK:
1132*cb5caa98Sdjl 		case RTM_OLDADD:
1133*cb5caa98Sdjl 		case RTM_OLDDEL:
1134*cb5caa98Sdjl 		case RTM_RESOLVE:
1135*cb5caa98Sdjl 		case RTM_IFINFO:
1136*cb5caa98Sdjl 			break;
1137*cb5caa98Sdjl 		default:
1138*cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
1139*cb5caa98Sdjl 			(me, "rx unknown msg type (%d) on routing socket.\n",
1140*cb5caa98Sdjl 			    ifam->ifam_type);
1141*cb5caa98Sdjl 			break;
1142*cb5caa98Sdjl 		}
1143*cb5caa98Sdjl 	}
1144*cb5caa98Sdjl }
1145*cb5caa98Sdjl 
1146*cb5caa98Sdjl static void
1147*cb5caa98Sdjl keep_open_dns_socket(void)
1148*cb5caa98Sdjl {
1149*cb5caa98Sdjl 	_res.options |= RES_STAYOPEN; /* just keep this udp socket open */
1150*cb5caa98Sdjl }
1151