ypserv.c revision 1.2 1 /* $NetBSD: ypserv.c,v 1.2 1996/10/02 18:21:03 ws 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 {
283 FILE *pidfile = fopen(YPSERV_PID_PATH, "w");
284
285 if (pidfile != NULL) {
286 fprintf(pidfile, "%d\n", getpid());
287 fclose(pidfile);
288 } else
289 err(1, "can't write PID file");
290 }
291
292 #ifndef RPC_SVC_FG
293 if (daemon(0, 0))
294 err(1, "can't detatch");
295 openlog("ypserv", LOG_PID, LOG_DAEMON);
296 #endif
297 sock = RPC_ANYSOCK;
298 (void) pmap_unset(YPPROG, YPVERS);
299
300 ypopenlog(); /* open log file */
301 ypdb_init(); /* init db stuff */
302
303 (void)signal(SIGCHLD, sig_child);
304 (void)signal(SIGHUP, sig_hup);
305
306 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
307 transp = svcudp_create(sock);
308 if (transp == NULL) {
309 _msgout("cannot create udp service.");
310 exit(1);
311 }
312 if (!_rpcpmstart)
313 proto = IPPROTO_UDP;
314 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
315 _msgout("unable to register (YPPROG, YPVERS, udp).");
316 exit(1);
317 }
318 }
319
320 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
321 if (_rpcpmstart)
322 transp = svcfd_create(sock, 0, 0);
323 else
324 transp = svctcp_create(sock, 0, 0);
325 if (transp == NULL) {
326 _msgout("cannot create tcp service.");
327 exit(1);
328 }
329 if (!_rpcpmstart)
330 proto = IPPROTO_TCP;
331 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
332 _msgout("unable to register (YPPROG, YPVERS, tcp).");
333 exit(1);
334 }
335 }
336
337 if (transp == (SVCXPRT *)NULL) {
338 _msgout("could not create a handle");
339 exit(1);
340 }
341 if (_rpcpmstart) {
342 (void) signal(SIGALRM, (SIG_PF) closedown);
343 (void) alarm(_RPCSVC_CLOSEDOWN);
344 }
345 svc_run();
346 _msgout("svc_run returned");
347 exit(1);
348 /* NOTREACHED */
349 }
350
351 void
352 sig_child()
353 {
354
355 while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
356 }
357
358 void
359 sig_hup()
360 {
361
362 acl_reset();
363 yplog("sig_hup: reread %s", aclfile ? aclfile : YP_SECURENET_FILE);
364 acl_parse(aclfile);
365 }
366
367 void
368 usage()
369 {
370
371 fprintf(stderr, "usage: %s [-a aclfile] [-d] [-x]\n", __progname);
372 exit(1);
373 }
374