home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / DIALER.C < prev    next >
C/C++ Source or Header  |  1992-05-15  |  9KB  |  399 lines

  1. /* Automatic SLIP/PPP line dialer.
  2.  *
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  *    Mar '91    Bill Simpson & Glenn McGregor
  6.  *        completely re-written;
  7.  *        human readable control file;
  8.  *        includes wait for string, and speed sense;
  9.  *        dials immediately when invoked.
  10.  *    May '91 Bill Simpson
  11.  *        re-ordered command line;
  12.  *        allow dial only;
  13.  *        allow inactivity timeout without ping.
  14.  *    Sep '91 Bill Simpson
  15.  *        Check known DTR & RSLD state for redial decision
  16.  *    Mar '92    Phil Karn
  17.  *        autosense modem control stuff removed
  18.  *        Largely rewritten to do demand dialing
  19.  */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <stdlib.h>
  23. #include "global.h"
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #include "netuser.h"
  29. #include "n8250.h"
  30. #include "asy.h"
  31. #include "tty.h"
  32. #include "socket.h"
  33. #include "cmdparse.h"
  34. #include "devparam.h"
  35. #include "files.h"
  36. #include "main.h"
  37. #include "trace.h"
  38. #include "commands.h"
  39.  
  40. static int redial __ARGS((struct iface *ifp,char *file));
  41. static void dropline __ARGS((void *));
  42. static void dropit(int,void *,void *);
  43.  
  44. static int dodial_control    __ARGS((int argc,char *argv[],void *p));
  45. static int dodial_send        __ARGS((int argc,char *argv[],void *p));
  46. static int dodial_speed        __ARGS((int argc,char *argv[],void *p));
  47. static int dodial_status    __ARGS((int argc,char *argv[],void *p));
  48. static int dodial_wait        __ARGS((int argc,char *argv[],void *p));
  49.  
  50. static struct cmds dial_cmds[] = {
  51.     "",        donothing,    0, 0, "",
  52.     "control",    dodial_control,    0, 2, "control up | down",
  53.     "send",        dodial_send,    0, 2,
  54.     "send \"string\" [<milliseconds>]",
  55.     "speed",    dodial_speed,    0, 2, "speed <bps>",
  56.     "status",    dodial_status, 0, 2, "status up | down",
  57.     "wait",        dodial_wait,    0, 2,
  58.     "wait <milliseconds> [ \"string\" [speed] ]",
  59.     NULLCHAR,    NULLFP,        0, 0, "Unknown command",
  60. };
  61. /* 
  62.  * dial <iface> <seconds> <raisefile> <dropfile>
  63.  * dial <iface>
  64.  * dial <iface> 0
  65.  */
  66. int
  67. dodialer(argc,argv,p)
  68. int argc;
  69. char *argv[];
  70. void *p;
  71. {
  72.     struct iface *ifp;
  73.     struct asy *ap;
  74.     int32 timeout;
  75.  
  76.     if((ifp = if_lookup(argv[1])) == NULLIF){
  77.         printf("Interface %s unknown\n",argv[1]);
  78.         return 1;
  79.     }
  80.     if(ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp){
  81.         printf("Interface %s not asy port\n",argv[1]);
  82.         return 1;
  83.     }
  84.     ap = &Asy[ifp->dev];
  85.     if(argc < 3){
  86.         printf("%s: %s",ifp->name,(ap->msr & MSR_RLSD) ? "UP":"DOWN");
  87.         printf(", idle timer %ld/%ld",read_timer(&ap->idle)/1000L,
  88.           dur_timer(&ap->idle)/1000L);
  89.         if(ap->actfile != NULLCHAR)
  90.             printf(", up script: %s",ap->actfile);
  91.         if(ap->dropfile != NULLCHAR)
  92.             printf(", down script: %s\n",ap->dropfile);
  93.         else
  94.             printf("\n");
  95.  
  96.         printf("Calls originated %ld, carrier up transitions %ld\n",
  97.             ap->originates,ap->answers);
  98.         printf("Calls timed out %ld, carrier down transitions %ld\n",
  99.             ap->localdrops,ap->remdrops);
  100.         return 0;
  101.     }
  102.     timeout = atol(argv[2]) * 1000L;
  103.     if(timeout != 0 && argc < 5){
  104.         printf("Usage: dial <iface> <timeout> <raisefile> <dropfile>\n");
  105.         printf("       dial <iface> 0\n");
  106.         return 1;
  107.     }
  108.     if(!ap->rlsd){
  109.         printf("Must set 'r' flag at attach time\n");
  110.         return 1;
  111.     }
  112.     stop_timer(&ap->idle);
  113.     set_timer(&ap->idle,timeout);
  114.     ap->idle.func = dropline;
  115.     ap->idle.arg = ifp;
  116.     if(ap->actfile != NULLCHAR){
  117.         free(ap->actfile);
  118.         ap->actfile = NULLCHAR;
  119.     }
  120.     if(ap->dropfile != NULLCHAR){
  121.         free(ap->dropfile);
  122.         ap->dropfile = NULLCHAR;
  123.     }
  124.     if(timeout != 0){
  125.         ap->actfile = strdup(argv[3]);
  126.         ap->dropfile = strdup(argv[4]);
  127.         start_timer(&ap->idle);
  128.     }
  129.     return 0;
  130. }
  131. void
  132. dialer_kick(asyp)
  133. struct asy *asyp;
  134. {
  135.     int backoff = -1;
  136.     int pw;
  137.  
  138.     stop_timer(&asyp->idle);
  139.     while(asyp->rlsd && (asyp->msr & MSR_RLSD) == 0
  140.      && asyp->actfile != NULLCHAR){
  141.         /* Line down, we need to redial
  142.          * But if it's failing, perform random binary
  143.          * exponential backoff
  144.          */
  145.         if(backoff++ >= 0){
  146.             alarm(1000L*random(30L << backoff));
  147.             pw = pwait(&asyp->rlsd);
  148.             alarm(0L);
  149.             if(pw == 0)
  150.                 continue; /* CD changed, maybe we got called */
  151.         }
  152.         asyp->originates++;
  153.         redial(asyp->iface,asyp->actfile);
  154.     }
  155. }
  156.  
  157. /* Called when idle line timer expires -- executes script to drop line */
  158. static void
  159. dropline(p)
  160. void *p;
  161. {
  162.     /* Fork this off to prevent wedging the timer task */
  163.     newproc("dropit",512,dropit,0,p,NULL,0);
  164. }
  165.  
  166. static void
  167. dropit(i,p,u)
  168. int i;
  169. void *p;
  170. void *u;
  171. {
  172.     struct iface *ifp = p;
  173.     struct asy *ap;
  174.  
  175.     ap = &Asy[ifp->dev];
  176.     if(ap->msr & MSR_RLSD){
  177.         ap->localdrops++;
  178.         redial(ifp,ap->dropfile);    /* Drop only if still up */
  179.     }
  180. }
  181.  
  182. /* execute dialer commands
  183.  * returns: -1 fatal error, 0 OK, 1 try again
  184.  */
  185. static int
  186. redial(ifp,file)
  187. struct iface *ifp;
  188. char *file;
  189. {
  190.     char *inbuf, *intmp;
  191.     FILE *fp;
  192.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  193.     int result = 0;
  194.  
  195.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  196.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  197.             tprintf(ifp,"redial: can't read %s\n",file);
  198.         return -1;
  199.     }
  200.     /* Save output handler and temporarily redirect output to null */
  201.     if(ifp->raw == bitbucket){
  202.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  203.             tprintf(ifp,"redial: tip or dialer already active on %s\n",ifp->name);
  204.  
  205.         return -1;
  206.     }
  207.  
  208.     if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  209.         tprintf(ifp,"Dialing on %s\n\n",ifp->name);
  210.  
  211.     /* Save output handler and temporarily redirect output to null */
  212.     rawsave = ifp->raw;
  213.     ifp->raw = bitbucket;
  214.  
  215.     /* Suspend the packet input driver. Note that the transmit driver
  216.      * is left running since we use it to send buffers to the line.
  217.      */
  218.     suspend(ifp->rxproc);
  219.  
  220.     inbuf = mallocw(BUFSIZ);
  221.     intmp = mallocw(BUFSIZ);
  222.     while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
  223.         strcpy(intmp,inbuf);
  224.         rip(intmp);
  225.         log(-1,"%s dialer: %s",ifp->name,intmp);
  226.         if((result = cmdparse(dial_cmds,inbuf,ifp)) != 0){
  227.             if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  228.                 tprintf(ifp,"input line: %s",intmp);
  229.             break;
  230.         }
  231.     }
  232.     free(inbuf);
  233.     free(intmp);
  234.     fclose(fp);
  235.  
  236.     if(result == 0){
  237.         ifp->lastsent = ifp->lastrecv = secclock();
  238.     }
  239.     ifp->raw = rawsave;
  240.     resume(ifp->rxproc);
  241.     if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  242.         tprintf(ifp,"\nDial %s complete\n",ifp->name);
  243.  
  244.     return result;
  245. }
  246.  
  247.  
  248. static int
  249. dodial_control(argc,argv,p)
  250. int argc;
  251. char *argv[];
  252. void *p;
  253. {
  254.     struct iface *ifp = p;
  255.     int param;
  256.  
  257.     if ( ifp->ioctl == NULL )
  258.         return -1;
  259.  
  260.     if ( (param = devparam( argv[1] )) == -1 )
  261.         return -1;
  262.  
  263.     (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
  264.     return 0;
  265. }
  266.  
  267.  
  268. static int
  269. dodial_send(argc,argv,p)
  270. int argc;
  271. char *argv[];
  272. void *p;
  273. {
  274.     struct iface *ifp = p;
  275.     struct mbuf *bp;
  276.  
  277.     if(argc > 2){
  278.         /* Send characters with inter-character delay
  279.          * (for dealing with prehistoric Micom switches that
  280.          * can't take back-to-back characters...yes, they
  281.          * still exist.)
  282.          */
  283.         char *cp;
  284.         int32 cdelay = atol(argv[2]);
  285.  
  286.         for(cp = argv[1];*cp != '\0';cp++){
  287.             asy_write(ifp->dev,cp,1);
  288.             pause(cdelay);
  289.         }
  290.     } else {
  291.         if (ifp->trace & IF_TRACE_RAW)
  292.             raw_dump( ifp, IF_TRACE_OUT, bp );
  293.         asy_write(ifp->dev,argv[1],strlen(argv[1]));
  294.     }
  295.     return 0;
  296. }
  297.  
  298.  
  299. static int
  300. dodial_speed(argc,argv,p)
  301. int argc;
  302. char *argv[];
  303. void *p;
  304. {
  305.     struct iface *ifp = p;
  306.  
  307.     if ( argc < 2 ) {
  308.         if(ifp->trace & (IF_TRACE_IN|IF_TRACE_OUT))
  309.             tprintf(ifp,"current speed = %u bps\n", Asy[ifp->dev].speed);
  310.         return 0;
  311.     }
  312.     return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
  313. }
  314.  
  315.  
  316. static int
  317. dodial_status(argc,argv,p)
  318. int argc;
  319. char *argv[];
  320. void *p;
  321. {
  322.     struct iface *ifp = p;
  323.     int param;
  324.  
  325.     if ( ifp->iostatus == NULL )
  326.         return -1;
  327.  
  328.     if ( (param = devparam( argv[1] )) == -1 )
  329.         return -1;
  330.  
  331.     (*ifp->iostatus)( ifp, param, atol( argv[2] ) );
  332.     return 0;
  333. }
  334.  
  335.  
  336. static int
  337. dodial_wait(argc,argv,p)
  338. int argc;
  339. char *argv[];
  340. void *p;
  341. {
  342.     struct iface *ifp = p;
  343.     register int c = -1;
  344.  
  345.     alarm(atol(argv[1]));
  346.  
  347.     if(argc == 2){
  348.         while((c = get_asy(ifp->dev)) != -1 ){
  349.             c &= 0x7f;
  350.             if(ifp->trace & IF_TRACE_IN){
  351.                 fputc(c,ifp->trfp);
  352.                 fflush(ifp->trfp);
  353.             }
  354.         }
  355.         alarm(0L);
  356.         return 0;
  357.     } else {
  358.         register char *cp = argv[2];
  359.  
  360.         while(*cp != '\0' && (c = get_asy(ifp->dev)) != -1){
  361.             c &= 0x7f;
  362.             if(ifp->trace & IF_TRACE_IN){
  363.                 fputc(c,ifp->trfp);
  364.                 fflush(ifp->trfp);
  365.             }
  366.             if(*cp++ != c){
  367.                 cp = argv[2];
  368.             }
  369.         }
  370.  
  371.         if(argc > 3){
  372.             if(stricmp( argv[3], "speed") == 0){
  373.                 int16 speed = 0;
  374.  
  375.                 while((c = get_asy(ifp->dev)) != -1){
  376.                     c &= 0x7f;
  377.                     if(ifp->trace & IF_TRACE_IN){
  378.                         fputc(c,ifp->trfp);
  379.                         fflush(ifp->trfp);
  380.                     }
  381.                     if(isdigit(c)){
  382.                         speed *= 10;
  383.                         speed += c - '0';
  384.                     } else {
  385.                         alarm(0L);
  386.                         return asy_speed( ifp->dev, speed );
  387.                     }
  388.                 }
  389.             } else {
  390.                 return -1;
  391.             }
  392.         }
  393.     }
  394.     alarm(0L);
  395.     return (c == -1);
  396. }
  397.  
  398.  
  399.