home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / ppp / dp-2.3 / dpd / dpd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-22  |  9.8 KB  |  422 lines

  1. /*
  2. **  Copyright (c) 1991 Bolt Beranek and Newman, Inc.
  3. **  All rights reserved.
  4. **
  5. **  Redistribution and use in source and binary forms are permitted
  6. **  provided that: (1) source distributions retain this entire copyright
  7. **  notice and comment, and (2) distributions including binaries display
  8. **  the following acknowledgement:  ``This product includes software
  9. **  developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
  10. **  documentation or other materials provided with the distribution and in
  11. **  all advertising materials mentioning features or use of this software.
  12. **  Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
  13. **  to endorse or promote products derived from this software without
  14. **  specific prior written permission.
  15. **
  16. **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17. **  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18. **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19. */
  20. /*
  21.  * Copyright (c) 1992 Purdue University
  22.  * All rights reserved.
  23.  *
  24.  * Redistribution and use in source and binary forms are permitted
  25.  * provided that the above copyright notice and this paragraph are
  26.  * duplicated in all such forms and that any documentation,
  27.  * advertising materials, and other materials related to such
  28.  * distribution and use acknowledge that the software was developed
  29.  * by Purdue University.  The name of the University may not be used
  30.  * to endorse or promote products derived * from this software without
  31.  * specific prior written permission.
  32.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  33.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  34.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  35.  *
  36.  * Note: this copyright applies to portions of this software developed
  37.  * at Purdue beyond the software covered by the original copyright.
  38.  */
  39. #include <stdio.h>
  40. #include <signal.h>
  41. #include <errno.h>
  42. #include <setjmp.h>
  43. #include <sys/types.h>
  44. #include <sys/wait.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/time.h>
  47. #include <sys/file.h>
  48. #include <sys/param.h>
  49. #include <sys/stream.h>
  50. #include <netinet/in.h>
  51. #include <netinet/in_systm.h>
  52. #include <netinet/ip.h>
  53. #include <sys/socket.h>
  54. #include <net/if.h>
  55. #include <stropts.h>
  56. #include "dp_str.h"
  57. #include "dp.h"
  58. #include "dpd.h"
  59.  
  60. typedef struct _TABLE {
  61.     int        Protocol;
  62.     char    *Name;
  63. } TABLE;
  64.  
  65. static int    reqtrace;
  66.  
  67. static jmp_buf    context;
  68. static int    pleaserescan;
  69. static int    pleasequit;
  70. static char    *WHERE = "dpd";
  71. static TABLE    ProtocolNames[] = {
  72. #ifdef    IPPROTO_IP
  73.     { IPPROTO_IP, "IP Dummy" },
  74. #endif
  75. #ifdef    IPPROTO_ICMP
  76.     { IPPROTO_ICMP, "ICMP" },
  77. #endif
  78. #ifdef    IPPROTO_GGP
  79.     { IPPROTO_GGP, "GGP" },
  80. #endif
  81. #ifdef    IPPROTO_TCP
  82.     { IPPROTO_TCP, "TCP" },
  83. #endif
  84. #ifdef    IPPROTO_EGP
  85.     { IPPROTO_EGP, "EGP" },
  86. #endif
  87. #ifdef    IPPROTO_PUP
  88.     { IPPROTO_PUP, "PUP" },
  89. #endif
  90. #ifdef    IPPROTO_UDP
  91.     { IPPROTO_UDP, "UDP" },
  92. #endif
  93. #ifdef IPPROTO_IDP
  94.     { IPPROTO_IDP, "IDP" },
  95. #endif
  96. #ifdef IPPROTO_RAW
  97.     { IPPROTO_RAW, "RAW" },
  98. #endif
  99.     { 0, NULL }
  100. };
  101.  
  102.  
  103.  
  104. static int
  105. authorized(rp, pkt)
  106.     register REMOTE        *rp;
  107.     register struct dp_req    *pkt;
  108. {
  109.     register int        i;
  110.     register TABLE        *tp;
  111.     struct timeval        tv;
  112.     struct tm            *tm;
  113.  
  114.     if (reqtrace) {
  115.     int fd;
  116.     char *tf = expand_dir_file("$DPLOG_DIR", TRACE_FILE);
  117.     if ((fd = open(tf, O_WRONLY|O_APPEND|O_CREAT, 0644)) >= 0) {
  118.         time_t t = time((time_t *)0);
  119.         (void)write(fd, (char *)&t, sizeof(t));
  120.         (void)write(fd, (char *)pkt, sizeof(* pkt));
  121.         (void)close(fd);
  122.     }
  123.     (void)free(tf);
  124.     }
  125.     /*
  126.      * Check that device address hasn't changed.
  127.      */
  128.     if (memcmp((char *)&pkt->dr_sin.sin_addr,
  129.            (char *)&rp->DstAddress, sizeof(rp->DstAddress))) {
  130.     char dst1[32], dst2[32];
  131.     (void)strcpy(dst1, inet_ntoa(rp->DstAddress));
  132.     (void)strcpy(dst2, inet_ntoa(pkt->dr_sin.sin_addr));
  133.     d_log(DLOG_INFO, WHERE,
  134.           "Interface destination address changed? %s -> %s",
  135.           dst1, dst2);
  136.     return 0;
  137.     }
  138.     
  139.  
  140.     /* check protocol */
  141.     i = pkt->dr_ip.ip_p;
  142.     if ((rp->Protocols[P_WORD(i)] & P_BIT(i)) == 0) {
  143.     for (tp = ProtocolNames; tp->Name; tp++)
  144.         if (i == tp->Protocol)
  145.         break;
  146.     d_log(DLOG_INFO, WHERE, "Bad protocol %s (%d)",
  147.         tp ? tp->Name : "unknown");
  148.     return 0;
  149.     }
  150.  
  151.     /* Check time. */
  152.     if (gettimeofday(&tv, (struct timezone *)NULL) < 0) {
  153.     d_log(DLOG_GENERAL, WHERE, "Can't do gettimeofday, %m");
  154.     return 0;
  155.     }
  156.     if ((tm = localtime(&tv.tv_sec)) == NULL) {
  157.     d_log(DLOG_GENERAL, WHERE, "Can't do localtime, %m");
  158.     return 0;
  159.     }
  160.     if ((rp->Times[tm->tm_wday] & (1L << tm->tm_hour)) == 0) {
  161.     d_log(DLOG_INFO, WHERE, "Bad time to call");
  162.     return 0;
  163.     }
  164.  
  165.     /* Check addresses. */
  166.     if (rp->AllowCount && !hostinlist(rp->AllowTo, pkt->dr_ip.ip_dst)) {
  167.     d_log(DLOG_INFO, WHERE, "Bad destination address \"%s\"",
  168.         inet_ntoa(pkt->dr_ip.ip_dst));
  169.     return 0;
  170.     }
  171.     if (rp->DisallowCount && hostinlist(rp->DisallowFrom, pkt->dr_ip.ip_src)) {
  172.     d_log(DLOG_INFO, WHERE, "Bad source address \"%s\"",
  173.         inet_ntoa(pkt->dr_ip.ip_src));
  174.     return 0;
  175.     }
  176.  
  177.     /* o.k. to make call */
  178.     return 1;
  179. }
  180.  
  181.  
  182. static void
  183. catchsigterm()
  184. {
  185.     pleasequit++;
  186.     longjmp(context, 1);
  187. }
  188.  
  189.  
  190. static void
  191. catchsighup()
  192. {
  193.     pleaserescan++;
  194.     (void)signal(SIGHUP, catchsighup);
  195.     longjmp(context, 1);
  196. }
  197.  
  198.  
  199. static void
  200. catchsigchld()
  201. {
  202.     union wait    wstatus;
  203.  
  204.     while (wait3(&wstatus, WNOHANG, (struct rusage *)NULL) > 0)
  205.     ;
  206. }
  207.  
  208.  
  209.  
  210. static void
  211. usage()
  212. {
  213.     (void)fprintf(stderr, "usage: %s [options]\n", progname);
  214.     d_log(DLOG_GENERAL, WHERE, "Usage error");
  215.     exit(1);
  216. }
  217.  
  218.  
  219. main(argc, argv)
  220.     int            argc;
  221.     char        *argv[];
  222. {
  223.     int            f;
  224.     int            dofork;
  225.     int            i;
  226.     struct dp_req    pkt;
  227.     REMOTE        *rp;
  228.     char        buff[256];
  229.     char        *configfile;
  230.     struct strbuf ctlb, datab;
  231.     int    sf;
  232.  
  233.     /* Set defaults. */
  234.     setprogname(argv[0]);
  235.     WHERE = progname;
  236.     dofork = 1;
  237.     configfile = DP_CONFIG;
  238.  
  239.     /* Parse flags. */
  240.     while ((i = getopt(argc, argv, "c:d:Ft")) != EOF)
  241.     switch (i) {
  242.     default:
  243.         usage();
  244.         /* NOTREACHED */
  245.     case 'c':
  246.         configfile = optarg;
  247.         break;
  248.     case 'd':
  249.         log_level = atoi(optarg);
  250.         break;
  251.     case 'F':
  252.         dofork = 0;
  253.         break;
  254.     case 't':
  255.         reqtrace = 1;
  256.         break;
  257.     }
  258.     argc -= optind;
  259.     argv += optind;
  260.     if (argc)
  261.     usage();
  262.  
  263.     /* Fork us off */
  264.     if (dofork) {
  265.     if ((i = fork()) < 0) {
  266.         d_log(DLOG_GENERAL, WHERE, "Can't fork, %m");
  267.         exit(1);
  268.     }
  269.     if (i > 0)
  270.         exit(0);
  271.  
  272.     }
  273.  
  274.     /*
  275.      * Sanitize our process state.
  276.      */
  277.     if (dofork) {
  278.     for (f = getdtablesize() ; f ; f--)
  279.         (void)close(f);
  280.     (void)open("/", O_RDONLY);
  281.     (void)dup2(0, 1);
  282.     (void)dup2(0, 2);
  283.     (void)setsid();
  284.     }
  285.     else
  286.     for (f = getdtablesize() ; f > 2 ; f--)
  287.         (void)close(f);
  288.  
  289.     /*
  290.      * Figure out where everything is located.
  291.      */
  292.     init_pathconf();
  293.  
  294.     /*
  295.      * Read network and modem configuration.
  296.      */
  297.     if (!readconfig(configfile))
  298.     exit(1);
  299.  
  300.     if (!set_if_timeouts())
  301.     exit(1);
  302.  
  303.     /* Open the request device. */
  304.     if ((f = open(DEVDIAL, O_RDONLY)) < 0) {
  305.     d_log(DLOG_GENERAL, WHERE, "Can't open \"%s\", %m", DEVDIAL);
  306.     exit(1);
  307.     }
  308. #ifdef    FIOCLEX
  309.     if (ioctl(f, FIOCLEX, (caddr_t)NULL) < 0)
  310.     d_log(DLOG_INFO, WHERE, "Can't do FIOCLEX on \"%s\", %m", DEVDIAL);
  311. #endif    /* FIOCLEX */
  312.  
  313.     /* Tell the log file where are here */
  314.     d_log(DLOG_GENERAL, WHERE, "%s started", dp_release());
  315.     record_pid(progname);
  316.  
  317.     /* Process requests */
  318.     (void)signal(SIGHUP, catchsighup);
  319.     (void)signal(SIGTERM, catchsigterm);
  320.     (void)signal(SIGCHLD, catchsigchld);
  321.     for ( ; ; ) {
  322.     (void)setjmp(context);
  323.     if (pleasequit)
  324.         break;
  325.     if (pleaserescan) {
  326.         d_log(DLOG_GENERAL, WHERE, "Rescanning config files");
  327. #define    MDEBUG
  328. #ifdef    MDEBUG
  329.         mem_report();
  330. #endif
  331.         if (!readconfig(configfile)) {
  332.         unlock_pid();
  333.         exit(1);
  334.         }
  335.         if (!set_if_timeouts()) {
  336.         unlock_pid();
  337.         exit(1);
  338.         }
  339.         (void)signal(SIGHUP, catchsighup);
  340.         pleaserescan = 0;
  341.         continue;
  342.     }
  343.  
  344.     ctlb.maxlen = -1;
  345.     ctlb.buf = (char *)0;
  346.     datab.maxlen = sizeof(struct dp_req);
  347.     datab.buf = (char *)&pkt;
  348.     sf = 0;
  349.     if (i = getmsg(f, &ctlb, &datab, &sf)) {
  350.         if (errno != EINTR)
  351.         d_log(DLOG_GENERAL, WHERE,
  352.             "Bad getmsg (returned %d) from \"%s\", %m",
  353.             i, DEVDIAL);
  354.         continue;
  355.     }
  356.     if (datab.len < sizeof(dp_reqinfo) + DR_MINHDRLEN ||
  357.         datab.len > sizeof(dp_reqinfo) + DR_MAXHDRLEN ||
  358.         datab.len != sizeof(dp_reqinfo) + pkt.dr_hdrlen) {
  359.         d_log(DLOG_GENERAL, WHERE,
  360.             "Request packet length (%d) out of range", pkt.dr_hdrlen);
  361.         continue;
  362.     }
  363.     if (pkt.dr_hdrlen < DR_MINHDRLEN || pkt.dr_hdrlen > DR_MAXHDRLEN) {
  364.         d_log(DLOG_GENERAL, WHERE,
  365.             "Request header length (%d) out of range", pkt.dr_hdrlen);
  366.         continue;
  367.     }
  368.     d_log(DLOG_ALL, WHERE, "request received");
  369.  
  370.     /* Find config data for the address. */
  371.     (void)sprintf(buff, "%s%d", pkt.dr_ifname, pkt.dr_ifunit);
  372.     if ((rp = findconfig(buff)) == NULL) {
  373.         d_log(DLOG_GENERAL, WHERE, "Address %s not configured",
  374.         inet_ntoa(pkt.dr_sin.sin_addr));
  375.         continue;
  376.     }
  377.  
  378.     /* Is this packet is authorized? */
  379.     if ((pkt.dr_flag & DP_REQ_CHECKIT) && !authorized(rp, &pkt)) {
  380.         (void)strcpy(buff, inet_ntoa(pkt.dr_ip.ip_src));
  381.         failcall(rp, (MODEM *)0, DP_FAILURE,
  382.              "%s not authorized to reach %s",
  383.              buff, inet_ntoa(pkt.dr_ip.ip_dst));
  384.         continue;
  385.     }
  386.  
  387.     /* Make the call. */
  388.     if (!dofork) {
  389.         makecall(rp, &pkt);
  390.         continue;
  391.     }
  392.     if ((i = fork()) == 0) {
  393.         (void)setpgrp(0, getpgrp(0));
  394.         (void)close(f);
  395.         if (rp->LogLevel > log_level)
  396.         log_level = rp->LogLevel;
  397.         makecall(rp, &pkt);
  398.         break;
  399.     }
  400.     if (i < 0)
  401.         d_log(DLOG_GENERAL, WHERE, "Can't fork dialing process, %m");
  402.     }
  403.  
  404.     d_log(DLOG_GENERAL, WHERE, "%s exiting", dp_release());
  405.     unlock_pid();
  406.     exit(0);
  407.     /* NOTREACHED */
  408. }
  409.  
  410. #ifdef    MDEBUG
  411. #include <malloc.h>
  412.  
  413. mem_report()
  414. {
  415.     struct mallinfo ma;
  416.     ma = mallinfo();
  417.     d_log(DLOG_GENERAL, WHERE,
  418.       "arena = %5d, usmblks = %5d, uordblks = %5d",
  419.       ma.arena, ma.usmblks, ma.uordblks);
  420. }
  421. #endif
  422.