home *** CD-ROM | disk | FTP | other *** search
- /* Automatic SLIP/PPP line redialer.
- * Very simpleminded - If a specified interval goes by without any
- * receiver activity, ping the other end. If this repeatedly fails,
- * spit a file containing modem commands at the line and try again.
- *
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "iface.h"
- #include "8250.h"
- #include "asy.h"
- #include "session.h"
- #include "proc.h"
- #include "tty.h"
- #include "socket.h"
- #include "commands.h"
- #include "netuser.h"
- #include "timer.h"
-
- static int redial __ARGS((struct iface *ifp,char *file));
- static void monitor __ARGS((int s,void *v1,void *v2));
-
- int
- dodialer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int s;
- struct iface *ifp;
- int32 target;
- int32 interval;
- int dev;
- struct asy *ap;
-
- if((ifp = if_lookup(argv[1])) == NULLIF){
- tprintf("Interface %s unknown\n",argv[1]);
- return 1;
- }
- for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
- if(ap->iface == ifp)
- break;
- if(dev == ASY_MAX){
- tprintf("Interface %s not asy port\n",argv[1]);
- return 1;
- }
- if((interval = atol(argv[2])) == 0){
- if(ifp->supv != NULLPROC){
- alert(ifp->supv,1);
- tprintf("dialer terminated on %s\n",argv[1]);
- } else {
- tprintf("no dialer active on %s\n",argv[1]);
- }
- return 0;
- }
- if(argc < 5){
- tprintf("not enough args\n");
- return -1;
- }
- if(ifp->supv != NULLPROC){
- tprintf("dialer already active on %s\n",argv[1]);
- return 1;
- }
- if((target = resolve(argv[3])) == 0){
- tprintf(Badhost,argv[3]);
- return 1;
- }
- ifp->supv = Curproc;
-
- for(;;){
- if((s = pause(interval*1000)) != 0){ /* Wait a while */
- break; /* We're being terminated */
- }
- if(secclock() - ifp->lastrecv > 4*interval){
- /* Receiver has remained idle after four pings;
- * assume the connection has dropped.
- */
- if(redial(ifp,argv[4]) != 0)
- break;
- }
- if(secclock() - ifp->lastrecv > interval){
- /* Receiver has been idle since last check */
- if((s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1)
- continue; /* Wait and try again */
- pingem(s,target,0,(int16)s,0);
- close_s(s);
- }
- }
- ifp->supv = NULLPROC;
- return 0;
- }
- static int
- redial(ifp,file)
- struct iface *ifp;
- char *file;
- {
- FILE *fp;
- struct mbuf *bp;
- int32 delay;
- int c;
- int (*rawsave) __ARGS((struct iface *,struct mbuf *));
- struct proc *mon;
- int err_ret = 0;
-
- 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 == dumppkt){
- tprintf("redial: tip or dialer already active on %s\n",ifp->name);
- return -1;
- }
- rawsave = ifp->raw;
- ifp->raw = dumppkt;
-
- /* 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);
-
- /* Start up monitor so we can see what's happening */
- mon = newproc("dial monitor",300,monitor,0,(void *)ifp,NULL,0);
-
- while((c = getc(fp)) != EOF){
- if(c == '\\'){
- /* delay escape */
- delay = 0;
- while(c = getc(fp),c != EOF && c != 'd'){
- delay = delay * 10 + (c-'0');
- }
- if(c == EOF)
- break;
- if(pause(delay) != 0){
- err_ret = 1;
- break;
- }
- continue;
- }
- if(c == EOF)
- break; /* Normal termination */
- if(c == '\n')
- c = '\r';
- bp = pushdown(NULLBUF,1);
- bp->data[0] = c;
- asy_send(ifp->dev,bp);
- }
- fclose(fp);
- killproc(mon);
- ifp->raw = rawsave;
- resume(ifp->rxproc);
- return err_ret;
- }
- static void
- monitor(s,v1,v2)
- int s;
- void *v1;
- void *v2;
- {
- int c;
- struct iface *ifp;
-
- ifp = (struct iface *)v1;
- while((c = get_asy(ifp->dev)) != -1){
- if(ifp->trace & IF_TRACE_IN)
- putchar(c & 0x7f);
- }
- }
-