home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "global.h"
- #include "mbuf.h"
- #include "session.h"
- #include "ax25.h"
- #include "ax_mbx.h"
- #include "timer.h"
- #include "iface.h"
- #include "lapb.h"
- #include "cmdparse.h"
- #include "netuser.h"
- #include "misc.h"
- #include "vterm.h"
-
- static int doaxreset(int, char **);
- static int doaxstat(int, char **);
- static void dumpstat(struct ax25_cb *);
- static int domycall(int, char **);
- static int dodigipeat(int, char **);
- static int dot1(int, char **);
- static int dot2(int, char **);
- static int dot3(int, char **);
- static int dot4(int, char **);
- static int don2(int, char **);
- static int domaxframe(int, char **);
- static int doheard(int, char **);
- static int dopaclen(int, char **);
- static int dopthresh(int, char **);
- static int doaxwindow(int, char **);
-
- static int mh_compare(const void *, const void *);
-
- char *ax25states[] = {
- "Disconnected",
- "Conn pending",
- "Disc pending",
- "Connected",
- "Recovery",
- "Frame Reject",
- };
-
- static struct cmds axcmds[] = {
- "digipeat", dodigipeat, 0, NULLCHAR, NULLCHAR,
- "heard", doheard, 0, NULLCHAR, NULLCHAR,
- "maxframe", domaxframe, 0, NULLCHAR, NULLCHAR,
- "mycall", domycall, 0, NULLCHAR, NULLCHAR,
- "paclen", dopaclen, 0, NULLCHAR, NULLCHAR,
- "pthresh", dopthresh, 0, NULLCHAR, NULLCHAR,
- "reset", doaxreset, 2, "ax25 reset <axcb>", NULLCHAR,
- "retry", don2, 0, NULLCHAR, NULLCHAR,
- "status", doaxstat, 0, NULLCHAR, NULLCHAR,
- "t1", dot1, 0, NULLCHAR, NULLCHAR,
- "t2", dot2, 0, NULLCHAR, NULLCHAR,
- "t3", dot3, 0, NULLCHAR, NULLCHAR,
- "t4", dot4, 0, NULLCHAR, NULLCHAR,
- "window", doaxwindow, 0, NULLCHAR, NULLCHAR,
- NULLCHAR,
- };
-
- /* Multiplexer for top-level ax25 command */
- int doax25(int argc, char **argv)
- {
- return subcmd(axcmds,argc,argv);
- }
-
- static int doaxreset(int argc, char **argv)
- {
- struct ax25_cb *axp;
- extern char notval[];
-
- argc = argc;
-
- axp = (struct ax25_cb *)htol(argv[1]);
- if (!ax25val(axp))
- {
- cwprintf(NULL, notval);
- return 1;
- }
- reset_ax25(axp);
- return 0;
- }
-
- /* Display AX.25 link level control blocks */
- static int doaxstat(int argc, char **argv)
- {
- register int i;
- register struct ax25_cb *axp;
- char tmp[10];
- extern char notval[];
-
- if (argc < 2)
- {
- cwprintf(NULL, " &AXB IF Snd-Q Rcv-Q Remote State\r\n");
- for (i=0;i<NHASH;i++)
- {
- for (axp = ax25_cb[i];axp != NULLAX25; axp = axp->next)
- {
- pax25(tmp,&axp->addr.dest);
- cwprintf(NULL, "%8lx %-5s%-8d%-8d%-10s%s\r\n",
- (long)axp,axp->interface->name,
- len_q(axp->txq),len_mbuf(axp->rxq),
- tmp,ax25states[axp->state]);
- }
- }
- return 0;
- }
- axp = (struct ax25_cb *)htol(argv[1]);
- if (!ax25val(axp))
- {
- cwprintf(NULL, notval);
- return 1;
- }
- dumpstat(axp);
- return 0;
- }
- /* Dump one control block */
- static void dumpstat(register struct ax25_cb *axp)
- {
- char tmp[10];
- int i;
-
- if (axp == NULLAX25 || axp->interface == NULLIF)
- return;
- cwprintf(NULL, "&AXB IF Remote RB V(S) V(R) Unack P Retry State\r\n");
- pax25(tmp,&axp->addr.dest);
- cwprintf(NULL, "%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
- cwputchar(NULL, axp->rejsent ? 'R' : ' ');
- cwputchar(NULL, axp->remotebusy ? 'B' : ' ');
- cwprintf(NULL, " %4d %4d",axp->vs,axp->vr);
- cwprintf(NULL, " %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
- cwprintf(NULL, " %02u/%02u",axp->retries,axp->n2);
- cwprintf(NULL, " %s\r\n",ax25states[axp->state]);
-
- cwprintf(NULL, "T1: ");
- if (run_timer(&axp->t1))
- cwprintf(NULL, "%lu",(axp->t1.start - axp->t1.count) * MSPTICK);
- else
- cwprintf(NULL, "stop");
- cwprintf(NULL, "/%lu ms; ",axp->t1.start * MSPTICK);
-
- cwprintf(NULL, "T2: ");
- if (run_timer(&axp->t2))
- cwprintf(NULL, "%lu",(axp->t2.start - axp->t2.count) * MSPTICK);
- else
- cwprintf(NULL, "stop");
- cwprintf(NULL, "/%lu ms; ",axp->t2.start * MSPTICK);
-
- cwprintf(NULL, "T3: ");
- if (run_timer(&axp->t3))
- cwprintf(NULL, "%lu",(axp->t3.start - axp->t3.count) * MSPTICK);
- else
- cwprintf(NULL, "stop");
- cwprintf(NULL, "/%lu ms; ",axp->t3.start * MSPTICK);
-
- cwprintf(NULL, "T4: ");
- if (run_timer(&axp->t4))
- cwprintf(NULL, "%lu",(axp->t4.start - axp->t4.count) * MSPTICK);
- else
- cwprintf(NULL, "stop");
- cwprintf(NULL, "/%lu ms\r\n",axp->t4.start * MSPTICK);
-
- if (axp->addr.ndigis == 0)
- return;
- cwprintf(NULL, "Digipeaters:");
- for (i=0;i<axp->addr.ndigis;i++)
- {
- pax25(tmp,&axp->addr.digis[i]);
- cwprintf(NULL, " %s",tmp);
- }
- cwprintf(NULL, "\r\n");
- }
-
- /* Display or change our AX.25 address */
- static int domycall(int argc, char **argv)
- {
- char buf[15];
-
- if (argc < 2)
- {
- pax25(buf,&mycall);
- cwprintf(NULL, "%s\r\n",buf);
- return 0;
- }
- if (setcall(&mycall,argv[1]) == -1)
- return -1;
- mycall.ssid |= E;
- return 0;
- }
-
- /* Control AX.25 digipeating */
- static int dodigipeat(int argc, char **argv)
- {
- extern int digipeat;
- extern int32 digisent;
-
- if (argc == 1)
- {
- cwprintf(NULL, "digipeat %s\r\n",digipeat ? "on" : "off");
- cwprintf(NULL, "digipeated packets = %lu\r\n",digisent);
- }
- else
- {
- if (strcmp(argv[1],"on") == 0)
- digipeat = 1;
- else
- digipeat = 0;
- }
- return(0);
- }
-
- /* Set retransmission timer */
- static int dot1(int argc, char **argv)
- {
- extern int16 t1init;
-
- if (argc == 1)
- {
- cwprintf(NULL, "T1 %lu ms\r\n",(long)t1init * MSPTICK);
- }
- else
- {
- t1init = (int16)(atol(argv[1]) / MSPTICK);
- }
- return(0);
- }
-
- /* Set acknowledgement delay timer */
- static int dot2(int argc, char **argv)
- {
- extern int16 t2init;
-
- if (argc == 1)
- {
- cwprintf(NULL, "T2 %lu ms\r\n",(long)t2init * MSPTICK);
- }
- else
- {
- t2init = (int16)(atol(argv[1]) / MSPTICK);
- }
- return(0);
- }
-
- /* Set idle timer */
- static int dot3(int argc, char **argv)
- {
- extern int16 t3init;
-
- if (argc == 1)
- {
- cwprintf(NULL, "T3 %lu ms\r\n",(long)t3init * MSPTICK);
- }
- else
- {
- t3init = (int16)(atol(argv[1]) / MSPTICK);
- }
- return(0);
- }
-
- /* Set link redundancy timer */
- static int dot4(int argc, char **argv)
- {
- extern int16 t4init;
-
- if (argc == 1)
- {
- cwprintf(NULL, "T4 %lu sec\r\n",((long)t4init * MSPTICK) / 1000);
- }
- else
- {
- t4init = (int16)((atol(argv[1]) * 1000) / MSPTICK);
- }
- return(0);
- }
-
- /* Set retry limit count */
- static int don2(int argc, char **argv)
- {
- extern int16 n2;
-
- if (argc == 1)
- {
- cwprintf(NULL, "Retry %u\r\n",n2);
- }
- else
- {
- n2 = (int16)(atoi(argv[1]));
- }
- return(0);
- }
-
- /* Set maximum number of frames that will be allowed in flight */
- static int domaxframe(int argc, char **argv)
- {
- extern int16 maxframe;
-
- if (argc == 1)
- {
- cwprintf(NULL, "Maxframe %u\r\n",maxframe);
- }
- else
- {
- maxframe = (int16)(atoi(argv[1]));
- }
- return(0);
- }
-
- /* Display the last x number of stations heard in the ether */
- static int doheard(int argc, char **argv)
- {
- extern struct ax25mh mhlist[]; /* the mheard table (ax25.c) */
- char mhcallsign[10]; /* field for call sign dumpout */
- char *mhtime; /* ascii time representation */
- int mhcolumn = 0; /* page column display counter */
- int mh_entry; /* index into mhlist */
-
- argv = argv;
-
- if (argc > 1) /* any second arg flushes mhlist */
- {
- for (mh_entry = 0; mh_entry < 40; mh_entry++)
- mhlist[mh_entry].mheard_time = 0; /* 0 time = empty */
- return(0);
- }
-
- qsort((void *)mhlist, 40, sizeof(struct ax25mh), mh_compare);
-
- for (mh_entry = 0; mh_entry < 40; mh_entry++)
- {
- if (mhlist[mh_entry].mheard_time == 0) /* empty entry? */
- break; /* all done now */
-
- if (mh_entry == 0)
- cwprintf(NULL, "AX25 Stations heard. (* = heard directly)\r\n");
-
- pax25(mhcallsign,&mhlist[mh_entry].mheard_call); /* dump callsign */
- mhtime = ctime(&mhlist[mh_entry].mheard_time); /* get time in ascii */
- rip(mhtime); /* lose the \n etc */
- cwprintf(NULL, "%s %s %-11s", mhtime, mhlist[mh_entry].mheard_digi ? " " : "*", mhcallsign) ;
- mhcolumn++;
- if (mhcolumn == 2)
- {
- mhcolumn = 0;
- cwprintf(NULL, "\r\n");
- }
- }
- if (mhcolumn == 1)
- cwprintf(NULL, "\r\n");
- return(0);
- }
-
- static int mh_compare(const void *mh1, const void *mh2)
- {
- struct ax25mh *mheard1 = (struct ax25mh *)mh1;
- struct ax25mh *mheard2 = (struct ax25mh *)mh2;
-
- if (mheard1->mheard_time == mheard2->mheard_time)
- return(0);
- if (mheard1->mheard_time > mheard2->mheard_time)
- return(-1);
- else
- return(1);
- }
-
- /* Set maximum length of I-frame data field */
- static int dopaclen(int argc, char **argv)
- {
- extern int16 paclen;
-
- if (argc == 1)
- {
- cwprintf(NULL, "Paclen %u\r\n",paclen);
- }
- else
- {
- paclen = atoi(argv[1]);
- }
- return(0);
- }
- /* Set size of I-frame above which polls will be sent after a timeout */
- static int dopthresh(int argc, char **argv)
- {
- extern int16 pthresh;
-
- if (argc == 1)
- {
- cwprintf(NULL, "Pthresh %u\r\n",pthresh);
- }
- else
- {
- pthresh = atoi(argv[1]);
- }
- return(0);
- }
-
- /* Set high water mark on receive queue that triggers RNR */
- static int doaxwindow(int argc, char **argv)
- {
- extern int16 axwindow;
-
- if (argc == 1)
- {
- cwprintf(NULL, "Axwindow %u\r\n",axwindow);
- }
- else
- {
- axwindow = atoi(argv[1]);
- }
- return(0);
- }
- /* End of ax25 subcommands */
-
- /* Initiate interactive AX.25 connect to remote station */
- int doconnect(int argc, char **argv)
- {
- struct ax25_addr dest;
- struct ax25 addr;
- struct interface *ifp;
- struct session *s;
- extern int16 axwindow;
- int i;
-
- 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;
- }
-
- if (strcmp(argv[1],"netrom") == 0)
- {
- cwprintf(NULL, "Connect on netrom interface not supported.\r\n");
- return 1;
- }
- setcall(&dest, argv[2]);
- /* See if a session already exists */
- for (s = sessions; s < &sessions[nsessions]; s++)
- {
- if (s->type == AX25TNC && addreq(&s->cb.ax25_cb->addr.dest,&dest))
- {
- cwprintf(NULL, "Session %u to %s already exists\r\n", s - sessions,argv[2]);
- return 1;
- }
- }
- /* Allocate a session descriptor */
- if ((s = newsession()) == NULLSESSION)
- {
- cwprintf(NULL, "Too many sessions\r\n");
- return 1;
- }
- if ((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
- strcpy(s->name,argv[2]);
- s->type = AX25TNC;
- s->parse = (void(*)())ax_parse;
- s->echo = TRUE;
- /* use callsign dedicated to this interface */
- memcpy(&addr.source, ifp->hwaddr, sizeof(struct ax25_addr));
- setcall(&addr.dest, argv[2]);
- for (i = 3; i < argc; i++)
- setcall(&addr.digis[i - 3], argv[i]);
- addr.ndigis = i - 3;
- s->cb.ax25_cb = open_ax25(&addr, axwindow, (void(*)())ax_rx, (void(*)())ax_tx, (void(*)())ax_state, ifp, (char *) s);
- s->window = s->cb.ax25_cb->terminal;
- s->cb.ax25_cb->terminal->Session = s;
-
- vterm_open(s->window->vt);
-
- /* {
- wimp_wstate window_state;
-
- wimp_get_wind_state(s->window->Window_Handle, &window_state);
- window_state.o.behind = -1;
- wimp_open_wind(&window_state.o);
- } */
- go(s);
- return 0;
- }
-
-
- /* Display changes in AX.25 state */
- void ax_state(struct ax25_cb *axp, int old, int new)
- {
- struct session *s;
-
- s = (struct session *)axp->user;
-
- if (current != NULLSESSION && current->type == AX25TNC && current == s)
- {
- /* Don't print transitions between CONNECTED and RECOVERY */
- if (new != RECOVERY && !(old == RECOVERY && new == CONNECTED))
- cwprintf(NULL, "%s\r\n", ax25states[new]);
- if (new == DISCONNECTED)
- cmdmode();
- }
- if (new == DISCONNECTED)
- {
- axp->user = NULLCHAR;
- freesession(s);
- }
- }
- /* Handle typed characters on AX.25 connection */
- void ax_parse(struct session *active, char *buf, int16 cnt)
- {
- struct mbuf *bp;
- register char *cp;
- char c;
-
- if (active->window == NULL && (active == NULLSESSION || active->type != AX25TNC))
- return; /* "can't happen" */
-
- /* If recording is on, record outgoing stuff too */
- if (active->record != NULLFILE)
- fwrite(buf,1,cnt,active->record);
-
- /* Allocate buffer and start it with the PID */
- bp = alloc_mbuf(cnt + 1);
- *bp->data = PID_NO_L3;
- bp->cnt++;
-
- /* Copy keyboard buffer to output, stripping line feeds */
- cp = bp->data + 1;
- while(cnt-- != 0)
- {
- c = *buf++;
- if (c != '\n')
- {
- *cp++ = c;
- bp->cnt++;
- }
- }
- send_ax25(active->cb.ax25_cb,bp);
- }
- /* Handle new incoming terminal sessions
- * This is the default receive upcall function, used when
- * someone else connects to us
- */
- void ax_incom(register struct ax25_cb *axp, int16 cnt)
- {
- if (ax25mbox)
- {
- mbx_incom(axp,cnt) ;
- }
- else
- {
- ax_session(axp,cnt) ;
- }
- return ;
-
- }
-
- /* This function sets up an ax25 chat session */
- void ax_session(register struct ax25_cb *axp, int16 cnt)
- {
- struct session *s;
- char remote[10];
- extern char hostname[];
- extern int attended;
- char *cp;
- time_t t;
-
- cnt = cnt;
-
- time(&t);
- cp = ctime(&t);
- rip(cp);
-
- pax25(remote, &axp->addr.dest);
- if ((s = newsession()) == NULLSESSION)
- {
- /* Out of sessions */
- disc_ax25(axp);
- return;
- }
- s->type = AX25TNC;
- s->name = malloc((int16) strlen(remote) + 1);
- s->cb.ax25_cb = axp;
- s->parse = (void(*)())ax_parse;
- s->window = axp->terminal;
- s->window->Session = s;
- s->echo = TRUE;
- strcpy(s->name, remote);
- axp->r_upcall = (void(*)())ax_rx;
- axp->s_upcall = ax_state;
- axp->t_upcall = (void(*)())ax_tx;
- axp->user = (char *) s;
- vterm_open(s->window->vt);
- /* {
- wimp_wstate window_state;
-
- wimp_get_wind_state(s->window->Window_Handle, &window_state);
- window_state.o.behind = -1;
- wimp_open_wind(&window_state.o);
- } */
- cwtitle(axp->terminal, "AX25 - From %s", remote);
- cwprintf(NULL, "%s : Incoming AX25 session %u from %s\r\n", cp, s - sessions, remote);
- log_event(NULL, "AX25 Chatter session requested : %s", remote);
- if (attended)
- aprintf(axp, "Welcome %s to the %s system's 'Chat' mode.\r", remote, hostname);
- else
- aprintf(axp, "Sorry %s, the %s system is UNATTENDED.\r", remote, hostname);
- }
-
- /* Handle incoming terminal traffic */
- void ax_rx(struct ax25_cb *axp, int16 cnt)
- {
- extern int ttyflow;
- register struct mbuf *bp;
- register char *s;
- register char *t;
- char *line;
- struct session *active = (struct session *) axp->user;
-
- /* Hold output if we're typing */
- if (axp->window == NULL && (mode != CONV_MODE || active == NULLSESSION || ttyflow == 0
- || active->type != AX25TNC || active->cb.ax25_cb != axp))
- return;
-
- if ((bp = recv_ax25(axp, cnt)) == NULLBUF)
- return;
-
- /* Display received characters, translating CR's to CR/LF */
- if ((line = s = malloc(len_mbuf(bp) + 1)) == NULLCHAR)
- {
- cwprintf(NULL, "Out of memory in AX25CMD\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 (active->record)
- {
- fwrite(line, 1, s - line, active->record);
- fflush(active->record);
- }
-
- *s = '\0';
- cwprintf(axp->terminal, line);
- free(line);
- }
- /* Handle transmit upcalls. Used only for file uploading */
- void ax_tx(struct ax25_cb *axp, int16 cnt)
- {
- register char *cp;
- struct session *s;
- register struct mbuf *bp;
- int16 size;
- int c;
-
- if ((s = (struct session *)axp->user) == NULLSESSION
- || s->upload == NULLFILE)
- return;
- while(cnt != 0)
- {
- size = min(cnt,axp->paclen+1);
- if ((bp = alloc_mbuf(size)) == NULLBUF)
- break;
- cp = bp->data;
- /* Start with the PID */
- *cp++ = PID_NO_L3;
- bp->cnt++;
-
- /* 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++;
- }
- if (bp->cnt > 1)
- {
- send_ax25(axp,bp);
- }
- else
- {
- /* Empty frame, don't bother sending */
- free_p(bp);
- break;
- }
- cnt -= bp->cnt;
- }
- if (cnt != 0)
- {
- /* Error or end-of-file */
- fclose(s->upload);
- s->upload = NULLFILE;
- free(s->ufile);
- s->ufile = NULLCHAR;
- }
- }
-
-