inetd.c revision 1.13 1 /* $NetBSD: inetd.c,v 1.13 1996/12/04 13:37:18 mrg Exp $ */
2 /*
3 * Copyright (c) 1983,1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #ifndef lint
36 char copyright[] =
37 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
38 All rights reserved.\n";
39 #endif /* not lint */
40
41 #ifndef lint
42 /*static char sccsid[] = "from: @(#)inetd.c 5.30 (Berkeley) 6/3/91";*/
43 static char rcsid[] = "$Id: inetd.c,v 1.13 1996/12/04 13:37:18 mrg Exp $";
44 #endif /* not lint */
45
46 /*
47 * Inetd - Internet super-server
48 *
49 * This program invokes all internet services as needed.
50 * connection-oriented services are invoked each time a
51 * connection is made, by creating a process. This process
52 * is passed the connection as file descriptor 0 and is
53 * expected to do a getpeername to find out the source host
54 * and port.
55 *
56 * Datagram oriented services are invoked when a datagram
57 * arrives; a process is created and passed a pending message
58 * on file descriptor 0. Datagram servers may either connect
59 * to their peer, freeing up the original socket for inetd
60 * to receive further messages on, or ``take over the socket'',
61 * processing all arriving datagrams and, eventually, timing
62 * out. The first type of server is said to be ``multi-threaded'';
63 * the second type of server ``single-threaded''.
64 *
65 * Inetd uses a configuration file which is read at startup
66 * and, possibly, at some later time in response to a hangup signal.
67 * The configuration file is ``free format'' with fields given in the
68 * order shown below. Continuation lines for an entry must being with
69 * a space or tab. All fields must be present in each entry.
70 *
71 * service name must be in /etc/services
72 * socket type stream/dgram/raw/rdm/seqpacket
73 * protocol must be in /etc/protocols
74 * wait/nowait[.max] single-threaded/multi-threaded, max #
75 * user[.group] user/group to run daemon as
76 * server program full path name
77 * server program arguments maximum of MAXARGS (20)
78 *
79 * For RPC services
80 * service name/version must be in /etc/rpc
81 * socket type stream/dgram/raw/rdm/seqpacket
82 * protocol must be in /etc/protocols
83 * wait/nowait[.max] single-threaded/multi-threaded
84 * user[.group] user to run daemon as
85 * server program full path name
86 * server program arguments maximum of MAXARGS (20)
87 *
88 * Comment lines are indicated by a `#' in column 1.
89 */
90
91 /*
92 * Here's the scoop concerning the user.group feature:
93 *
94 * 1) set-group-option off.
95 *
96 * a) user = root: NO setuid() or setgid() is done
97 *
98 * b) other: setuid()
99 * setgid(primary group as found in passwd)
100 * initgroups(name, primary group)
101 *
102 * 2) set-group-option on.
103 *
104 * a) user = root: NO setuid()
105 * setgid(specified group)
106 * NO initgroups()
107 *
108 * b) other: setuid()
109 * setgid(specified group)
110 * initgroups(name, specified group)
111 *
112 */
113
114 #include <sys/param.h>
115 #include <sys/stat.h>
116 #include <sys/ioctl.h>
117 #include <sys/socket.h>
118 #include <sys/un.h>
119 #include <sys/file.h>
120 #include <sys/wait.h>
121 #include <sys/time.h>
122 #include <sys/resource.h>
123
124 #ifndef RLIMIT_NOFILE
125 #define RLIMIT_NOFILE RLIMIT_OFILE
126 #endif
127
128 #define RPC
129
130 #include <netinet/in.h>
131 #include <arpa/inet.h>
132
133 #include <errno.h>
134 #include <signal.h>
135 #include <netdb.h>
136 #include <syslog.h>
137 #include <pwd.h>
138 #include <grp.h>
139 #include <stdio.h>
140 #include <stdlib.h>
141 #include <string.h>
142 #ifdef RPC
143 #include <rpc/rpc.h>
144 #endif
145 #include "pathnames.h"
146
147 #ifdef LIBWRAP
148 # include <tcpd.h>
149 #ifndef LIBWRAP_ALLOW_FACILITY
150 # define LIBWRAP_ALLOW_FACILITY 0 /* Don't modify our default */
151 #endif
152 #ifndef LIBWRAP_ALLOW_SEVERITY
153 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
154 #endif
155 #ifndef LIBWRAP_DENY_FACILITY
156 # define LIBWRAP_DENY_FACILITY 0 /* Don't modify our default */
157 #endif
158 #ifndef LIBWRAP_DENY_SEVERITY
159 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
160 #endif
161 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
162 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
163 #endif
164
165 #define TOOMANY 40 /* don't start more than TOOMANY */
166 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
167 #define RETRYTIME (60*10) /* retry after bind or server fail */
168
169 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
170
171 extern int errno;
172
173 void config(), reapchild(), retry(), goaway();
174 char *index();
175
176 int debug;
177 #ifdef LIBWRAP
178 int lflag;
179 #endif
180 int nsock, maxsock;
181 fd_set allsock;
182 int options;
183 int timingout;
184 struct servent *sp;
185 char *curdom;
186
187 #ifndef OPEN_MAX
188 #define OPEN_MAX 64
189 #endif
190
191 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
192 #define FD_MARGIN (8)
193 typeof(((struct rlimit *)0)->rlim_cur) rlim_ofile_cur = OPEN_MAX;
194
195 #ifdef RLIMIT_NOFILE
196 struct rlimit rlim_ofile;
197 #endif
198
199 struct servtab {
200 char *se_service; /* name of service */
201 int se_socktype; /* type of socket to use */
202 int se_family; /* address family */
203 char *se_proto; /* protocol used */
204 int se_rpcprog; /* rpc program number */
205 int se_rpcversl; /* rpc program lowest version */
206 int se_rpcversh; /* rpc program highest version */
207 #define isrpcservice(sep) ((sep)->se_rpcversl != 0)
208 short se_wait; /* single threaded server */
209 short se_checked; /* looked at during merge */
210 char *se_user; /* user name to run as */
211 char *se_group; /* group name to run as */
212 struct biltin *se_bi; /* if built-in, description */
213 char *se_server; /* server program */
214 #define MAXARGV 20
215 char *se_argv[MAXARGV+1]; /* program arguments */
216 int se_fd; /* open descriptor */
217 union {
218 struct sockaddr se_un_ctrladdr;
219 struct sockaddr_in se_un_ctrladdr_in;
220 struct sockaddr_un se_un_ctrladdr_un;
221 } se_un; /* bound address */
222 #define se_ctrladdr se_un.se_un_ctrladdr
223 #define se_ctrladdr_in se_un.se_un_ctrladdr_in
224 #define se_ctrladdr_un se_un.se_un_ctrladdr_un
225 int se_ctrladdr_size;
226 int se_max; /* max # of instances of this service */
227 int se_count; /* number started since se_time */
228 struct timeval se_time; /* start of se_count */
229 #ifdef MULOG
230 int se_log;
231 #define MULOG_RFC931 0x40000000
232 #endif
233 struct servtab *se_next;
234 } *servtab;
235
236 int echo_stream(), discard_stream(), machtime_stream();
237 int daytime_stream(), chargen_stream();
238 int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg();
239
240 struct biltin {
241 char *bi_service; /* internally provided service name */
242 int bi_socktype; /* type of socket supported */
243 short bi_fork; /* 1 if should fork before call */
244 short bi_wait; /* 1 if should wait for child */
245 int (*bi_fn)(); /* function which performs it */
246 } biltins[] = {
247 /* Echo received data */
248 "echo", SOCK_STREAM, 1, 0, echo_stream,
249 "echo", SOCK_DGRAM, 0, 0, echo_dg,
250
251 /* Internet /dev/null */
252 "discard", SOCK_STREAM, 1, 0, discard_stream,
253 "discard", SOCK_DGRAM, 0, 0, discard_dg,
254
255 /* Return 32 bit time since 1900 */
256 "time", SOCK_STREAM, 0, 0, machtime_stream,
257 "time", SOCK_DGRAM, 0, 0, machtime_dg,
258
259 /* Return human-readable time */
260 "daytime", SOCK_STREAM, 0, 0, daytime_stream,
261 "daytime", SOCK_DGRAM, 0, 0, daytime_dg,
262
263 /* Familiar character generator */
264 "chargen", SOCK_STREAM, 1, 0, chargen_stream,
265 "chargen", SOCK_DGRAM, 0, 0, chargen_dg,
266 0
267 };
268
269 #define NUMINT (sizeof(intab) / sizeof(struct inent))
270 char *CONFIG = _PATH_INETDCONF;
271 char **Argv;
272 char *LastArg;
273 char *progname;
274
275 #ifdef sun
276 /*
277 * Sun's RPC library caches the result of `dtablesize()'
278 * This is incompatible with our "bumping" of file descriptors "on demand"
279 */
280 int
281 _rpc_dtablesize()
282 {
283 return rlim_ofile_cur;
284 }
285 #endif
286
287 main(argc, argv, envp)
288 int argc;
289 char *argv[], *envp[];
290 {
291 extern char *optarg;
292 extern int optind;
293 register struct servtab *sep;
294 register struct passwd *pwd;
295 register struct group *grp;
296 register int tmpint;
297 struct sigvec sv;
298 int ch, pid, dofork;
299 char buf[50];
300 #ifdef LIBWRAP
301 struct request_info req;
302 char *service;
303 #endif
304
305 Argv = argv;
306 if (envp == 0 || *envp == 0)
307 envp = argv;
308 while (*envp)
309 envp++;
310 LastArg = envp[-1] + strlen(envp[-1]);
311
312 progname = strrchr(argv[0], '/');
313 progname = progname ? progname + 1 : argv[0];
314
315 while ((ch = getopt(argc, argv,
316 #ifdef LIBWRAP
317 "dl"
318 #else
319 "d"
320 #endif
321 )) != EOF)
322 switch(ch) {
323 case 'd':
324 debug = 1;
325 options |= SO_DEBUG;
326 break;
327 #ifdef LIBWRAP
328 case 'l':
329 lflag = 1;
330 break;
331 #endif
332 case '?':
333 default:
334 fprintf(stderr, "usage: %s [-d] [conf]", progname);
335 exit(1);
336 }
337 argc -= optind;
338 argv += optind;
339
340 if (argc > 0)
341 CONFIG = argv[0];
342
343 if (debug == 0)
344 daemon(0, 0);
345 openlog(progname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
346 logpid();
347
348 #ifdef RLIMIT_NOFILE
349 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
350 syslog(LOG_ERR, "getrlimit: %m");
351 } else {
352 rlim_ofile_cur = rlim_ofile.rlim_cur;
353 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */
354 rlim_ofile_cur = OPEN_MAX;
355 }
356 #endif
357
358 bzero((char *)&sv, sizeof(sv));
359 sv.sv_mask = SIGBLOCK;
360 sv.sv_handler = retry;
361 sigvec(SIGALRM, &sv, (struct sigvec *)0);
362 config();
363 sv.sv_handler = config;
364 sigvec(SIGHUP, &sv, (struct sigvec *)0);
365 sv.sv_handler = reapchild;
366 sigvec(SIGCHLD, &sv, (struct sigvec *)0);
367 sv.sv_handler = goaway;
368 sigvec(SIGTERM, &sv, (struct sigvec *)0);
369 sv.sv_handler = goaway;
370 sigvec(SIGINT, &sv, (struct sigvec *)0);
371
372 {
373 /* space for daemons to overwrite environment for ps */
374 #define DUMMYSIZE 100
375 char dummy[DUMMYSIZE];
376
377 (void)memset(dummy, 'x', DUMMYSIZE - 1);
378 dummy[DUMMYSIZE - 1] = '\0';
379
380 (void)setenv("inetd_dummy", dummy, 1);
381 }
382
383 for (;;) {
384 int n, ctrl;
385 fd_set readable;
386
387 if (nsock == 0) {
388 (void) sigblock(SIGBLOCK);
389 while (nsock == 0)
390 sigpause(0L);
391 (void) sigsetmask(0L);
392 }
393 readable = allsock;
394 if ((n = select(maxsock + 1, &readable, (fd_set *)0,
395 (fd_set *)0, (struct timeval *)0)) <= 0) {
396 if (n < 0 && errno != EINTR)
397 syslog(LOG_WARNING, "select: %m\n");
398 sleep(1);
399 continue;
400 }
401 for (sep = servtab; n && sep; sep = sep->se_next)
402 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
403 n--;
404 if (debug)
405 fprintf(stderr, "someone wants %s\n", sep->se_service);
406 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
407 /* XXX here do the libwrap check-before-accept */
408 ctrl = accept(sep->se_fd, (struct sockaddr *)0,
409 (int *)0);
410 if (debug)
411 fprintf(stderr, "accept, ctrl %d\n", ctrl);
412 if (ctrl < 0) {
413 if (errno == EINTR)
414 continue;
415 syslog(LOG_WARNING, "accept (for %s): %m",
416 sep->se_service);
417 continue;
418 }
419 #ifdef LIBWRAP
420 request_init(&req, RQ_DAEMON, sep->se_argv[0], RQ_FILE, ctrl, NULL);
421 fromhost(&req);
422 if (!hosts_access(&req)) {
423 sp = getservbyport(sep->se_ctrladdr_in.sin_port, sep->se_proto);
424 if (sp == NULL) {
425 (void)snprintf(buf, sizeof buf, "%d",
426 ntohs(sep->se_ctrladdr_in.sin_port));
427 service = buf;
428 } else
429 service = sp->s_name;
430 syslog(LOG_WARNING,
431 "refused connection from %.500s, service %s (%s)",
432 eval_client(&req), service, sep->se_proto);
433 shutdown(ctrl, 2);
434 close(ctrl);
435 continue;
436 }
437 if (lflag) {
438 sp = getservbyport(sep->se_ctrladdr_in.sin_port, sep->se_proto);
439 if (sp == NULL) {
440 (void)snprintf(buf, sizeof buf, "%d",
441 ntohs(sep->se_ctrladdr_in.sin_port));
442 service = buf;
443 } else
444 service = sp->s_name;
445 syslog(LOG_INFO, "connection from %.500s, service %s (%s)",
446 eval_client(&req), service, sep->se_proto);
447 }
448 #endif /* LIBWRAP */
449 } else
450 ctrl = sep->se_fd;
451 (void) sigblock(SIGBLOCK);
452 pid = 0;
453 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
454 if (dofork) {
455 if (sep->se_count++ == 0)
456 (void)gettimeofday(&sep->se_time,
457 (struct timezone *)0);
458 else if (sep->se_count >= sep->se_max) {
459 struct timeval now;
460
461 (void)gettimeofday(&now, (struct timezone *)0);
462 if (now.tv_sec - sep->se_time.tv_sec >
463 CNT_INTVL) {
464 sep->se_time = now;
465 sep->se_count = 1;
466 } else {
467 syslog(LOG_ERR,
468 "%s/%s server failing (looping), service terminated\n",
469 sep->se_service, sep->se_proto);
470 FD_CLR(sep->se_fd, &allsock);
471 (void) close(sep->se_fd);
472 sep->se_fd = -1;
473 sep->se_count = 0;
474 nsock--;
475 sigsetmask(0L);
476 if (!timingout) {
477 timingout = 1;
478 alarm(RETRYTIME);
479 }
480 continue;
481 }
482 }
483 pid = fork();
484 }
485 if (pid < 0) {
486 syslog(LOG_ERR, "fork: %m");
487 if (sep->se_socktype == SOCK_STREAM)
488 close(ctrl);
489 sigsetmask(0L);
490 sleep(1);
491 continue;
492 }
493 if (pid && sep->se_wait) {
494 sep->se_wait = pid;
495 FD_CLR(sep->se_fd, &allsock);
496 nsock--;
497 }
498 sigsetmask(0L);
499 if (pid == 0) {
500 if (debug && dofork)
501 setsid();
502 if (sep->se_bi)
503 (*sep->se_bi->bi_fn)(ctrl, sep);
504 else {
505 if ((pwd = getpwnam(sep->se_user)) == NULL) {
506 syslog(LOG_ERR,
507 "getpwnam: %s: No such user",
508 sep->se_user);
509 if (sep->se_socktype != SOCK_STREAM)
510 recv(0, buf, sizeof (buf), 0);
511 _exit(1);
512 }
513 if (sep->se_group &&
514 (grp = getgrnam(sep->se_group)) == NULL) {
515 syslog(LOG_ERR,
516 "getgrnam: %s: No such group",
517 sep->se_group);
518 if (sep->se_socktype != SOCK_STREAM)
519 recv(0, buf, sizeof (buf), 0);
520 _exit(1);
521 }
522 if (pwd->pw_uid) {
523 if (sep->se_group)
524 pwd->pw_gid = grp->gr_gid;
525 (void) setgid((gid_t)pwd->pw_gid);
526 initgroups(pwd->pw_name, pwd->pw_gid);
527 (void) setuid((uid_t)pwd->pw_uid);
528 } else if (sep->se_group) {
529 (void) setgid((gid_t)grp->gr_gid);
530 }
531 if (debug)
532 fprintf(stderr, "%d execl %s\n",
533 getpid(), sep->se_server);
534 #ifdef MULOG
535 if (sep->se_log)
536 dolog(sep, ctrl);
537 #endif
538 dup2(ctrl, 0);
539 close(ctrl);
540 dup2(0, 1);
541 dup2(0, 2);
542 #ifdef RLIMIT_NOFILE
543 if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
544 if (setrlimit(RLIMIT_NOFILE,
545 &rlim_ofile) < 0)
546 syslog(LOG_ERR,"setrlimit: %m");
547 }
548 #endif
549 for (tmpint = rlim_ofile_cur-1; --tmpint > 2; )
550 (void)close(tmpint);
551 execv(sep->se_server, sep->se_argv);
552 if (sep->se_socktype != SOCK_STREAM)
553 recv(0, buf, sizeof (buf), 0);
554 syslog(LOG_ERR, "execv %s: %m", sep->se_server);
555 _exit(1);
556 }
557 }
558 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
559 close(ctrl);
560 }
561 }
562 }
563
564 void
565 reapchild()
566 {
567 int status;
568 int pid;
569 register struct servtab *sep;
570
571 for (;;) {
572 pid = wait3(&status, WNOHANG, (struct rusage *)0);
573 if (pid <= 0)
574 break;
575 if (debug)
576 fprintf(stderr, "%d reaped\n", pid);
577 for (sep = servtab; sep; sep = sep->se_next)
578 if (sep->se_wait == pid) {
579 if (WIFEXITED(status) && WEXITSTATUS(status))
580 syslog(LOG_WARNING,
581 "%s: exit status 0x%x",
582 sep->se_server, WEXITSTATUS(status));
583 else if (WIFSIGNALED(status))
584 syslog(LOG_WARNING,
585 "%s: exit signal 0x%x",
586 sep->se_server, WTERMSIG(status));
587 sep->se_wait = 1;
588 FD_SET(sep->se_fd, &allsock);
589 nsock++;
590 if (debug)
591 fprintf(stderr, "restored %s, fd %d\n",
592 sep->se_service, sep->se_fd);
593 }
594 }
595 }
596
597 void
598 config()
599 {
600 register struct servtab *sep, *cp, **sepp;
601 struct servtab *getconfigent(), *enter();
602 long omask;
603 int n;
604
605 if (!setconfig()) {
606 syslog(LOG_ERR, "%s: %m", CONFIG);
607 return;
608 }
609 for (sep = servtab; sep; sep = sep->se_next)
610 sep->se_checked = 0;
611 while (cp = getconfigent()) {
612 for (sep = servtab; sep; sep = sep->se_next)
613 if (strcmp(sep->se_service, cp->se_service) == 0 &&
614 strcmp(sep->se_proto, cp->se_proto) == 0)
615 break;
616 if (sep != 0) {
617 int i;
618
619 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;}
620
621 omask = sigblock(SIGBLOCK);
622 /*
623 * sep->se_wait may be holding the pid of a daemon
624 * that we're waiting for. If so, don't overwrite
625 * it unless the config file explicitly says don't
626 * wait.
627 */
628 if (cp->se_bi == 0 &&
629 (sep->se_wait == 1 || cp->se_wait == 0))
630 sep->se_wait = cp->se_wait;
631 SWAP(int, cp->se_max, sep->se_max);
632 SWAP(char *, sep->se_user, cp->se_user);
633 SWAP(char *, sep->se_group, cp->se_group);
634 SWAP(char *, sep->se_server, cp->se_server);
635 for (i = 0; i < MAXARGV; i++)
636 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
637 #undef SWAP
638 if (isrpcservice(sep))
639 unregister_rpc(sep);
640 sep->se_rpcversl = cp->se_rpcversl;
641 sep->se_rpcversh = cp->se_rpcversh;
642 sigsetmask(omask);
643 freeconfig(cp);
644 if (debug)
645 print_service("REDO", sep);
646 } else {
647 sep = enter(cp);
648 if (debug)
649 print_service("ADD ", sep);
650 }
651 sep->se_checked = 1;
652
653 switch (sep->se_family) {
654 case AF_UNIX:
655 if (sep->se_fd != -1)
656 break;
657 (void)unlink(sep->se_service);
658 n = strlen(sep->se_service);
659 if (n > sizeof sep->se_ctrladdr_un.sun_path - 1)
660 n = sizeof sep->se_ctrladdr_un.sun_path - 1;
661 strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n);
662 sep->se_ctrladdr_un.sun_family = AF_UNIX;
663 sep->se_ctrladdr_size = n +
664 sizeof sep->se_ctrladdr_un.sun_family;
665 setup(sep);
666 break;
667 case AF_INET:
668 sep->se_ctrladdr_in.sin_family = AF_INET;
669 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
670 if (isrpcservice(sep)) {
671 struct rpcent *rp;
672
673 sep->se_rpcprog = atoi(sep->se_service);
674 if (sep->se_rpcprog == 0) {
675 rp = getrpcbyname(sep->se_service);
676 if (rp == 0) {
677 syslog(LOG_ERR,
678 "%s: unknown service",
679 sep->se_service);
680 continue;
681 }
682 sep->se_rpcprog = rp->r_number;
683 }
684 if (sep->se_fd == -1)
685 setup(sep);
686 if (sep->se_fd != -1)
687 register_rpc(sep);
688 } else {
689 u_short port = htons(atoi(sep->se_service));
690
691 if (!port) {
692 sp = getservbyname(sep->se_service,
693 sep->se_proto);
694 if (sp == 0) {
695 syslog(LOG_ERR,
696 "%s/%s: unknown service",
697 sep->se_service, sep->se_proto);
698 continue;
699 }
700 port = sp->s_port;
701 }
702 if (port != sep->se_ctrladdr_in.sin_port) {
703 sep->se_ctrladdr_in.sin_port = port;
704 if (sep->se_fd != -1) {
705 FD_CLR(sep->se_fd, &allsock);
706 nsock--;
707 (void) close(sep->se_fd);
708 }
709 sep->se_fd = -1;
710 }
711 if (sep->se_fd == -1)
712 setup(sep);
713 }
714 }
715 }
716 endconfig();
717 /*
718 * Purge anything not looked at above.
719 */
720 omask = sigblock(SIGBLOCK);
721 sepp = &servtab;
722 while (sep = *sepp) {
723 if (sep->se_checked) {
724 sepp = &sep->se_next;
725 continue;
726 }
727 *sepp = sep->se_next;
728 if (sep->se_fd != -1) {
729 FD_CLR(sep->se_fd, &allsock);
730 nsock--;
731 (void) close(sep->se_fd);
732 }
733 if (isrpcservice(sep))
734 unregister_rpc(sep);
735 if (sep->se_family == AF_UNIX)
736 (void)unlink(sep->se_service);
737 if (debug)
738 print_service("FREE", sep);
739 freeconfig(sep);
740 free((char *)sep);
741 }
742 (void) sigsetmask(omask);
743 }
744
745 void
746 retry()
747 {
748 register struct servtab *sep;
749
750 timingout = 0;
751 for (sep = servtab; sep; sep = sep->se_next) {
752 if (sep->se_fd == -1) {
753 switch (sep->se_family) {
754 case AF_UNIX:
755 case AF_INET:
756 setup(sep);
757 if (sep->se_fd != -1 && isrpcservice(sep))
758 register_rpc(sep);
759 break;
760 }
761 }
762 }
763 }
764
765 void
766 goaway()
767 {
768 register struct servtab *sep;
769
770 for (sep = servtab; sep; sep = sep->se_next) {
771 if (sep->se_fd == -1)
772 continue;
773
774 switch (sep->se_family) {
775 case AF_UNIX:
776 (void)unlink(sep->se_service);
777 break;
778 case AF_INET:
779 if (sep->se_wait == 1 && isrpcservice(sep))
780 unregister_rpc(sep);
781 break;
782 }
783 (void)close(sep->se_fd);
784 }
785 (void)unlink(_PATH_INETDPID);
786 exit(0);
787 }
788
789
790 setup(sep)
791 register struct servtab *sep;
792 {
793 int on = 1;
794
795 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
796 syslog(LOG_ERR, "%s/%s: socket: %m",
797 sep->se_service, sep->se_proto);
798 return;
799 }
800 #define turnon(fd, opt) \
801 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
802 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
803 turnon(sep->se_fd, SO_DEBUG) < 0)
804 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
805 if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
806 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
807 #undef turnon
808 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
809 syslog(LOG_ERR, "%s/%s: bind: %m",
810 sep->se_service, sep->se_proto);
811 (void) close(sep->se_fd);
812 sep->se_fd = -1;
813 if (!timingout) {
814 timingout = 1;
815 alarm(RETRYTIME);
816 }
817 return;
818 }
819 if (sep->se_socktype == SOCK_STREAM)
820 listen(sep->se_fd, 10);
821
822 FD_SET(sep->se_fd, &allsock);
823 nsock++;
824 if (sep->se_fd > maxsock) {
825 maxsock = sep->se_fd;
826 if (maxsock > rlim_ofile_cur - FD_MARGIN)
827 bump_nofile();
828 }
829 }
830
831 register_rpc(sep)
832 register struct servtab *sep;
833 {
834 #ifdef RPC
835 int n;
836 struct sockaddr_in sin;
837 struct protoent *pp;
838
839 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) {
840 syslog(LOG_ERR, "%s: getproto: %m",
841 sep->se_proto);
842 return;
843 }
844 n = sizeof sin;
845 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) {
846 syslog(LOG_ERR, "%s/%s: getsockname: %m",
847 sep->se_service, sep->se_proto);
848 return;
849 }
850
851 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
852 if (debug)
853 fprintf(stderr, "pmap_set: %u %u %u %u\n",
854 sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port));
855 (void)pmap_unset(sep->se_rpcprog, n);
856 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port)))
857 syslog(LOG_ERR, "pmap_set: %u %u %u %u: %m",
858 sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port));
859 }
860 #endif /* RPC */
861 }
862
863 unregister_rpc(sep)
864 register struct servtab *sep;
865 {
866 #ifdef RPC
867 int n;
868
869 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
870 if (debug)
871 fprintf(stderr, "pmap_unset(%u, %u)\n",
872 sep->se_rpcprog, n);
873 if (!pmap_unset(sep->se_rpcprog, n))
874 syslog(LOG_ERR, "pmap_unset(%u, %u)\n",
875 sep->se_rpcprog, n);
876 }
877 #endif /* RPC */
878 }
879
880
881 struct servtab *
882 enter(cp)
883 struct servtab *cp;
884 {
885 register struct servtab *sep;
886 long omask;
887
888 sep = (struct servtab *)malloc(sizeof (*sep));
889 if (sep == (struct servtab *)0) {
890 syslog(LOG_ERR, "Out of memory.");
891 exit(-1);
892 }
893 *sep = *cp;
894 sep->se_fd = -1;
895 sep->se_rpcprog = -1;
896 omask = sigblock(SIGBLOCK);
897 sep->se_next = servtab;
898 servtab = sep;
899 sigsetmask(omask);
900 return (sep);
901 }
902
903 FILE *fconfig = NULL;
904 struct servtab serv;
905 char line[256];
906 char *skip(), *nextline();
907
908 setconfig()
909 {
910
911 if (fconfig != NULL) {
912 fseek(fconfig, 0L, L_SET);
913 return (1);
914 }
915 fconfig = fopen(CONFIG, "r");
916 return (fconfig != NULL);
917 }
918
919 endconfig()
920 {
921 if (fconfig) {
922 (void) fclose(fconfig);
923 fconfig = NULL;
924 }
925 }
926
927 struct servtab *
928 getconfigent()
929 {
930 register struct servtab *sep = &serv;
931 int argc;
932 char *cp, *arg, *newstr();
933
934 more:
935 #ifdef MULOG
936 while ((cp = nextline(fconfig)) && *cp == '#') {
937 /* Avoid use of `skip' if there is a danger of it looking
938 * at continuation lines.
939 */
940 do {
941 cp++;
942 } while (*cp == ' ' || *cp == '\t');
943 if (*cp == '\0')
944 continue;
945 if ((arg = skip(&cp)) == NULL)
946 continue;
947 if (strcmp(arg, "DOMAIN"))
948 continue;
949 if (curdom)
950 free(curdom);
951 curdom = NULL;
952 while (*cp == ' ' || *cp == '\t')
953 cp++;
954 if (*cp == '\0')
955 continue;
956 arg = cp;
957 while (*cp && *cp != ' ' && *cp != '\t')
958 cp++;
959 if (*cp != '\0')
960 *cp++ = '\0';
961 curdom = newstr(arg);
962 }
963 #else
964 while ((cp = nextline(fconfig)) && *cp == '#')
965 ;
966 #endif
967 if (cp == NULL)
968 return ((struct servtab *)0);
969 bzero((char *)sep, sizeof *sep);
970 sep->se_service = newstr(skip(&cp));
971 arg = skip(&cp);
972 if (arg == NULL)
973 goto more;
974
975 if (strcmp(arg, "stream") == 0)
976 sep->se_socktype = SOCK_STREAM;
977 else if (strcmp(arg, "dgram") == 0)
978 sep->se_socktype = SOCK_DGRAM;
979 else if (strcmp(arg, "rdm") == 0)
980 sep->se_socktype = SOCK_RDM;
981 else if (strcmp(arg, "seqpacket") == 0)
982 sep->se_socktype = SOCK_SEQPACKET;
983 else if (strcmp(arg, "raw") == 0)
984 sep->se_socktype = SOCK_RAW;
985 else
986 sep->se_socktype = -1;
987
988 sep->se_proto = newstr(skip(&cp));
989 if (strcmp(sep->se_proto, "unix") == 0) {
990 sep->se_family = AF_UNIX;
991 } else {
992 sep->se_family = AF_INET;
993 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
994 #ifdef RPC
995 char *cp, *ccp;
996 cp = index(sep->se_service, '/');
997 if (cp == 0) {
998 syslog(LOG_ERR, "%s: no rpc version",
999 sep->se_service);
1000 goto more;
1001 }
1002 *cp++ = '\0';
1003 sep->se_rpcversl =
1004 sep->se_rpcversh = strtol(cp, &ccp, 0);
1005 if (ccp == cp) {
1006 badafterall:
1007 syslog(LOG_ERR, "%s/%s: bad rpc version",
1008 sep->se_service, cp);
1009 goto more;
1010 }
1011 if (*ccp == '-') {
1012 cp = ccp + 1;
1013 sep->se_rpcversh = strtol(cp, &ccp, 0);
1014 if (ccp == cp)
1015 goto badafterall;
1016 }
1017 #else
1018 syslog(LOG_ERR, "%s: rpc services not suported",
1019 sep->se_service);
1020 goto more;
1021 #endif /* RPC */
1022 }
1023 }
1024 arg = skip(&cp);
1025 if (arg == NULL)
1026 goto more;
1027 {
1028 char *s = index(arg, '.');
1029 if (s) {
1030 *s++ = '\0';
1031 sep->se_max = atoi(s);
1032 } else
1033 sep->se_max = TOOMANY;
1034 }
1035 sep->se_wait = strcmp(arg, "wait") == 0;
1036 sep->se_user = newstr(skip(&cp));
1037 if (sep->se_group = index(sep->se_user, '.')) {
1038 *sep->se_group++ = '\0';
1039 }
1040 sep->se_server = newstr(skip(&cp));
1041 if (strcmp(sep->se_server, "internal") == 0) {
1042 register struct biltin *bi;
1043
1044 for (bi = biltins; bi->bi_service; bi++)
1045 if (bi->bi_socktype == sep->se_socktype &&
1046 strcmp(bi->bi_service, sep->se_service) == 0)
1047 break;
1048 if (bi->bi_service == 0) {
1049 syslog(LOG_ERR, "internal service %s unknown\n",
1050 sep->se_service);
1051 goto more;
1052 }
1053 sep->se_bi = bi;
1054 sep->se_wait = bi->bi_wait;
1055 } else
1056 sep->se_bi = NULL;
1057 argc = 0;
1058 for (arg = skip(&cp); cp; arg = skip(&cp)) {
1059 #if MULOG
1060 char *colon, *rindex();
1061
1062 if (argc == 0 && (colon = rindex(arg, ':'))) {
1063 while (arg < colon) {
1064 int x;
1065 char *ccp;
1066
1067 switch (*arg++) {
1068 case 'l':
1069 x = 1;
1070 if (isdigit(*arg)) {
1071 x = strtol(arg, &ccp, 0);
1072 if (ccp == arg)
1073 break;
1074 arg = ccp;
1075 }
1076 sep->se_log &= ~MULOG_RFC931;
1077 sep->se_log |= x;
1078 break;
1079 case 'a':
1080 sep->se_log |= MULOG_RFC931;
1081 break;
1082 default:
1083 break;
1084 }
1085 }
1086 arg = colon + 1;
1087 }
1088 #endif
1089 if (argc < MAXARGV)
1090 sep->se_argv[argc++] = newstr(arg);
1091 }
1092 while (argc <= MAXARGV)
1093 sep->se_argv[argc++] = NULL;
1094 return (sep);
1095 }
1096
1097 freeconfig(cp)
1098 register struct servtab *cp;
1099 {
1100 int i;
1101
1102 if (cp->se_service)
1103 free(cp->se_service);
1104 if (cp->se_proto)
1105 free(cp->se_proto);
1106 if (cp->se_user)
1107 free(cp->se_user);
1108 /* Note: se_group is part of the newstr'ed se_user */
1109 if (cp->se_server)
1110 free(cp->se_server);
1111 for (i = 0; i < MAXARGV; i++)
1112 if (cp->se_argv[i])
1113 free(cp->se_argv[i]);
1114 }
1115
1116 char *
1117 skip(cpp)
1118 char **cpp;
1119 {
1120 register char *cp = *cpp;
1121 char *start;
1122
1123 if (*cpp == NULL)
1124 return ((char *)0);
1125
1126 again:
1127 while (*cp == ' ' || *cp == '\t')
1128 cp++;
1129 if (*cp == '\0') {
1130 int c;
1131
1132 c = getc(fconfig);
1133 (void) ungetc(c, fconfig);
1134 if (c == ' ' || c == '\t')
1135 if (cp = nextline(fconfig))
1136 goto again;
1137 *cpp = (char *)0;
1138 return ((char *)0);
1139 }
1140 start = cp;
1141 while (*cp && *cp != ' ' && *cp != '\t')
1142 cp++;
1143 if (*cp != '\0')
1144 *cp++ = '\0';
1145 *cpp = cp;
1146 return (start);
1147 }
1148
1149 char *
1150 nextline(fd)
1151 FILE *fd;
1152 {
1153 char *cp;
1154
1155 if (fgets(line, sizeof (line), fd) == NULL)
1156 return ((char *)0);
1157 cp = index(line, '\n');
1158 if (cp)
1159 *cp = '\0';
1160 return (line);
1161 }
1162
1163 char *
1164 newstr(cp)
1165 char *cp;
1166 {
1167 if (cp = strdup(cp ? cp : ""))
1168 return(cp);
1169 syslog(LOG_ERR, "strdup: %m");
1170 exit(-1);
1171 }
1172
1173 inetd_setproctitle(a, s)
1174 char *a;
1175 int s;
1176 {
1177 int size;
1178 register char *cp;
1179 struct sockaddr_in sin;
1180 char buf[80];
1181
1182 cp = Argv[0];
1183 size = sizeof(sin);
1184 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1185 (void)snprintf(buf, sizeof buf, "-%s [%s]", a,
1186 inet_ntoa(sin.sin_addr));
1187 else
1188 (void)snprintf(buf, sizeof buf, "-%s", a);
1189 strncpy(cp, buf, LastArg - cp);
1190 cp += strlen(cp);
1191 while (cp < LastArg)
1192 *cp++ = ' ';
1193 }
1194
1195 logpid()
1196 {
1197 FILE *fp;
1198
1199 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) {
1200 fprintf(fp, "%u\n", getpid());
1201 (void)fclose(fp);
1202 }
1203 }
1204
1205 bump_nofile()
1206 {
1207 #ifdef RLIMIT_NOFILE
1208
1209 #define FD_CHUNK 32
1210
1211 struct rlimit rl;
1212
1213 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1214 syslog(LOG_ERR, "getrlimit: %m");
1215 return -1;
1216 }
1217 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1218 if (rl.rlim_cur <= rlim_ofile_cur) {
1219 syslog(LOG_ERR,
1220 "bump_nofile: cannot extend file limit, max = %d",
1221 rl.rlim_cur);
1222 return -1;
1223 }
1224
1225 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1226 syslog(LOG_ERR, "setrlimit: %m");
1227 return -1;
1228 }
1229
1230 rlim_ofile_cur = rl.rlim_cur;
1231 return 0;
1232
1233 #else
1234 syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
1235 return -1;
1236 #endif
1237 }
1238
1239 /*
1240 * Internet services provided internally by inetd:
1241 */
1242 #define BUFSIZE 4096
1243
1244 /* ARGSUSED */
1245 echo_stream(s, sep) /* Echo service -- echo data back */
1246 int s;
1247 struct servtab *sep;
1248 {
1249 char buffer[BUFSIZE];
1250 int i;
1251
1252 inetd_setproctitle(sep->se_service, s);
1253 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1254 write(s, buffer, i) > 0)
1255 ;
1256 exit(0);
1257 }
1258
1259 /* ARGSUSED */
1260 echo_dg(s, sep) /* Echo service -- echo data back */
1261 int s;
1262 struct servtab *sep;
1263 {
1264 char buffer[BUFSIZE];
1265 int i, size;
1266 struct sockaddr sa;
1267
1268 size = sizeof(sa);
1269 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
1270 return;
1271 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
1272 }
1273
1274 /* ARGSUSED */
1275 discard_stream(s, sep) /* Discard service -- ignore data */
1276 int s;
1277 struct servtab *sep;
1278 {
1279 char buffer[BUFSIZE];
1280
1281 inetd_setproctitle(sep->se_service, s);
1282 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1283 errno == EINTR)
1284 ;
1285 exit(0);
1286 }
1287
1288 /* ARGSUSED */
1289 discard_dg(s, sep) /* Discard service -- ignore data */
1290 int s;
1291 struct servtab *sep;
1292 {
1293 char buffer[BUFSIZE];
1294
1295 (void) read(s, buffer, sizeof(buffer));
1296 }
1297
1298 #include <ctype.h>
1299 #define LINESIZ 72
1300 char ring[128];
1301 char *endring;
1302
1303 initring()
1304 {
1305 register int i;
1306
1307 endring = ring;
1308
1309 for (i = 0; i <= 128; ++i)
1310 if (isprint(i))
1311 *endring++ = i;
1312 }
1313
1314 /* ARGSUSED */
1315 chargen_stream(s, sep) /* Character generator */
1316 int s;
1317 struct servtab *sep;
1318 {
1319 register char *rs;
1320 int len;
1321 char text[LINESIZ+2];
1322
1323 inetd_setproctitle(sep->se_service, s);
1324
1325 if (!endring) {
1326 initring();
1327 rs = ring;
1328 }
1329
1330 text[LINESIZ] = '\r';
1331 text[LINESIZ + 1] = '\n';
1332 for (rs = ring;;) {
1333 if ((len = endring - rs) >= LINESIZ)
1334 bcopy(rs, text, LINESIZ);
1335 else {
1336 bcopy(rs, text, len);
1337 bcopy(ring, text + len, LINESIZ - len);
1338 }
1339 if (++rs == endring)
1340 rs = ring;
1341 if (write(s, text, sizeof(text)) != sizeof(text))
1342 break;
1343 }
1344 exit(0);
1345 }
1346
1347 /* ARGSUSED */
1348 chargen_dg(s, sep) /* Character generator */
1349 int s;
1350 struct servtab *sep;
1351 {
1352 struct sockaddr sa;
1353 static char *rs;
1354 int len, size;
1355 char text[LINESIZ+2];
1356
1357 if (endring == 0) {
1358 initring();
1359 rs = ring;
1360 }
1361
1362 size = sizeof(sa);
1363 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
1364 return;
1365
1366 if ((len = endring - rs) >= LINESIZ)
1367 bcopy(rs, text, LINESIZ);
1368 else {
1369 bcopy(rs, text, len);
1370 bcopy(ring, text + len, LINESIZ - len);
1371 }
1372 if (++rs == endring)
1373 rs = ring;
1374 text[LINESIZ] = '\r';
1375 text[LINESIZ + 1] = '\n';
1376 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
1377 }
1378
1379 /*
1380 * Return a machine readable date and time, in the form of the
1381 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1382 * returns the number of seconds since midnight, Jan 1, 1970,
1383 * we must add 2208988800 seconds to this figure to make up for
1384 * some seventy years Bell Labs was asleep.
1385 */
1386
1387 long
1388 machtime()
1389 {
1390 struct timeval tv;
1391
1392 if (gettimeofday(&tv, (struct timezone *)0) < 0) {
1393 fprintf(stderr, "Unable to get time of day\n");
1394 return (0L);
1395 }
1396 return (htonl((long)tv.tv_sec + 2208988800UL));
1397 }
1398
1399 /* ARGSUSED */
1400 machtime_stream(s, sep)
1401 int s;
1402 struct servtab *sep;
1403 {
1404 long result;
1405
1406 result = machtime();
1407 (void) write(s, (char *) &result, sizeof(result));
1408 }
1409
1410 /* ARGSUSED */
1411 machtime_dg(s, sep)
1412 int s;
1413 struct servtab *sep;
1414 {
1415 long result;
1416 struct sockaddr sa;
1417 int size;
1418
1419 size = sizeof(sa);
1420 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
1421 return;
1422 result = machtime();
1423 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
1424 }
1425
1426 /* ARGSUSED */
1427 daytime_stream(s, sep) /* Return human-readable time of day */
1428 int s;
1429 struct servtab *sep;
1430 {
1431 char buffer[256];
1432 time_t time(), clock;
1433 int len;
1434
1435 clock = time((time_t *) 0);
1436
1437 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1438 (void) write(s, buffer, len);
1439 }
1440
1441 /* ARGSUSED */
1442 daytime_dg(s, sep) /* Return human-readable time of day */
1443 int s;
1444 struct servtab *sep;
1445 {
1446 char buffer[256];
1447 time_t time(), clock;
1448 struct sockaddr sa;
1449 int size;
1450
1451 clock = time((time_t *) 0);
1452
1453 size = sizeof(sa);
1454 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
1455 return;
1456 size = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock));
1457 (void) sendto(s, buffer, size, 0, &sa, sizeof(sa));
1458 }
1459
1460 /*
1461 * print_service:
1462 * Dump relevant information to stderr
1463 */
1464 print_service(action, sep)
1465 char *action;
1466 struct servtab *sep;
1467 {
1468 if (isrpcservice(sep))
1469 fprintf(stderr,
1470 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n",
1471 action, sep->se_service,
1472 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
1473 sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
1474 (long)sep->se_bi, sep->se_server);
1475 else
1476 fprintf(stderr,
1477 "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n",
1478 action, sep->se_service, sep->se_proto,
1479 sep->se_wait, sep->se_max, sep->se_user, sep->se_group,
1480 (long)sep->se_bi, sep->se_server);
1481 }
1482
1483 #ifdef MULOG
1484 dolog(sep, ctrl)
1485 struct servtab *sep;
1486 int ctrl;
1487 {
1488 struct sockaddr sa;
1489 struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
1490 int len = sizeof(sa);
1491 struct hostent *hp;
1492 char *host, *dp, buf[BUFSIZ], *rfc931_name();
1493 int connected = 1;
1494
1495 if (sep->se_family != AF_INET)
1496 return;
1497
1498 if (getpeername(ctrl, &sa, &len) < 0) {
1499 if (errno != ENOTCONN) {
1500 syslog(LOG_ERR, "getpeername: %m");
1501 return;
1502 }
1503 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, &sa, &len) < 0) {
1504 syslog(LOG_ERR, "recvfrom: %m");
1505 return;
1506 }
1507 connected = 0;
1508 }
1509 if (sa.sa_family != AF_INET) {
1510 syslog(LOG_ERR, "unexpected address family %u", sa.sa_family);
1511 return;
1512 }
1513
1514 hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
1515 sizeof (sin->sin_addr.s_addr), AF_INET);
1516
1517 host = hp?hp->h_name:inet_ntoa(sin->sin_addr);
1518
1519 switch (sep->se_log & ~MULOG_RFC931) {
1520 case 0:
1521 return;
1522 case 1:
1523 if (curdom == NULL || *curdom == '\0')
1524 break;
1525 dp = host + strlen(host) - strlen(curdom);
1526 if (dp < host)
1527 break;
1528 if (debug)
1529 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n",
1530 host, curdom);
1531 if (strcasecmp(dp, curdom) == 0)
1532 return;
1533 break;
1534 case 2:
1535 default:
1536 break;
1537 }
1538
1539 openlog("", LOG_NOWAIT, MULOG);
1540
1541 if (connected && (sep->se_log & MULOG_RFC931))
1542 syslog(LOG_INFO, "%s@%s wants %s",
1543 rfc931_name(sin, ctrl), host, sep->se_service);
1544 else
1545 syslog(LOG_INFO, "%s wants %s",
1546 host, sep->se_service);
1547 }
1548 /*
1549 * From tcp_log by
1550 * Wietse Venema, Eindhoven University of Technology, The Netherlands.
1551 */
1552 #if 0
1553 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46";
1554 #endif
1555
1556 #include <setjmp.h>
1557
1558 #define RFC931_PORT 113 /* Semi-well-known port */
1559 #define TIMEOUT 4
1560 #define TIMEOUT2 10
1561
1562 static jmp_buf timebuf;
1563
1564 /* timeout - handle timeouts */
1565
1566 static void timeout(sig)
1567 int sig;
1568 {
1569 longjmp(timebuf, sig);
1570 }
1571
1572 /* rfc931_name - return remote user name */
1573
1574 char *
1575 rfc931_name(there, ctrl)
1576 struct sockaddr_in *there; /* remote link information */
1577 int ctrl;
1578 {
1579 struct sockaddr_in here; /* local link information */
1580 struct sockaddr_in sin; /* for talking to RFC931 daemon */
1581 int length;
1582 int s;
1583 unsigned remote;
1584 unsigned local;
1585 static char user[256]; /* XXX */
1586 char buf[256];
1587 char *cp;
1588 char *result = "USER_UNKNOWN";
1589 int len;
1590
1591 /* Find out local port number of our stdin. */
1592
1593 length = sizeof(here);
1594 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) {
1595 syslog(LOG_ERR, "getsockname: %m");
1596 return (result);
1597 }
1598 /* Set up timer so we won't get stuck. */
1599
1600 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
1601 syslog(LOG_ERR, "socket: %m");
1602 return (result);
1603 }
1604
1605 sin = here;
1606 sin.sin_port = htons(0);
1607 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
1608 syslog(LOG_ERR, "bind: %m");
1609 return (result);
1610 }
1611
1612 signal(SIGALRM, timeout);
1613 if (setjmp(timebuf)) {
1614 close(s); /* not: fclose(fp) */
1615 return (result);
1616 }
1617 alarm(TIMEOUT);
1618
1619 /* Connect to the RFC931 daemon. */
1620
1621 sin = *there;
1622 sin.sin_port = htons(RFC931_PORT);
1623 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
1624 close(s);
1625 alarm(0);
1626 return (result);
1627 }
1628
1629 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
1630 (void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(there->sin_port),
1631 ntohs(here.sin_port));
1632
1633
1634 for (len = 0, cp = buf; len < strlen(buf); ) {
1635 int n;
1636
1637 if ((n = write(s, cp, strlen(buf) - len)) == -1) {
1638 close(s);
1639 alarm(0);
1640 return (result);
1641 }
1642 cp += n;
1643 len += n;
1644 }
1645
1646 /* Read response */
1647 for (cp = buf; cp < buf + sizeof(buf) - 1; ) {
1648 char c;
1649 if (read(s, &c, 1) != 1) {
1650 close(s);
1651 alarm(0);
1652 return (result);
1653 }
1654 if (c == '\n')
1655 break;
1656 *cp++ = c;
1657 }
1658 *cp = '\0';
1659
1660 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3
1661 && ntohs(there->sin_port) == remote
1662 && ntohs(here.sin_port) == local) {
1663
1664 /* Strip trailing carriage return. */
1665 if (cp = strchr(user, '\r'))
1666 *cp = 0;
1667 result = user;
1668 }
1669
1670 alarm(0);
1671 close(s);
1672 return (result);
1673 }
1674 #endif
1675