home *** CD-ROM | disk | FTP | other *** search
- /* Automatic SLIP/PPP line dialer.
- *
- * Copyright 1991 Phil Karn, KA9Q
- *
- * Mar '91 Bill Simpson & Glenn McGregor
- * completely re-written;
- * human readable control file;
- * includes wait for string, and speed sense;
- * dials immediately when invoked.
- * May '91 Bill Simpson
- * re-ordered command line;
- * allow dial only;
- * allow inactivity timeout without ping.
- * Sep '91 Bill Simpson
- * Check known DTR & RSLD state for redial decision
- */
- #include <stdio.h>
- #include <ctype.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "proc.h"
- #include "iface.h"
- #include "netuser.h"
- #include "8250.h"
- #include "asy.h"
- #include "tty.h"
- #include "session.h"
- #include "socket.h"
- #include "cmdparse.h"
- #include "devparam.h"
- #include "icmp.h"
- #include "files.h"
- #include "main.h"
- #include "trace.h"
-
- #define MIN_INTERVAL 5L
-
- static int redial __ARGS((struct iface *ifp,char *file));
-
- static int dodial_control __ARGS((int argc,char *argv[],void *p));
- static int dodial_send __ARGS((int argc,char *argv[],void *p));
- static int dodial_speed __ARGS((int argc,char *argv[],void *p));
- static int dodial_status __ARGS((int argc,char *argv[],void *p));
- static int dodial_wait __ARGS((int argc,char *argv[],void *p));
-
-
- static struct cmds dial_cmds[] = {
- "control", dodial_control, 0, 2, "control up | down",
- "send", dodial_send, 0, 2,
- "send \"string\" [<milliseconds>]",
- "speed", dodial_speed, 0, 2, "speed <bps>",
- "status", dodial_status, 0, 2, "status up | down",
- "wait", dodial_wait, 0, 2,
- "wait <milliseconds> [ \"string\" [speed] ]",
- NULLCHAR, NULLFP, 0, 0, "Unknown command",
- };
-
-
- /* dial <iface> <filename> [ <seconds> [ <pings> [<hostid>] ] ]
- * <iface> must be asy type
- * <filename> contains commands which are executed.
- * missing: kill outstanding dialer.
- * <seconds> interval to check for activity on <iface>.
- * <pings> number of missed pings before redial.
- * <hostid> interface to ping.
- */
- int
- dodialer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- struct asy *ap;
- int32 interval = 0L; /* in seconds */
- int32 last_wait = 0L;
- int32 target = 0L;
- int pings = 0;
- int countdown;
- char *filename;
- char *ifn;
- int result;
- int s;
-
- if((ifp = if_lookup(argv[1])) == NULLIF){
- tprintf("Interface %s unknown\n",argv[1]);
- return 1;
- }
- if( ifp->dev >= ASY_MAX || Asy[ifp->dev].iface != ifp ){
- tprintf("Interface %s not asy port\n",argv[1]);
- return 1;
- }
-
- if(ifp->supv != NULLPROC){
- while ( ifp->supv != NULLPROC ) {
- alert(ifp->supv, EABORT);
- pwait(NULL);
- }
- tprintf("dialer terminated on %s\n",argv[1]);
- }
-
- if ( argc < 3 ) {
- /* just terminating */
- return 0;
- }
-
- chname( Curproc, ifn = if_name( ifp, " dialer" ) );
- free( ifn );
- filename = rootdircat(argv[2]);
-
- /* handle minimal command (just thru filename) */
- if ( argc < 4 ) {
- /* just dialing */
- result = redial(ifp, filename);
-
- if ( filename != argv[2] )
- free(filename);
- return result;
-
- /* get polling interval (arg 3) */
- } else if ( (interval = atol(argv[3])) <= MIN_INTERVAL ) {
- tprintf("interval must be > %d seconds\n", MIN_INTERVAL);
- return 1;
- }
-
- /* get the number of pings before redialing (arg 4) */
- if ( argc < 5 ) {
- } else if ( (pings = atoi(argv[4])) <= 0 ){
- tprintf("pings must be > 0\n");
- return 1;
- }
-
- /* retrieve the host name (arg 5) */
- if ( argc < 6 ) {
- } else if ( (target = resolve(argv[5])) == 0L ) {
- tprintf(Badhost,argv[5]);
- return 1;
- }
-
- countdown = pings;
- ifp->supv = Curproc;
- ap = &Asy[ ifp->dev ];
-
- while ( !main_exit ) {
- int32 wait_for = interval;
-
- if ( ap->dtr_usage == FOUND_DOWN
- || ap->dtr_usage == MOVED_DOWN
- || ap->rlsd_line_control == MOVED_DOWN ) {
- /* definitely down */
- if ( redial(ifp,filename) < 0 )
- break;
- } else if ( ifp->lastrecv >= last_wait ) {
- /* got something recently */
- wait_for -= secclock() - ifp->lastrecv;
- countdown = pings;
- } else if ( countdown < 1 ) {
- /* we're down, or host we ping is down */
- if ( redial(ifp,filename) < 0 )
- break;
- countdown = pings;
- } else if ( target != 0L
- && (s = socket(AF_INET,SOCK_RAW,ICMP_PTCL)) != -1 ) {
- pingem(s,target,0,(int16)s,0);
- close_s(s);
- countdown--;
- } else if ( ifp->echo != NULLFP ) {
- (*ifp->echo)(ifp,NULLBUF);
- countdown--;
- }
-
- last_wait = secclock();
- if ( wait_for != 0L ) {
- alarm( wait_for * 1000L );
- if ( pwait( &(ifp->supv) ) == EABORT )
- break;
- alarm(0L); /* clear alarm */
- }
- }
-
- if ( filename != argv[2] )
- free(filename);
- ifp->supv = NULLPROC; /* We're being terminated */
- return 0;
- }
-
-
- /* execute dialer commands
- * returns: -1 fatal error, 0 OK, 1 try again
- */
- static int
- redial( ifp, file )
- struct iface *ifp;
- char *file;
- {
- char *inbuf, *intmp;
- FILE *fp;
- int (*rawsave) __ARGS((struct iface *,struct mbuf *));
- struct session *sp;
- int result = 0;
- int save_input = Curproc->input;
- int save_output = Curproc->output;
-
- if((fp = fopen(file,READ_TEXT)) == NULLFILE){
- tprintf("redial: can't read %s\n",file);
- return -1; /* Causes dialer proc to terminate */
- }
- /* Save output handler and temporarily redirect output to null */
- if(ifp->raw == bitbucket){
- tprintf("redial: tip or dialer already active on %s\n",ifp->name);
- return -1;
- }
-
- /* allocate a session descriptor */
- if ( (sp = newsession( ifp->name, DIAL )) == NULLSESSION ) {
- tprintf( "Too many sessions\n" );
- return 1;
- }
- tprintf( "Dialing on %s\n\n", ifp->name );
-
- /* Save output handler and temporarily redirect output to null */
- rawsave = ifp->raw;
- ifp->raw = bitbucket;
-
- /* Suspend the packet input driver. Note that the transmit driver
- * is left running since we use it to send buffers to the line.
- */
- suspend(ifp->rxproc);
-
- #ifdef notdef
- tprintf("rlsd: 0x%02x, dtr: 0x%02x\n",
- Asy[ifp->dev].rlsd_line_control,
- Asy[ifp->dev].dtr_usage );
- #endif
-
- inbuf = mallocw(BUFSIZ);
- intmp = mallocw(BUFSIZ);
- while ( fgets( inbuf, BUFSIZ, fp ) != NULLCHAR ) {
- strcpy(intmp,inbuf);
- rip( intmp );
- log( -1, "%s dialer: %s", ifp->name, intmp );
- if( (result = cmdparse(dial_cmds,inbuf,ifp)) != 0 ){
- tprintf("input line: %s",intmp);
- break;
- }
- }
- free(inbuf);
- free(intmp);
- fclose(fp);
-
- if ( result == 0 ) {
- ifp->lastsent = ifp->lastrecv = secclock();
- }
-
- ifp->raw = rawsave;
- resume(ifp->rxproc);
- tprintf( "\nDial %s complete\n", ifp->name );
-
- /* Wait for awhile, so the user can read the screen,
- * AND to give it time to send some packets on the new connection!
- */
- pause( 10000L );
- freesession( sp );
- Curproc->input = save_input;
- Curproc->output = save_output;
- return result;
- }
-
-
- static int
- dodial_control(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp = p;
- int param;
-
- if ( ifp->ioctl == NULL )
- return -1;
-
- if ( (param = devparam( argv[1] )) == -1 )
- return -1;
-
- (*ifp->ioctl)( ifp, param, TRUE, atol( argv[2] ) );
- return 0;
- }
-
-
- static int
- dodial_send(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp = p;
- struct mbuf *bp;
-
- if(argc > 2){
- /* Send characters with inter-character delay
- * (for dealing with prehistoric Micom switches that
- * can't take back-to-back characters...yes, they
- * still exist.)
- */
- char *cp;
- int32 cdelay = atol(argv[2]);
-
- for(cp = argv[1];*cp != '\0';cp++){
- bp = qdata(cp,1);
- asy_send(ifp->dev,bp);
- pause(cdelay);
- }
- } else {
- bp = qdata( argv[1], strlen(argv[1]) );
-
- if (ifp->trace & IF_TRACE_RAW)
- raw_dump( ifp, IF_TRACE_OUT, bp );
- asy_send( ifp->dev, bp );
- }
- return 0;
- }
-
-
- static int
- dodial_speed(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp = p;
-
- if ( argc < 2 ) {
- tprintf( "current speed = %u bps\n", Asy[ifp->dev].speed );
- return 0;
- }
- return asy_speed( ifp->dev, (int16)atol( argv[1] ) );
- }
-
-
- static int
- dodial_status(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp = p;
- int param;
-
- if ( ifp->iostatus == NULL )
- return -1;
-
- if ( (param = devparam( argv[1] )) == -1 )
- return -1;
-
- (*ifp->iostatus)( ifp, param, atol( argv[2] ) );
- return 0;
- }
-
-
- static int
- dodial_wait(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp = p;
- register int c = -1;
-
- alarm( atol( argv[1] ) );
-
- if ( argc == 2 ) {
- while ( (c = get_asy(ifp->dev)) != -1 ) {
- tputc( c &= 0x7F );
- tflush();
- }
- alarm( 0L );
- return 0;
- } else {
- register char *cp = argv[2];
-
- while ( *cp != '\0' && (c = get_asy(ifp->dev)) != -1 ) {
- tputc( c &= 0x7F );
- tflush();
-
- if (*cp++ != c) {
- cp = argv[2];
- }
- }
-
- if ( argc > 3 ) {
- if ( stricmp( argv[3], "speed" ) == 0 ){
- int16 speed = 0;
-
- while ( (c = get_asy(ifp->dev)) != -1 ) {
- tputc( c &= 0x7F );
- tflush();
-
- if ( isdigit(c) ) {
- speed *= 10;
- speed += c - '0';
- } else {
- alarm( 0L );
- return asy_speed( ifp->dev, speed );
- }
- }
- } else {
- return -1;
- }
- }
- }
- alarm( 0L );
- return ( c == -1 );
- }
-
-
-