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