home *** CD-ROM | disk | FTP | other *** search
- /*
- AX25DUMP.C -- Dumps AX.25 packets in human readable format
-
- Poor Man's Packet (PMP)
- Copyright (c) 1991 by Andrew C. Payne All Rights Reserved.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
- granted, provided that the above copyright notice appear in all copies.
- The author makes no representations about the suitability of this software
- for any purpose. It is provided "as is" without express or implied warranty.
-
- August, 1989
- Andrew C. Payne
-
- 09/13/89 - changed to work with L2 packet structures /acp/
- */
-
- /* ----- Includes ----- */
- #include <stdio.h>
- #include <conio.h>
- #include <mem.h>
- #include <alloc.h>
- #include <string.h>
- #include "pmp.h"
- #ifdef NETROM
- #include "netrom.h"
- #endif
-
- /* ----- Local Variables ----- */
- static char ptext[1000]; /* packet text */
- static char *ploc; /* current location in packet text */
-
- /* cat(text)
- Concatenates text string onto packet text string.
- */
- static void cat(char *p)
- {
- while(*ploc++ = *p++)
- ;
- ploc--;
- }
-
- /* ----- Level 1 to Level 2 conversion ----- */
-
- /* AX25L1toL2(l1)
- Given a pointer to a level 1 packet, converts it to a level 2 packet
- structure and returns a pointer to the newly allocated level 2 packet
- structure.
-
- Returns NULL if an error in the structure of the level 1 packet
- */
- struct ax25_packet *AX25L1toL2(struct ax25_level1 *p1)
- {
- struct ax25_packet p2;
- struct ax25_packet *p;
- byte *d;
- byte t1,t2;
- int cr[] = { UNKNOWN, RESPONSE, COMMAND, UNKNOWN };
-
- if(p1->len < 17) /* no runt packets */
- return NULL;
-
- d = p1->data; /* packet data */
-
- /* copy destination callsign and ssid */
- memcpy(&p2.dest,d,MAXCLEN);
- d += MAXCLEN;
- p2.dest.ssid = SSIDMASK & (t1 = *d++);
-
- /* copy source callsign and ssid */
- memcpy(&p2.source,d,MAXCLEN);
- d += MAXCLEN;
- p2.source.ssid = SSIDMASK & (t2 = *d++);
-
- /* command/response bits */
- p2.cmdresp = cr[(((t1 & REPEATED) != 0) << 1) + ((t2 & REPEATED) != 0)];
-
- /* copy digipeaters, if any */
- p2.ndigis = 0;
- while(p2.ndigis < MAXDIGIS && ((d[-1] & 1) == 0)) {
- memcpy(&p2.digis[p2.ndigis],d,MAXCLEN);
- d += MAXCLEN;
- p2.digis[p2.ndigis].ssid = SSIDMASK & *d;
- p2.repeated[p2.ndigis++] = REPEATED & *d++;
- }
-
- if(p2.ndigis == MAXDIGIS) /* too many digipeaters */
- return NULL;
-
- /* control field */
- switch(FrameType(p2.cont = *d++)) {
- case I:
- case UI:
- p2.pid = *d++; /* protocol ID */
- }
-
- /* allocate record and copy in header and data field, if any */
- p2.dlen = p1->len - (d - p1->data) - 2; /* length remaining */
- if(p2.dlen > 256 || p2.dlen < 0)
- return NULL; /* out of range packets */
- p = malloc(sizeof(struct ax25_packet) + p2.dlen);
- if(p == NULL)
- return NULL; /* out of memory */
-
- memcpy(p, &p2, sizeof(struct ax25_packet));
- if(p2.dlen)
- memcpy(p->data, d, p2.dlen);
-
- /* return pointer to allocated packet */
- return p;
- }
-
- /* DumpLevel2Header(p)
- Given a pointer to a Level 2 packet structure, creates a human readable
- level 2 header and info field in ptext.
- */
- void DumpLevel2Header(struct ax25_packet *p)
- {
- int i;
- int showinfo; /* flag for fields w/ info */
- int type; /* frame type */
- char t[20]; /* temp space */
-
- ploc = ptext;
-
- /* print the to/from address */
- cat(GetAX25Addr(&p->source));
- cat(">");
- cat(GetAX25Addr(&p->dest));
-
- /* print digipeaters */
- if(p->ndigis) {
- cat(" [via ");
- for(i=0; i<p->ndigis; i++) {
- cat(GetAX25Addr(p->digis + i));
- if(p->repeated[i])
- cat("*");
- if(i != (p->ndigis - 1))
- cat(",");
- }
- cat("]");
- }
-
- /* decode and show control byte */
- cat(" <");
- showinfo = FALSE;
- switch(type = FrameType(p->cont)) {
- case I:
- cat("I");
- showinfo = TRUE;
- break;
- case RR:
- cat("RR");
- break;
- case RNR:
- cat("RNR");
- break;
- case REJ:
- cat("REJ");
- break;
- case SABM:
- cat("SABM");
- break;
- case DISC:
- cat("DISC");
- break;
- case DM:
- cat("DM");
- break;
- case UA:
- cat("UA");
- break;
- case FRMR:
- cat("FRMR");
- break;
- case UI:
- cat("UI");
- showinfo = TRUE;
- break;
- }
-
- /* show the protocol ID */
- if(showinfo) {
- switch(p->pid) {
- case PID_TEXT:
- cat(" (Text)");
- break;
- case PID_NETROM:
- cat(" (NET/ROM)");
- break;
- default:
- sprintf(t," (PID=0x%X)",p->pid);
- cat(t);
- break;
- }
- }
-
- /* show poll/final bit */
- if(p->cont & PF) {
- switch(p->cmdresp) {
- case COMMAND:
- cat(" (P)"); /* cmd, poll */
- break;
- case RESPONSE:
- cat(" (F)"); /* resp, final */
- break;
- case UNKNOWN:
- cat(" (P/F)");
- break;
- }
- }
-
- /* show sequence numbers */
- if((type & 3) != U) {
- sprintf(t," R%d",(p->cont >> 5) & 7);
- cat(t);
- }
- if(type == I) {
- sprintf(t," S%d",(p->cont >> 1) & 7);
- cat(t);
- }
- cat(">");
- }
-
- #ifdef NETROM
- /* ----- Net/Rom Packet Decoding ----- */
-
- /* NRDumpBdcst(d)
- Given a pointer to a broadcast data item, adds it to ptext.
- */
- static void NRDumpBdcst(struct nr_broadcast *p)
- {
- char t[80],t1[10],t2[10];
-
- /* copy space padded alias */
- memcpy(t1,p->alias,6);
- t1[6] = '\0';
-
- /* show routing entry */
- strcpy(t2, GetAX25Addr(&p->neighbor));
- sprintf(t,"%10s %10s %10s %d\n",
- GetAX25Addr(&p->dest),
- t1,
- t2,
- p->quality);
- cat(t);
- }
-
- /* NetRomDump(d,len)
- Given a Net/Rom packet, dumps it in human readable form (adds it to
- ptext)
- */
- void NetRomDump(byte *d, int len)
- {
- char t[80],t1[10];
- int i;
- int data;
-
- if(len == 0)
- return;
-
- data = FALSE;
- cat(" NET/ROM: ");
- /* handle routing broadcasts */
- if(*d == 0xff) {
- d++;
- len--;
- cat("Routing for ");
- memcpy(t,d,6);
- d += 6;
- len -= 6;
- t[6] = 0;
- cat(t);
- cat("\n");
- for(i=0; i<11; i++) {
- if(len == 0)
- break;
- NRDumpBdcst((struct nr_broadcast *)d);
- d += sizeof(struct nr_broadcast);
- len -= sizeof(struct nr_broadcast);
- }
- return;
- }
-
- /* decode network layer */
- cat(GetAX25Addr(d));
- cat(">");
- cat(GetAX25Addr(d += sizeof(struct ax25_addr)));
- d += sizeof(struct ax25_addr);
- sprintf(t," (ttl=%u) ",*d++);
- cat(t);
- len -= (sizeof(struct ax25_addr) * 2 + 1);
-
- /* decode transport layer */
- switch(d[4] & 0x0f) {
- case 0:
- sprintf(t," Protocol %u, family %u",d[0],d[1]);
- data = TRUE;
- break;
- case 1:
- strcpy(t1, GetAX25Addr(d+6));
- sprintf(t," Connect: %u/%u wnd %u %s@%s",
- d[0],d[1],d[5],
- t1,
- GetAX25Addr(d+6+sizeof(struct ax25_addr)));
- break;
- case 2:
- sprintf(t," Connect ack: ur %u/%u, my %u/%u, wnd %u",
- d[0],d[1],d[2],d[3],d[5]);
- break;
- case 3:
- sprintf(t," Disconnect: %u/%u",d[0],d[1]);
- break;
- case 4:
- sprintf(t," Disconnect ack: %u/%u",d[0],d[1]);
- break;
- case 5:
- sprintf(t," Info: %u/%u txseq %u rxseq %u ::",
- d[0],d[1],d[2],d[3]);
- data = TRUE;
- break;
- case 6:
- sprintf(t," Info ack: %u/%u txseq %u rxseq %u",
- d[0],d[1],d[2],d[3]);
- break;
- default:
- sprintf(t," Unknown transport %u",d[4] & 0xf);
- break;
- }
- cat(t);
-
- /* copy in the data field, if any */
- if(data) {
- d += 5;
- len -= 5;
- cat("\n");
- eol_in(EOL_CR, d, len);
- while(len--) { /* quick hack */
- if(*d)
- *ploc++ = *d;
- d++;
- }
- }
- cat("\n");
- }
- #endif /* Net/Rom */
-
- /* ----- Packet Dump Routines ----- */
-
- /* ShowLevel2(p)
- Given a pointer to a level 2 packet, shows the packet on the screen.
-
- Munges packet data slightly (converts EOL).
- */
- void ShowLevel2(struct ax25_packet *p)
- {
- /* show the header */
- DumpLevel2Header(p);
- if(p->dlen)
- cat(":\n");
- else
- cat("\n");
- GotoLeft();
- uputs(BrightAttr,ptext);
-
- /* show the data field if any */
- if(p->dlen) {
- switch(p->pid) {
- #ifdef NETROM
- case PID_NETROM:
- ploc = ptext;
- NetRomDump(p->data,p->dlen);
- uputs(NormalAttr,ptext);
- break;
- #endif
- default:
- eol_in(EOL_CR, p->data, p->dlen);
- uputtext(NormalAttr,p->data,p->dlen);
- break;
- }
- }
-
- /* make sure cursor is at column one */
- GotoLeft();
- }
-
- /* DumpLevel2(p)
- Given a pointer to a level 2 packet, translates the packet into
- human readable form and returns a pointer to the text string.
-
- (intended for file dump/log routines)
- */
- char *DumpLevel2(struct ax25_packet *p)
- {
- byte *data;
- int len;
-
- /* decode header */
- DumpLevel2Header(p);
- if(p->dlen)
- cat(":");
-
- /* decode info field if any */
- if(p->dlen) {
- cat("\n");
- switch(p->pid) {
- case PID_TEXT: /* copy in data, crude */
- len = p->dlen;
- data = p->data;
- while(len--)
- *ploc++ = *data++;
- break;
- #ifdef NETROM
- case PID_NETROM:
- NetRomDump(p->data,p->dlen);
- break;
- #endif
- }
- }
-
- *ploc = '\0'; /* terminate */
- return ptext;
- }
-