Move /var/svc/log to /var/log/svc
[unleashed/lotheac.git] / usr / src / cmd / ypcmd / ypserv.c
blob702e2fa9bff8c267a672f41a73e44f13f265a15a
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 2017 Gary Mills
24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
37 * This contains the mainline code for the YP server. Data
38 * structures which are process-global are also in this module.
41 /* this is so that ypserv will compile under 5.5 */
42 #define _SVID_GETTOD
43 #include <sys/time.h>
44 extern int gettimeofday(struct timeval *);
46 #include "ypsym.h"
47 #include <sys/types.h>
48 #include <sys/wait.h>
49 #include <fcntl.h>
50 #include <rpc/rpc.h>
51 #include <netconfig.h>
52 #include <netdir.h>
53 #include <sys/select.h>
54 #include <stdlib.h>
55 #include <unistd.h>
56 #include <stdio.h>
57 #include <stdarg.h>
58 #include <signal.h>
59 #include "shim.h"
60 #include "yptol.h"
61 #include <syslog.h>
63 static char register_failed[] = "ypserv: Unable to register service for ";
64 bool silent = TRUE;
67 * client_setup_failure will be TRUE, if setup of the
68 * connection to rpc.nisd_resolv failed
70 bool client_setup_failure = FALSE;
72 /* N2L options */
73 bool init_dit = FALSE;
74 bool init_containers = FALSE;
75 bool init_maps = FALSE;
76 char **ldapCLA = NULL;
78 /* For DNS forwarding command line option (-d) */
79 bool dnsforward = FALSE;
80 int resolv_pid = 0;
81 CLIENT *resolv_client = NULL;
82 char *resolv_tp = "ticots";
84 #ifdef MINUS_C_OPTION
85 /* For cluster support (-c) */
86 bool multiflag = FALSE;
87 #endif
89 static char logfile[] = "/var/yp/ypserv.log";
90 void logprintf(char *format, ...);
92 static void ypexit(void);
93 static void ypinit(int argc, char **argv);
94 static void ypdispatch(struct svc_req *rqstp, SVCXPRT *transp);
95 static void ypolddispatch(struct svc_req *rqstp, SVCXPRT *transp);
96 static void ypget_command_line_args(int argc, char **argv);
97 extern void setup_resolv(bool *fwding, int *child,
98 CLIENT **client, char *tp_type, long prognum);
99 static void cleanup_resolv(int);
102 * This is the main line code for the yp server.
105 main(int argc, char **argv)
107 if (geteuid() != 0) {
108 fprintf(stderr, "must be root to run %s\n", argv[0]);
109 exit(1);
112 /* Set up shop */
113 ypinit(argc, argv);
115 /* If requested set up the N2L maps. May take a while */
116 if (init_dit)
117 if (FAILURE == dump_maps_to_dit(init_containers)) {
118 fprintf(stderr, "Fatal error dumping maps to DIT."
119 " See syslog and LDAP server logs for details.\n");
120 exit(1);
123 if (init_maps)
124 if (FAILURE == dump_dit_to_maps()) {
125 fprintf(stderr, "Fatal error dumping DIT to maps."
126 " See syslog and LDAP server logs for details.\n");
127 exit(1);
131 * If we were asked to init the maps now exit. User will then use
132 * ypstart to restart ypserv and all the other NIS daemons.
134 if (init_dit || init_maps) {
135 printf("Map setup complete. Please now restart NIS daemons "
136 "with ypstart.\n");
137 exit(0);
140 svc_run();
143 * This is stupid, but the compiler likes to warn us about the
144 * absence of returns from main()
146 return (0);
149 typedef struct {
150 char *netid;
151 int fd;
152 int olddispatch; /* Register on protocol version 1 ? */
153 int class; /* Other services that must succeed */
154 SVCXPRT *xprt;
155 int ok; /* Registered successfully ? */
156 } ypservice_t;
158 ypservice_t service[] = {
159 { "udp", -1, 1, 4, 0, 0 },
160 { "tcp", -1, 1, 4, 0, 0 },
161 { "udp6", -1, 0, 6, 0, 0 },
162 { "tcp6", -1, 0, 6, 0, 0 }
165 #define MAXSERVICES (sizeof (service)/sizeof (service[0]))
167 int service_classes[MAXSERVICES];
170 * Does startup processing for the yp server.
172 static void
173 ypinit(int argc, char **argv)
175 int pid;
176 int stat;
177 struct sigaction act;
178 int ufd, tfd;
179 SVCXPRT *utransp, *ttransp;
180 struct netconfig *nconf;
181 int connmaxrec = RPC_MAXDATASIZE;
182 int i, j, services = 0;
186 * Init yptol flags. Will get redone by init_lock_system() but we need
187 * to know if we should parse yptol cmd line options.
189 init_yptol_flag();
191 ypget_command_line_args(argc, argv);
193 if (silent) {
194 pid = (int)fork();
196 if (pid == -1) {
197 logprintf("ypserv: ypinit fork failure.\n");
198 ypexit();
201 if (pid != 0) {
202 exit(0);
206 if (!init_lock_system(FALSE)) {
207 ypexit();
210 get_secure_nets(argv[0]);
212 if (silent) {
213 closelog();
214 closefrom(3);
217 if (yptol_mode) {
218 stat = parseConfig(ldapCLA, NTOL_MAP_FILE);
219 if (stat == 1) {
220 logprintf("NIS to LDAP mapping inactive.\n");
221 } else if (stat != 0) {
222 logprintf("Aborting after NIS to LDAP mapping "
223 "error.\n");
224 fflush(stderr);
225 exit(-1);
229 if (silent) {
230 freopen("/dev/null", "r", stdin);
231 if (access(logfile, _IOWRT)) {
232 freopen("/dev/null", "w", stdout);
233 freopen("/dev/null", "w", stderr);
234 } else {
235 freopen(logfile, "a", stdout);
236 freopen(logfile, "a", stderr);
239 (void) open("/dev/tty", O_RDWR);
241 setpgrp();
244 #ifdef SYSVCONFIG
245 sigset(SIGHUP, (void (*)())sysvconfig);
246 #else
247 sigset(SIGHUP, SIG_IGN);
248 #endif
251 * Setting disposition to SIG_IGN will not create zombies when child
252 * processes terminate.
254 sigset(SIGCHLD, SIG_IGN);
256 act.sa_handler = cleanup_resolv;
257 sigemptyset(&act.sa_mask);
258 act.sa_flags = SA_RESETHAND;
259 sigaction(SIGTERM, &act, NULL);
260 sigaction(SIGQUIT, &act, NULL);
261 sigaction(SIGABRT, &act, NULL);
262 sigaction(SIGBUS, &act, NULL);
263 sigaction(SIGSEGV, &act, NULL);
266 * Set non-blocking mode and maximum record size for
267 * connection oriented RPC transports.
269 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
270 logprintf("unable to set maximum RPC record size");
273 svc_unreg(YPPROG, YPVERS);
274 svc_unreg(YPPROG, YPVERS_ORIG);
276 for (i = 0; i < sizeof (service)/sizeof (ypservice_t); i++) {
278 service_classes[i] = -1;
280 if ((nconf = getnetconfigent(service[i].netid)) == NULL) {
281 logprintf("getnetconfigent(\"%s\") failed\n",
282 service[i].netid);
283 continue;
286 if ((service[i].fd = t_open(nconf->nc_device, O_RDWR, NULL)) <
287 0) {
288 logprintf("t_open failed for %s\n", service[i].netid);
289 freenetconfigent(nconf);
290 continue;
293 if (netdir_options(nconf, ND_SET_RESERVEDPORT, service[i].fd,
294 NULL) < 0) {
295 logprintf("could not set reserved port for %s\n",
296 service[i].netid);
297 (void) close(service[i].fd);
298 service[i].fd = -1;
299 freenetconfigent(nconf);
300 continue;
303 if ((service[i].xprt = svc_tli_create(service[i].fd, nconf,
304 NULL, 0, 0)) == NULL) {
305 logprintf("svc_tli_create failed for %s\n",
306 service[i].netid);
307 (void) close(service[i].fd);
308 service[i].fd = -1;
309 freenetconfigent(nconf);
310 continue;
313 if (!svc_reg(service[i].xprt, YPPROG, YPVERS, ypdispatch,
314 nconf)) {
315 logprintf("%s %s\n", service[i].netid, register_failed);
316 svc_destroy(service[i].xprt);
317 service[i].xprt = 0;
318 (void) close(service[i].fd);
319 service[i].fd = -1;
320 freenetconfigent(nconf);
321 continue;
324 if (service[i].olddispatch && !svc_reg(service[i].xprt, YPPROG,
325 YPVERS_ORIG, ypolddispatch, nconf)) {
326 logprintf("old %s %s\n",
327 service[i].netid, register_failed);
328 /* Can only unregister prognum/versnum */
329 svc_destroy(service[i].xprt);
330 service[i].xprt = 0;
331 (void) close(service[i].fd);
332 service[i].fd = -1;
333 freenetconfigent(nconf);
334 continue;
337 services++;
338 service[i].ok = 1;
339 service_classes[i] = service[i].class;
341 freenetconfigent(nconf);
346 * Check if we managed to register enough services to continue.
347 * It's OK if we managed to register all IPv4 services but no
348 * IPv6, or the other way around, but not if we (say) registered
349 * IPv4 UDP but not TCP.
351 if (services > 0) {
352 for (j = 0; j < MAXSERVICES; j++) {
353 if (service_classes[j] >= 0) {
355 * Must have all services of this class
356 * registered.
358 for (i = 0; i < MAXSERVICES; i++) {
359 if (service[i].ok == 0 &&
360 service[i].class ==
361 service_classes[j]) {
362 logprintf(
363 "unable to register all services for class %d\n",
364 service[i].class);
365 ypexit();
370 } else {
371 logprintf("unable to register any services\n");
372 ypexit();
375 /* Now we setup circuit_n or yp_all() and yp_update() will not work */
376 if (!svc_create(ypdispatch, YPPROG, YPVERS, "circuit_n")) {
377 logprintf("circuit_n %s\n", register_failed);
378 ypexit();
381 if (dnsforward) {
382 setup_resolv(&dnsforward, &resolv_pid,
383 &resolv_client, resolv_tp, 0);
384 if (resolv_client == NULL)
385 client_setup_failure = TRUE;
389 void
390 cleanup_resolv(int sig)
392 if (resolv_pid)
393 kill(resolv_pid, sig);
395 kill(getpid(), sig);
399 * This picks up any command line args passed from the process invocation.
401 static void
402 ypget_command_line_args(int argc, char **argv)
404 for (argv++; --argc; argv++) {
406 if ((*argv)[0] == '-') {
408 switch ((*argv)[1]) {
409 #ifdef MINUS_C_OPTION
410 case 'c':
411 multiflag = TRUE;
412 break;
413 #endif
414 case 'd':
415 if (access("/etc/resolv.conf", F_OK) == -1) {
416 fprintf(stderr,
417 "No /etc/resolv.conf file, -d option ignored\n");
418 } else {
419 dnsforward = TRUE;
421 break;
422 case 'I':
423 init_containers = TRUE;
424 /* ... and also do -i stuff */
425 case 'i':
426 if (yptol_mode) {
427 init_dit = TRUE;
428 } else {
429 fprintf(stderr, "-%c option is illegal "
430 "if not in NIS to LDAP mode. Exiting\n",
431 (*argv)[1]);
432 fflush(stderr);
433 exit(-1);
436 /* Handle -ir */
437 if ('r' != (*argv)[2])
438 break;
440 case 'r':
441 if (yptol_mode) {
442 init_maps = TRUE;
443 } else {
444 fprintf(stderr, "-r option is illegal "
445 "if not in NIS to LDAP mode. "
446 "Exiting\n");
447 fflush(stderr);
448 exit(-1);
450 break;
451 case 'v':
452 silent = FALSE;
453 break;
458 /* If setting up don't run silent or demonize */
459 if (init_dit || init_maps)
460 silent = FALSE;
465 * This dispatches to server action routines based on the input procedure
466 * number. ypdispatch is called from the RPC function svc_run.
468 static void
469 ypdispatch(struct svc_req *rqstp, SVCXPRT *transp)
471 sigset_t set, oset;
474 #ifdef SYSVCONFIG
475 /* prepare to answer questions about system v filesystem aliases */
476 sysvconfig();
477 #endif
479 sigemptyset(&set);
480 sigaddset(&set, SIGCHLD);
481 sigprocmask(SIG_BLOCK, &set, &oset);
483 switch (rqstp->rq_proc) {
485 case YPPROC_NULL:
487 if (!svc_sendreply(transp, xdr_void, 0))
488 logprintf("ypserv: Can't reply to rpc call.\n");
489 break;
491 case YPPROC_DOMAIN:
492 ypdomain(transp, TRUE);
493 break;
495 case YPPROC_DOMAIN_NONACK:
496 ypdomain(transp, FALSE);
497 break;
499 case YPPROC_MATCH:
500 ypmatch(transp, rqstp);
501 break;
503 case YPPROC_FIRST:
504 ypfirst(transp);
505 break;
507 case YPPROC_NEXT:
508 ypnext(transp);
509 break;
511 case YPPROC_XFR:
512 ypxfr(transp, YPPROC_XFR);
513 break;
515 case YPPROC_NEWXFR:
516 ypxfr(transp, YPPROC_NEWXFR);
517 break;
519 case YPPROC_CLEAR:
520 ypclr_current_map();
522 if (!svc_sendreply(transp, xdr_void, 0))
523 logprintf("ypserv: Can't reply to rpc call.\n");
524 break;
526 case YPPROC_ALL:
527 ypall(transp);
528 break;
530 case YPPROC_MASTER:
531 ypmaster(transp);
532 break;
534 case YPPROC_ORDER:
535 yporder(transp);
536 break;
538 case YPPROC_MAPLIST:
539 ypmaplist(transp);
540 break;
542 default:
543 svcerr_noproc(transp);
544 break;
548 sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
552 static void
553 ypolddispatch(struct svc_req *rqstp, SVCXPRT *transp)
555 sigset_t set, oset;
557 sigemptyset(&set);
558 sigaddset(&set, SIGCHLD);
559 sigprocmask(SIG_BLOCK, &set, &oset);
561 switch (rqstp->rq_proc) {
563 case YPOLDPROC_NULL:
564 if (!svc_sendreply(transp, xdr_void, 0))
565 logprintf("ypserv: Can't replay to rpc call.\n");
566 break;
568 case YPOLDPROC_DOMAIN:
569 ypdomain(transp, TRUE);
570 break;
572 case YPOLDPROC_DOMAIN_NONACK:
573 ypdomain(transp, FALSE);
574 break;
576 case YPOLDPROC_MATCH:
577 ypoldmatch(transp, rqstp);
578 break;
580 case YPOLDPROC_FIRST:
581 ypoldfirst(transp);
582 break;
584 case YPOLDPROC_NEXT:
585 ypoldnext(transp);
586 break;
588 case YPOLDPROC_POLL:
589 ypoldpoll(transp);
590 break;
592 case YPOLDPROC_PUSH:
593 ypoldpush(transp);
594 break;
596 case YPOLDPROC_PULL:
597 ypoldpull(transp);
598 break;
600 case YPOLDPROC_GET:
601 ypoldget(transp);
603 default:
604 svcerr_noproc(transp);
605 break;
608 sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
612 * This flushes output to stderr, then aborts the server process to leave a
613 * core dump.
615 static void
616 ypexit(void)
618 fflush(stderr);
619 abort();
623 * This constructs a logging record.
625 void
626 logprintf(char *format, ...)
628 va_list ap;
629 struct timeval t;
631 va_start(ap, format);
633 if (silent) {
634 gettimeofday(&t);
635 fseek(stderr, 0, 2);
636 fprintf(stderr, "%19.19s: ", ctime(&t.tv_sec));
639 vfprintf(stderr, format, ap);
640 va_end(ap);
641 fflush(stderr);