home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-12-27 | 37.0 KB | 1,209 lines |
- /* net/rom user command processing
- * Copyright 1989 by Daniel M. Frank, W9NK. Permission granted for
- * non-commercial distribution only.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <ctype.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "timer.h"
- #include "iface.h"
- #include "lapb.h"
- #include "netuser.h"
- #include "netrom.h"
- #include "nr4.h"
- #include "ax_mbx.h"
- #include "cmdparse.h"
- #include "session.h"
- #include "misc.h"
-
- #undef NRDEBUG
-
- static int donrroute(int, char **);
- static int doroutedump(void);
- static int putalias(char *, char *, int);
- static int doroutedrop(int, char **);
- static int donodetimer(int, char **);
- static int donodetick(void);
- static int doobsotimer(int, char **);
- static int doobsotick(void);
- static int donodefilter(int, char **);
- static int donfdump(void);
- static int donfadd(int, char **);
- static int donfdrop(int, char **);
- static int donfmode(int, char **);
- static int donrttl(int, char **);
- static int donrverbose(int, char **);
- static int donracktime(int, char **);
- static int donrchoketime(int, char **);
- static int donrirtt(int, char **);
- static int donrqlimit(int, char **);
- static int donrwindow(int, char **);
- static int donrretries(int, char **);
- static int donrstatus(int, char **);
- static void donrdump(struct nr4cb *);
- static int dominquality(int, char **);
-
- char *Nr4states[] = {
- "Disconnected",
- "Conn Pending",
- "Connected",
- "Disc Pending"
- } ;
-
- char *Nr4reasons[] = {
- "Normal",
- "By Peer",
- "Timeout",
- "Reset",
- "Refused"
- } ;
-
-
- static struct cmds nrcmds[] = {
- "acktime", donracktime, 0, NULLCHAR, NULLCHAR,
- "bcnodes", dobcnodes, 2, "netrom bcnodes <interface>", NULLCHAR,
-
- /* Put connect before choketime to make it the default expansion of 'c' */
-
- "connect", donrconnect,2, "netrom connect <node>", NULLCHAR,
- "choketime", donrchoketime, 0, NULLCHAR, NULLCHAR,
- "interface", dointerface, 4,
- "netrom interface <interface> <alias> <quality>", NULLCHAR,
- "irtt", donrirtt, 0, NULLCHAR, NULLCHAR,
- "kick", donrkick, 0, NULLCHAR, NULLCHAR,
- "nodefilter", donodefilter, 0, NULLCHAR, NULLCHAR,
- "nodetimer", donodetimer, 0, NULLCHAR, NULLCHAR,
- "minquality", dominquality, 0, NULLCHAR, NULLCHAR,
- "obsotimer", doobsotimer, 0, NULLCHAR, NULLCHAR,
- "qlimit", donrqlimit, 0, NULLCHAR, NULLCHAR,
- "reset", donrreset, 2, "netrom reset <&nrcb>", NULLCHAR,
- "retries", donrretries,0, NULLCHAR, NULLCHAR,
- "route", donrroute, 0, NULLCHAR, NULLCHAR,
- "status", donrstatus, 0, NULLCHAR, NULLCHAR,
- "ttl", donrttl, 0, NULLCHAR, NULLCHAR,
- "verbose", donrverbose,0, NULLCHAR, NULLCHAR,
- "window", donrwindow, 0, NULLCHAR, NULLCHAR,
- NULLCHAR, NULLFP, 0,
- "netrom subcommands: acktime bcnodes connect choketime interface irtt kick\n minquality nodetimer nodefilter obsotimer qlimit reset\n retries route status ttl verbose window",
- NULLCHAR
- } ;
-
- static struct timer nodetimer ; /* timer for nodes broadcasts */
- static struct timer obsotimer ; /* timer for aging routes */
-
- /* Command multiplexer */
- int donetrom(int argc, char **argv)
- {
- return subcmd(nrcmds,argc,argv) ;
- }
-
- static struct cmds routecmds[] = {
- "add", dorouteadd, 6,
- "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
- "add failed",
- "drop", doroutedrop, 4,
- "netrom route drop <destination> <neighbor> <interface>",
- "drop failed",
- "info", dorouteinfo, 2,
- "netrom route info <destination>", NULLCHAR,
- NULLCHAR, NULLFP, 0,
- "netrom route subcommands: add drop info",
- NULLCHAR
- } ;
-
- /* Route command multiplexer */
- static int donrroute(int argc, char **argv)
- {
- if (argc < 2) {
- doroutedump() ;
- return 0 ;
- }
- return subcmd(routecmds,argc,argv) ;
- }
-
- /* Dump a list of known routes */
- static int doroutedump(void)
- {
- register struct nrroute_tab *rp ;
- register int i, column ;
- char buf[16] ;
- char *cp ;
-
- column = 1 ;
-
- for (i = 0 ; i < NRNUMCHAINS ; i++)
- for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
- strcpy(buf,rp->alias) ;
- /* remove trailing spaces */
- if ((cp = strchr(buf,' ')) == NULLCHAR)
- cp = &buf[strlen(buf)] ;
- if (cp != buf) /* don't include colon for null alias */
- *cp++ = ':' ;
- pax25(cp,&rp->call) ;
- cwprintf(NULL, "%-16s ",buf) ;
- if (column++ == 4) {
- cwprintf(NULL, "\r\n") ;
- column = 1 ;
- }
- }
-
- if (column != 1)
- cwprintf(NULL, "\r\n") ;
-
- return 0 ;
- }
-
- /* print detailed information on an individual route */
- int dorouteinfo(int argc, char **argv)
- {
- register struct nrroute_tab *rp ;
- register struct nr_bind *bp ;
- register struct nrnbr_tab *np ;
- struct ax25_addr dest ;
- char neighbor[60] ;
-
- argc = argc;
-
- if (setcall(&dest,argv[1]) == -1) {
- cwprintf(NULL, "bad destination name\r\n") ;
- return -1 ;
- }
-
- if ((rp = find_nrroute(&dest)) == NULLNRRTAB) {
- cwprintf(NULL, "no such route\r\n") ;
- return -1 ;
- }
-
- for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
- np = bp->via ;
- psax25(neighbor,np->call) ;
- cwprintf(NULL, "%1s %3d %3d %-8s %s\r\n",
- (bp->flags & NRB_PERMANENT ? "P" :
- bp->flags & NRB_RECORDED ? "R" : " "),
- bp->quality,bp->obsocnt,
- nrifaces[np->interface].interface->name,
- neighbor) ;
- }
- return 0 ;
- }
-
- /* convert a null-terminated alias name to a blank-filled, upcased */
- /* version. Return -1 on failure. */
- static int putalias(register char *to, register char *from, int complain)
- {
- int len, i ;
-
- if ((len = strlen(from)) > ALEN) {
- if (complain)
- cwprintf(NULL, "alias too long - six characters max\r\n") ;
- return -1 ;
- }
-
- for (i = 0 ; i < ALEN ; i++) {
- if (i < len) {
- if (islower(*from))
- *to++ = toupper(*from++) ;
- else
- *to++ = *from++ ;
- }
- else
- *to++ = ' ' ;
- }
-
- *to = '\0' ;
- return 0 ;
- }
-
- /* Add a route */
- int dorouteadd(int argc, char **argv)
- {
- char alias[7] ;
- struct ax25_addr dest ;
- unsigned quality ;
- char neighbor[AXALEN * 3] ;
- register int i ;
- int naddr ;
-
- /* format alias (putalias prints error message if necessary) */
- if (putalias(alias,argv[1],1) == -1)
- return -1 ;
-
- /* format destination callsign */
- if (setcall(&dest,argv[2]) == -1) {
- cwprintf(NULL, "bad destination callsign\r\n") ;
- return -1 ;
- }
-
- /* find interface */
- for (i = 0 ; i < nr_numiface ; i++)
- if (!strcmp(nrifaces[i].interface->name,argv[3]))
- break ;
- if (i == nr_numiface) {
- cwprintf(NULL, "Interface \"%s\" not found\r\n",argv[3]) ;
- return -1 ;
- }
-
- /* get and check quality value */
- if ((quality = atoi(argv[4])) > 255) {
- cwprintf(NULL, "maximum route quality is 255\r\n") ;
- return -1 ;
- }
-
- /* make sure no more than 2 digis */
- naddr = argc - 5 ;
- if (naddr > 3) {
- cwprintf(NULL, "no more than 2 digipeaters for a net/rom neighbor\r\n") ;
- return -1 ;
- }
-
- /* format neighbor address string */
- setpath(neighbor,&argv[5],naddr) ;
-
- return nr_routeadd(alias,&dest,i,quality,neighbor,1,0) ;
- }
-
-
- /* drop a route */
- static int doroutedrop(int argc, char **argv)
- {
- struct ax25_addr dest, neighbor ;
- register int i ;
-
- argc = argc;
-
- /* format destination and neighbor callsigns */
- if (setcall(&dest,argv[1]) == -1) {
- cwprintf(NULL, "bad destination callsign\r\n") ;
- return -1 ;
- }
- if (setcall(&neighbor,argv[2]) == -1) {
- cwprintf(NULL, "bad neighbor callsign\r\n") ;
- return -1 ;
- }
-
- /* find interface */
- for (i = 0 ; i < nr_numiface ; i++)
- if (!strcmp(nrifaces[i].interface->name,argv[3]))
- break ;
- if (i == nr_numiface) {
- cwprintf(NULL, "Interface \"%s\" not found\r\n",argv[3]) ;
- return -1 ;
- }
-
- return nr_routedrop(&dest,&neighbor,i) ;
- }
-
-
- /* make an interface available to net/rom */
- int dointerface(int argc, char **argv)
- {
- int i;
- register struct interface *ifp ;
- extern struct interface *ifaces ;
-
- argc = argc;
-
- if (nr_interface == NULLIF) {
- cwprintf(NULL, "Attach netrom interface first\r\n") ;
- return 1 ;
- }
-
- if (nr_numiface >= NRNUMIFACE) {
- cwprintf(NULL, "Only %d net/rom interfaces available\r\n",NRNUMIFACE) ;
- return 1 ;
- }
-
- for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
- if(strcmp(argv[1],ifp->name) == 0)
- break;
- }
- if(ifp == NULLIF){
- cwprintf(NULL, "Interface \"%s\" unknown\r\n",argv[1]);
- return 1;
- }
- for (i = 0 ; i < nr_numiface ; i++)
- if (nrifaces[i].interface == ifp) {
- cwprintf(NULL, "Interface \"%s\" is already registered\r\n",argv[1]) ;
- return 1 ;
- }
-
- nrifaces[nr_numiface].interface = ifp ;
-
- if (putalias(nrifaces[nr_numiface].alias,argv[2],1) == -1)
- return 1 ;
-
- if ((nrifaces[nr_numiface].quality = atoi(argv[3])) > 255) {
- cwprintf(NULL, "Quality cannot be greater than 255\r\n") ;
- return 1 ;
- }
-
- nr_numiface++ ; /* accept this interface */
- return 0 ;
- }
-
- /* Broadcast nodes list on named interface. */
-
- int dobcnodes(int argc, char **argv)
-
- {
- register int i ;
-
- argc = argc;
-
- for (i = 0 ; i < nr_numiface ; i++)
- if (!strcmp(nrifaces[i].interface->name,argv[1]))
- break ;
- if (i == nr_numiface) {
- cwprintf(NULL, "Interface \"%s\" not found\r\n",argv[1]) ;
- return 1 ;
- }
-
- nr_bcnodes(i) ;
-
- return 0;
- }
-
- #define TICKSPERSEC (1000L / MSPTICK) /* Ticks per second */
-
- /* Set outbound node broadcast interval */
- static int donodetimer(int argc, char **argv)
- {
- if(argc < 2){
- cwprintf(NULL, "%lu/%lu\r\n",
- (nodetimer.start - nodetimer.count)/TICKSPERSEC,
- nodetimer.start/TICKSPERSEC);
- return 0;
- }
- stop_timer(&nodetimer) ; /* in case it's already running */
- nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
- nodetimer.arg = NULLCHAR; /* dummy value */
- nodetimer.start = atol(argv[1])*TICKSPERSEC; /* set timer duration */
- start_timer(&nodetimer); /* and fire it up */
- return 0;
- }
-
- static int donodetick(void)
- {
- register int i ;
-
- for (i = 0 ; i < nr_numiface ; i++)
- nr_bcnodes(i) ;
-
- /* Restart timer */
- start_timer(&nodetimer) ;
-
- return 0;
- }
-
- /* Set timer for aging routes */
- static int doobsotimer(int argc, char **argv)
- {
- if(argc < 2){
- cwprintf(NULL, "%lu/%lu\r\n",(obsotimer.start - obsotimer.count)/TICKSPERSEC,
- obsotimer.start/TICKSPERSEC);
- return 0;
- }
- stop_timer(&obsotimer) ; /* just in case it's already running */
- obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
- obsotimer.arg = NULLCHAR; /* dummy value */
- obsotimer.start = atol(argv[1])*TICKSPERSEC; /* set timer duration */
- start_timer(&obsotimer); /* and fire it up */
- return 0;
- }
-
-
- /* Go through the routing table, reducing the obsolescence count of
- * non-permanent routes, and purging them if the count reaches 0
- */
- static int doobsotick(void)
- {
- register struct nrnbr_tab *np ;
- register struct nrroute_tab *rp, *rpnext ;
- register struct nr_bind *bp, *bpnext ;
- struct ax25_addr neighbor ;
- int i ;
-
- for (i = 0 ; i < NRNUMCHAINS ; i++) {
- for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
- rpnext = rp->next ; /* save in case we free this route */
- for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
- bpnext = bp->next ; /* in case we free this binding */
- if (bp->flags & NRB_PERMANENT) /* don't age these */
- continue ;
- if (--bp->obsocnt == 0) { /* time's up! */
- if (bp->next != NULLNRBIND)
- bp->next->prev = bp->prev ;
- if (bp->prev != NULLNRBIND)
- bp->prev->next = bp->next ;
- else
- rp->routes = bp->next ;
- rp->num_routes-- ; /* one less binding */
- np = bp->via ; /* find the neighbor */
- free(bp) ; /* now we can free the bind */
- /* Check to see if we can free the neighbor */
- if (--np->refcnt == 0) {
- if (np->next != NULLNTAB)
- np->next->prev = np->prev ;
- if (np->prev != NULLNTAB)
- np->prev->next = np->next ;
- else {
- memcpy(neighbor.call,np->call,ALEN) ;
- neighbor.ssid = np->call[ALEN] ;
- nrnbr_tab[nrhash(&neighbor)] = np->next ;
- }
- free(np) ; /* free the storage */
- }
- }
- }
- if (rp->num_routes == 0) { /* did we free them all? */
- if (rp->next != NULLNRRTAB)
- rp->next->prev = rp->prev ;
- if (rp->prev != NULLNRRTAB)
- rp->prev->next = rp->next ;
- else
- nrroute_tab[i] = rp->next ;
-
- free(rp) ;
- }
- }
- }
-
- start_timer(&obsotimer) ;
-
- return 0;
- }
-
- static struct cmds nfcmds[] = {
- "add", donfadd, 3,
- "netrom nodefilter add <neighbor> <interface>",
- "add failed",
- "drop", donfdrop, 3,
- "netrom nodefilter drop <neighbor> <interface>",
- "drop failed",
- "mode", donfmode, 0, NULLCHAR, NULLCHAR,
- NULLCHAR, NULLFP, 0,
- "nodefilter subcommands: add drop mode",
- NULLCHAR
- } ;
-
- /* nodefilter command multiplexer */
- static int donodefilter(int argc, char **argv)
- {
- if (argc < 2) {
- donfdump() ;
- return 0 ;
- }
- return subcmd(nfcmds,argc,argv) ;
- }
-
- /* display a list of <callsign,interface> pairs from the filter
- * list.
- */
- static int donfdump(void)
- {
- int i, column = 1 ;
- struct nrnf_tab *fp ;
- char buf[16] ;
-
- for (i = 0 ; i < NRNUMCHAINS ; i++)
- for (fp = nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
- pax25(buf,&fp->neighbor) ;
- cwprintf(NULL, "%-7s %-8s ",
- buf,nrifaces[fp->interface].interface->name) ;
- if (column++ == 4) {
- cwprintf(NULL, "\r\n") ;
- column = 1 ;
- }
- }
-
- if (column != 1)
- cwprintf(NULL, "\r\n") ;
-
- return 0 ;
- }
-
- /* add an entry to the filter table */
- static int donfadd(int argc, char **argv)
- {
- struct ax25_addr neighbor ;
- register int i ;
-
- argc = argc;
-
- /* format callsign */
- if (setcall(&neighbor,argv[1]) == -1) {
- cwprintf(NULL, "bad neighbor callsign\r\n") ;
- return -1 ;
- }
-
- /* find interface */
- for (i = 0 ; i < nr_numiface ; i++)
- if (!strcmp(nrifaces[i].interface->name,argv[2]))
- break ;
- if (i == nr_numiface) {
- cwprintf(NULL, "Interface \"%s\" not found\r\n",argv[2]) ;
- return -1 ;
- }
-
- return nr_nfadd(&neighbor,i) ;
- }
-
- /* drop an entry from the filter table */
- static int donfdrop(int argc, char **argv)
- {
- struct ax25_addr neighbor ;
- register int i ;
-
- argc = argc;
-
- /* format neighbor callsign */
- if (setcall(&neighbor,argv[1]) == -1) {
- cwprintf(NULL, "bad neighbor callsign\r\n") ;
- return -1 ;
- }
-
- /* find interface */
- for (i = 0 ; i < nr_numiface ; i++)
- if (!strcmp(nrifaces[i].interface->name,argv[2]))
- break ;
- if (i == nr_numiface) {
- cwprintf(NULL, "Interface \"%s\" not found\r\n",argv[2]) ;
- return -1 ;
- }
-
- return nr_nfdrop(&neighbor,i) ;
- }
-
- /* nodefilter mode subcommand */
- static int donfmode(int argc, char **argv)
- {
- if (argc < 2) {
- cwprintf(NULL, "filter mode is ") ;
- switch (nr_nfmode) {
- case NRNF_NOFILTER:
- cwprintf(NULL, "none\r\n") ;
- break ;
- case NRNF_ACCEPT:
- cwprintf(NULL, "accept\r\n") ;
- break ;
- case NRNF_REJECT:
- cwprintf(NULL, "reject\r\n") ;
- break ;
- default:
- cwprintf(NULL, "some strange, unknown value\r\n") ;
- }
- return 0 ;
- }
-
- switch (argv[1][0]) {
- case 'n':
- case 'N':
- nr_nfmode = NRNF_NOFILTER ;
- break ;
- case 'a':
- case 'A':
- nr_nfmode = NRNF_ACCEPT ;
- break ;
- case 'r':
- case 'R':
- nr_nfmode = NRNF_REJECT ;
- break ;
- default:
- cwprintf(NULL, "modes are: none accept reject\r\n") ;
- return -1 ;
- }
-
- return 0 ;
- }
-
-
- /* netrom network packet time-to-live initializer */
- static donrttl(int argc, char **argv)
- {
- int val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%d\r\n", nr_ttl) ;
- return 0 ;
- }
-
- val = atoi(argv[1]) ;
-
- if (val < 0 || val > 255) {
- cwprintf(NULL, "ttl must be between 0 and 255\r\n") ;
- return 1 ;
- }
-
- nr_ttl = val ;
-
- return 0 ;
- }
-
- /* verbose route broadcast */
- static int donrverbose(int argc, char **argv)
- {
- if (argc < 2) {
- cwprintf(NULL, "verbose is %s\r\n", nr_verbose ? "yes" : "no" ) ;
- return 0 ;
- }
-
- switch (argv[1][0]) {
- case 'n':
- case 'N':
- nr_verbose = 0 ;
- break ;
- case 'y':
- case 'Y':
- nr_verbose = 1 ;
- break ;
- default:
- cwprintf(NULL, "use: netrom verbose [yes|no]\r\n") ;
- return -1 ;
- }
-
- return 0 ;
- }
-
- /* Initiate a NET/ROM transport connection */
- int donrconnect(int argc, char **argv)
- {
- struct ax25_addr node, *np ;
- struct session *s ;
- char alias[7] ;
-
- argc = argc;
-
- /* See if the requested destination could be an alias, and */
- /* find and use it if it is. Otherwise assume it is an ax.25 */
- /* address. */
-
- if (putalias(alias,argv[1],0) != -1 &&
- (np = find_nralias(alias)) != NULLAXADDR)
- node = *np ;
- else
- setcall(&node,argv[1]) ; /* parse ax25 callsign */
-
- /* Get a session descriptor */
-
- if ((s = newsession()) == NULLSESSION) {
- cwprintf(NULL, "Too many sessions\r\n") ;
- return 1 ;
- }
- if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
- strcpy(s->name,argv[1]);
- s->type = NRSESSION ;
- s->parse = (void (*)())nr4_parse ;
- current = s;
-
- s->cb.nr4_cb = open_nr4(&node,&mycall,(void (*)())nr4_rx,(void (*)())nr4_tx,nr4_state,(char *)s) ;
- go(s) ;
- return 0 ;
- }
-
- /* Display changes in NET/ROM state */
- void nr4_state(struct nr4cb *cb, int old, int new)
- {
- struct session *s;
-
- old = old;
-
- s = (struct session *)cb->puser;
-
- if(current != NULLSESSION && current->type == NRSESSION && current == s){
- cwprintf(NULL, "%s",Nr4states[new]);
- if(new == NR4STDISC) {
- cwprintf(NULL, " (%s)\r\n", Nr4reasons[cb->dreason]) ;
- cmdmode();
- } else
- cwprintf(NULL, "\r\n") ;
- }
- if(new == NR4STDISC){
- cb->puser = NULLCHAR;
- freesession(s);
- }
- }
-
- /* Handle typed characters on a NET/ROM connection */
- void nr4_parse(char *buf, int16 cnt)
- {
- struct mbuf *bp;
- register char *cp;
- int16 size, i ;
- char c;
-
- if(current == NULLSESSION || current->type != NRSESSION)
- return; /* "can't happen" */
-
- /* If recording is on, record outgoing stuff too */
- if(current->record != NULLFILE)
- fwrite(buf,1,cnt,current->record);
-
- /* Parse it out, splitting at transport frame boundaries */
-
- while (cnt != 0) {
- #ifdef NRDEBUG
- cwprintf(NULL, "Once around the parse loop - cnt = %d\r\n", cnt) ;
- #endif
- size = min(cnt, NR4MAXINFO) ;
- if ((bp = alloc_mbuf(size)) == NULLBUF)
- break ;
- /* Copy keyboard buffer to output, stripping line feeds */
- cp = bp->data ;
- for (i = 0 ; i < size ; i++){
- c = *buf++;
- if(c != '\n'){
- *cp++ = c;
- bp->cnt++;
- }
- }
- cnt -= size ;
- send_nr4(current->cb.nr4_cb,bp);
- }
- }
-
- /* Handle new incoming terminal sessions
- * This is the default state change upcall function, used when
- * someone else connects to us
- */
- void nr4_incom(struct nr4cb *cb, int oldstate, int newstate)
- {
- oldstate = oldstate;
-
- if (newstate != NR4STCON) /* why are you bothering us? */
- return ; /* (shouldn't happen) */
-
- if (ax25mbox)
- mbx_nr4incom(cb) ;
- else
- nr4_session(cb) ;
- return ;
-
- }
-
- /* This function sets up a NET/ROM chat session */
- void nr4_session(struct nr4cb *cb)
- {
- struct session *s;
- char remote[10];
- extern char hostname[];
- extern int attended;
- char *cp;
- time_t t;
-
- time(&t);
- cp = ctime(&t);
- rip(cp);
-
- pax25(remote,&cb->user);
- if((s = newsession()) == NULLSESSION){
- /* Out of sessions */
- disc_nr4(cb);
- return;
- }
- s->type = NRSESSION ;
- s->name = malloc((int16)strlen(remote)+1);
- s->cb.nr4_cb = cb ;
- s->parse = (void (*)())nr4_parse;
- strcpy(s->name,remote);
- cb->r_upcall = (void (*)())nr4_rx;
- cb->s_upcall = nr4_state;
- cb->t_upcall = (void (*)())nr4_tx;
- cb->puser = (char *)s;
- cwprintf(NULL, "%s : Incoming NET/ROM session %u from %s\r\n",cp,s - sessions,remote);
- log_event(NULL,"NET/ROM Chatter session requested : %s",remote);
- if(attended)
- nr4_printf(cb,"Welcome %s to the %s system's 'Chat' mode.\r",remote,hostname);
- else
- nr4_printf(cb,"Sorry %s, the %s system is UNATTENDED.\r",remote,hostname);
- }
-
- /* Handle incoming terminal traffic */
- void nr4_rx(struct nr4cb *cb, int16 cnt)
- {
- extern int ttyflow;
- register struct mbuf *bp;
- register char *s;
- register char *t;
- char *line;
-
- /* Hold output if we're not the current session */
- if(mode != CONV_MODE || current == NULLSESSION || ttyflow == 0
- || current->type != NRSESSION || current->cb.nr4_cb != cb)
- return;
-
- if((bp = recv_nr4(cb,cnt)) == NULLBUF)
- return;
-
- /* Display received characters, translating CR's to CR/LF */
- if ((line = s = malloc(len_mbuf(bp) + 1)) == NULL)
- {
- cwprintf(NULL, "Out of memory in NRCMD\r\n");
- free_p(bp);
- return;
- }
- while(bp != NULLBUF){
- t = bp->data;
- while(bp->cnt-- != 0){
- if (*t == '\r')
- *(++t) = '\n';
- *s++ = *t++;
- }
- bp = free_mbuf(bp);
- }
- if (current->record) {
- fwrite(line, 1, s - line, current->record);
- fflush(current->record);
- }
- *s = '\0';
- cwputs(NULL, line);
- free(line);
- }
-
- /* Handle transmit upcalls. Used only for file uploading */
- void nr4_tx(struct nr4cb *cb, int16 cnt)
- {
- register char *cp;
- struct session *s;
- register struct mbuf *bp;
- int16 size;
- int c;
-
- if((s = (struct session *)cb->puser) == NULLSESSION
- || s->upload == NULLFILE)
- return;
- while(cnt != 0){
- size = min(cnt,NR4MAXINFO);
- if((bp = alloc_mbuf(size)) == NULLBUF)
- break;
- cp = bp->data;
-
- /* Now send data characters, translating between local
- * keyboard end-of-line sequences and the (unwritten)
- * AX.25 convention, which is carriage-return only
- */
-
- while(bp->cnt < size){
- if((c = getc(s->upload)) == EOF)
- break;
- if(c == '\n')
- c = '\r';
- *cp++ = c;
- bp->cnt++;
- }
- cnt -= bp->cnt;
- send_nr4(cb,bp);
- }
- if(cnt != 0){
- /* Error or end-of-file */
- fclose(s->upload);
- s->upload = NULLFILE;
- free(s->ufile);
- s->ufile = NULLCHAR;
- }
- }
-
- /* Reset a net/rom connection abruptly */
-
- int donrreset(int argc, char **argv)
- {
- struct nr4cb *cb ;
- extern char notval[];
-
- argc = argc;
-
- cb = (struct nr4cb *)htol(argv[1]);
- if(!nr4valcb(cb)){
- cwprintf(NULL, notval);
- return 1;
- }
- reset_nr4(cb);
- return 0;
- }
-
- /* Force retransmission on a net/rom connection */
-
- int donrkick(int argc, char **argv)
- {
- struct nr4cb *cb ;
- extern char notval[];
-
- argc = argc;
-
- cb = (struct nr4cb *)htol(argv[1]);
-
- if (kick_nr4(cb) == -1) {
- cwprintf(NULL, notval);
- return 1;
- } else
- return 0;
- }
-
- /* netrom transport ACK delay timer */
-
- static int donracktime(int argc, char **argv)
- {
- long val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%lu\r\n", Nr4acktime) ;
- return 0 ;
- }
-
- val = atol(argv[1]) ;
-
- Nr4acktime = val ;
-
- return 0 ;
- }
-
- /* netrom transport choke timeout */
-
- static int donrchoketime(int argc, char **argv)
- {
- long val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%lu\r\n", Nr4choketime) ;
- return 0 ;
- }
-
- val = atol(argv[1]) ;
-
- Nr4choketime = val ;
-
- return 0 ;
- }
-
- /* netrom transport initial round trip time */
-
- static int donrirtt(int argc, char **argv)
- {
- long val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%lu\r\n", Nr4irtt) ;
- return 0 ;
- }
-
- val = atol(argv[1]) ;
-
- Nr4irtt = val ;
-
- return 0 ;
- }
-
- /* netrom transport receive queue length limit. This is the */
- /* threshhold at which we will CHOKE the sender. */
-
- static int donrqlimit(int argc, char **argv)
- {
- unsigned val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%u\r\n", Nr4qlimit) ;
- return 0 ;
- }
-
- val = atoi(argv[1]) ;
-
- if (val == 0) {
- cwprintf(NULL, "You cannot set the queue limit to 0\r\n") ;
- return 1 ;
- }
-
- Nr4qlimit = val ;
-
- return 0 ;
- }
-
- /* netrom transport maximum window. This is the largest send and */
- /* receive window we may negotiate */
-
- static int donrwindow(int argc, char **argv)
- {
- unsigned val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%u\r\n", Nr4window) ;
- return 0 ;
- }
-
- val = atoi(argv[1]) ;
-
- if (val == 0 || val > NR4MAXWIN) {
- cwprintf(NULL, "Illegal NET/ROM window size. Range is [1,%d]\r\n",
- NR4MAXWIN) ;
- return 1 ;
- }
-
- Nr4window = val ;
-
- return 0 ;
- }
-
- /* netrom transport maximum retries. This is used in connect and */
- /* disconnect attempts; I haven't decided what to do about actual */
- /* data retries yet. */
-
- static int donrretries(int argc, char **argv)
- {
- unsigned val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%u\r\n", Nr4retries) ;
- return 0 ;
- }
-
- val = atoi(argv[1]) ;
-
- if (val == 0) {
- cwprintf(NULL, "Impatient, aren't we? Zero retries not possible\r\n") ;
- return 1 ;
- }
-
- Nr4retries = val ;
-
- return 0 ;
- }
-
- /* Display the status of NET/ROM connections */
-
- static int donrstatus(int argc, char **argv)
- {
- int i ;
- struct nr4cb *cb ;
- char luser[10], ruser[10], node[10] ;
- extern char notval[] ;
-
- if (argc < 2) {
- cwprintf(NULL, " &CB Snd-W Snd-Q Rcv-Q LUser RUser @Node State\r\n");
- for (i = 0 ; i < NR4MAXCIRC ; i++) {
- if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
- continue ;
- pax25(luser,&cb->luser) ;
- pax25(ruser,&cb->user) ;
- pax25(node,&cb->node) ;
- cwprintf(NULL, "%8lx %3d %5d %5d %9s %9s %-9s %s\r\n",
- (long)cb, cb->nbuffered, len_q(cb->txq),
- len_mbuf(cb->rxq), luser, ruser, node,
- Nr4states[cb->state]) ;
- }
- return 0 ;
- }
-
- cb = (struct nr4cb *)htol(argv[1]) ;
- if (!nr4valcb(cb)) {
- cwprintf(NULL, notval) ;
- return 1 ;
- }
-
- donrdump(cb) ;
- return 0 ;
- }
-
- /* Dump one control block */
-
- static void donrdump(struct nr4cb *cb)
- {
- char luser[10], ruser[10], node[10] ;
- unsigned seq ;
- struct nr4txbuf *b ;
- struct timer *t ;
-
- pax25(luser,&cb->luser) ;
- pax25(ruser,&cb->user) ;
- pax25(node, &cb->node) ;
-
- cwprintf(NULL, "Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\r\n",
- luser, cb->mynum, cb->myid, ruser, node,
- cb->yournum, cb->yourid, Nr4states[cb->state]) ;
-
- cwprintf(NULL, "Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\r\n",
- cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
- len_mbuf(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
-
- cwprintf(NULL, " Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\r\n",
- cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
- len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
-
- cwprintf(NULL, "TACK: ") ;
- if (run_timer(&cb->tack))
- cwprintf(NULL, "%lu", (cb->tack.start - cb->tack.count) * MSPTICK) ;
- else
- cwprintf(NULL, "stop") ;
- cwprintf(NULL, "/%lu ms; ", cb->tack.start * MSPTICK) ;
-
- cwprintf(NULL, "TChoke: ") ;
- if (run_timer(&cb->tchoke))
- cwprintf(NULL, "%lu", (cb->tchoke.start - cb->tchoke.count) * MSPTICK) ;
- else
- cwprintf(NULL, "stop") ;
- cwprintf(NULL, "/%lu ms; ", cb->tchoke.start * MSPTICK) ;
-
- cwprintf(NULL, "TCD: ") ;
- if (run_timer(&cb->tcd))
- cwprintf(NULL, "%lu", (cb->tcd.start - cb->tcd.count) * MSPTICK) ;
- else
- cwprintf(NULL, "stop") ;
- cwprintf(NULL, "/%lu ms", cb->tcd.start * MSPTICK) ;
-
- if (run_timer(&cb->tcd))
- cwprintf(NULL, "; Tries: %u\r\n", cb->cdtries) ;
- else
- cwprintf(NULL, "\r\n") ;
-
- cwprintf(NULL, "Backoff Level %u SRTT %ld ms Mean dev %ld ms\r\n",
- cb->blevel, cb->srtt, cb->mdev) ;
-
- /* If we are connected and the send window is open, display */
- /* the status of all the buffers and their timers */
-
- if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
-
- cwprintf(NULL, "TxBuffers: Seq Size Tries Timer\r\n") ;
-
- for (seq = cb->ackxpected ;
- nr4between(cb->ackxpected, seq, cb->nextosend) ;
- seq = (seq + 1) & NR4SEQMASK) {
-
- b = &cb->txbufs[seq % cb->window] ;
- t = &b->tretry ;
-
- cwprintf(NULL, " %3u %3d %5d %lu/%lu\r\n",
- seq, len_mbuf(b->data), b->retries + 1,
- (t->start - t->count) * MSPTICK, t->start * MSPTICK) ;
- }
-
- }
-
- }
-
- static int dominquality(int argc, char **argv)
- {
- unsigned val ;
-
- if (argc < 2) {
- cwprintf(NULL, "%u\r\n", nr_autofloor) ;
- return 0 ;
- }
-
- val = atoi(argv[1]) ;
-
- if (val == 0 || val > 255 ) {
- cwprintf(NULL, "The minimum acceptable quality must be 1 to 255\r\n") ;
- return 1 ;
- }
-
- nr_autofloor = val ;
-
- return 0 ;
- }
-
-