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
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]
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 */
45 extern int gettimeofday(struct timeval
*);
48 #include <sys/types.h>
52 #include <netconfig.h>
54 #include <sys/select.h>
64 static char register_failed
[] = "ypserv: Unable to register service for ";
68 * client_setup_failure will be TRUE, if setup of the
69 * connection to rpc.nisd_resolv failed
71 bool client_setup_failure
= FALSE
;
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
;
82 CLIENT
*resolv_client
= NULL
;
83 char *resolv_tp
= "ticots";
86 /* For cluster support (-c) */
87 bool multiflag
= FALSE
;
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]);
116 /* If requested set up the N2L maps. May take a while */
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");
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");
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 "
144 * This is stupid, but the compiler likes to warn us about the
145 * absence of returns from main()
153 int olddispatch
; /* Register on protocol version 1 ? */
154 int class; /* Other services that must succeed */
156 int ok
; /* Registered successfully ? */
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.
174 ypinit(int argc
, char **argv
)
178 struct sigaction act
;
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.
192 ypget_command_line_args(argc
, argv
);
198 logprintf("ypserv: ypinit fork failure.\n");
207 if (!init_lock_system(FALSE
)) {
211 get_secure_nets(argv
[0]);
219 stat
= parseConfig(ldapCLA
, NTOL_MAP_FILE
);
221 logprintf("NIS to LDAP mapping inactive.\n");
222 } else if (stat
!= 0) {
223 logprintf("Aborting after NIS to LDAP mapping "
231 freopen("/dev/null", "r", stdin
);
232 if (access(logfile
, _IOWRT
)) {
233 freopen("/dev/null", "w", stdout
);
234 freopen("/dev/null", "w", stderr
);
236 freopen(logfile
, "a", stdout
);
237 freopen(logfile
, "a", stderr
);
240 t
= open("/dev/tty", O_RDWR
);
246 sigset(SIGHUP
, (void (*)())sysvconfig
);
248 sigset(SIGHUP
, SIG_IGN
);
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
, NULL
);
261 sigaction(SIGQUIT
, &act
, NULL
);
262 sigaction(SIGABRT
, &act
, NULL
);
263 sigaction(SIGBUS
, &act
, NULL
);
264 sigaction(SIGSEGV
, &act
, 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",
287 if ((service
[i
].fd
= t_open(nconf
->nc_device
, O_RDWR
, NULL
)) <
289 logprintf("t_open failed for %s\n", service
[i
].netid
);
290 freenetconfigent(nconf
);
294 if (netdir_options(nconf
, ND_SET_RESERVEDPORT
, service
[i
].fd
,
296 logprintf("could not set reserved port for %s\n",
298 (void) close(service
[i
].fd
);
300 freenetconfigent(nconf
);
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",
308 (void) close(service
[i
].fd
);
310 freenetconfigent(nconf
);
314 if (!svc_reg(service
[i
].xprt
, YPPROG
, YPVERS
, ypdispatch
,
316 logprintf("%s %s\n", service
[i
].netid
, register_failed
);
317 svc_destroy(service
[i
].xprt
);
319 (void) close(service
[i
].fd
);
321 freenetconfigent(nconf
);
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
);
332 (void) close(service
[i
].fd
);
334 freenetconfigent(nconf
);
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.
353 for (j
= 0; j
< MAXSERVICES
; j
++) {
354 if (service_classes
[j
] >= 0) {
356 * Must have all services of this class
359 for (i
= 0; i
< MAXSERVICES
; i
++) {
360 if (service
[i
].ok
== 0 &&
362 service_classes
[j
]) {
364 "unable to register all services for class %d\n",
372 logprintf("unable to register any services\n");
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
);
383 setup_resolv(&dnsforward
, &resolv_pid
,
384 &resolv_client
, resolv_tp
, 0);
385 if (resolv_client
== NULL
)
386 client_setup_failure
= TRUE
;
391 cleanup_resolv(int sig
)
394 kill(resolv_pid
, sig
);
400 * This picks up any command line args passed from the process invocation.
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
416 if (access("/etc/resolv.conf", F_OK
) == -1) {
418 "No /etc/resolv.conf file, -d option ignored\n");
424 init_containers
= TRUE
;
425 /* ... and also do -i stuff */
430 fprintf(stderr
, "-%c option is illegal "
431 "if not in NIS to LDAP mode. Exiting\n",
438 if ('r' != (*argv
)[2])
445 fprintf(stderr
, "-r option is illegal "
446 "if not in NIS to LDAP mode. "
459 /* If setting up don't run silent or demonize */
460 if (init_dit
|| init_maps
)
466 * This dispatches to server action routines based on the input procedure
467 * number. ypdispatch is called from the RPC function svc_run.
470 ypdispatch(struct svc_req
*rqstp
, SVCXPRT
*transp
)
476 /* prepare to answer questions about system v filesystem aliases */
481 sigaddset(&set
, SIGCHLD
);
482 sigprocmask(SIG_BLOCK
, &set
, &oset
);
484 switch (rqstp
->rq_proc
) {
488 if (!svc_sendreply(transp
, xdr_void
, 0))
489 logprintf("ypserv: Can't reply to rpc call.\n");
493 ypdomain(transp
, TRUE
);
496 case YPPROC_DOMAIN_NONACK
:
497 ypdomain(transp
, FALSE
);
501 ypmatch(transp
, rqstp
);
513 ypxfr(transp
, YPPROC_XFR
);
517 ypxfr(transp
, YPPROC_NEWXFR
);
523 if (!svc_sendreply(transp
, xdr_void
, 0))
524 logprintf("ypserv: Can't reply to rpc call.\n");
544 svcerr_noproc(transp
);
549 sigprocmask(SIG_SETMASK
, &oset
, (sigset_t
*)NULL
);
554 ypolddispatch(struct svc_req
*rqstp
, SVCXPRT
*transp
)
559 sigaddset(&set
, SIGCHLD
);
560 sigprocmask(SIG_BLOCK
, &set
, &oset
);
562 switch (rqstp
->rq_proc
) {
565 if (!svc_sendreply(transp
, xdr_void
, 0))
566 logprintf("ypserv: Can't replay to rpc call.\n");
569 case YPOLDPROC_DOMAIN
:
570 ypdomain(transp
, TRUE
);
573 case YPOLDPROC_DOMAIN_NONACK
:
574 ypdomain(transp
, FALSE
);
577 case YPOLDPROC_MATCH
:
578 ypoldmatch(transp
, rqstp
);
581 case YPOLDPROC_FIRST
:
605 svcerr_noproc(transp
);
609 sigprocmask(SIG_SETMASK
, &oset
, (sigset_t
*)NULL
);
613 * This flushes output to stderr, then aborts the server process to leave a
624 * This constructs a logging record.
627 logprintf(char *format
, ...)
632 va_start(ap
, format
);
637 fprintf(stderr
, "%19.19s: ", ctime(&t
.tv_sec
));
640 vfprintf(stderr
, format
, ap
);