home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / DIALER.C < prev    next >
C/C++ Source or Header  |  1991-09-21  |  9KB  |  418 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.  */
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include "global.h"
  20. #include "config.h"
  21. #include "mbuf.h"
  22. #include "timer.h"
  23. #include "proc.h"
  24. #include "iface.h"
  25. #include "netuser.h"
  26. #include "8250.h"
  27. #include "asy.h"
  28. #include "tty.h"
  29. #include "session.h"
  30. #include "socket.h"
  31. #include "cmdparse.h"
  32. #include "devparam.h"
  33. #include "icmp.h"
  34. #include "files.h"
  35. #include "main.h"
  36. #include "trace.h"
  37.  
  38. #define MIN_INTERVAL    5L
  39.  
  40. static int redial __ARGS((struct iface *ifp,char *file));
  41.  
  42. static int dodial_control    __ARGS((int argc,char *argv[],void *p));
  43. static int dodial_send        __ARGS((int argc,char *argv[],void *p));
  44. static int dodial_speed        __ARGS((int argc,char *argv[],void *p));
  45. static int dodial_status    __ARGS((int argc,char *argv[],void *p));
  46. static int dodial_wait        __ARGS((int argc,char *argv[],void *p));
  47.  
  48.  
  49. static struct cmds dial_cmds[] = {
  50.     "control",    dodial_control,    0, 2, "control up | down",
  51.     "send",        dodial_send,    0, 2,
  52.     "send \"string\" [<milliseconds>]",
  53.     "speed",    dodial_speed,    0, 2, "speed <bps>",
  54.     "status",    dodial_status, 0, 2, "status up | down",
  55.     "wait",        dodial_wait,    0, 2,
  56.     "wait <milliseconds> [ \"string\" [speed] ]",
  57.     NULLCHAR,    NULLFP,        0, 0, "Unknown command",
  58. };
  59.  
  60.  
  61. /* dial <iface> <filename> [ <seconds> [ <pings> [<hostid>] ] ]
  62.  *    <iface>        must be asy type
  63.  *    <filename>    contains commands which are executed.
  64.  *            missing: kill outstanding dialer.
  65.  *    <seconds>    interval to check for activity on <iface>.
  66.  *    <pings>     number of missed pings before redial.
  67.  *    <hostid>    interface to ping.
  68.  */
  69. int
  70. dodialer(argc,argv,p)
  71. int argc;
  72. char *argv[];
  73. void *p;
  74. {
  75.     struct iface *ifp;
  76.     struct asy *ap;
  77.     int32 interval = 0L;        /* in seconds */
  78.     int32 last_wait = 0L;
  79.     int32 target = 0L;
  80.     int pings = 0;
  81.     int countdown;
  82.     char *filename;
  83.     char *ifn;
  84.     int result;
  85.     int s;
  86.  
  87.     if((ifp = if_lookup(argv[1])) == NULLIF){
  88.         tprintf("Interface %s unknown\n",argv[1]);
  89.         return 1;
  90.     }
  91.     if( ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp ){
  92.         tprintf("Interface %s not asy port\n",argv[1]);
  93.         return 1;
  94.     }
  95.  
  96.     if(ifp->supv != NULLPROC){
  97.         while ( ifp->supv != NULLPROC ) {
  98.             alert(ifp->supv, EABORT);
  99.             pwait(NULL);
  100.         }
  101.         tprintf("dialer terminated on %s\n",argv[1]);
  102.     }
  103.  
  104.     if ( argc < 3 ) {
  105.         /* just terminating */
  106.         return 0;
  107.     }
  108.  
  109.     chname( Curproc, ifn = if_name( ifp, " dialer" ) );
  110.     free( ifn );
  111.     filename = rootdircat(argv[2]);
  112.  
  113.     /* handle minimal command (just thru filename) */
  114.     if ( argc < 4 ) {
  115.         /* just dialing */
  116.         result = redial(ifp, filename);
  117.  
  118.         if ( filename != argv[2] )
  119.             free(filename);
  120.         return result;
  121.  
  122.     /* get polling interval (arg 3) */
  123.     } else if ( (interval = atol(argv[3])) <= MIN_INTERVAL ) {
  124.         tprintf("interval must be > %d seconds\n", MIN_INTERVAL);
  125.         return 1;
  126.     }
  127.  
  128.     /* get the number of pings before redialing (arg 4) */
  129.     if ( argc < 5 ) {
  130.     } else if ( (pings = atoi(argv[4])) <= 0 ){
  131.         tprintf("pings must be > 0\n");
  132.         return 1;
  133.     }
  134.  
  135.     /* retrieve the host name (arg 5) */
  136.     if ( argc < 6 ) {
  137.     } else if ( (target = resolve(argv[5])) == 0L ) {
  138.         tprintf(Badhost,argv[5]);
  139.         return 1;
  140.     }
  141.  
  142.     countdown = pings;
  143.     ifp->supv = Curproc;
  144.     ap = &Asy[ ifp->dev ];
  145.  
  146.     while ( !main_exit ) {
  147.         int32 wait_for = interval;
  148.  
  149.         if ( ap->dtr_usage == FOUND_DOWN
  150.          ||  ap->dtr_usage == MOVED_DOWN
  151.          ||  ap->rlsd_line_control == MOVED_DOWN ) {
  152.             /* definitely down */
  153.             if ( redial(ifp,filename) < 0 )
  154.                 break;
  155.         } else if ( ifp->lastrecv >= last_wait ) {
  156.             /* got something recently */
  157.             wait_for -= secclock() - ifp->lastrecv;
  158.             countdown = pings;
  159.         } else if ( countdown < 1 ) {
  160.             /* we're down, or host we ping is down */
  161.             if ( redial(ifp,filename) < 0 )
  162.                 break;
  163.             countdown = pings;
  164.         } else if ( target != 0L
  165.            && (s = socket(AF_INET,SOCK_RAW,ICMP_PTCL)) != -1 ) {
  166.             pingem(s,target,0,(int16)s,0);
  167.             close_s(s);
  168.             countdown--;
  169.         } else if ( ifp->echo != NULLFP ) {
  170.             (*ifp->echo)(ifp,NULLBUF);
  171.             countdown--;
  172.         }
  173.  
  174.         last_wait = secclock();
  175.         if ( wait_for != 0L ) {
  176.             alarm( wait_for * 1000L );
  177.             if ( pwait( &(ifp->supv) ) == EABORT )
  178.                 break;
  179.             alarm(0L);        /* clear alarm */
  180.         }
  181.     }
  182.  
  183.     if ( filename != argv[2] )
  184.         free(filename);
  185.     ifp->supv = NULLPROC;    /* We're being terminated */
  186.     return 0;
  187. }
  188.  
  189.  
  190. /* execute dialer commands
  191.  * returns: -1 fatal error, 0 OK, 1 try again
  192.  */
  193. static int
  194. redial( ifp, file )
  195. struct iface *ifp;
  196. char *file;
  197. {
  198.     char *inbuf, *intmp;
  199.     FILE *fp;
  200.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  201.     struct session *sp;
  202.     int result = 0;
  203.     int save_input = Curproc->input;
  204.     int save_output = Curproc->output;
  205.  
  206.     if((fp = fopen(file,READ_TEXT)) == NULLFILE){
  207.         tprintf("redial: can't read %s\n",file);
  208.         return -1;    /* Causes dialer proc to terminate */
  209.     }
  210.     /* Save output handler and temporarily redirect output to null */
  211.     if(ifp->raw == bitbucket){
  212.         tprintf("redial: tip or dialer already active on %s\n",ifp->name);
  213.         return -1;
  214.     }
  215.  
  216.     /* allocate a session descriptor */
  217.     if ( (sp = newsession( ifp->name, DIAL )) == NULLSESSION ) {
  218.         tprintf( "Too many sessions\n" );
  219.         return 1;
  220.     }
  221.     tprintf( "Dialing on %s\n\n", ifp->name );
  222.  
  223.     /* Save output handler and temporarily redirect output to null */
  224.     rawsave = ifp->raw;
  225.     ifp->raw = bitbucket;
  226.  
  227.     /* Suspend the packet input driver. Note that the transmit driver
  228.      * is left running since we use it to send buffers to the line.
  229.      */
  230.     suspend(ifp->rxproc);
  231.  
  232. #ifdef notdef
  233. tprintf("rlsd: 0x%02x, dtr: 0x%02x\n",
  234.     Asy[ifp->dev].rlsd_line_control,
  235.     Asy[ifp->dev].dtr_usage );
  236. #endif
  237.  
  238.     inbuf = mallocw(BUFSIZ);
  239.     intmp = mallocw(BUFSIZ);
  240.     while ( fgets( inbuf, BUFSIZ, fp ) != NULLCHAR ) {
  241.         strcpy(intmp,inbuf);
  242.         rip( intmp );
  243.         log( -1, "%s dialer: %s", ifp->name, intmp );
  244.         if( (result = cmdparse(dial_cmds,inbuf,ifp)) != 0 ){
  245.             tprintf("input line: %s",intmp);
  246.             break;
  247.         }
  248.     }
  249.     free(inbuf);
  250.     free(intmp);
  251.     fclose(fp);
  252.  
  253.     if ( result == 0 ) {
  254.         ifp->lastsent = ifp->lastrecv = secclock();
  255.     }
  256.  
  257.     ifp->raw = rawsave;
  258.     resume(ifp->rxproc);
  259.     tprintf( "\nDial %s complete\n", ifp->name );
  260.  
  261.     /* Wait for awhile, so the user can read the screen,
  262.      * AND to give it time to send some packets on the new connection!
  263.      */
  264.     pause( 10000L );
  265.     freesession( sp );
  266.     Curproc->input = save_input;
  267.     Curproc->output = save_output;
  268.     return result;
  269. }
  270.  
  271.  
  272. static int
  273. dodial_control(argc,argv,p)
  274. int argc;
  275. char *argv[];
  276. void *p;
  277. {
  278.     struct iface *ifp = p;
  279.     int param;
  280.  
  281.     if ( ifp->ioctl == NULL )
  282.         return -1;
  283.  
  284.     if ( (param = devparam( argv[1] )) == -1 )
  285.         return -1;
  286.  
  287.     (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
  288.     return 0;
  289. }
  290.  
  291.  
  292. static int
  293. dodial_send(argc,argv,p)
  294. int argc;
  295. char *argv[];
  296. void *p;
  297. {
  298.     struct iface *ifp = p;
  299.     struct mbuf *bp;
  300.  
  301.     if(argc > 2){
  302.         /* Send characters with inter-character delay
  303.          * (for dealing with prehistoric Micom switches that
  304.          * can't take back-to-back characters...yes, they
  305.          * still exist.)
  306.          */
  307.         char *cp;
  308.         int32 cdelay = atol(argv[2]);
  309.  
  310.         for(cp = argv[1];*cp != '\0';cp++){
  311.             bp = qdata(cp,1);
  312.             asy_send(ifp->dev,bp);
  313.             pause(cdelay);
  314.         }
  315.     } else {
  316.         bp = qdata( argv[1], strlen(argv[1]) );
  317.  
  318.         if (ifp->trace & IF_TRACE_RAW)
  319.             raw_dump( ifp, IF_TRACE_OUT, bp );
  320.         asy_send( ifp->dev, bp );
  321.     }
  322.     return 0;
  323. }
  324.  
  325.  
  326. static int
  327. dodial_speed(argc,argv,p)
  328. int argc;
  329. char *argv[];
  330. void *p;
  331. {
  332.     struct iface *ifp = p;
  333.  
  334.     if ( argc < 2 ) {
  335.         tprintf( "current speed = %u bps\n", Asy[ifp->dev].speed );
  336.         return 0;
  337.     }
  338.     return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
  339. }
  340.  
  341.  
  342. static int
  343. dodial_status(argc,argv,p)
  344. int argc;
  345. char *argv[];
  346. void *p;
  347. {
  348.     struct iface *ifp = p;
  349.     int param;
  350.  
  351.     if ( ifp->iostatus == NULL )
  352.         return -1;
  353.  
  354.     if ( (param = devparam( argv[1] )) == -1 )
  355.         return -1;
  356.  
  357.     (*ifp->iostatus)( ifp, param, atol( argv[2] ) );
  358.     return 0;
  359. }
  360.  
  361.  
  362. static int
  363. dodial_wait(argc,argv,p)
  364. int argc;
  365. char *argv[];
  366. void *p;
  367. {
  368.     struct iface *ifp = p;
  369.     register int c = -1;
  370.  
  371.     alarm( atol( argv[1] ) );
  372.  
  373.     if ( argc == 2 ) {
  374.         while ( (c = get_asy(ifp->dev)) != -1 ) {
  375.             tputc( c &= 0x7F );
  376.             tflush();
  377.         }
  378.         alarm( 0L );
  379.         return 0;
  380.     } else {
  381.         register char *cp = argv[2];
  382.  
  383.         while ( *cp != '\0'  &&  (c = get_asy(ifp->dev)) != -1 ) {
  384.             tputc( c &= 0x7F );
  385.             tflush();
  386.  
  387.             if (*cp++ != c) {
  388.                 cp = argv[2];
  389.             }
  390.         }
  391.  
  392.         if ( argc > 3 ) {
  393.             if ( stricmp( argv[3], "speed" ) == 0 ){
  394.                 int16 speed = 0;
  395.  
  396.                 while ( (c = get_asy(ifp->dev)) != -1 ) {
  397.                     tputc( c &= 0x7F );
  398.                     tflush();
  399.  
  400.                     if ( isdigit(c) ) {
  401.                         speed *= 10;
  402.                         speed += c - '0';
  403.                     } else {
  404.                         alarm( 0L );
  405.                         return asy_speed( ifp->dev, speed );
  406.                     }
  407.                 }
  408.             } else {
  409.                 return -1;
  410.             }
  411.         }
  412.     }
  413.     alarm( 0L );
  414.     return ( c == -1 );
  415. }
  416.  
  417.  
  418.