home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / dialer.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  4KB  |  171 lines

  1. /* Automatic SLIP/PPP line redialer.
  2.  * Very simpleminded - If a specified interval goes by without any
  3.  * receiver activity, ping the other end. If this repeatedly fails,
  4.  * spit a file containing modem commands at the line and try again.
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  */
  8. #include <stdio.h>
  9. #include "global.h"
  10. #include "mbuf.h"
  11. #include "iface.h"
  12. #include "8250.h"
  13. #include "asy.h"
  14. #include "session.h"
  15. #include "proc.h"
  16. #include "tty.h"
  17. #include "socket.h"
  18. #include "commands.h"
  19. #include "netuser.h"
  20. #include "timer.h"
  21.  
  22. static int redial __ARGS((struct iface *ifp,char *file));
  23. static void monitor __ARGS((int s,void *v1,void *v2));
  24.  
  25. int
  26. dodialer(argc,argv,p)
  27. int argc;
  28. char *argv[];
  29. void *p;
  30. {
  31.     int s;
  32.     struct iface *ifp;
  33.     int32 target;
  34.     int32 interval;
  35.     int dev;
  36.     struct asy *ap;
  37.  
  38.     if((ifp = if_lookup(argv[1])) == NULLIF){
  39.         tprintf("Interface %s unknown\n",argv[1]);
  40.         return 1;
  41.     }
  42.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  43.         if(ap->iface == ifp)
  44.             break;
  45.     if(dev == ASY_MAX){
  46.         tprintf("Interface %s not asy port\n",argv[1]);
  47.         return 1;
  48.     }
  49.     if((interval = atol(argv[2])) == 0){
  50.         if(ifp->supv != NULLPROC){
  51.             alert(ifp->supv,1);
  52.             tprintf("dialer terminated on %s\n",argv[1]);
  53.         } else {
  54.             tprintf("no dialer active on %s\n",argv[1]);
  55.         }
  56.         return 0;
  57.     }
  58.     if(argc < 5){
  59.         tprintf("not enough args\n");
  60.         return -1;
  61.     }
  62.     if(ifp->supv != NULLPROC){
  63.         tprintf("dialer already active on %s\n",argv[1]);
  64.         return 1;
  65.     }
  66.     if((target = resolve(argv[3])) == 0){
  67.         tprintf(Badhost,argv[3]);
  68.         return 1;
  69.     }
  70.     ifp->supv = Curproc;
  71.  
  72.     for(;;){
  73.         if((s = pause(interval*1000)) != 0){    /* Wait a while */
  74.             break;        /* We're being terminated */
  75.         }
  76.         if(secclock() - ifp->lastrecv > 4*interval){
  77.             /* Receiver has remained idle after four pings;
  78.              * assume the connection has dropped.
  79.              */
  80.             if(redial(ifp,argv[4]) != 0)
  81.                 break;
  82.         }
  83.         if(secclock() - ifp->lastrecv > interval){
  84.             /* Receiver has been idle since last check */
  85.             if((s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1)
  86.                 continue;    /* Wait and try again */
  87.             pingem(s,target,0,(int16)s,0);
  88.             close_s(s);
  89.         }
  90.     }
  91.     ifp->supv = NULLPROC;
  92.     return 0;
  93. static int
  94. redial(ifp,file)
  95. struct iface *ifp;
  96. char *file;
  97. {
  98.     FILE *fp;
  99.     struct mbuf *bp;
  100.     int32 delay;
  101.     int c;
  102.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  103.     struct proc *mon;
  104.     int err_ret = 0;
  105.  
  106.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  107.         tprintf("redial: can't read %s\n",file);
  108.         return -1;    /* Causes dialer proc to terminate */
  109.     }
  110.     /* Save output handler and temporarily redirect output to null */
  111.     if(ifp->raw == dumppkt){
  112.         tprintf("redial: tip or dialer already active on %s\n",ifp->name);
  113.         return -1;
  114.     }
  115.     rawsave = ifp->raw;
  116.     ifp->raw = dumppkt;
  117.  
  118.     /* Suspend the packet input driver. Note that the transmit driver
  119.      * is left running since we use it to send buffers to the line.
  120.      */
  121.     suspend(ifp->rxproc);
  122.  
  123.     /* Start up monitor so we can see what's happening */
  124.     mon = newproc("dial monitor",300,monitor,0,(void *)ifp,NULL,0);
  125.  
  126.     while((c = getc(fp)) != EOF){
  127.         if(c == '\\'){
  128.             /* delay escape */
  129.             delay = 0;
  130.             while(c = getc(fp),c != EOF && c != 'd'){
  131.                 delay = delay * 10 + (c-'0');
  132.             }
  133.             if(c == EOF)
  134.                 break;
  135.             if(pause(delay) != 0){
  136.                 err_ret = 1;
  137.                 break;
  138.             }
  139.             continue;
  140.         }
  141.         if(c == EOF)
  142.             break;    /* Normal termination */
  143.         if(c == '\n')
  144.             c = '\r';
  145.         bp = pushdown(NULLBUF,1);
  146.         bp->data[0] = c;
  147.         asy_send(ifp->dev,bp);
  148.     }
  149.     fclose(fp);
  150.     killproc(mon);
  151.     ifp->raw = rawsave;
  152.     resume(ifp->rxproc);
  153.     return err_ret;
  154. }
  155. static void
  156. monitor(s,v1,v2)
  157. int s;
  158. void *v1;
  159. void *v2;
  160. {
  161.     int c;
  162.     struct iface *ifp;
  163.  
  164.     ifp = (struct iface *)v1;
  165.     while((c = get_asy(ifp->dev)) != -1){
  166.         if(ifp->trace & IF_TRACE_IN)
  167.             putchar(c & 0x7f);
  168.     }
  169. }
  170.