home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3
/
hamradioversion3.0examsandprograms1992.iso
/
misc
/
9q920411
/
ax25cmd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-09
|
12KB
|
564 lines
/* AX25 control commands
* Copyright 1991 Phil Karn, KA9Q
*/
#include <stdio.h>
#include "global.h"
#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"
static int axdest __ARGS((struct iface *ifp));
static int axheard __ARGS((struct iface *ifp));
static void axflush __ARGS((struct iface *ifp));
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));
static int doaxstat __ARGS((int argc,char *argv[],void *p));
static int doaxwindow __ARGS((int argc,char *argv[],void *p));
static int doblimit __ARGS((int argc,char *argv[],void *p));
static int dodigipeat __ARGS((int argc,char *argv[],void *p));
static int domaxframe __ARGS((int argc,char *argv[],void *p));
static int domycall __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 doversion __ARGS((int argc,char *argv[],void *p));
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 Axcmds[] = {
"blimit", doblimit, 0, 0, NULLCHAR,
"destlist", doaxdest, 0, 0, NULLCHAR,
"digipeat", dodigipeat, 0, 0, NULLCHAR,
"flush", doaxflush, 0, 0, NULLCHAR,
"heard", doaxheard, 0, 0, NULLCHAR,
"irtt", doaxirtt, 0, 0, NULLCHAR,
"kick", doaxkick, 0, 2, "ax25 kick <axcb>",
"maxframe", domaxframe, 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,
"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);
}
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("Interface %s unknown\n",argv[1]);
return 1;
}
if(ifp->output != ax_output){
tprintf("Interface %s not AX.25\n",argv[1]);
return 1;
}
axheard(ifp);
return 0;
}
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
if(ifp->output != ax_output)
continue; /* Not an ax.25 interface */
if(axheard(ifp) == EOF)
break;
}
return 0;
}
static int
axheard(ifp)
struct iface *ifp;
{
struct lq *lp;
char tmp[AXBUF];
if(ifp->hwaddr == NULLCHAR)
return 0;
tprintf("%s:\n",ifp->name);
tprintf("Station Last heard Pkts\n");
for(lp = Lq;lp != NULLLQ;lp = lp->next){
if(lp->iface != ifp)
continue;
if(tprintf("%-10s%-17s%8lu\n",pax25(tmp,lp->addr),
tformat(secclock() - lp->time),lp->currxcnt) == EOF)
return EOF;
}
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("Interface %s unknown\n",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);
tprintf("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
doaxflush(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
if(ifp->output != ax_output)
continue; /* Not an ax.25 interface */
axflush(ifp);
}
return 0;
}
static void
axflush(ifp)
struct iface *ifp;
{
struct lq *lp,*lp1;
struct ld *ld,*ld1;
ifp->rawsndcnt = 0;
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;
}
static
doaxreset(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
tprintf(Notval);
return 1;
}
reset_ax25(axp);
return 0;
}
/* Display AX.25 link level control blocks */
static
doaxstat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct ax25_cb *axp;
char tmp[AXBUF];
if(argc < 2){
tprintf(" &AXB Snd-Q Rcv-Q Remote State\n");
for(axp = Ax25_cb;axp != NULLAX25; axp = axp->next){
if(tprintf("%8lx %-8d%-8d%-10s%s\n",
ptol(axp),
len_q(axp->txq),len_p(axp->rxq),
pax25(tmp,axp->remote),
Ax25states[axp->state]) == EOF)
return 0;
}
return 0;
}
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
tprintf(Notval);
return 1;
}
st_ax25(axp);
return 0;
}
/* Dump one control block */
void
st_ax25(axp)
register struct ax25_cb *axp;
{
char tmp[AXBUF];
if(axp == NULLAX25)
return;
tprintf(" &AXB Remote RB V(S) V(R) Unack P Retry State\n");
tprintf("%8lx %-9s%c%c",ptol(axp),pax25(tmp,axp->remote),
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);
tprintf("T1: ");
if(run_timer(&axp->t1))
tprintf("%lu",read_timer(&axp->t1));
else
tprintf("stop");
tprintf("/%lu ms; ",dur_timer(&axp->t1));
tprintf("T3: ");
if(run_timer(&axp->t3))
tprintf("%lu",read_timer(&axp->t3));
else
tprintf("stop");
tprintf("/%lu ms\n",dur_timer(&axp->t3));
}
/* Display or change our AX.25 address */
static
domycall(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char tmp[AXBUF];
if(argc < 2){
tprintf("%s\n",pax25(tmp,Mycall));
return 0;
}
if(setcall(Mycall,argv[1]) == -1)
return -1;
return 0;
}
/* Control AX.25 digipeating */
static
dodigipeat(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setbool(&Digipeat,"Digipeat",argc,argv);
}
/* Set limit on retransmission backoff */
static
doblimit(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&Blimit,"blimit",argc,argv);
}
static
doversion(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Axversion,"AX25 version",argc,argv);
}
static
doaxirtt(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
}
/* Set idle timer */
static
dot3(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
}
/* Set retry limit count */
static
don2(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&N2,"Retry limit",argc,argv);
}
/* Force a retransmission */
static
doaxkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct ax25_cb *axp;
axp = (struct ax25_cb *)ltop(htol(argv[1]));
if(!ax25val(axp)){
tprintf(Notval);
return 1;
}
kick_ax25(axp);
return 0;
}
/* Set maximum number of frames that will be allowed in flight */
static
domaxframe(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Maxframe,"Window size (frames)",argc,argv);
}
/* Set maximum length of I-frame data field */
static
dopaclen(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
}
/* Set size of I-frame above which polls will be sent after a timeout */
static
dopthresh(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
}
/* Set high water mark on receive queue that triggers RNR */
static
doaxwindow(argc,argv,p)
int argc;
char *argv[];
void *p;
{
return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
}
/* End of ax25 subcommands */
/* 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;
int ndigis,i;
char digis[MAXDIGIS][AXALEN];
char target[AXALEN];
/* If digipeaters are given, put them in the routing table */
if(argc > 3){
setcall(target,argv[2]);
ndigis = argc - 3;
if(ndigis > MAXDIGIS){
tprintf("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_LOCAL,digis,ndigis) == NULLAXR){
tprintf("Route add failed\n");
return 1;
}
}
/* Allocate a session descriptor */
if((sp = newsession(argv[2],AX25TNC,1)) == NULLSESSION){
tprintf("Too many sessions\n");
return 1;
}
Current->flowmode = 0;
if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
tprintf("Can't create socket\n");
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));
}
/* 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];
if(argc < 2){
tprintf("Target Type Digipeaters\n");
for(axr = Ax_routes;axr != NULLAXR;axr = axr->next){
tprintf("%-10s%-6s",pax25(tmp,axr->target),
axr->type == AX_LOCAL ? "Local":"Auto");
for(i=0;i<axr->ndigis;i++){
tprintf(" %s",pax25(tmp,axr->digis[i]));
}
if(tprintf("\n") == EOF)
return 0;
}
return 0;
}
if(argc < 3){
tprintf("Usage: ax25 route add <target> [digis...]\n");
tprintf(" ax25 route drop <target>\n");
return 1;
}
if(setcall(target,argv[2]) == -1){
tprintf("Bad target %s\n",argv[2]);
return 1;
}
switch(argv[1][0]){
case 'a': /* Add route */
if(argc < 3){
tprintf("Usage: ax25 route add <target> [digis...]\n");
return 1;
}
ndigis = argc - 3;
if(ndigis > MAXDIGIS){
tprintf("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_LOCAL,digis,ndigis) == NULLAXR){
tprintf("Failed\n");
return 1;
}
break;
case 'd': /* Drop route */
if(ax_drop(target) == -1){
tprintf("Not in table\n");
return 1;
}
break;
default:
tprintf("Unknown command %s\n",argv[1]);
return 1;
}
return 0;
}