8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ypcmd / ypserv.c
blob6e1eaa679727bdeab056d860d85f06c9266118bb
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
35 #pragma ident "%Z%%M% %I% %E% SMI"
38 * This contains the mainline code for the YP server. Data
39 * structures which are process-global are also in this module.
42 /* this is so that ypserv will compile under 5.5 */
43 #define _SVID_GETTOD
44 #include <sys/time.h>
45 extern int gettimeofday(struct timeval *);
47 #include "ypsym.h"
48 #include <sys/types.h>
49 #include <sys/wait.h>
50 #include <fcntl.h>
51 #include <rpc/rpc.h>
52 #include <netconfig.h>
53 #include <netdir.h>
54 #include <sys/select.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <stdio.h>
58 #include <stdarg.h>
59 #include <signal.h>
60 #include "shim.h"
61 #include "yptol.h"
62 #include <syslog.h>
64 static char register_failed[] = "ypserv: Unable to register service for ";
65 bool silent = TRUE;
68 * client_setup_failure will be TRUE, if setup of the
69 * connection to rpc.nisd_resolv failed
71 bool client_setup_failure = FALSE;
73 /* N2L options */
74 bool init_dit = FALSE;
75 bool init_containers = FALSE;
76 bool init_maps = FALSE;
77 char **ldapCLA = NULL;
79 /* For DNS forwarding command line option (-d) */
80 bool dnsforward = FALSE;
81 int resolv_pid = 0;
82 CLIENT *resolv_client = NULL;
83 char *resolv_tp = "ticots";
85 #ifdef MINUS_C_OPTION
86 /* For cluster support (-c) */
87 bool multiflag = FALSE;
88 #endif
90 static char logfile[] = "/var/yp/ypserv.log";
91 void logprintf(char *format, ...);
93 static void ypexit(void);
94 static void ypinit(int argc, char **argv);
95 static void ypdispatch(struct svc_req *rqstp, SVCXPRT *transp);
96 static void ypolddispatch(struct svc_req *rqstp, SVCXPRT *transp);
97 static void ypget_command_line_args(int argc, char **argv);
98 extern void setup_resolv(bool *fwding, int *child,
99 CLIENT **client, char *tp_type, long prognum);
100 static void cleanup_resolv(int);
103 * This is the main line code for the yp server.
106 main(int argc, char **argv)
108 if (geteuid() != 0) {
109 fprintf(stderr, "must be root to run %s\n", argv[0]);
110 exit(1);
113 /* Set up shop */
114 ypinit(argc, argv);
116 /* If requested set up the N2L maps. May take a while */
117 if (init_dit)
118 if (FAILURE == dump_maps_to_dit(init_containers)) {
119 fprintf(stderr, "Fatal error dumping maps to DIT."
120 " See syslog and LDAP server logs for details.\n");
121 exit(1);
124 if (init_maps)
125 if (FAILURE == dump_dit_to_maps()) {
126 fprintf(stderr, "Fatal error dumping DIT to maps."
127 " See syslog and LDAP server logs for details.\n");
128 exit(1);
132 * If we were asked to init the maps now exit. User will then use
133 * ypstart to restart ypserv and all the other NIS daemons.
135 if (init_dit || init_maps) {
136 printf("Map setup complete. Please now restart NIS daemons "
137 "with ypstart.\n");
138 exit(0);
141 svc_run();
144 * This is stupid, but the compiler likes to warn us about the
145 * absence of returns from main()
147 return (0);
150 typedef struct {
151 char *netid;
152 int fd;
153 int olddispatch; /* Register on protocol version 1 ? */
154 int class; /* Other services that must succeed */
155 SVCXPRT *xprt;
156 int ok; /* Registered successfully ? */
157 } ypservice_t;
159 ypservice_t service[] = {
160 { "udp", -1, 1, 4, 0, 0 },
161 { "tcp", -1, 1, 4, 0, 0 },
162 { "udp6", -1, 0, 6, 0, 0 },
163 { "tcp6", -1, 0, 6, 0, 0 }
166 #define MAXSERVICES (sizeof (service)/sizeof (service[0]))
168 int service_classes[MAXSERVICES];
171 * Does startup processing for the yp server.
173 static void
174 ypinit(int argc, char **argv)
176 int pid;
177 int stat, t;
178 struct sigaction act;
179 int ufd, tfd;
180 SVCXPRT *utransp, *ttransp;
181 struct netconfig *nconf;
182 int connmaxrec = RPC_MAXDATASIZE;
183 int i, j, services = 0;
187 * Init yptol flags. Will get redone by init_lock_system() but we need
188 * to know if we should parse yptol cmd line options.
190 init_yptol_flag();
192 ypget_command_line_args(argc, argv);
194 if (silent) {
195 pid = (int)fork();
197 if (pid == -1) {
198 logprintf("ypserv: ypinit fork failure.\n");
199 ypexit();
202 if (pid != 0) {
203 exit(0);
207 if (!init_lock_system(FALSE)) {
208 ypexit();
211 get_secure_nets(argv[0]);
213 if (silent) {
214 closelog();
215 closefrom(3);
218 if (yptol_mode) {
219 stat = parseConfig(ldapCLA, NTOL_MAP_FILE);
220 if (stat == 1) {
221 logprintf("NIS to LDAP mapping inactive.\n");
222 } else if (stat != 0) {
223 logprintf("Aborting after NIS to LDAP mapping "
224 "error.\n");
225 fflush(stderr);
226 exit(-1);
230 if (silent) {
231 freopen("/dev/null", "r", stdin);
232 if (access(logfile, _IOWRT)) {
233 freopen("/dev/null", "w", stdout);
234 freopen("/dev/null", "w", stderr);
235 } else {
236 freopen(logfile, "a", stdout);
237 freopen(logfile, "a", stderr);
240 t = open("/dev/tty", 2);
242 setpgrp();
245 #ifdef SYSVCONFIG
246 sigset(SIGHUP, (void (*)())sysvconfig);
247 #else
248 sigset(SIGHUP, SIG_IGN);
249 #endif
252 * Setting disposition to SIG_IGN will not create zombies when child
253 * processes terminate.
255 sigset(SIGCHLD, SIG_IGN);
257 act.sa_handler = cleanup_resolv;
258 sigemptyset(&act.sa_mask);
259 act.sa_flags = SA_RESETHAND;
260 sigaction(SIGTERM, &act, (struct sigaction *)NULL);
261 sigaction(SIGQUIT, &act, (struct sigaction *)NULL);
262 sigaction(SIGABRT, &act, (struct sigaction *)NULL);
263 sigaction(SIGBUS, &act, (struct sigaction *)NULL);
264 sigaction(SIGSEGV, &act, (struct sigaction *)NULL);
267 * Set non-blocking mode and maximum record size for
268 * connection oriented RPC transports.
270 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
271 logprintf("unable to set maximum RPC record size");
274 svc_unreg(YPPROG, YPVERS);
275 svc_unreg(YPPROG, YPVERS_ORIG);
277 for (i = 0; i < sizeof (service)/sizeof (ypservice_t); i++) {
279 service_classes[i] = -1;
281 if ((nconf = getnetconfigent(service[i].netid)) == NULL) {
282 logprintf("getnetconfigent(\"%s\") failed\n",
283 service[i].netid);
284 continue;
287 if ((service[i].fd = t_open(nconf->nc_device, O_RDWR, NULL)) <
288 0) {
289 logprintf("t_open failed for %s\n", service[i].netid);
290 freenetconfigent(nconf);
291 continue;
294 if (netdir_options(nconf, ND_SET_RESERVEDPORT, service[i].fd,
295 NULL) < 0) {
296 logprintf("could not set reserved port for %s\n",
297 service[i].netid);
298 (void) close(service[i].fd);
299 service[i].fd = -1;
300 freenetconfigent(nconf);
301 continue;
304 if ((service[i].xprt = svc_tli_create(service[i].fd, nconf,
305 NULL, 0, 0)) == NULL) {
306 logprintf("svc_tli_create failed for %s\n",
307 service[i].netid);
308 (void) close(service[i].fd);
309 service[i].fd = -1;
310 freenetconfigent(nconf);
311 continue;
314 if (!svc_reg(service[i].xprt, YPPROG, YPVERS, ypdispatch,
315 nconf)) {
316 logprintf("%s %s\n", service[i].netid, register_failed);
317 svc_destroy(service[i].xprt);
318 service[i].xprt = 0;
319 (void) close(service[i].fd);
320 service[i].fd = -1;
321 freenetconfigent(nconf);
322 continue;
325 if (service[i].olddispatch && !svc_reg(service[i].xprt, YPPROG,
326 YPVERS_ORIG, ypolddispatch, nconf)) {
327 logprintf("old %s %s\n",
328 service[i].netid, register_failed);
329 /* Can only unregister prognum/versnum */
330 svc_destroy(service[i].xprt);
331 service[i].xprt = 0;
332 (void) close(service[i].fd);
333 service[i].fd = -1;
334 freenetconfigent(nconf);
335 continue;
338 services++;
339 service[i].ok = 1;
340 service_classes[i] = service[i].class;
342 freenetconfigent(nconf);
347 * Check if we managed to register enough services to continue.
348 * It's OK if we managed to register all IPv4 services but no
349 * IPv6, or the other way around, but not if we (say) registered
350 * IPv4 UDP but not TCP.
352 if (services > 0) {
353 for (j = 0; j < MAXSERVICES; j++) {
354 if (service_classes[j] >= 0) {
356 * Must have all services of this class
357 * registered.
359 for (i = 0; i < MAXSERVICES; i++) {
360 if (service[i].ok == 0 &&
361 service[i].class ==
362 service_classes[j]) {
363 logprintf(
364 "unable to register all services for class %d\n",
365 service[i].class);
366 ypexit();
371 } else {
372 logprintf("unable to register any services\n");
373 ypexit();
376 /* Now we setup circuit_n or yp_all() and yp_update() will not work */
377 if (!svc_create(ypdispatch, YPPROG, YPVERS, "circuit_n")) {
378 logprintf("circuit_n %s\n", register_failed);
379 ypexit();
382 if (dnsforward) {
383 setup_resolv(&dnsforward, &resolv_pid,
384 &resolv_client, resolv_tp, 0);
385 if (resolv_client == NULL)
386 client_setup_failure = TRUE;
390 void
391 cleanup_resolv(int sig)
393 if (resolv_pid)
394 kill(resolv_pid, sig);
396 kill(getpid(), sig);
400 * This picks up any command line args passed from the process invocation.
402 static void
403 ypget_command_line_args(int argc, char **argv)
405 for (argv++; --argc; argv++) {
407 if ((*argv)[0] == '-') {
409 switch ((*argv)[1]) {
410 #ifdef MINUS_C_OPTION
411 case 'c':
412 multiflag = TRUE;
413 break;
414 #endif
415 case 'd':
416 if (access("/etc/resolv.conf", F_OK) == -1) {
417 fprintf(stderr,
418 "No /etc/resolv.conf file, -d option ignored\n");
419 } else {
420 dnsforward = TRUE;
422 break;
423 case 'I':
424 init_containers = TRUE;
425 /* ... and also do -i stuff */
426 case 'i':
427 if (yptol_mode) {
428 init_dit = TRUE;
429 } else {
430 fprintf(stderr, "-%c option is illegal "
431 "if not in NIS to LDAP mode. Exiting\n",
432 (*argv)[1]);
433 fflush(stderr);
434 exit(-1);
437 /* Handle -ir */
438 if ('r' != (*argv)[2])
439 break;
441 case 'r':
442 if (yptol_mode) {
443 init_maps = TRUE;
444 } else {
445 fprintf(stderr, "-r option is illegal "
446 "if not in NIS to LDAP mode. "
447 "Exiting\n");
448 fflush(stderr);
449 exit(-1);
451 break;
452 case 'v':
453 silent = FALSE;
454 break;
459 /* If setting up don't run silent or demonize */
460 if (init_dit || init_maps)
461 silent = FALSE;
466 * This dispatches to server action routines based on the input procedure
467 * number. ypdispatch is called from the RPC function svc_run.
469 static void
470 ypdispatch(struct svc_req *rqstp, SVCXPRT *transp)
472 sigset_t set, oset;
475 #ifdef SYSVCONFIG
476 /* prepare to answer questions about system v filesystem aliases */
477 sysvconfig();
478 #endif
480 sigemptyset(&set);
481 sigaddset(&set, SIGCHLD);
482 sigprocmask(SIG_BLOCK, &set, &oset);
484 switch (rqstp->rq_proc) {
486 case YPPROC_NULL:
488 if (!svc_sendreply(transp, xdr_void, 0))
489 logprintf("ypserv: Can't reply to rpc call.\n");
490 break;
492 case YPPROC_DOMAIN:
493 ypdomain(transp, TRUE);
494 break;
496 case YPPROC_DOMAIN_NONACK:
497 ypdomain(transp, FALSE);
498 break;
500 case YPPROC_MATCH:
501 ypmatch(transp, rqstp);
502 break;
504 case YPPROC_FIRST:
505 ypfirst(transp);
506 break;
508 case YPPROC_NEXT:
509 ypnext(transp);
510 break;
512 case YPPROC_XFR:
513 ypxfr(transp, YPPROC_XFR);
514 break;
516 case YPPROC_NEWXFR:
517 ypxfr(transp, YPPROC_NEWXFR);
518 break;
520 case YPPROC_CLEAR:
521 ypclr_current_map();
523 if (!svc_sendreply(transp, xdr_void, 0))
524 logprintf("ypserv: Can't reply to rpc call.\n");
525 break;
527 case YPPROC_ALL:
528 ypall(transp);
529 break;
531 case YPPROC_MASTER:
532 ypmaster(transp);
533 break;
535 case YPPROC_ORDER:
536 yporder(transp);
537 break;
539 case YPPROC_MAPLIST:
540 ypmaplist(transp);
541 break;
543 default:
544 svcerr_noproc(transp);
545 break;
549 sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
553 static void
554 ypolddispatch(struct svc_req *rqstp, SVCXPRT *transp)
556 sigset_t set, oset;
558 sigemptyset(&set);
559 sigaddset(&set, SIGCHLD);
560 sigprocmask(SIG_BLOCK, &set, &oset);
562 switch (rqstp->rq_proc) {
564 case YPOLDPROC_NULL:
565 if (!svc_sendreply(transp, xdr_void, 0))
566 logprintf("ypserv: Can't replay to rpc call.\n");
567 break;
569 case YPOLDPROC_DOMAIN:
570 ypdomain(transp, TRUE);
571 break;
573 case YPOLDPROC_DOMAIN_NONACK:
574 ypdomain(transp, FALSE);
575 break;
577 case YPOLDPROC_MATCH:
578 ypoldmatch(transp, rqstp);
579 break;
581 case YPOLDPROC_FIRST:
582 ypoldfirst(transp);
583 break;
585 case YPOLDPROC_NEXT:
586 ypoldnext(transp);
587 break;
589 case YPOLDPROC_POLL:
590 ypoldpoll(transp);
591 break;
593 case YPOLDPROC_PUSH:
594 ypoldpush(transp);
595 break;
597 case YPOLDPROC_PULL:
598 ypoldpull(transp);
599 break;
601 case YPOLDPROC_GET:
602 ypoldget(transp);
604 default:
605 svcerr_noproc(transp);
606 break;
609 sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
613 * This flushes output to stderr, then aborts the server process to leave a
614 * core dump.
616 static void
617 ypexit(void)
619 fflush(stderr);
620 abort();
624 * This constructs a logging record.
626 void
627 logprintf(char *format, ...)
629 va_list ap;
630 struct timeval t;
632 va_start(ap, format);
634 if (silent) {
635 gettimeofday(&t);
636 fseek(stderr, 0, 2);
637 fprintf(stderr, "%19.19s: ", ctime(&t.tv_sec));
640 vfprintf(stderr, format, ap);
641 va_end(ap);
642 fflush(stderr);