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