ypserv.c revision 1.3 1 /* $NetBSD: ypserv.c,v 1.3 1997/03/05 07:19:52 mikel Exp $ */
2
3 /*
4 * Copyright (c) 1994 Mats O Jansson <moj (at) stacken.kth.se>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Mats O Jansson
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/wait.h>
37
38 #include <netinet/in.h>
39
40 #include <memory.h>
41 #include <netdb.h>
42 #include <signal.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <rpc/rpc.h>
48 #include <rpc/xdr.h>
49 #include <rpc/pmap_clnt.h>
50
51 #include <rpcsvc/yp_prot.h>
52
53 #ifdef SYSLOG
54 #include <syslog.h>
55 #else
56 #define LOG_ERR 1
57 #define openlog(a, b, c)
58 #endif
59
60 #include "acl.h"
61 #include "yplog.h"
62 #include "ypdef.h"
63 #include "ypserv.h"
64
65 #ifdef __STDC__
66 #define SIG_PF void(*)(int)
67 #endif
68
69 #ifdef DEBUG
70 #define RPC_SVC_FG
71 #endif
72
73 #define _RPCSVC_CLOSEDOWN 120
74 static int _rpcpmstart; /* Started by a port monitor ? */
75 static int _rpcfdtype; /* Whether Stream or Datagram ? */
76 static int _rpcsvcdirty; /* Still serving ? */
77
78 int usedns;
79 char *aclfile;
80
81 extern char *__progname; /* from crt0.s */
82 extern char *optarg;
83 extern int optind;
84
85 void usage __P((void));
86
87 void sig_child();
88 void sig_hup();
89
90 static
91 void _msgout(char* msg)
92 {
93 #ifdef RPC_SVC_FG
94 if (_rpcpmstart)
95 syslog(LOG_ERR, msg);
96 else
97 warnx("%s", msg);
98 #else
99 syslog(LOG_ERR, msg);
100 #endif
101 }
102
103 static void
104 closedown()
105 {
106 if (_rpcsvcdirty == 0) {
107 extern fd_set svc_fdset;
108 static int size;
109 int i, openfd;
110
111 if (_rpcfdtype == SOCK_DGRAM)
112 exit(0);
113 if (size == 0) {
114 size = getdtablesize();
115 }
116 for (i = 0, openfd = 0; i < size && openfd < 2; i++)
117 if (FD_ISSET(i, &svc_fdset))
118 openfd++;
119 if (openfd <= (_rpcpmstart?0:1))
120 exit(0);
121 }
122 (void) alarm(_RPCSVC_CLOSEDOWN);
123 }
124
125 static void
126 ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
127 {
128 union {
129 char * ypproc_domain_2_arg;
130 char * ypproc_domain_nonack_2_arg;
131 struct ypreq_key ypproc_match_2_arg;
132 struct ypreq_nokey ypproc_first_2_arg;
133 struct ypreq_key ypproc_next_2_arg;
134 struct ypreq_xfr ypproc_xfr_2_arg;
135 struct ypreq_nokey ypproc_all_2_arg;
136 struct ypreq_nokey ypproc_master_2_arg;
137 struct ypreq_nokey ypproc_order_2_arg;
138 char * ypproc_maplist_2_arg;
139 } argument;
140 char *result;
141 xdrproc_t xdr_argument, xdr_result;
142 void *(*local) __P((void *, struct svc_req *));
143
144 _rpcsvcdirty = 1;
145 switch (rqstp->rq_proc) {
146 case YPPROC_NULL:
147 xdr_argument = xdr_void;
148 xdr_result = xdr_void;
149 local = ypproc_null_2_svc;
150 break;
151
152 case YPPROC_DOMAIN:
153 xdr_argument = xdr_ypdomain_wrap_string;
154 xdr_result = xdr_bool;
155 local = ypproc_domain_2_svc;
156 break;
157
158 case YPPROC_DOMAIN_NONACK:
159 xdr_argument = xdr_ypdomain_wrap_string;
160 xdr_result = xdr_bool;
161 local = ypproc_domain_nonack_2_svc;
162 break;
163
164 case YPPROC_MATCH:
165 xdr_argument = xdr_ypreq_key;
166 xdr_result = xdr_ypresp_val;
167 local = ypproc_match_2_svc;
168 break;
169
170 case YPPROC_FIRST:
171 xdr_argument = xdr_ypreq_nokey;
172 xdr_result = xdr_ypresp_key_val;
173 local = ypproc_first_2_svc;
174 break;
175
176 case YPPROC_NEXT:
177 xdr_argument = xdr_ypreq_key;
178 xdr_result = xdr_ypresp_key_val;
179 local = ypproc_next_2_svc;
180 break;
181
182 case YPPROC_XFR:
183 xdr_argument = xdr_ypreq_xfr;
184 xdr_result = xdr_ypresp_xfr;
185 local = ypproc_xfr_2_svc;
186 break;
187
188 case YPPROC_CLEAR:
189 xdr_argument = xdr_void;
190 xdr_result = xdr_void;
191 local = ypproc_clear_2_svc;
192 break;
193
194 case YPPROC_ALL:
195 xdr_argument = xdr_ypreq_nokey;
196 xdr_result = xdr_ypresp_all;
197 local = ypproc_all_2_svc;
198 break;
199
200 case YPPROC_MASTER:
201 xdr_argument = xdr_ypreq_nokey;
202 xdr_result = xdr_ypresp_master;
203 local = ypproc_master_2_svc;
204 break;
205
206 case YPPROC_ORDER:
207 xdr_argument = xdr_ypreq_nokey;
208 xdr_result = xdr_ypresp_order;
209 local = ypproc_order_2_svc;
210 break;
211
212 case YPPROC_MAPLIST:
213 xdr_argument = xdr_ypdomain_wrap_string;
214 xdr_result = xdr_ypresp_maplist;
215 local = ypproc_maplist_2_svc;
216 break;
217
218 default:
219 svcerr_noproc(transp);
220 _rpcsvcdirty = 0;
221 return;
222 }
223 (void) memset((char *)&argument, 0, sizeof (argument));
224 if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) {
225 svcerr_decode(transp);
226 _rpcsvcdirty = 0;
227 return;
228 }
229 result = (*local)(&argument, rqstp);
230 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
231 svcerr_systemerr(transp);
232 }
233 if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) {
234 _msgout("unable to free arguments");
235 exit(1);
236 }
237 _rpcsvcdirty = 0;
238 return;
239 }
240
241 int
242 main(argc, argv)
243 int argc;
244 char **argv;
245 {
246 register SVCXPRT *transp;
247 int sock, proto;
248 struct sockaddr_in saddr;
249 int asize = sizeof(saddr);
250 int xflag = 0;
251 int ch;
252
253 while ((ch = getopt(argc, argv, "a:dx")) != -1) {
254 switch (ch) {
255 case 'a':
256 aclfile = optarg;
257 break;
258
259 case 'd':
260 usedns = 1;
261 break;
262
263 case 'x':
264 xflag = 1;
265 break;
266
267 default:
268 usage();
269 }
270 }
271
272 /* This program must be run by root. */
273 if (geteuid() != 0)
274 errx(1, "must run as root");
275
276 /* Deal with the acl file. */
277 acl_parse(aclfile);
278
279 if (xflag)
280 exit(1);
281
282 #ifndef RPC_SVC_FG
283 if (daemon(0, 0))
284 err(1, "can't detach");
285 openlog("ypserv", LOG_PID, LOG_DAEMON);
286 #endif
287
288 {
289 FILE *pidfile = fopen(YPSERV_PID_PATH, "w");
290
291 if (pidfile != NULL) {
292 fprintf(pidfile, "%d\n", getpid());
293 fclose(pidfile);
294 } else
295 err(1, "can't write PID file");
296 }
297
298 sock = RPC_ANYSOCK;
299 (void) pmap_unset(YPPROG, YPVERS);
300
301 ypopenlog(); /* open log file */
302 ypdb_init(); /* init db stuff */
303
304 (void)signal(SIGCHLD, sig_child);
305 (void)signal(SIGHUP, sig_hup);
306
307 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
308 transp = svcudp_create(sock);
309 if (transp == NULL) {
310 _msgout("cannot create udp service.");
311 exit(1);
312 }
313 if (!_rpcpmstart)
314 proto = IPPROTO_UDP;
315 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
316 _msgout("unable to register (YPPROG, YPVERS, udp).");
317 exit(1);
318 }
319 }
320
321 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
322 if (_rpcpmstart)
323 transp = svcfd_create(sock, 0, 0);
324 else
325 transp = svctcp_create(sock, 0, 0);
326 if (transp == NULL) {
327 _msgout("cannot create tcp service.");
328 exit(1);
329 }
330 if (!_rpcpmstart)
331 proto = IPPROTO_TCP;
332 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
333 _msgout("unable to register (YPPROG, YPVERS, tcp).");
334 exit(1);
335 }
336 }
337
338 if (transp == (SVCXPRT *)NULL) {
339 _msgout("could not create a handle");
340 exit(1);
341 }
342 if (_rpcpmstart) {
343 (void) signal(SIGALRM, (SIG_PF) closedown);
344 (void) alarm(_RPCSVC_CLOSEDOWN);
345 }
346 svc_run();
347 _msgout("svc_run returned");
348 exit(1);
349 /* NOTREACHED */
350 }
351
352 void
353 sig_child()
354 {
355
356 while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
357 }
358
359 void
360 sig_hup()
361 {
362
363 acl_reset();
364 yplog("sig_hup: reread %s", aclfile ? aclfile : YP_SECURENET_FILE);
365 acl_parse(aclfile);
366 }
367
368 void
369 usage()
370 {
371
372 fprintf(stderr, "usage: %s [-a aclfile] [-d] [-x]\n", __progname);
373 exit(1);
374 }
375