home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Pier Shareware 6
/
The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso
/
024
/
psi110g.zip
/
AX25CMD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
36KB
|
1,480 lines
/* AX25 control commands
* Copyright 1991 Phil Karn, KA9Q
*
* Mods by G1EMM
* Mods by PA0GRI
* Mods by N1BEE
*/
/*
** FILE: ax25cmd.c
**
** AX.25 command handler.
**
** 09/24/90 Bob Applegate, wa2zzx
** Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
** string using UI frames.
**
** 27/09/91 Mike Bilow, N1BEE
** Added Filter command for axheard control
*/
#ifdef MSDOS
#include <dos.h>
#endif
#include "global.h"
#ifdef AX25
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#include "ax25.h"
#include "lapb.h"
#include "cmdparse.h"
#include "socket.h"
#include "mailbox.h"
#include "session.h"
#include "tty.h"
#include "nr4.h"
#include "commands.h"
#include "pktdrvr.h"
#include "netrom.h"
int axheard __ARGS((struct iface *ifp));
static int doaxfilter __ARGS((int argc,char *argv[],void *p));
static int doaxflush __ARGS((int argc,char *argv[],void *p));
static int doaxirtt __ARGS((int argc,char *argv[],void *p));
static int doaxkick __ARGS((int argc,char *argv[],void *p));
static int doaxreset __ARGS((int argc,char *argv[],void *p));
static int doaxroute __ARGS((int argc,char *argv[],void *p));
int doaxstat __ARGS((int argc,char *argv[],void *p));
static int dobc __ARGS((int argc,char *argv[],void *p));
static int dobcint __ARGS((int argc,char *argv[],void *p));
static int dobcport __ARGS((int argc,char *argv[],void *p));
static int dobctext __ARGS((int argc,char *argv[],void *p));
static int doaxhport __ARGS((int argc,char *argv[],void *p));
static int doaxhsize __ARGS((int argc,char *argv[],void *p));
static int dodigipeat __ARGS((int argc,char *argv[],void *p));
static int domycall __ARGS((int argc,char *argv[],void *p));
static int dobbscall __ARGS((int argc,char *argv[],void *p));
int donralias __ARGS((int argc,char *argv[],void *p));
static void ax_bc __ARGS((struct iface *axif));
static int axdest __ARGS((struct iface *ifp));
#ifdef TTYCALL
static int dottycall __ARGS((int argc, char *argv[], void *p));
#endif
static int doaxwindow __ARGS((int argc,char *argv[],void *p));
static int doblimit __ARGS((int argc,char *argv[],void *p));
static int domaxframe __ARGS((int argc,char *argv[],void *p));
static int don2 __ARGS((int argc,char *argv[],void *p));
static int dopaclen __ARGS((int argc,char *argv[],void *p));
static int dopthresh __ARGS((int argc,char *argv[],void *p));
static int dot3 __ARGS((int argc,char *argv[],void *p));
static int doaxtype __ARGS((int argc,char *argv[],void *p));
static int dot4 __ARGS((int argc,char *argv[],void *p));
static int doversion __ARGS((int argc,char *argv[],void *p));
static int doaxmaxwait __ARGS((int argc,char *argv[],void *p));
long Axmaxwait;
extern char Myalias[AXALEN]; /* the NETROM alias in 'call' form */
extern char Nralias[ALEN+1]; /* the NETROM alias in 'alias' form */
#ifdef TTYCALL
extern char Ttycall[AXALEN]; /* the ttylink call in 'call' form */
#endif
extern int axheard_filter_flag; /* in axheard.c */
/* Defaults for IDing. */
char *axbctext; /* Text to send */
static struct timer Broadtimer; /* timer for broadcasts */
char *Ax25states[] = {
"",
"Disconnected",
"Listening",
"Conn pending",
"Disc pending",
"Connected",
"Recovery",
};
/* Ascii explanations for the disconnect reasons listed in lapb.h under
* "reason" in ax25_cb
*/
char *Axreasons[] = {
"Normal",
"DM received",
"Timeout"
};
static struct cmds DFAR Axcmds[] = {
"alias", donralias, 0, 0, NULLCHAR,
#ifdef MAILBOX
"bbscall", dobbscall, 0, 0, NULLCHAR,
#endif
"bc", dobc, 0, 0, NULLCHAR,
"bcinterval",dobcint, 0, 0, NULLCHAR,
"bcport", dobcport, 0, 0, NULLCHAR,
"blimit", doblimit, 0, 0, NULLCHAR,
"bctext", dobctext, 0, 0, NULLCHAR,
"dest", doaxdest, 0, 0, NULLCHAR,
"digipeat", dodigipeat, 0, 0, NULLCHAR,
"filter", doaxfilter, 0, 0, NULLCHAR,
"flush", doaxflush, 0, 0, NULLCHAR,
"heard", doaxheard, 0, 0, NULLCHAR,
"hearddest", doaxdest, 0, 0, NULLCHAR,
"hport", doaxhport, 0, 0, NULLCHAR,
"hsize", doaxhsize, 0, 0, NULLCHAR,
"irtt", doaxirtt, 0, 0, NULLCHAR,
"kick", doaxkick, 0, 2, "ax25 kick <axcb>",
"maxframe", domaxframe, 0, 0, NULLCHAR,
"maxwait", doaxmaxwait, 0, 0, NULLCHAR,
"mycall", domycall, 0, 0, NULLCHAR,
"paclen", dopaclen, 0, 0, NULLCHAR,
"pthresh", dopthresh, 0, 0, NULLCHAR,
"reset", doaxreset, 0, 2, "ax25 reset <axcb>",
"retry", don2, 0, 0, NULLCHAR,
"route", doaxroute, 0, 0, NULLCHAR,
"status", doaxstat, 0, 0, NULLCHAR,
"t3", dot3, 0, 0, NULLCHAR,
"t4", dot4, 0, 0, NULLCHAR,
"timertype", doaxtype, 0, 0, NULLCHAR,
#ifdef TTYCALL
"ttycall", dottycall, 0, 0, NULLCHAR,
#endif
"version", doversion, 0, 0, NULLCHAR,
"window", doaxwindow, 0, 0, NULLCHAR,
NULLCHAR,
};
/* Multiplexer for top-level ax25 command */
int
doax25(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return subcmd(Axcmds,argc,argv,p);
}
/* define the system's alias callsign ,
* if netrom is used, this is also the netrom alias ! - WG7J
*/
#ifdef MAILBOX
extern char Mbnrid[];
extern void setmbnrid();
#endif
int
donralias(argc,argv,p)
int argc ;
char *argv[] ;
void *p;
{
int len;
char tmp[AXBUF];
if(argc < 2) {
tprintf("%s\n",pax25(tmp,Myalias));
return 0;
}
if( (setcall(Myalias,argv[1]) == -1)
#ifdef NETROM
|| (putalias(Nralias,argv[1],1) == -1)
#endif
){
tputs("can't set alias\n");
Myalias[0] = '\0';
#ifdef NETROM
Nralias[0] = '\0';
#endif
return 0;
}
#ifdef MAILBOX
setmbnrid();
#endif
return 0;
}
/*
** This function is called to send the current broadcast message
** and reset the timer.
*/
static int dobc(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifa;
if (argc < 2)
{
tprintf("you need to specify an interface\n");
return 1;
}
if((ifa=if_lookup(argv[1])) == NULLIF)
tprintf(Badinterface,argv[1]);
else if (ifa->type != CL_AX25)
tputs("not an AX.25 interface\n");
else
{
ax_bc(ifa);
stop_timer(&Broadtimer) ; /* in case it's already running */
start_timer(&Broadtimer); /* and fire it up */
}
return 0;
}
/*
** View/Change the message we broadcast.
*/
static int dobctext(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
if (argc < 2) {
if(axbctext)
tprintf("Broadcast text: %s\n",axbctext);
else
tputs("not set\n");
} else {
if (axbctext != NULL)
free(axbctext);
axbctext = strdup(argv[1]);
/* Set all ax.25 interfaces with no bc text */
for(ifp=Ifaces;ifp->next;ifp=ifp->next)
if(ifp->type == CL_AX25 && ifp->ax25->bctext == NULL)
ifp->ax25->bctext = strdup(axbctext);
}
return 0;
}
#define TICKSPERSEC (1000L / MSPTICK) /* Ticks per second */
/*
** Examine/change the broadcast interval.
*/
static int dobcint(argc,argv,p)
int argc;
char *argv[];
void *p;
{
void dobroadtick();
if(argc < 2)
{
tprintf("Broadcast timer %lu/%lu seconds\n",
read_timer(&Broadtimer)/1000L,
dur_timer(&Broadtimer)/1000L);
return 0;
}
stop_timer(&Broadtimer) ; /* in case it's already running */
Broadtimer.func = (void (*)())dobroadtick;/* what to call on timeout */
Broadtimer.arg = NULLCHAR; /* dummy value */
set_timer(&Broadtimer,atoi(argv[1])*1000L); /* set timer duration */
start_timer(&Broadtimer); /* and fire it up */
return 0;
}
/* Configure a port to do ax.25 beacon broadcasting */
static int
dobcport(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setflag(argc,argv[1],AX25_BEACON,argv[2]);
}
int Maxax25heard;
/* Set the size of the ax.25 heard list */
int doaxhsize(int argc,char *argv[],void *p) {
return setint(&Maxax25heard,"Max ax-heard",argc,argv);
}
/* Configure a port to do ax.25 heard logging */
static int
doaxhport(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setflag(argc,argv[1],LOG_AXHEARD,argv[2]);
}
void
dobroadtick()
{
struct iface *ifa;
ifa = Ifaces;
while (ifa != NULL)
{
if (ifa->flags & AX25_BEACON)
ax_bc(ifa);
ifa = ifa->next;
}
/* Restart timer */
start_timer(&Broadtimer) ;
}
/*
** This is the low-level broadcast function.
*/
static void ax_bc(axiface)
struct iface *axiface;
{
struct mbuf *hbp;
int i;
/* prepare the header */
i = 0;
if(axiface->ax25->bctext)
i = strlen(axiface->ax25->bctext);
if((hbp = alloc_mbuf(i)) == NULLBUF)
return;
hbp->cnt = i;
if(i)
memcpy(hbp->data,axiface->ax25->bctext,i);
(*axiface->output)(axiface, Ax25multi[IDCALL], axiface->hwaddr,
PID_NO_L3, hbp); /* send it */
/*
** Call another function to reset the timer...
reset_bc_timer();
*/
}
int
doaxheard(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
if(argc > 1){
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badinterface,argv[1]);
return 1;
}
if(ifp->type != CL_AX25){
tprintf("Interface %s not AX.25\n",argv[1]);
return 1;
}
if(ifp->flags & LOG_AXHEARD)
axheard(ifp);
else
tputs("not active\n");
return 0;
}
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
if(ifp->type != CL_AX25 || !(ifp->flags & LOG_AXHEARD))
continue; /* Not an ax.25 interface */
if(axheard(ifp) == EOF)
break;
}
return 0;
}
int
axheard(ifp)
struct iface *ifp;
{
int col = 0;
struct lq *lp;
char tmp[AXBUF];
if(ifp->hwaddr == NULLCHAR)
return 0;
tputs("Interface Station Time since send Pkts sent\n");
tprintf("%-9s %-9s %12s %7lu\n",ifp->name,pax25(tmp,ifp->hwaddr),
tformat(secclock() - ifp->lastsent),ifp->rawsndcnt);
tputs("Station Time since heard Pkts rcvd : ");
tputs("Station Time since heard Pkts rcvd\n");
for(lp = Lq;lp != NULLLQ;lp = lp->next){
if(lp->iface != ifp)
continue;
if(col)
tputs(" : ");
if(tprintf("%-9s %12s %7lu",pax25(tmp,lp->addr),
tformat(secclock() - lp->time),lp->currxcnt) == EOF)
return EOF;
if(col){
if(tputc('\n') == EOF){
return EOF;
} else {
col = 0;
}
} else {
col = 1;
}
}
if(col)
tputc('\n');
return 0;
}
int
doaxdest(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
if(argc > 1){
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badinterface,argv[1]);
return 1;
}
if(ifp->output != ax_output){
tprintf("Interface %s not AX.25\n",argv[1]);
return 1;
}
axdest(ifp);
return 0;
}
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
if(ifp->output != ax_output)
continue; /* Not an ax.25 interface */
if(axdest(ifp) == EOF)
break;
}
return 0;
}
static int
axdest(ifp)
struct iface *ifp;
{
struct ld *lp;
struct lq *lq;
char tmp[AXBUF];
if(ifp->hwaddr == NULLCHAR)
return 0;
tprintf("%s:\n",ifp->name);
tputs("Station Last ref Last heard Pkts\n");
for(lp = Ld;lp != NULLLD;lp = lp->next){
if(lp->iface != ifp)
continue;
tprintf("%-10s%-17s",
pax25(tmp,lp->addr),tformat(secclock() - lp->time));
if(addreq(lp->addr,ifp->hwaddr)){
/* Special case; it's our address */
tprintf("%-17s",tformat(secclock() - ifp->lastsent));
} else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
tprintf("%-17s","");
} else {
tprintf("%-17s",tformat(secclock() - lq->time));
}
if(tprintf("%8lu\n",lp->currxcnt) == EOF)
return EOF;
}
return 0;
}
static int
doaxfilter(argc,argv,p)
int argc;
char *argv[];
void *p;
{
if(argc >= 2){
setint(&axheard_filter_flag,"ax25 heard filter",argc,argv);
} else {
tputs("Usage: ax25 filter <0|1|2|3>\n");
return 1;
}
tputs("Callsign loggin by source ");
if(axheard_filter_flag & AXHEARD_NOSRC)
tputs("disabled, ");
else
tputs("enabled, ");
tputs("by destination ");
if(axheard_filter_flag & AXHEARD_NODST)
tputs("disabled\n");
else
tputs("enabled\n");
return 0;
}
static int
doaxflush(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct lq *lp,*lp1;
struct ld *ld,*ld1;
for(lp = Lq;lp != NULLLQ;lp = lp1){
lp1 = lp->next;
free((char *)lp);
}
Lq = NULLLQ;
for(ld = Ld;ld != NULLLD;ld = ld1){
ld1 = ld->next;
free((char *)ld);
}
Ld = NULLLD;
return 0;
}
static int
doaxreset(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = MK_FP(htoi(argv[1]),8);
if(!ax25val(axp)){
tputs(Notval);
return 1;
}
reset_ax25(axp);
return 0;
}
/* Display AX.25 link level control blocks */
int
doaxstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct ax25_cb *axp;
char tmp[AXBUF];
char tmp2[AXBUF];
if(argc < 2){
#ifdef UNIX
tprintf("&AXB Snd-Q Rcv-Q Remote Local Iface State\n");
#else
tputs("&AXB Snd-Q Rcv-Q Remote Local Iface State\n");
#endif
for(axp = Ax25_cb;axp != NULLAX25; axp = axp->next){
#ifdef UNIX
if(tprintf("%8.8x %-8d%-8d%-10s%-10s%-7s%s\n",
#else
if(tprintf("%4.4x %-8d%-8d%-10s%-10s%-7s%s\n",
#endif
FP_SEG(axp),
len_q(axp->txq),len_p(axp->rxq),
pax25(tmp,axp->remote),
pax25(tmp2,axp->local),
axp->iface?axp->iface->name:"",
Ax25states[axp->state]) == EOF)
return 0;
}
return 0;
}
axp = MK_FP(htoi(argv[1]),8);
if(!ax25val(axp)){
tputs(Notval);
return 1;
}
st_ax25(axp);
return 0;
}
/* Dump one control block */
void
st_ax25(axp)
register struct ax25_cb *axp;
{
char tmp[AXBUF];
char tmp2[AXBUF];
if(axp == NULLAX25)
return;
#ifdef UNIX
tprintf("&AXB Local Remote Iface RB V(S) V(R) Unack P Retry State\n");
tprintf("%8.8x %-9s %-9s %-6s %c%c",FP_SEG(axp),
#else
tputs("&AXB Local Remote Iface RB V(S) V(R) Unack P Retry State\n");
tprintf("%4.4x %-9s %-9s %-6s %c%c",FP_SEG(axp),
#endif
pax25(tmp,axp->local),
pax25(tmp2,axp->remote),
axp->iface?axp->iface->name:"",
axp->flags.rejsent ? 'R' : ' ',
axp->flags.remotebusy ? 'B' : ' ');
tprintf(" %4d %4d",axp->vs,axp->vr);
tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
tprintf(" %02u/%02u",axp->retries,axp->n2);
tprintf(" %s\n",Ax25states[axp->state]);
tprintf("srtt = %lu mdev = %lu ",axp->srt,axp->mdev);
tputs("T1: ");
if(run_timer(&axp->t1))
tprintf("%lu",read_timer(&axp->t1));
else
tputs("stop");
tprintf("/%lu ms; ",dur_timer(&axp->t1));
tputs("T3: ");
if(run_timer(&axp->t3))
tprintf("%lu",read_timer(&axp->t3));
else
tputs("stop");
tprintf("/%lu ms; ",dur_timer(&axp->t3));
tputs("T4: ");
if(run_timer(&axp->t4))
tprintf("%lu",(read_timer(&axp->t4)/1000L));
else
tputs("stop");
tprintf("/%lu sec\n",(dur_timer(&axp->t4)/1000L));
}
/* Set limit on retransmission backoff */
int
doax25blimit(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong((long *)p,"blimit",argc,argv);
}
static int
doblimit(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25blimit(argc,argv,(void *)&Blimit);
}
/* Set limit on retransmission in ms */
int
doax25maxwait(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong((long *)p,"retry maxwait",argc,argv);
}
static int
doaxmaxwait(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25maxwait(argc,argv,(void *)&Axmaxwait);
}
/* Display or change our AX.25 address */
static int
domycall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
#ifdef MAILBOX
extern void setmbnrid();
#endif
char tmp[AXBUF];
if(argc < 2){
tprintf("%s\n",pax25(tmp,Mycall));
return 0;
}
if(setcall(Mycall,argv[1]) == -1)
return -1;
#ifdef MAILBOX
if(Bbscall[0] == 0)
memcpy(Bbscall,Mycall,AXALEN);
setmbnrid();
#endif
return 0;
}
#ifdef MAILBOX
/* Display or change our BBS address */
static int
dobbscall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char tmp[AXBUF];
struct iface *ifp;
if(argc < 2){
tprintf("%s\n",pax25(tmp,Bbscall));
return 0;
}
if(setcall(Bbscall,argv[1]) == -1)
return -1;
/* Set the bbs call on all appropriate interfaces
* that don't have a bbs call set yet.
*/
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
if(ifp->type == CL_AX25 && ifp->ax25->bbscall[0] == 0)
memcpy(ifp->ax25->bbscall,Bbscall,AXALEN);
return 0;
}
#endif
#ifdef TTYCALL
/* Display or change ttylink AX.25 address */
static int
dottycall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char tmp[AXBUF];
if(argc < 2){
tprintf("%s\n",pax25(tmp,Ttycall));
return 0;
}
if(setcall(Ttycall,argv[1]) == -1)
return -1;
return 0;
}
#endif
/* Control AX.25 digipeating */
static int
dodigipeat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setflag(argc,argv[1],AX25_DIGI,argv[2]);
}
int
doax25version(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"AX25 version",argc,argv);
}
static int
doversion(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25version(argc,argv,(void *)&Axversion);
}
static int
doax25irtt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong((long *)p,"Initial RTT (ms)",argc,argv);
}
static int
doaxirtt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25irtt(argc,argv,(void *)&Axirtt);
}
/* Set idle timer */
int
doax25t3(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong((long *)p,"Idle poll timer (ms)",argc,argv);
}
/* Set idle timer */
static int
dot3(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25t3(argc,argv,&T3init);
}
/* Set link redundancy timer */
int
doax25t4(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong((long *)p,"Link redundancy timer (sec)",argc,argv);
}
/* Set link redundancy timer */
static int
dot4(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25t4(argc,argv,(long *)&T4init);
}
/* Set retry limit count */
int
doax25n2(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"Retry limit",argc,argv);
}
static int
don2(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25n2(argc,argv,(void *)&N2);
}
/* Force a retransmission */
static int
doaxkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = MK_FP(htoi(argv[1]),8);
if(!ax25val(axp)){
tputs(Notval);
return 1;
}
kick_ax25(axp);
return 0;
}
/* Set maximum number of frames that will be allowed in flight */
int
doax25maxframe(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"Window size (frames)",argc,argv);
}
static int
domaxframe(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25maxframe(argc,argv,(void *)&Maxframe);
}
/* Set maximum length of I-frame data field */
int
doax25paclen(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"Max frame length (bytes)",argc,argv);
}
static int
dopaclen(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25paclen(argc,argv,(void *)&Paclen);
}
/* Set size of I-frame above which polls will be sent after a timeout */
int
doax25pthresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"Poll threshold (bytes)",argc,argv);
}
static int
dopthresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25pthresh(argc,argv,(void *)&Pthresh);
}
/* Set high water mark on receive queue that triggers RNR */
int
doax25window(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort((unsigned short *)p,"AX25 receive window (bytes)",argc,argv);
}
static int
doaxwindow(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return doax25window(argc,argv,(void *)&Axwindow);
}
/* End of ax25 subcommands */
#ifdef AX25SESSION
/* Initiate interactive AX.25 connect to remote station */
int
doconnect(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct sockaddr_ax fsocket;
struct session *sp;
struct iface *ifp;
int ndigis,i;
char digis[MAXDIGIS][AXALEN];
char target[AXALEN];
int split = 0;
/*Make sure this comes from console - WG7J*/
if(Curproc->input != Command->input)
return 0;
#ifdef SPLITSCREEN
if(argv[0][0] == 's') /* use split screen */
split = 1;
#endif
if(((ifp = if_lookup(argv[1])) != NULLIF) && (ifp->type != CL_AX25)) {
tprintf("Iface %s not an AX25 type interface\n",argv[1]);
return 1;
}
if(setcall(target,argv[2]) == -1){
tprintf("Bad callsign %s\n", argv[2]);
return 1;
}
/* If digipeaters are given, put them in the routing table */
if(argc > 3){
if(setcall(target,argv[2]) == -1){
tprintf("Bad callsign %s\n", argv[2]);
return 1;
}
ndigis = argc - 3;
if(ndigis > MAXDIGIS){
tputs("Too many digipeaters\n");
return 1;
}
for(i=0;i<ndigis;i++){
if(setcall(digis[i],argv[i+3]) == -1){
tprintf("Bad digipeater %s\n",argv[i+3]);
return 1;
}
}
if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
tputs("Route add failed\n");
return 1;
}
}
/* Allocate a session descriptor */
if((sp = newsession(argv[2],AX25TNC,split)) == NULLSESSION){
tputs(TooManySessions);
return 1;
}
if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
tputs(Nosock);
freesession(sp);
keywait(NULLCHAR,1);
return 1;
}
fsocket.sax_family = AF_AX25;
setcall(fsocket.ax25_addr,argv[2]);
strncpy(fsocket.iface,argv[1],ILEN);
return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
}
#endif
/* Display and modify AX.25 routing table */
static int
doaxroute(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char tmp[AXBUF];
int i,ndigis;
register struct ax_route *axr;
char target[AXALEN],digis[MAXDIGIS][AXALEN];
struct iface *iface;
if(argc < 2){
tputs("Target Iface Type Mode Digipeaters\n");
for(axr = Ax_routes;axr != NULLAXR;axr = axr->next){
tprintf("%-10s%-7s%-6s",pax25(tmp,axr->target),
axr->iface->name,axr->type == AX_LOCAL ? "Local":"Auto");
switch(axr->mode){
case AX_VC_MODE:
tputs(" VC ");
break;
case AX_DATMODE:
tputs(" DG ");
break;
case AX_DEFMODE:
tputs(" IF ");
break;
default:
tputs(" ?? ");
break;
}
for(i=0;i<axr->ndigis;i++){
tprintf(" %s",pax25(tmp,axr->digis[i]));
}
if(tputc('\n') == EOF)
return 0;
}
return 0;
}
if(argc < 4){
tputs("Usage: ax25 route add <target> <iface> [digis...]\n");
tputs(" ax25 route drop <target> <iface>\n");
tputs(" ax25 route mode <target> <iface> [mode]\n");
return 1;
}
if(setcall(target,argv[2]) == -1){
tprintf("Bad target %s\n",argv[2]);
return 1;
}
if((iface = if_lookup(argv[3])) == NULLIF){
tprintf(Badinterface,argv[3]);
return 1;
}
switch(argv[1][0]){
case 'a': /* Add route */
ndigis = argc - 4;
if(ndigis > MAXDIGIS){
tputs("Too many digipeaters\n");
return 1;
}
for(i=0;i<ndigis;i++){
if(setcall(digis[i],argv[i+4]) == -1){
tprintf("Bad digipeater %s\n",argv[i+4]);
return 1;
}
}
if(ax_add(target,AX_LOCAL,digis,ndigis,iface) == NULLAXR){
tputs("Failed\n");
return 1;
}
break;
case 'd': /* Drop route */
if(ax_drop(target,iface) == -1){
tputs("Not in table\n");
return 1;
}
break;
case 'm': /* Alter route mode */
if((axr = ax_lookup(target,iface)) == NULLAXR){
tputs("Not in table\n");
return 1;
}
switch(argv[4][0]){
case 'i': /* use default interface mode */
axr->mode = AX_DEFMODE;
break;
case 'v': /* use virtual circuit mode */
axr->mode = AX_VC_MODE;
break;
case 'd': /* use datagram mode */
axr->mode = AX_DATMODE;
break;
default:
tprintf("Unknown mode %s\n", argv[4]);
return 1;
}
break;
default:
tprintf("Unknown command %s\n",argv[1]);
return 1;
}
return 0;
}
extern int lapbtimertype;
/* ax25 timers type - linear v exponential */
int
doax25timertype(argc,argv,p)
int argc ;
char *argv[] ;
void *p ;
{
if (argc < 2) {
tputs("AX25 timer type is ");
switch(*(int *)p){
case 2:
tputs("original\n");
break;
case 1:
tputs("linear\n");
break;
case 0:
tputs("exponential\n");
break;
}
return 0 ;
}
switch (argv[1][0]) {
case 'o':
case 'O':
*(int *)p = 2 ;
break ;
case 'l':
case 'L':
*(int *)p = 1 ;
break ;
case 'e':
case 'E':
*(int *)p = 0 ;
break ;
default:
tputs("usage: ax25 timertype [original|linear|exponential]\n") ;
return -1 ;
}
return 0 ;
}
/* ax25 timers type - linear v exponential */
static int
doaxtype(argc,argv,p)
int argc ;
char *argv[] ;
void *p ;
{
return doax25timertype(argc,argv,(void *)&lapbtimertype);
}
void init_ifax25(struct ifax25 *ax25) {
if(!ax25)
return;
/* Set interface to the defaults */
ax25->paclen = Paclen;
ax25->lapbtimertype = lapbtimertype;
ax25->irtt = Axirtt;
ax25->version = Axversion;
ax25->t3 = T3init;
ax25->t4 = T4init;
ax25->n2 = N2;
ax25->maxframe = Maxframe;
ax25->pthresh = Pthresh;
ax25->window = Axwindow;
ax25->blimit = Blimit;
ax25->maxwait = Axmaxwait;
if(axbctext)
ax25->bctext = strdup(axbctext);
#ifdef MAILBOX
memcpy(ax25->bbscall,Bbscall,AXALEN);
#endif
}
static int doifax25paclen __ARGS((int argc, char *argv[], void *p));
static int doifax25timertype __ARGS((int argc, char *argv[], void *p));
static int doifax25irtt __ARGS((int argc, char *argv[], void *p));
static int doifax25version __ARGS((int argc, char *argv[], void *p));
static int doifax25t3 __ARGS((int argc, char *argv[], void *p));
static int doifax25t4 __ARGS((int argc, char *argv[], void *p));
static int doifax25n2 __ARGS((int argc, char *argv[], void *p));
static int doifax25maxframe __ARGS((int argc, char *argv[], void *p));
static int doifax25pthresh __ARGS((int argc, char *argv[], void *p));
static int doifax25window __ARGS((int argc, char *argv[], void *p));
static int doifax25blimit __ARGS((int argc, char *argv[], void *p));
static int doifax25maxwait __ARGS((int argc, char *argv[], void *p));
static int doifax25bctext __ARGS((int argc, char *argv[], void *p));
static int doifax25bbscall __ARGS((int argc, char *argv[], void *p));
static int doifax25cdigi __ARGS((int argc, char *argv[], void *p));
/* These are the command that set ax.25 parameters per interface */
static struct cmds DFAR Ifaxcmds[] = {
#ifdef MAILBOX
"bbscall", doifax25bbscall, 0, 0, NULLCHAR,
#endif
"bctext", doifax25bctext, 0, 0, NULLCHAR,
"blimit", doifax25blimit, 0, 0, NULLCHAR,
"cdigi", doifax25cdigi, 0, 0, NULLCHAR,
"irtt", doifax25irtt, 0, 0, NULLCHAR,
"maxframe", doifax25maxframe, 0, 0, NULLCHAR,
"maxwait", doifax25maxwait, 0, 0, NULLCHAR,
"paclen", doifax25paclen, 0, 0, NULLCHAR,
"pthresh", doifax25pthresh, 0, 0, NULLCHAR,
"retry", doifax25n2, 0, 0, NULLCHAR,
"timertype",doifax25timertype, 0, 0, NULLCHAR,
"t3", doifax25t3, 0, 0, NULLCHAR,
"t4", doifax25t4, 0, 0, NULLCHAR,
"version", doifax25version, 0, 0, NULLCHAR,
"window", doifax25window, 0, 0, NULLCHAR,
NULLCHAR
};
int ifax25(int argc,char *argv[],void *p) {
if(((struct iface *)p)->type != CL_AX25)
return tputs("not an AX.25 interface\n");
return subcmd(Ifaxcmds,argc,argv,p);
};
#ifdef MAILBOX
/* Set bbs ax.25 address */
static int
doifax25bbscall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
char tmp[AXBUF];
if(argc == 1)
tprintf("Bbscall %s\n",pax25(tmp,ifp->ax25->bbscall));
else
setcall(ifp->ax25->bbscall,argv[1]);
return 0;
}
#endif
/* Set ax.25 bctext */
static int
doifax25bctext(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
if(argc == 1)
tprintf("Bctext : %s\n",ifp->ax25->bctext);
else {
if(ifp->ax25->bctext)
free(ifp->ax25->bctext);
if(strlen(argv[1]) == 0) /* clearing the buffer */
ifp->ax25->bctext = NULL;
else
ifp->ax25->bctext = strdup(argv[1]);
}
return 0;
}
static int
doifax25blimit(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25blimit(argc,argv,(void *)&ifp->ax25->blimit);
}
/* Set cross band digi call address */
static int
doifax25cdigi(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
char tmp[AXBUF];
if(argc == 1)
tprintf("Cdigi %s\n",pax25(tmp,ifp->ax25->cdigi));
else
setcall(ifp->ax25->cdigi,argv[1]);
return 0;
}
static int
doifax25irtt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25irtt(argc,argv,(void *)&ifp->ax25->irtt);
}
static int
doifax25maxframe(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25maxframe(argc,argv,(void *)&ifp->ax25->maxframe);
}
static int
doifax25maxwait(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25maxwait(argc,argv,(void *)&ifp->ax25->maxwait);
}
/* Set interface AX.25 Paclen, and adjust the NETROM mtu for the
* smallest paclen. - WG7J
*/
static int
doifax25paclen(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
#ifdef NETROM
int tmp;
#endif
doax25paclen(argc,argv,(void *)&ifp->ax25->paclen);
#ifdef NETROM
if(argc > 1 && ifp->flags & IS_NR_IFACE) {
if((tmp=ifp->ax25->paclen - 20) < Nr_iface->mtu)
Nr_iface->mtu = tmp;
}
#endif
return 0;
}
static int
doifax25pthresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25pthresh(argc,argv,(void *)&ifp->ax25->pthresh);
}
static int
doifax25n2(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25n2(argc,argv,(void *)&ifp->ax25->n2);
}
static int
doifax25timertype(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25timertype(argc,argv,(void *)&ifp->ax25->lapbtimertype);
}
static int
doifax25t3(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25t3(argc,argv,(void *)&ifp->ax25->t3);
}
static int
doifax25t4(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25t4(argc,argv,(void *)&ifp->ax25->t4);
}
static int
doifax25version(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25version(argc,argv,(void *)&ifp->ax25->version);
}
static int
doifax25window(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp = p;
return doax25window(argc,argv,(void *)&ifp->ax25->window);
}
#endif /* AX25 */