home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
misc
/
src0131
/
dialer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-26
|
4KB
|
171 lines
/* 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);
}
}