home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Copyright (c) 1991 Bolt Beranek and Newman, Inc.
- ** All rights reserved.
- **
- ** Redistribution and use in source and binary forms are permitted
- ** provided that: (1) source distributions retain this entire copyright
- ** notice and comment, and (2) distributions including binaries display
- ** the following acknowledgement: ``This product includes software
- ** developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
- ** documentation or other materials provided with the distribution and in
- ** all advertising materials mentioning features or use of this software.
- ** Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
- ** to endorse or promote products derived from this software without
- ** specific prior written permission.
- **
- ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- ** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
- /*
- * Copyright (c) 1992 Purdue University
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Purdue University. The name of the University may not be used
- * to endorse or promote products derived * from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Note: this copyright applies to portions of this software developed
- * at Purdue beyond the software covered by the original copyright.
- */
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
- #include <setjmp.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <sys/file.h>
- #include <sys/param.h>
- #include <sys/stream.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <stropts.h>
- #include "dp_str.h"
- #include "dp.h"
- #include "dpd.h"
-
- typedef struct _TABLE {
- int Protocol;
- char *Name;
- } TABLE;
-
- static int reqtrace;
-
- static jmp_buf context;
- static int pleaserescan;
- static int pleasequit;
- static char *WHERE = "dpd";
- static TABLE ProtocolNames[] = {
- #ifdef IPPROTO_IP
- { IPPROTO_IP, "IP Dummy" },
- #endif
- #ifdef IPPROTO_ICMP
- { IPPROTO_ICMP, "ICMP" },
- #endif
- #ifdef IPPROTO_GGP
- { IPPROTO_GGP, "GGP" },
- #endif
- #ifdef IPPROTO_TCP
- { IPPROTO_TCP, "TCP" },
- #endif
- #ifdef IPPROTO_EGP
- { IPPROTO_EGP, "EGP" },
- #endif
- #ifdef IPPROTO_PUP
- { IPPROTO_PUP, "PUP" },
- #endif
- #ifdef IPPROTO_UDP
- { IPPROTO_UDP, "UDP" },
- #endif
- #ifdef IPPROTO_IDP
- { IPPROTO_IDP, "IDP" },
- #endif
- #ifdef IPPROTO_RAW
- { IPPROTO_RAW, "RAW" },
- #endif
- { 0, NULL }
- };
-
-
-
- static int
- authorized(rp, pkt)
- register REMOTE *rp;
- register struct dp_req *pkt;
- {
- register int i;
- register TABLE *tp;
- struct timeval tv;
- struct tm *tm;
-
- if (reqtrace) {
- int fd;
- char *tf = expand_dir_file("$DPLOG_DIR", TRACE_FILE);
- if ((fd = open(tf, O_WRONLY|O_APPEND|O_CREAT, 0644)) >= 0) {
- time_t t = time((time_t *)0);
- (void)write(fd, (char *)&t, sizeof(t));
- (void)write(fd, (char *)pkt, sizeof(* pkt));
- (void)close(fd);
- }
- (void)free(tf);
- }
- /*
- * Check that device address hasn't changed.
- */
- if (memcmp((char *)&pkt->dr_sin.sin_addr,
- (char *)&rp->DstAddress, sizeof(rp->DstAddress))) {
- char dst1[32], dst2[32];
- (void)strcpy(dst1, inet_ntoa(rp->DstAddress));
- (void)strcpy(dst2, inet_ntoa(pkt->dr_sin.sin_addr));
- d_log(DLOG_INFO, WHERE,
- "Interface destination address changed? %s -> %s",
- dst1, dst2);
- return 0;
- }
-
-
- /* check protocol */
- i = pkt->dr_ip.ip_p;
- if ((rp->Protocols[P_WORD(i)] & P_BIT(i)) == 0) {
- for (tp = ProtocolNames; tp->Name; tp++)
- if (i == tp->Protocol)
- break;
- d_log(DLOG_INFO, WHERE, "Bad protocol %s (%d)",
- tp ? tp->Name : "unknown");
- return 0;
- }
-
- /* Check time. */
- if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't do gettimeofday, %m");
- return 0;
- }
- if ((tm = localtime(&tv.tv_sec)) == NULL) {
- d_log(DLOG_GENERAL, WHERE, "Can't do localtime, %m");
- return 0;
- }
- if ((rp->Times[tm->tm_wday] & (1L << tm->tm_hour)) == 0) {
- d_log(DLOG_INFO, WHERE, "Bad time to call");
- return 0;
- }
-
- /* Check addresses. */
- if (rp->AllowCount && !hostinlist(rp->AllowTo, pkt->dr_ip.ip_dst)) {
- d_log(DLOG_INFO, WHERE, "Bad destination address \"%s\"",
- inet_ntoa(pkt->dr_ip.ip_dst));
- return 0;
- }
- if (rp->DisallowCount && hostinlist(rp->DisallowFrom, pkt->dr_ip.ip_src)) {
- d_log(DLOG_INFO, WHERE, "Bad source address \"%s\"",
- inet_ntoa(pkt->dr_ip.ip_src));
- return 0;
- }
-
- /* o.k. to make call */
- return 1;
- }
-
-
- static void
- catchsigterm()
- {
- pleasequit++;
- longjmp(context, 1);
- }
-
-
- static void
- catchsighup()
- {
- pleaserescan++;
- (void)signal(SIGHUP, catchsighup);
- longjmp(context, 1);
- }
-
-
- static void
- catchsigchld()
- {
- union wait wstatus;
-
- while (wait3(&wstatus, WNOHANG, (struct rusage *)NULL) > 0)
- ;
- }
-
-
-
- static void
- usage()
- {
- (void)fprintf(stderr, "usage: %s [options]\n", progname);
- d_log(DLOG_GENERAL, WHERE, "Usage error");
- exit(1);
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int f;
- int dofork;
- int i;
- struct dp_req pkt;
- REMOTE *rp;
- char buff[256];
- char *configfile;
- struct strbuf ctlb, datab;
- int sf;
-
- /* Set defaults. */
- setprogname(argv[0]);
- WHERE = progname;
- dofork = 1;
- configfile = DP_CONFIG;
-
- /* Parse flags. */
- while ((i = getopt(argc, argv, "c:d:Ft")) != EOF)
- switch (i) {
- default:
- usage();
- /* NOTREACHED */
- case 'c':
- configfile = optarg;
- break;
- case 'd':
- log_level = atoi(optarg);
- break;
- case 'F':
- dofork = 0;
- break;
- case 't':
- reqtrace = 1;
- break;
- }
- argc -= optind;
- argv += optind;
- if (argc)
- usage();
-
- /* Fork us off */
- if (dofork) {
- if ((i = fork()) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't fork, %m");
- exit(1);
- }
- if (i > 0)
- exit(0);
-
- }
-
- /*
- * Sanitize our process state.
- */
- if (dofork) {
- for (f = getdtablesize() ; f ; f--)
- (void)close(f);
- (void)open("/", O_RDONLY);
- (void)dup2(0, 1);
- (void)dup2(0, 2);
- (void)setsid();
- }
- else
- for (f = getdtablesize() ; f > 2 ; f--)
- (void)close(f);
-
- /*
- * Figure out where everything is located.
- */
- init_pathconf();
-
- /*
- * Read network and modem configuration.
- */
- if (!readconfig(configfile))
- exit(1);
-
- if (!set_if_timeouts())
- exit(1);
-
- /* Open the request device. */
- if ((f = open(DEVDIAL, O_RDONLY)) < 0) {
- d_log(DLOG_GENERAL, WHERE, "Can't open \"%s\", %m", DEVDIAL);
- exit(1);
- }
- #ifdef FIOCLEX
- if (ioctl(f, FIOCLEX, (caddr_t)NULL) < 0)
- d_log(DLOG_INFO, WHERE, "Can't do FIOCLEX on \"%s\", %m", DEVDIAL);
- #endif /* FIOCLEX */
-
- /* Tell the log file where are here */
- d_log(DLOG_GENERAL, WHERE, "%s started", dp_release());
- record_pid(progname);
-
- /* Process requests */
- (void)signal(SIGHUP, catchsighup);
- (void)signal(SIGTERM, catchsigterm);
- (void)signal(SIGCHLD, catchsigchld);
- for ( ; ; ) {
- (void)setjmp(context);
- if (pleasequit)
- break;
- if (pleaserescan) {
- d_log(DLOG_GENERAL, WHERE, "Rescanning config files");
- #define MDEBUG
- #ifdef MDEBUG
- mem_report();
- #endif
- if (!readconfig(configfile)) {
- unlock_pid();
- exit(1);
- }
- if (!set_if_timeouts()) {
- unlock_pid();
- exit(1);
- }
- (void)signal(SIGHUP, catchsighup);
- pleaserescan = 0;
- continue;
- }
-
- ctlb.maxlen = -1;
- ctlb.buf = (char *)0;
- datab.maxlen = sizeof(struct dp_req);
- datab.buf = (char *)&pkt;
- sf = 0;
- if (i = getmsg(f, &ctlb, &datab, &sf)) {
- if (errno != EINTR)
- d_log(DLOG_GENERAL, WHERE,
- "Bad getmsg (returned %d) from \"%s\", %m",
- i, DEVDIAL);
- continue;
- }
- if (datab.len < sizeof(dp_reqinfo) + DR_MINHDRLEN ||
- datab.len > sizeof(dp_reqinfo) + DR_MAXHDRLEN ||
- datab.len != sizeof(dp_reqinfo) + pkt.dr_hdrlen) {
- d_log(DLOG_GENERAL, WHERE,
- "Request packet length (%d) out of range", pkt.dr_hdrlen);
- continue;
- }
- if (pkt.dr_hdrlen < DR_MINHDRLEN || pkt.dr_hdrlen > DR_MAXHDRLEN) {
- d_log(DLOG_GENERAL, WHERE,
- "Request header length (%d) out of range", pkt.dr_hdrlen);
- continue;
- }
- d_log(DLOG_ALL, WHERE, "request received");
-
- /* Find config data for the address. */
- (void)sprintf(buff, "%s%d", pkt.dr_ifname, pkt.dr_ifunit);
- if ((rp = findconfig(buff)) == NULL) {
- d_log(DLOG_GENERAL, WHERE, "Address %s not configured",
- inet_ntoa(pkt.dr_sin.sin_addr));
- continue;
- }
-
- /* Is this packet is authorized? */
- if ((pkt.dr_flag & DP_REQ_CHECKIT) && !authorized(rp, &pkt)) {
- (void)strcpy(buff, inet_ntoa(pkt.dr_ip.ip_src));
- failcall(rp, (MODEM *)0, DP_FAILURE,
- "%s not authorized to reach %s",
- buff, inet_ntoa(pkt.dr_ip.ip_dst));
- continue;
- }
-
- /* Make the call. */
- if (!dofork) {
- makecall(rp, &pkt);
- continue;
- }
- if ((i = fork()) == 0) {
- (void)setpgrp(0, getpgrp(0));
- (void)close(f);
- if (rp->LogLevel > log_level)
- log_level = rp->LogLevel;
- makecall(rp, &pkt);
- break;
- }
- if (i < 0)
- d_log(DLOG_GENERAL, WHERE, "Can't fork dialing process, %m");
- }
-
- d_log(DLOG_GENERAL, WHERE, "%s exiting", dp_release());
- unlock_pid();
- exit(0);
- /* NOTREACHED */
- }
-
- #ifdef MDEBUG
- #include <malloc.h>
-
- mem_report()
- {
- struct mallinfo ma;
- ma = mallinfo();
- d_log(DLOG_GENERAL, WHERE,
- "arena = %5d, usmblks = %5d, uordblks = %5d",
- ma.arena, ma.usmblks, ma.uordblks);
- }
- #endif
-