home *** CD-ROM | disk | FTP | other *** search
- /*
- stats.c - monitor AX.25 channel and gather network performance
- statistics.
-
- Hardware: IBM PC or compatable with at least 1 serial port,
- TNC with "KISS" firmware installed.
-
- Other software: W0RLI or WA7MBL compatable serial BIOS such
- as COMBIOS or MBBIOS. KISS software for
- TNC.
-
- Language = Microsoft C version 4.0, Microsoft Macro Assembler version 4.0
-
-
- This source is distributed freely and may be copied and
- redistributed with the following provisos:
-
- You may not sell it, nor may you charge for making
- copies beyond the actual cost of mailing and media.
-
- Written by Skip Hansen WB6YMH and Harold Price NK6K.
-
- Feedback is desired.
-
- RCP/M (213) 541-2503 300/1200/2400 baud
- or via packet WB6YMH @ WB6YMH-2 or
- NK6K @ NK6K
-
- Modification history:
-
- 8/10/87 WB6YMH: Initial release.
- ver 1.0
-
- 10/18/87 First general release.
- ver 1.1
-
- */
-
- #include <stdio.h>
- #include <time.h>
- #include <dos.h>
- #include "monfile.h"
-
- /* configuration constants */
-
- #define DUMP_INTERVAL 60*5 /* number of seconds between table dumps */
- #define MAX_CIRCUIT 200 /* number of entrys in circuit table */
- #define MAX_DIGIS 100 /* number of entrys in digi table */
-
- /* misc constants */
-
- #define FALSE 0
- #define TRUE !FALSE
-
- #define FEND 0300
- #define FESC 0333
- #define TFEND 0334
- #define TFESC 0335
-
- #define MIN_SIZE 17 /* minimum size of valid ax.25 frame */
- #define MAX_SIZE 330 /* maximum size of a valid frame */
-
-
- /* global variables */
-
- union REGS inregs, outregs;
-
- unsigned char frame_buf[1024]; /* incomming SLIP frame is assembled here */
-
- int frame_size; /* number of bytes in frame, including CRC */
-
- unsigned char *cp,c;
-
- unsigned char getbyte();
-
- unsigned long get_cd_active(); /* assembly interrupt routines */
- unsigned long get_cd_inactive();
-
- /* NET/ROM network header */
-
- struct netrom {
- char org_node[7];
- char dest_node[7];
- unsigned char ttl;
- unsigned char cndx;
- unsigned char cid;
- unsigned char tx;
- unsigned char rx;
- unsigned char opcode;
- union{
- struct {
- unsigned char p_wind;
- char user[7];
- char at_node[7];
- } con;
-
- struct {
- unsigned char a_wind;
- } con_ack;
-
- struct {
- char info[236];
- } i;
- } v;
- };
-
- struct netrom *netp;
-
- /* NET/ROM routing table broadcast structure */
-
- struct node_list{
- unsigned char signature;
- char mnemonic[6];
- struct routes{
- char dest_node[7];
- char dest_mnemonic[6];
- char best_neighbor[7];
- unsigned char best_quality;
- } route[11];
- };
-
- struct node_list *uip;
-
- /* circuit table */
-
- struct CIRCUIT_RECORD ctab[MAX_CIRCUIT];
-
- /* digipeater table */
-
- struct DIGI_RECORD dtab[MAX_DIGIS];
-
- /* frequency wide statistics */
-
- struct FREQ_RECORD freq;
-
- /* misc variable used to trace state of circuit */
-
- struct STATE_TABLE{
- unsigned int n[8]; /* array of checksums of i frames by n(s) */
- unsigned int digi_bits[8]; /* heard digipeater bit field */
- unsigned int last_ui; /* checksum of last ui frame */
- unsigned int ui_bits; /* heard digipeater bit field for ui */
- unsigned int s_bits; /* heard digipeater bit fields for s */
- unsigned char last_ns; /* last n(s) we heard */
- unsigned char last_s; /* last control field we heard */
- unsigned char first_digi; /* first digipeater we heard */
- } stab[MAX_CIRCUIT];
-
-
- int nr_circuits; /* number of active entrys in circuit table */
-
- unsigned int nr_digis; /* number of active entrys in digipeater table */
-
- unsigned char digi_num; /* number of digi current frame was heard from */
-
- int nr_digi; /* total number of digis this connection */
-
- unsigned int cnum; /* circuit number of current frame */
-
- unsigned int dnum; /* circuit number of current frame for */
- /* "non-digipeated" counters */
-
- unsigned int i_size; /* size of data portion of UI or I frame */
-
- char retry; /* retry flag */
-
- char last_c; /* last character sent to screen */
-
- unsigned char crtype; /* command/response flag */
-
- unsigned char n_s;
-
- unsigned int isum; /* checksum of data portion of UI or I frame */
-
- unsigned int digi_bit; /* bit representing current hop */
-
- unsigned long write_time,start_time;
-
-
- /* parser variables */
-
- int p_timestamp=0;
- int p_baud=4800;
- int p_port=0; /* COM1 */
- int port_base = 0x3f8; /* COM1 */
- char using_combios;
- char ints_active;
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- unsigned char to[10],from[10];
- long cur_time;
- int i,j;
- unsigned char s[128];
-
-
- printf("STATS version 1.1 - Packet radio network performance monitoring program\n");
- printf("October 1987, written by WB6YMH and NK6K\n\n");
- printf("Type ALT-C for command prompt.\n\n");
-
- if (argc>1) { /* package up command line args for parser */
- j=0;
- for (i=1;i<argc;i++) {
- while(*argv[i]!='\0') {
- s[j]=*argv[i];
- j++;
- *argv[i]++;
- }
- s[j++]=' ';
- }
- s[j-1]='\0';
- parse(1,s);
- }
-
- /* check for presence of COMBIOS for our com port */
-
- inregs.h.ah = 4; /* Inquiry */
- inregs.x.dx = p_port;
- int86(0x14,&inregs,&outregs);
- if(outregs.x.ax == 0xaa55){
- ints_active = FALSE;
- using_combios = TRUE;
- }
- else{
- if(p_port < 0 || p_port > 1){
- printf("Error: Port number must be COM1 or COM2 unless COMBIOS is loaded.\n");
- exit(1);
- }
- serlinit(p_port);
- using_combios = FALSE;
- ints_active = TRUE;
- }
-
- if(p_port){
- set_base(0x2f8); /* com2 */
- }
- else{
- set_base(0x3f8); /* com1 */
- }
-
- tick_init();
-
- nr_circuits = 0;
- time(&start_time);
- write_time = start_time + DUMP_INTERVAL;
- init_freq();
-
- while(1){
- if(kbhit())
- do_kbhit();
-
- /* get a frame, check for reasonable frame size */
- /* Some versions of KISS seem to pass bad frames */
- /* once in a while which drives the monitoring */
- /* code nuts if the frame is a runt. */
-
- do{
- get_frame();
-
- } while( frame_size < MIN_SIZE || frame_size > MAX_SIZE);
-
- cp=&frame_buf[1]; /* skip SLIP type byte */
-
- /* put a null at the end of the frame for convience */
-
- cp[frame_size-2]=0;
-
- freq.t_packets++;
- freq.t_bytes += frame_size;
-
- if(frame_size <= 32)
- freq.l32++;
- else if(frame_size <=64)
- freq.l64++;
- else if(frame_size <= 128)
- freq.l128++;
- else if(frame_size <= 256)
- freq.l256++;
- else
- freq.g256++;
-
- if (p_timestamp) {
- time(&cur_time);
- printf("[%15.15s] ",ctime(&cur_time)+4);
- }
- pcall(cp+7,0);
- bcall(cp+7,from);
- putchar('>');
- pcall(cp,0);
- bcall(cp,to);
-
- /* check for ax25v1 vs ax25v2 */
-
- if ((cp[6] & 0x80) == (cp[13] & 0x80))
- crtype='o';
- else if (cp[6] & 0x80)
- crtype='c';
- else
- crtype='r';
-
- cp+=7;
-
- /* print the digipeater list */
-
- nr_digi = 0;
- digi_num = 0;
- digi_bit = 1;
- while(!(cp[6] & 1)){
- putchar(',');
- nr_digi++;
- pcall(cp+7,1);
- if(cp[13] & 0x80 && (cp[13] & 1 || !(cp[20] & 0x80))){
- do_digi(cp+7); /* update digi record */
- digi_bit = 1 << nr_digi;
- digi_num = nr_digi;
- }
- cp+=7;
- }
- cp+=7;
-
- /* lookup this circuit in the tables */
-
- find_circuit(from,to);
-
- /* The global variable cnum points to current circuit. */
-
- ctab[cnum].t_packets++;
- ctab[cnum].t_bytes += frame_size;
-
- if(*cp & 0x10) { /* p/f bit set */
- if(crtype == 'c')
- ctab[dnum].poll++;
- else if(crtype == 'r')
- ctab[dnum].final++;
- }
-
- /* Decode control field of frame to find frame type */
-
- if(!(*cp & 1)){
- do_iframe();
- }
- else if((*cp & 0xef) == 3){
- do_ui();
- }
- else{
- do_stype();
- }
-
- if(last_c != 0xd) /* prevent doublespaced output */
- printf("\n");
- last_c = 0;
-
- /* The global variable dnum points to current circuit if */
- /* and only if this is a "non-digipeated" frame otherwise */
- /* dnum points to an unused entry in the table. This */
- /* kluge helps to eliminate the need for tons of if */
- /* statements. */
-
- ctab[dnum].nd_packets++;
- ctab[dnum].nd_bytes += frame_size;
-
- /* now a few sanity checks */
-
- if(ctab[cnum].u_dbytes > ctab[cnum].nd_dbytes){
- printf("\007Error: U_dbytes > nd_dbytes!\n");
- }
- if(ctab[cnum].t_dbytes > ctab[cnum].t_bytes){
- printf("\007Error: T_dbytes > t_bytes!\n");
- }
- }
- }
-
- do_iframe()
- {
- do_i_size(); /* Calculate size of data portion and checksum */
-
- printf("{%d,%d,%c",(*cp & 0xe0) >> 5,n_s=(*cp & 0xe) >> 1,
- crtype);
- if(*cp & 0x10)
- putchar('*');
- cp++; /* point to pid */
- ctab[cnum].pid = *cp;
- if(stab[cnum].last_ns == n_s || /* expected n(s) */
- /* - or - */
- stab[cnum].n[n_s] != isum){ /* different i */
- /* than last time*/
- stab[cnum].last_ns = (n_s + 1) & 0x7;
- stab[cnum].n[n_s] = isum;
- stab[cnum].digi_bits[n_s] = 0;
- ctab[cnum].u_dpackets++;
- ctab[cnum].u_dbytes += i_size;
-
- freq.u_packets++;
- freq.u_bytes += frame_size;
- if(i_size <= 32)
- ctab[cnum].l32++;
- else if(i_size <= 64)
- ctab[cnum].l64++;
- else if(i_size <= 128)
- ctab[cnum].l128++;
- else if(i_size <=256)
- ctab[cnum].l256++;
- else
- ctab[cnum].g256++;
- }
-
- do_bitmap(&stab[cnum].digi_bits[n_s]);
-
- ctab[dnum].i++;
- ctab[cnum].t_dpackets++;
- ctab[dnum].nd_dpackets++;
- ctab[cnum].t_dbytes += i_size;
- ctab[dnum].nd_dbytes += i_size;
-
- if(retry)
- printf(",retry");
-
- putchar('}');
-
- if(*cp == 0xcf) /* check for netrom PID */
- do_netrom();
- else
- cp++; /* skip PID */
-
- /* print data portion of frame */
-
- while(*cp){
- last_c = *cp;
- if( (*cp & 0x7f) != 7)
- putchar(*cp);
- if(*cp == 0xd)
- putchar(0xa);
- cp++;
- }
- }
-
- do_ui()
- {
- do_i_size(); /* Calculate size of data portion and checksum */
-
- do_bitmap(&stab[cnum].s_bits);
-
- printf("{ui,%c",crtype);
- if(*cp & 0x10)
- putchar('*');
-
- if(stab[cnum].last_ui != isum){
-
- /* unique frame if checksums is different than last UI frame */
-
- stab[cnum].s_bits = 0;
- freq.u_packets++;
- ctab[cnum].u_dpackets++;
- ctab[cnum].u_dbytes += i_size;
- ctab[dnum].nd_dbytes += i_size;
-
- freq.u_bytes += frame_size;
- stab[cnum].last_ui = isum;
- if(i_size <= 32)
- ctab[cnum].l32++;
- else if(i_size <= 64)
- ctab[cnum].l64++;
- else if(i_size <= 128)
- ctab[cnum].l128++;
- else if(i_size <=256)
- ctab[cnum].l256++;
- else
- ctab[cnum].g256++;
- }
-
- if(retry)
- printf(",retry");
-
- putchar('}');
-
- cp++; /* point to pid */
- ctab[cnum].pid = *cp;
- switch(*cp){
- case 0xcf:
- /* net/rom node list broadcast */
- do_routes();
- break;
-
- case 0xcc:
- /* ip frames */
- do_ip();
- break;
-
- case 0xcd:
- /* arp frames */
- do_arp();
- break;
-
- case 0xf0:
- /* "normal" ui frames */
- cp++; /* skip pid */
- while(*cp){
- last_c = *cp;
- if( (*cp & 0x7f) != 7)
- putchar(*cp);
- if(*cp == 0xd)
- putchar(0xa);
- cp++;
- }
- break;
- default:
- printf("Unknown PID in ui frame: 0x%02X\n",*cp);
- break;
- }
-
- ctab[dnum].ui++;
- ctab[cnum].t_dpackets++;
- ctab[dnum].nd_dpackets++;
- ctab[cnum].t_dbytes += i_size;
- }
-
- do_stype()
- {
- if(stab[cnum].last_s != *cp){
-
- /* unique frame if control field is different than last frame */
-
- stab[cnum].last_s = *cp;
- stab[cnum].s_bits = 0;
- freq.u_packets++;
- freq.u_bytes += frame_size;
- }
-
- do_bitmap(&stab[cnum].s_bits);
-
- switch(*cp & 0x3){
- case 1: /* S type frames */
- switch((*cp & 0xc) >> 2){
- case 0:
- ctab[dnum].rr++;
- printf("{rr,%d",(*cp & 0xc0) >> 5);
- break;
- case 1:
- printf("{rnr,%d",(*cp & 0xc0) >> 5);
- ctab[dnum].rnr++;
- break;
- case 2:
- printf("{rej,%d",(*cp & 0xc0) >> 5);
- ctab[dnum].rej++;
- break;
- default:
- printf("{unknown S type ctrl: 0x%X}",*cp);
- return;
- break;
- }
- break;
- case 0x3: /* U frame types */
- /* UI frames handled elsewhere */
- switch(*cp & 0xef){
- case 0x2f:
- printf("{sabm");
- ctab[dnum].sabm++;
- break;
- case 0x43:
- printf("{disc");
- ctab[dnum].disc++;
- break;
- case 0xf:
- printf("{dm");
- ctab[dnum].dm++;
- break;
- case 0x63:
- printf("{ua");
- ctab[dnum].ua++;
- break;
- case 0x87:
- printf("{frmr!");
- ctab[dnum].frmr++;
- break;
- default:
- printf("{unknown frame type ctrl: 0x%02X}",*cp);
- return;
- }
- break;
- default:
- printf("{unknown frame type ctrl: 0x%02X}",*cp);
- return;
- break;
- }
- printf(",%c",crtype);
- if(*cp & 0x10)
- putchar('*');
-
- if(retry)
- printf(",retry");
-
- putchar('}');
- }
-
- /*
- Decode and print NET/ROM network header
- */
-
- do_netrom()
- {
- int i;
-
- cp++; /* point to network header */
- netp = (struct netrom *) cp;
- printf("\n{netrom>");
- pcall(netp->org_node);
- putchar('>');
- pcall(netp->dest_node);
- printf(", ttl:%d, cndx:%d, ",netp->ttl,netp->cndx);
- printf("cid:%d, tx:%d, rx:%d",netp->cid,netp->tx,netp->rx);
- if(netp->opcode & 0x80)
- printf(", Choke");
- if(netp->opcode & 0x40)
- printf(", Nak");
- if(netp->opcode & 0x20)
- printf(", More");
- if(netp->opcode & 0x10)
- printf(", Rsvd");
- switch(netp->opcode & 0xf){
- case 1:
- printf(", Conn");
- printf(", win:%d}\nuser:",netp->v.con.p_wind);
- pcall(netp->v.con.user);
- printf(" node:");
- pcall(netp->v.con.at_node);
- *cp = 0;
- break;
- case 2:
- printf(", Conack");
- printf(", win:%d}",netp->v.con_ack.a_wind);
- *cp = 0;
- break;
- case 3:
- printf(", Discon}");
- *cp = 0;
- break;
- case 4:
- printf(", Disack}");
- *cp = 0;
- break;
- case 5:
- printf(", iframe}\n");
- cp = netp->v.i.info;
- break;
- case 6:
- printf(", iack}");
- *cp = 0;
- break;
- default:
- printf("unknown opcode 0x%2X",netp->opcode);
- printf("\n");
- for(i=0; i< 13; i++)
- printf("%x ",cp[i]);
- printf("\n");
- *cp = 0;
- break;
- }
- }
-
- /*
- Decode and print NET/ROM routing broadcast
- */
-
- do_routes()
- {
- int i, nr_nodes;
-
- cp++;
- uip = (struct node_list *) cp;
- if(uip->signature != 0xff){
- printf("Routing broadcast with unknown signature: 0x%02X\n",uip->signature);
- return;
- }
-
- /* calculate number of nodes in this frame */
-
- nr_nodes = (frame_size - 19) / sizeof(struct routes);
-
- printf("Routing table broadcast from ");
- p_mnem(uip->mnemonic);
- printf("\n");
-
- for(i=0; i < nr_nodes; i++){
- p_mnem(uip->route[i].dest_mnemonic);
- putchar(':');
- pcall(uip->route[i].dest_node);
- printf(" via ");
- pcall(uip->route[i].best_neighbor);
- printf(" quality: %d\n",uip->route[i].best_quality);
- }
- }
-
- /*
- Get a frame from the SLIP interface.
- NOTE: leading type byte IS transfered into the buffer
- */
-
- get_frame()
- {
- char *bptr;
-
- bptr = frame_buf;
- while(getbyte() != FEND); /* wait for start of frame */
- while( (c = getbyte()) == FEND); /* ignore any extra FENDS */
- frame_size = 0;
- do{
- if(c == FESC){
- c = getbyte();
- switch(c){
- case TFEND:
- *bptr++ = FEND;
- frame_size++;
- break;
-
- case TFESC:
- *bptr++ = FESC;
- frame_size++;
- break;
-
- default:
- break;
- }
- }
- else{
- *bptr++ = c;
- frame_size++;
- }
- c = getbyte();
- } while( c != FEND);
-
- /* adjust for CRC bytes which are not transfered */
-
- frame_size++;
- }
-
- /*
- Get a byte from the serial line
- */
-
- unsigned char getbyte()
- {
- int x,not_ready;
-
- do{
- if(kbhit())
- do_kbhit();
- if(time(0) >= write_time)
- dump_data();
- if(using_combios){
- inregs.h.ah = 3; /* get com port status */
- inregs.x.dx = p_port;
- int86(0x14,&inregs,&outregs);
- not_ready = !(outregs.h.ah & 1);
- }
- else{
- x = rcvbyte();
- not_ready = x == -1;
- }
- } while(not_ready);
-
- if(using_combios){
- inregs.h.ah = 2; /* read character */
- int86(0x14,&inregs,&outregs);
- return outregs.h.al;
- }
- else{
- return x & 0xff;
- }
- }
-
- /*
- Print a 6 character mnemonic
- */
-
- p_mnem(string)
- char *string;
- {
- int i;
-
- for(i=0; i < 6; i++)
- putchar(*string++);
- }
-
- /*
- Print IP datagram header
- */
-
- do_ip()
- {
- printf("IP frame\n");
- }
-
- /*
- Print ARP frame type
- */
-
- do_arp()
- {
- printf("ARP frame\n");
- }
-
- /*
- Locate entry in the statistics table for this circuit.
- Generate a new entry if the circuit doesn't exist.
- */
-
- find_circuit(from,to)
- char *from;
- char *to;
- {
- int i;
-
- /* attempt to lookup existing circuit in table */
-
- for(i=0; i < nr_circuits; i++){
- if(!strcmp(ctab[i].to,to) && !strcmp(ctab[i].from,from)){
- cnum = i;
- return;
- }
- }
-
- /* check for table overflow */
-
- if(i == MAX_CIRCUIT){
- dump_data();
- err_exit("The circuit table is full!");
- }
-
- /* initialize new table entry */
-
- nr_circuits++;
- memset(&ctab[i],'\0',sizeof(struct CIRCUIT_RECORD));
- memset(&stab[i],'\0',sizeof(struct STATE_TABLE));
- strcpy(ctab[i].to,to);
- strcpy(ctab[i].from,from);
- ctab[i].digis = nr_digi;
- time(&ctab[i].c_time); /* timestamp entry */
- stab[i].last_s = 0; /* impossible sup type */
- cnum = i;
- }
-
- /*
- Compute size of data portion of I or UI frame types.
- Calculate Checksum on data portion.
- */
-
- do_i_size()
- {
- unsigned char *tmp;
- int x;
-
- /* cp is currently pointing at the frames control byte */
-
- i_size = frame_size - (cp - &frame_buf[1]) - 4;
-
- /* calculate checksum of data portion of the frame */
-
- isum = 0;
- tmp = cp;
- x = i_size + 1;
- tmp++; /* point to pid byte */
-
- /* calculate checksum of I portion of frame */
-
- while(x--){
- isum += *tmp++;
- }
- }
-
- /*
- Dump the statistic tables to disk
- */
-
- dump_data()
- {
- int i;
- FILE *fp;
-
- freq.dcd_on_ticks = get_cd_active();
- freq.dcd_off_ticks = get_cd_inactive();
-
- if(!(fp = fopen("LOG","a")))
- err_exit("Opening LOG file.");
-
- fprintf(fp,"T,%lu\n",start_time);
-
- fprintf(fp,"F,%lu,%lu,%lu,",freq.t_packets,freq.t_bytes,freq.u_packets);
- fprintf(fp,"%lu,%lu,%lu,",freq.u_bytes,freq.l32,freq.l64);
- fprintf(fp,"%lu,%lu,%lu,",freq.l128,freq.l256,freq.g256);
- fprintf(fp,"%lu,%lu\n",freq.dcd_on_ticks,freq.dcd_off_ticks);
- printf("\n\n { Opening log file at %s",ctime(&start_time));
- printf(" Writing %d digipeater records...",nr_digis);
- for(i=0; i < nr_digis; i++){
- fprintf(fp,"D,%s,%lu,",dtab[i].call,dtab[i].t_packets);
- fprintf(fp,"%lu\n",dtab[i].t_bytes);
- }
- printf("\n Writing %d circuit records...",nr_circuits);
- for(i=0; i < nr_circuits; i++){
- fprintf(fp,"C,%s,%s,%d,",ctab[i].to,ctab[i].from,ctab[i].digis);
- fprintf(fp,"%d,",ctab[i].pid);
- fprintf(fp,"%lu,%lu,",ctab[i].u_dpackets,ctab[i].nd_dpackets);
- fprintf(fp,"%lu,%lu,",ctab[i].t_dpackets,ctab[i].nd_packets);
- fprintf(fp,"%lu,%lu,",ctab[i].t_packets,ctab[i].u_dbytes);
- fprintf(fp,"%lu,",ctab[i].nd_dbytes);
- fprintf(fp,"%lu,%lu,",ctab[i].t_dbytes,ctab[i].nd_bytes);
- fprintf(fp,"%lu,",ctab[i].t_bytes);
- fprintf(fp,"%lu,",ctab[i].c_time);
- fprintf(fp,"%lu,%lu,%lu,",ctab[i].sabm,ctab[i].ua,ctab[i].disc);
- fprintf(fp,"%lu,%lu,%lu,",ctab[i].dm,ctab[i].rej,ctab[i].rr);
- fprintf(fp,"%lu,%lu,",ctab[i].rnr,ctab[i].i);
- fprintf(fp,"%lu,%lu,",ctab[i].ui,ctab[i].frmr);
- fprintf(fp,"%lu,%lu,%lu,",ctab[i].poll,ctab[i].final,ctab[i].l32);
- fprintf(fp,"%lu,%lu,%lu,",ctab[i].l64,ctab[i].l128,ctab[i].l256);
- fprintf(fp,"%lu\n",ctab[i].g256);
- }
- printf("\n Closing LOG file...}");
- if(fclose(fp))
- err_exit("Closing LOG file.");
- printf("\n");
- init_freq();
- time(&start_time);
- write_time = start_time + DUMP_INTERVAL;
- }
-
- /*
- Build an ASCII callsign from left shifted AX.25 format
- callsign.
- */
-
- bcall(from,to)
- unsigned char *from;
- unsigned char *to;
- {
- int i;
- unsigned char c,*tmp;
-
- tmp = to;
- for(i=0; i < 6; i++){
- c = *from++ >> 1;
- if(c != ' ')
- *to++ = c;
- }
-
- if(tmp == to){
- sprintf(to,"BLANK");
- }
- else{
- c = (*from >>1) & 0xf;
-
- if(c)
- sprintf(to,"-%d",c);
- else
- *to = 0;
- }
- }
-
- /*
- Clear the frequency wide statistical counters.
- */
-
- init_freq()
- {
- freq.t_packets =
- freq.t_bytes =
- freq.u_packets =
- freq.u_bytes =
- freq.l32 =
- freq.l64 =
- freq.l128 =
- freq.l256 =
- freq.g256 = 0l;
- nr_circuits =
- nr_digis = 0;
- }
-
- /*
- Gather statistics on Digipeater activity
- */
-
- do_digi(dptr)
- unsigned char *dptr;
- {
- int i;
- unsigned char digi_call[10];
-
- bcall(dptr,digi_call);
-
- /* lookup digipeater callsign in digipeater table */
-
- for(i=0; i < nr_digis; i++){
- if(!strcmp(dtab[i].call,digi_call)){
- dtab[i].t_packets++;
- dtab[i].t_bytes += frame_size;
- return;
- }
- }
-
- /* check for table overflow */
-
- if(i == MAX_DIGIS){
- printf("\007Error: The digipeater table is full!\n");
- return;
- }
-
- /* initialize new digipeater table entry */
-
- nr_digis++;
- strcpy(dtab[i].call,digi_call);
- dtab[i].t_packets = 1l;
- dtab[i].t_bytes = frame_size;
- }
-
- /*
- Print fatal error message, shutdown background interrupt
- processes and exit.
- */
-
- err_exit(string)
- char *string;
- {
- printf("\007Error: %s\n",string);
- if(!using_combios)
- serldone();
- tick_stop();
- exit();
- }
-
- /*
- Process keystrokes entered by user
- */
-
- do_kbhit()
- {
- unsigned char kbdata;
- kbdata = getch();
- if(kbdata == 0){
- kbdata = getch();
- if (kbdata == 45/*X*/) {
-
- /* ALT-X - exit */
-
- if(ints_active)
- serldone();
- tick_stop();
- dump_data();
- exit();
- }
- else if (kbdata == 46/*C*/) {
- cprintf("cmd:");
- parse(0,NULL);
- }
- }
- }
-
- /*
- Print Call in AX.25 left shifted format. Add an
- '*' after call if it's an digipeater and the has been
- digipeated bit is set and the next digipeater's bit is
- not set.
- */
-
- pcall(string,flag)
- unsigned char *string;
- int flag; /* set if call is a digipeater call */
- {
- int i;
- char c;
-
- /* print the callsign */
-
- for(i = 0; i< 6; i++){
- c=*string++ >> 1;
- if(c != ' ')
- putchar(c);
- }
-
- /* display SSID if there is one */
-
- c=(*string >> 1) & 0xf;
- if(c)
- printf("-%d",c);
-
- /* display the has been digipeated bit if appropriate */
-
- if (flag) {
- if(*string & 0x80 && (*string & 1 || !(string[7] & 0x80)))
- putchar('*');
- }
- }
-
- /*
- Process the digipeaters heard bit map, set the global retry flag
- if the frame has been heard from this hop before.
- */
-
- do_bitmap(bit_map)
- unsigned int *bit_map;
- {
- if(*bit_map & digi_bit){
-
- /* this digi was heard before, this must be a retry */
-
- *bit_map = digi_bit; /* clear other bits */
- dnum = cnum; /* increment nd counters */
- retry = TRUE;
- }
- else if(*bit_map){
-
- /* some other digi was heard, this must be another */
- /* digipeater hop, don't do nd counters */
-
- *bit_map |= digi_bit; /* set our bit */
- dnum = nr_circuits; /* don't do nd counters, point */
- /* dnum somewhere harmless */
- retry = FALSE;
- }
- else{
-
- /* no one was heard from before, this must be */
- /* the first time this packet was heard */
-
- *bit_map |= digi_bit; /* set our bit */
- dnum = cnum; /* increment nd counters */
- retry = FALSE;
- }
- }