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.
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.
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]
22 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2016 by Delphix. All rights reserved.
27 * Simple doors name server cache daemon
38 #include <tsol/label.h>
41 #include <sys/resource.h>
44 #include "nscd_selfcred.h"
45 #include "nscd_frontend.h"
46 #include "nscd_common.h"
47 #include "nscd_admin.h"
48 #include "nscd_door.h"
49 #include "nscd_switch.h"
56 #define NSCDOPT "S:Kf:c:ge:p:n:i:l:d:s:h:o:GFR"
58 /* assume this is a single nscd or, if multiple, the main nscd */
59 int _whoami
= NSCD_MAIN
;
62 static char *cfgfile
= NULL
;
64 extern nsc_ctx_t
*cache_ctx_p
[];
66 static void usage(char *);
67 static void detachfromtty(void);
69 static char debug_level
[32] = { 0 };
70 static char logfile
[128] = { 0 };
71 static int will_become_server
;
76 while (*s
&& *s
!= ',')
78 return ((*s
== ',') ? (s
+ 1) : NULL
);
82 * declaring this causes the files backend to use hashing
83 * this is of course an utter hack, but provides a nice
84 * quiet back door to enable this feature for only the nscd.
87 __nss_use_files_hash(void)
91 static int saved_argc
= 0;
92 static char **saved_argv
= NULL
;
93 static char saved_execname
[MAXPATHLEN
];
98 const char *name
= getexecname();
100 saved_execname
[0] = 0;
102 if (name
[0] != '/') { /* started w/ relative path */
103 (void) getcwd(saved_execname
, MAXPATHLEN
);
104 (void) strlcat(saved_execname
, "/", MAXPATHLEN
);
106 (void) strlcat(saved_execname
, name
, MAXPATHLEN
);
110 main(int argc
, char ** argv
)
119 char *ret_textdomain
;
123 ret_locale
= setlocale(LC_ALL
, "");
124 if (ret_locale
== NULL
)
125 (void) fprintf(stderr
, gettext("Unable to set locale\n"));
127 ret_textdomain
= textdomain(TEXT_DOMAIN
);
128 if (ret_textdomain
== NULL
)
129 (void) fprintf(stderr
, gettext("Unable to set textdomain\n"));
132 * The admin model for TX is that labeled zones are managed
133 * in global zone where most trusted configuration database
134 * resides. However, nscd will run in any labeled zone if
135 * file /var/tsol/doors/nscd_per_label exists.
137 if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID
)) {
139 if (stat(TSOL_NSCD_PER_LABEL_FILE
, &sbuf
) < 0) {
140 (void) fprintf(stderr
,
141 gettext("With Trusted Extensions nscd runs only in the "
142 "global zone (if nscd_per_label flag not set)\n"));
148 * Special case non-root user here - they can only print stats
152 (strcmp(argv
[1], "-g") && strcmp(argv
[1], "-G"))) {
153 (void) fprintf(stderr
,
154 gettext("Must be root to use any option other than -g\n\n"));
158 if (_nscd_doorcall(NSCD_PING
) != NSS_SUCCESS
) {
159 (void) fprintf(stderr
,
160 gettext("%s doesn't appear to be running.\n"),
164 if (_nscd_client_getadmin(argv
[1][1]) != 0) {
165 (void) fprintf(stderr
,
166 gettext("unable to get configuration and statistics data\n"));
170 _nscd_client_showstats();
175 * Determine if there is already a daemon (main nscd) running.
176 * If not, will start it. Forker NSCD will always become a
179 will_become_server
= (_nscd_doorcall(NSCD_PING
) != NSS_SUCCESS
);
180 if (argc
>= 2 && strcmp(argv
[1], "-F") == 0) {
181 will_become_server
= 1;
182 _whoami
= NSCD_FORKER
;
185 * allow time for the main nscd to get ready
186 * to receive the IMHERE door request this
187 * process will send later
189 (void) usleep(100000);
193 * first get the config file path. Also detect
194 * invalid option as soon as possible.
196 while ((opt
= getopt(argc
, argv
, NSCDOPT
)) != EOF
) {
200 if ((cfgfile
= strdup(optarg
)) == NULL
)
204 if (will_become_server
) {
205 (void) fprintf(stderr
,
206 gettext("nscd not running, no statistics to show\n\n"));
211 if (will_become_server
) {
212 (void) fprintf(stderr
,
213 gettext("nscd not running, no cache to invalidate\n\n"));
228 * perform more initialization and load configuration
229 * if to become server
231 if (will_become_server
) {
233 /* initialize switch engine and config/stats management */
234 if ((rc
= _nscd_init(cfgfile
)) != NSCD_SUCCESS
) {
235 (void) fprintf(stderr
,
236 gettext("initialization of switch failed (rc = %d)\n"), rc
);
239 _nscd_get_log_info(debug_level
, sizeof (debug_level
),
240 logfile
, sizeof (logfile
));
243 * initialize cache store
245 if ((rc
= init_cache(0)) != NSCD_SUCCESS
) {
246 (void) fprintf(stderr
,
247 gettext("initialization of cache store failed (rc = %d)\n"), rc
);
253 * process usual options
255 optind
= 1; /* this is a rescan */
257 while ((opt
= getopt(argc
, argv
, NSCDOPT
)) != EOF
) {
261 case 'K': /* undocumented feature */
262 (void) _nscd_doorcall(NSCD_KILLSERVER
);
273 if (_nscd_add_admin_mod(optarg
, 'p',
275 msg
, sizeof (msg
)) == -1)
281 if (_nscd_add_admin_mod(optarg
, 'n',
283 msg
, sizeof (msg
)) == -1)
289 if (_nscd_add_admin_mod(optarg
, 'c',
291 msg
, sizeof (msg
)) == -1)
297 if (_nscd_add_admin_mod(optarg
, 'i', NULL
,
298 msg
, sizeof (msg
)) == -1)
304 (void) strlcpy(logfile
, optarg
, sizeof (logfile
));
309 (void) strlcpy(debug_level
, optarg
,
310 sizeof (debug_level
));
314 /* silently ignore secure-mode */
318 /* silently ignore suggested-size */
322 /* silently ignore old-data-ok */
327 if (_nscd_add_admin_mod(optarg
, 'h',
329 msg
, sizeof (msg
)) == -1)
335 if (_nscd_add_admin_mod(optarg
, 'e',
337 msg
, sizeof (msg
)) == -1)
342 _whoami
= NSCD_FORKER
;
354 (void) fprintf(stderr
, "\n%s: %s\n\n", argv
[0], msg
);
359 * if main nscd already running and not forker nscd,
360 * can only do admin work
362 if (_whoami
== NSCD_MAIN
) {
363 if (!will_become_server
) {
365 if (_nscd_client_getadmin('g')) {
366 (void) fprintf(stderr
,
367 gettext("Cannot contact nscd properly(?)\n"));
370 _nscd_client_showstats();
374 if (_nscd_client_setadmin() < 0) {
375 (void) fprintf(stderr
,
376 gettext("Error during admin call\n"));
380 if (!showstats
&& !doset
) {
381 (void) fprintf(stderr
,
382 gettext("%s already running.... no administration option specified\n"),
390 * daemon from here on
393 if (_whoami
== NSCD_MAIN
) {
395 /* save enough info in case need to restart or fork */
401 * if a log file is not specified, set it to
402 * "stderr" or "/dev/null" based on debug level
404 if (*logfile
== '\0') {
405 if (*debug_level
!= '\0')
406 /* we're debugging... */
407 (void) strcpy(logfile
, "stderr");
409 (void) strcpy(logfile
, "/dev/null");
411 (void) _nscd_add_admin_mod(NULL
, 'l', logfile
,
413 (void) _nscd_add_admin_mod(NULL
, 'd', debug_level
,
416 /* activate command options */
417 if (_nscd_server_setadmin(NULL
) != NSCD_SUCCESS
) {
418 (void) fprintf(stderr
,
419 gettext("unable to set command line options\n"));
423 if (*debug_level
!= '\0') {
424 /* we're debugging, no forking of nscd */
427 * forker nscd will be started if self credential
430 _nscd_start_forker(saved_execname
, saved_argc
,
434 * daemonize the nscd (forker nscd will also
435 * be started if self credential is configured)
439 } else { /* NSCD_FORKER */
441 * To avoid PUN (Per User Nscd) processes from becoming
442 * zombies after they exit, the forking nscd should
443 * ignore the SIGCLD signal so that it does not
444 * need to wait for every child PUN to exit.
446 (void) signal(SIGCLD
, SIG_IGN
);
447 (void) open("/dev/null", O_RDWR
, 0);
453 /* set NOFILE to unlimited */
454 rl
.rlim_cur
= rl
.rlim_max
= RLIM_INFINITY
;
455 if (setrlimit(RLIMIT_NOFILE
, &rl
) < 0) {
456 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
457 (me
, "Cannot set open file limit: %s\n", strerror(errno
));
461 /* set up door and establish our own server thread pool */
462 if ((_doorfd
= _nscd_setup_server(saved_execname
, saved_argv
)) == -1) {
463 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
464 (me
, "unable to set up door\n");
468 /* inform the main nscd that this forker is ready */
469 if (_whoami
== NSCD_FORKER
) {
472 for (ret
= NSS_ALTRETRY
; ret
== NSS_ALTRETRY
; )
473 ret
= _nscd_doorcall_sendfd(_doorfd
,
474 NSCD_IMHERE
| (NSCD_FORKER
& NSCD_WHOAMI
),
480 (void) _nscd_doorcall(NSCD_REFRESH
);
484 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
490 (void) fprintf(stderr
,
491 "Usage: %s [-d debug_level] [-l logfilename]\n", s
);
492 (void) fprintf(stderr
,
493 " [-p cachename,positive_time_to_live]\n");
494 (void) fprintf(stderr
,
495 " [-n cachename,negative_time_to_live]\n");
496 (void) fprintf(stderr
,
497 " [-i cachename]\n");
498 (void) fprintf(stderr
,
499 " [-h cachename,keep_hot_count]\n");
500 (void) fprintf(stderr
,
501 " [-e cachename,\"yes\"|\"no\"] [-g] " \
502 "[-c cachename,\"yes\"|\"no\"]\n");
503 (void) fprintf(stderr
,
504 " [-f configfilename] \n");
505 (void) fprintf(stderr
,
506 "\n Supported caches:\n");
507 (void) fprintf(stderr
,
508 " auth_attr, bootparams, ethers\n");
509 (void) fprintf(stderr
,
510 " exec_attr, group, hosts, ipnodes, netmasks\n");
511 (void) fprintf(stderr
,
512 " networks, passwd, printers, prof_attr, project\n");
513 (void) fprintf(stderr
,
514 " protocols, rpc, services, tnrhtp, tnrhdb\n");
515 (void) fprintf(stderr
,
527 char *me
= "detachfromtty";
531 for (i
= 0; i
< _logfd
; i
++)
533 closefrom(_logfd
+ 1);
542 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
543 (me
, "unable to fork: pid = %d, %s\n",
544 getpid(), strerror(errno
));
549 /* start the forker nscd if so configured */
550 _nscd_start_forker(saved_execname
, saved_argc
, saved_argv
);
557 (void) open("/dev/null", O_RDWR
, 0);
563 * start monitoring the states of the name service clients
565 rc
= _nscd_init_smf_monitor();
566 if (rc
!= NSCD_SUCCESS
) {
567 _NSCD_LOG(NSCD_LOG_FRONT_END
, NSCD_LOG_LEVEL_ERROR
)
568 (me
, "unable to start the SMF monitor (rc = %d)\n", rc
);