]> git.saurik.com Git - apple/network_cmds.git/blob - ypserv.tproj/ypserv.c
8ca6b15e5681ffdae2ae647592abc444e8292c18
[apple/network_cmds.git] / ypserv.tproj / ypserv.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* $OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $ */
24
25 /*
26 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by Mats O Jansson
40 * 4. The name of the author may not be used to endorse or promote products
41 * derived from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
56 #ifndef LINT
57 static char rcsid[] = "$OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $";
58 #endif
59
60 #include "yp.h"
61 #include "ypv1.h"
62 #include <stdio.h>
63 #include <stdlib.h>/* getenv, exit */
64 #include <rpc/pmap_clnt.h> /* for pmap_unset */
65 #include <string.h> /* strcmp */
66 #include <unistd.h>
67 #include <netdb.h>
68 #include <signal.h>
69 #include <errno.h>
70 #include <sys/ttycom.h>/* TIOCNOTTY */
71 #ifdef __cplusplus
72 #include <sysent.h> /* getdtablesize, open */
73 #endif /* __cplusplus */
74 #include <memory.h>
75 #include <sys/socket.h>
76 #include <netinet/in.h>
77 #include <syslog.h>
78 #include "acl.h"
79 #include "yplog.h"
80 #include "ypdef.h"
81 #include <sys/wait.h>
82 #include <sys/ioctl.h> /* for ioctl */
83 #include <sys/fcntl.h> /* for open */
84
85 #ifdef __STDC__
86 #define SIG_PF void(*)(int)
87 #endif
88
89 #ifdef DEBUG
90 #define RPC_SVC_FG
91 #endif
92
93 #define _RPCSVC_CLOSEDOWN 120
94 static int _rpcpmstart; /* Started by a port monitor ? */
95 static int _rpcfdtype; /* Whether Stream or Datagram ? */
96 static int _rpcsvcdirty; /* Still serving ? */
97
98 int usedns = FALSE;
99 char *progname = "ypserv";
100 char *aclfile = NULL;
101
102 void sig_child();
103 void sig_hup();
104
105 /* in the RPC library */
106 SVCXPRT *svcfd_create(int, u_int, u_int);
107
108 static
109 void _msgout(char* msg)
110 {
111 #ifdef RPC_SVC_FG
112 if (_rpcpmstart)
113 syslog(LOG_ERR, msg);
114 else
115 (void) fprintf(stderr, "%s\n", msg);
116 #else
117 syslog(LOG_ERR, msg);
118 #endif
119 }
120
121 static void
122 closedown()
123 {
124 if (_rpcsvcdirty == 0) {
125 extern fd_set svc_fdset;
126 static int size;
127 int i, openfd;
128
129 if (_rpcfdtype == SOCK_DGRAM)
130 exit(0);
131 if (size == 0) {
132 size = getdtablesize();
133 }
134 for (i = 0, openfd = 0; i < size && openfd < 2; i++)
135 if (FD_ISSET(i, &svc_fdset))
136 openfd++;
137 if (openfd <= (_rpcpmstart?0:1))
138 exit(0);
139 }
140 (void) alarm(_RPCSVC_CLOSEDOWN);
141 }
142
143 static void
144 ypprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
145 {
146 union {
147 domainname ypproc_domain_1_arg;
148 domainname ypproc_domain_nonack_1_arg;
149 yprequest ypproc_match_1_arg;
150 yprequest ypproc_first_1_arg;
151 yprequest ypproc_next_1_arg;
152 yprequest ypproc_poll_1_arg;
153 yprequest ypproc_push_1_arg;
154 yprequest ypproc_pull_1_arg;
155 yprequest ypproc_get_1_arg;
156 } argument;
157 char *result;
158 xdrproc_t xdr_argument, xdr_result;
159 char *(*local)(char *, struct svc_req *);
160
161 _rpcsvcdirty = 1;
162 switch (rqstp->rq_proc) {
163 case YPOLDPROC_NULL:
164 xdr_argument = (xdrproc_t) xdr_void;
165 xdr_result = (xdrproc_t) xdr_void;
166 local = (char *(*)(char *, struct svc_req *)) ypproc_null_1_svc;
167 break;
168
169 case YPOLDPROC_DOMAIN:
170 xdr_argument = (xdrproc_t) xdr_domainname;
171 xdr_result = (xdrproc_t) xdr_bool;
172 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_1_svc;
173 break;
174
175 case YPOLDPROC_DOMAIN_NONACK:
176 xdr_argument = (xdrproc_t) xdr_domainname;
177 xdr_result = (xdrproc_t) xdr_bool;
178 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_1_svc;
179 break;
180
181 case YPOLDPROC_MATCH:
182 xdr_argument = (xdrproc_t) xdr_yprequest;
183 xdr_result = (xdrproc_t) xdr_ypresponse;
184 local = (char *(*)(char *, struct svc_req *)) ypproc_match_1_svc;
185 break;
186
187 case YPOLDPROC_FIRST:
188 xdr_argument = (xdrproc_t) xdr_yprequest;
189 xdr_result = (xdrproc_t) xdr_ypresponse;
190 local = (char *(*)(char *, struct svc_req *)) ypproc_first_1_svc;
191 break;
192
193 case YPOLDPROC_NEXT:
194 xdr_argument = (xdrproc_t) xdr_yprequest;
195 xdr_result = (xdrproc_t) xdr_ypresponse;
196 local = (char *(*)(char *, struct svc_req *)) ypproc_next_1_svc;
197 break;
198
199 case YPOLDPROC_POLL:
200 xdr_argument = (xdrproc_t) xdr_yprequest;
201 xdr_result = (xdrproc_t) xdr_ypresponse;
202 local = (char *(*)(char *, struct svc_req *)) ypproc_poll_1_svc;
203 break;
204
205 case YPOLDPROC_PUSH:
206 xdr_argument = (xdrproc_t) xdr_yprequest;
207 xdr_result = (xdrproc_t) xdr_void;
208 local = (char *(*)(char *, struct svc_req *)) ypproc_push_1_svc;
209 break;
210
211 case YPOLDPROC_PULL:
212 xdr_argument = (xdrproc_t) xdr_yprequest;
213 xdr_result = (xdrproc_t) xdr_void;
214 local = (char *(*)(char *, struct svc_req *)) ypproc_pull_1_svc;
215 break;
216
217 case YPOLDPROC_GET:
218 xdr_argument = (xdrproc_t) xdr_yprequest;
219 xdr_result = (xdrproc_t) xdr_void;
220 local = (char *(*)(char *, struct svc_req *)) ypproc_get_1_svc;
221 break;
222
223 default:
224 svcerr_noproc(transp);
225 _rpcsvcdirty = 0;
226 return;
227 }
228 (void) memset((char *)&argument, 0, sizeof (argument));
229 if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
230 svcerr_decode(transp);
231 _rpcsvcdirty = 0;
232 return;
233 }
234 result = (*local)((char *)&argument, rqstp);
235 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
236 svcerr_systemerr(transp);
237 }
238 if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
239 _msgout("unable to free arguments");
240 exit(1);
241 }
242 _rpcsvcdirty = 0;
243 return;
244 }
245
246 static void
247 ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
248 {
249 union {
250 domainname ypproc_domain_2_arg;
251 domainname ypproc_domain_nonack_2_arg;
252 ypreq_key ypproc_match_2_arg;
253 ypreq_nokey ypproc_first_2_arg;
254 ypreq_key ypproc_next_2_arg;
255 ypreq_xfr ypproc_xfr_2_arg;
256 ypreq_nokey ypproc_all_2_arg;
257 ypreq_nokey ypproc_master_2_arg;
258 ypreq_nokey ypproc_order_2_arg;
259 domainname ypproc_maplist_2_arg;
260 } argument;
261 char *result;
262 xdrproc_t xdr_argument, xdr_result;
263 char *(*local)(char *, struct svc_req *);
264
265 _rpcsvcdirty = 1;
266 switch (rqstp->rq_proc) {
267 case YPPROC_NULL:
268 xdr_argument = (xdrproc_t) xdr_void;
269 xdr_result = (xdrproc_t) xdr_void;
270 local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc;
271 break;
272
273 case YPPROC_DOMAIN:
274 xdr_argument = (xdrproc_t) xdr_domainname;
275 xdr_result = (xdrproc_t) xdr_bool;
276 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc;
277 break;
278
279 case YPPROC_DOMAIN_NONACK:
280 xdr_argument = (xdrproc_t) xdr_domainname;
281 xdr_result = (xdrproc_t) xdr_bool;
282 local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc;
283 break;
284
285 case YPPROC_MATCH:
286 xdr_argument = (xdrproc_t) xdr_ypreq_key;
287 xdr_result = (xdrproc_t) xdr_ypresp_val;
288 local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc;
289 break;
290
291 case YPPROC_FIRST:
292 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
293 xdr_result = (xdrproc_t) xdr_ypresp_key_val;
294 local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc;
295 break;
296
297 case YPPROC_NEXT:
298 xdr_argument = (xdrproc_t) xdr_ypreq_key;
299 xdr_result = (xdrproc_t) xdr_ypresp_key_val;
300 local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc;
301 break;
302
303 case YPPROC_XFR:
304 xdr_argument = (xdrproc_t) xdr_ypreq_xfr;
305 xdr_result = (xdrproc_t) xdr_ypresp_xfr;
306 local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc;
307 break;
308
309 case YPPROC_CLEAR:
310 xdr_argument = (xdrproc_t) xdr_void;
311 xdr_result = (xdrproc_t) xdr_void;
312 local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc;
313 break;
314
315 case YPPROC_ALL:
316 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
317 xdr_result = (xdrproc_t) xdr_ypresp_all;
318 local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc;
319 break;
320
321 case YPPROC_MASTER:
322 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
323 xdr_result = (xdrproc_t) xdr_ypresp_master;
324 local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc;
325 break;
326
327 case YPPROC_ORDER:
328 xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
329 xdr_result = (xdrproc_t) xdr_ypresp_order;
330 local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc;
331 break;
332
333 case YPPROC_MAPLIST:
334 xdr_argument = (xdrproc_t) xdr_domainname;
335 xdr_result = (xdrproc_t) xdr_ypresp_maplist;
336 local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc;
337 break;
338
339 default:
340 svcerr_noproc(transp);
341 _rpcsvcdirty = 0;
342 return;
343 }
344 (void) memset((char *)&argument, 0, sizeof (argument));
345 if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
346 svcerr_decode(transp);
347 _rpcsvcdirty = 0;
348 return;
349 }
350 result = (*local)((char *)&argument, rqstp);
351 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
352 svcerr_systemerr(transp);
353 }
354 if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
355 _msgout("unable to free arguments");
356 exit(1);
357 }
358 _rpcsvcdirty = 0;
359 return;
360 }
361
362 int
363 main (argc,argv)
364 int argc;
365 char *argv[];
366 {
367 register SVCXPRT *transp = NULL;
368 int sock;
369 int proto = 0;
370 struct sockaddr_in saddr;
371 int asize = sizeof (saddr);
372 int usage = 0;
373 int xflag = 0;
374 int allowv1 = 0;
375 int ch;
376 extern char *optarg;
377
378 while ((ch = getopt(argc, argv, "1a:dx")) != -1)
379 switch (ch) {
380 case '1':
381 allowv1 = TRUE;
382 break;
383 case 'a':
384 aclfile = optarg;
385 break;
386 case 'd':
387 usedns = TRUE;
388 break;
389 case 'x':
390 xflag = TRUE;
391 break;
392 default:
393 usage++;
394 break;
395 }
396
397 if (usage) {
398 (void)fprintf(stderr,"usage: %s [-a aclfile] [-d] [-x]\n",progname);
399 exit(1);
400 }
401
402 if (geteuid() != 0) {
403 (void)fprintf(stderr,"%s: must be root to run.\n",progname);
404 exit(1);
405 }
406
407 if (aclfile != NULL) {
408 (void)yp_acl_init(aclfile);
409 } else {
410 (void)yp_acl_securenet(YP_SECURENET_FILE);
411 }
412 if (xflag) {
413 exit(1);
414 };
415
416 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
417 int ssize = sizeof (int);
418
419 if (saddr.sin_family != AF_INET)
420 exit(1);
421 if (getsockopt(0, SOL_SOCKET, SO_TYPE,
422 (char *)&_rpcfdtype, &ssize) == -1)
423 exit(1);
424 sock = 0;
425 _rpcpmstart = 1;
426 proto = 0;
427 openlog("ypserv", LOG_PID, LOG_DAEMON);
428 } else {
429 #ifndef RPC_SVC_FG
430 int size;
431 int pid, i;
432
433 pid = fork();
434 if (pid < 0) {
435 perror("cannot fork");
436 exit(1);
437 }
438 if (pid)
439 exit(0);
440 size = getdtablesize();
441 for (i = 0; i < size; i++)
442 (void) close(i);
443 i = open("/dev/console", 2);
444 (void) dup2(i, 1);
445 (void) dup2(i, 2);
446 i = open("/dev/tty", 2);
447 if (i >= 0) {
448 (void) ioctl(i, TIOCNOTTY, (char *)NULL);
449 (void) close(i);
450 }
451 openlog("ypserv", LOG_PID, LOG_DAEMON);
452 #endif
453 sock = RPC_ANYSOCK;
454 (void) pmap_unset(YPPROG, YPVERS);
455 (void) pmap_unset(YPPROG, YPOLDVERS);
456 }
457
458 ypopenlog(); /* open log file */
459 ypdb_init(); /* init db stuff */
460
461 chdir("/");
462
463 (void)signal(SIGCHLD, sig_child);
464 (void)signal(SIGHUP, sig_hup);
465 { FILE *pidfile = fopen(YPSERV_PID_PATH, "w");
466 if (pidfile != NULL) {
467 fprintf(pidfile, "%d\n", getpid());
468 fclose(pidfile);
469 }
470 }
471
472 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
473 transp = svcudp_create(sock);
474 if (transp == NULL) {
475 _msgout("cannot create udp service.");
476 exit(1);
477 }
478 if (transp->xp_port >= IPPORT_RESERVED) {
479 _msgout("cannot allocate udp privileged port.");
480 exit(1);
481 }
482 if (!_rpcpmstart)
483 proto = IPPROTO_UDP;
484 if (allowv1) {
485 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
486 _msgout("unable to register (YPPROG, YPOLDVERS, udp).");
487 exit(1);
488 }
489 }
490 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
491 _msgout("unable to register (YPPROG, YPVERS, udp).");
492 exit(1);
493 }
494 }
495
496 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
497 if (_rpcpmstart)
498 transp = svcfd_create(sock, 0, 0);
499 else
500 transp = svctcp_create(sock, 0, 0);
501 if (transp == NULL) {
502 _msgout("cannot create tcp service.");
503 exit(1);
504 }
505 if (transp->xp_port >= IPPORT_RESERVED) {
506 _msgout("cannot allocate tcp privileged port.");
507 exit(1);
508 }
509 if (!_rpcpmstart)
510 proto = IPPROTO_TCP;
511 if (allowv1) {
512 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
513 _msgout("unable to register (YPPROG, YPOLDVERS, tcp).");
514 exit(1);
515 }
516 }
517 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
518 _msgout("unable to register (YPPROG, YPVERS, tcp).");
519 exit(1);
520 }
521 }
522
523 if (transp == (SVCXPRT *)NULL) {
524 _msgout("could not create a handle");
525 exit(1);
526 }
527 if (_rpcpmstart) {
528 (void) signal(SIGALRM, (SIG_PF) closedown);
529 (void) alarm(_RPCSVC_CLOSEDOWN);
530 }
531 svc_run();
532 _msgout("svc_run returned");
533 exit(1);
534 /* NOTREACHED */
535 }
536
537 void
538 sig_child()
539 {
540 int save_errno = errno;
541
542 while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0)
543 ;
544 errno = save_errno;
545 }
546
547 void
548 sig_hup()
549 {
550 yp_acl_reset();
551 if (aclfile != NULL) {
552 yplog("sig_hup: reread %s",aclfile);
553 (void)yp_acl_init(aclfile);
554 } else {
555 yplog("sig_hup: reread %s",YP_SECURENET_FILE);
556 (void)yp_acl_securenet(YP_SECURENET_FILE);
557 }
558 }