From 0fceb64d25ff3d9586549bb43d971c5eef904330 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Jun 1999 10:23:42 +0200 Subject: Import ax25-apps 0.0.1 from tarball --- listen/ax25dump.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 listen/ax25dump.c (limited to 'listen/ax25dump.c') diff --git a/listen/ax25dump.c b/listen/ax25dump.c new file mode 100644 index 0000000..34213f9 --- /dev/null +++ b/listen/ax25dump.c @@ -0,0 +1,362 @@ +/* @(#) $Header: ax25dump.c,v 1.5 91/02/24 20:16:33 deyke Exp $ */ + +/* AX25 header tracing + * Copyright 1991 Phil Karn, KA9Q + */ +#include +#include +#include +#include "listen.h" + +#define LAPB_UNKNOWN 0 +#define LAPB_COMMAND 1 +#define LAPB_RESPONSE 2 + +#define SEG_FIRST 0x80 +#define SEG_REM 0x7F + +#define PID_SEGMENT 0x08 +#define PID_ARP 0xCD +#define PID_NETROM 0xCF +#define PID_IP 0xCC +#define PID_X25 0x01 +#define PID_TEXNET 0xC3 +#define PID_FLEXNET 0xCE +#define PID_NO_L3 0xF0 + +#define I 0x00 +#define S 0x01 +#define RR 0x01 +#define RNR 0x05 +#define REJ 0x09 +#define U 0x03 +#define SABM 0x2F +#define SABME 0x6F +#define DISC 0x43 +#define DM 0x0F +#define UA 0x63 +#define FRMR 0x87 +#define UI 0x03 +#define PF 0x10 +#define EPF 0x01 + +#define MMASK 7 + +#define HDLCAEB 0x01 +#define SSID 0x1E +#define REPEATED 0x80 +#define C 0x80 +#define SSSID_SPARE 0x40 +#define ESSID_SPARE 0x20 + +#define ALEN 6 +#define AXLEN 7 + +#define W 1 +#define X 2 +#define Y 4 +#define Z 8 + +static int ftype(unsigned char *, int *, int *, int *, int *, int); +static char *decode_type(int); + +#define NDAMA_STRING "" +#define DAMA_STRING " [DAMA]" + + +/* FlexNet header compression display by Thomas Sailer sailer@ife.ee.ethz.ch */ + +/* Dump an AX.25 packet header */ +void ax25_dump(unsigned char *data, int length, int hexdump) +{ + char tmp[15]; + int ctlen, nr, ns, pf, pid, seg, type, end, cmdrsp, extseq; + char *dama; + + /* check for FlexNet compressed header first; FlexNet header compressed packets are at least 8 bytes long */ + if (length < 8) { + /* Something wrong with the header */ + lprintf(T_ERROR, "AX25: bad header!\n"); + return; + } + if (data[1] & HDLCAEB) { + /* this is a FlexNet compressed header */ + lprintf(T_PROTOCOL, "AX25: "); + tmp[6] = tmp[7] = extseq = 0; + tmp[0] = ' ' + (data[2] >> 2); + tmp[1] = ' ' + ((data[2] << 4) & 0x30) + (data[3] >> 4); + tmp[2] = ' ' + ((data[3] << 2) & 0x3c) + (data[4] >> 6); + tmp[3] = ' ' + (data[4] & 0x3f); + tmp[4] = ' ' + (data[5] >> 2); + tmp[5] = ' ' + ((data[5] << 4) & 0x30) + (data[6] >> 4); + if (data[6] & 0xf) + sprintf(tmp+7, "-%d", data[6] & 0xf); + lprintf(T_ADDR, "%d->%s%s", (data[0] << 6) | ((data[1] >> 2) & 0x3f), strtok(tmp, " "), tmp+7); + cmdrsp = (data[1] & 2) ? LAPB_COMMAND : LAPB_RESPONSE; + dama = NDAMA_STRING; + data += 7; + length -= 7; + } else { + /* Extract the address header */ + if (length < (AXLEN + AXLEN + 1)) { + /* Something wrong with the header */ + lprintf(T_ERROR, "AX25: bad header!\n"); + return; + } + + if ((data[AXLEN + ALEN] & SSSID_SPARE) == SSSID_SPARE) { + extseq = 0; + lprintf(T_PROTOCOL, "AX25: "); + } else { + extseq = 1; + lprintf(T_PROTOCOL, "EAX25: "); + } + + if ((data[AXLEN + ALEN] & ESSID_SPARE) == ESSID_SPARE) + dama = NDAMA_STRING; + else + dama = DAMA_STRING; + + lprintf(T_ADDR, "%s", pax25(tmp, data + AXLEN)); + lprintf(T_ADDR, "->%s", pax25(tmp, data)); + + cmdrsp = LAPB_UNKNOWN; + + if ((data[ALEN] & C) && !(data[AXLEN + ALEN] & C)) + cmdrsp = LAPB_COMMAND; + + if ((data[AXLEN + ALEN] & C) && !(data[ALEN] & C)) + cmdrsp = LAPB_RESPONSE; + + end = (data[AXLEN + ALEN] & HDLCAEB); + + data += (AXLEN + AXLEN); + length -= (AXLEN + AXLEN); + + if (!end) { + lprintf(T_AXHDR, " v"); + + while (!end) { + /* Print digi string */ + lprintf(T_ADDR," %s%s", pax25(tmp, data), (data[ALEN] & REPEATED) ? "*" : ""); + + end = (data[ALEN] & HDLCAEB); + + data += AXLEN; + length -= AXLEN; + } + } + } + + if (length == 0) return; + + ctlen = ftype(data, &type, &ns, &nr, &pf, extseq); + + data += ctlen; + length -= ctlen; + + lprintf(T_AXHDR, " <%s", decode_type(type)); + + switch (cmdrsp) { + case LAPB_COMMAND: + lprintf(T_AXHDR, " C"); + if (pf) lprintf(T_AXHDR, " P"); + break; + case LAPB_RESPONSE: + lprintf(T_AXHDR, " R"); + if (pf) lprintf(T_AXHDR, " F"); + break; + default: + break; + } + + if (type == I) + lprintf(T_AXHDR, " S%d", ns); + + if ((type & 0x3) != U) /* I or S frame? */ + lprintf(T_AXHDR, " R%d", nr); + + lprintf(T_AXHDR, ">"); + + if (type == I || type == UI) { + /* Decode I field */ + if (length > 0) { /* Get pid */ + pid = *data++; + length--; + + if (pid == PID_SEGMENT) { + seg = *data++; + length--; + lprintf(T_AXHDR, "%s remain %u", seg & SEG_FIRST ? " First seg;" : "", seg & SEG_REM); + + if (seg & SEG_FIRST) { + pid = *data++; + length--; + } + } + + switch (pid) { + case PID_SEGMENT: + lprintf(T_AXHDR,"%s\n", dama); + data_dump(data, length, hexdump); + break; + case PID_ARP: + lprintf(T_AXHDR," pid=ARP%s\n", dama); + arp_dump(data, length); + break; + case PID_NETROM: + lprintf(T_AXHDR," pid=NET/ROM%s\n", dama); + netrom_dump(data, length, hexdump); + break; + case PID_IP: + lprintf(T_AXHDR," pid=IP%s\n", dama); + ip_dump(data, length, hexdump); + break; + case PID_X25: + lprintf(T_AXHDR, " pid=X.25%s\n", dama); + rose_dump(data, length, hexdump); + break; + case PID_TEXNET: + lprintf(T_AXHDR, " pid=TEXNET%s\n", dama); + data_dump(data, length, hexdump); + break; + case PID_FLEXNET: + lprintf(T_AXHDR, " pid=FLEXNET%s\n", dama); + flexnet_dump(data, length, hexdump); + break; + case PID_NO_L3: + lprintf(T_AXHDR, " pid=Text%s\n", dama); + data_dump(data, length, hexdump); + break; + default: + lprintf(T_AXHDR, " pid=0x%x%s\n", pid, dama); + data_dump(data, length, hexdump); + break; + } + } + } else if (type == FRMR && length >= 3) { + /* FIX ME XXX + lprintf(T_AXHDR, ": %s", decode_type(ftype(data[0]))); + */ + lprintf(T_AXHDR, ": %02X", data[0]); + lprintf(T_AXHDR, " Vr = %d Vs = %d", + (data[1] >> 5) & MMASK, + (data[1] >> 1) & MMASK); + if(data[2] & W) + lprintf(T_ERROR, " Invalid control field"); + if(data[2] & X) + lprintf(T_ERROR, " Illegal I-field"); + if(data[2] & Y) + lprintf(T_ERROR, " Too-long I-field"); + if(data[2] & Z) + lprintf(T_ERROR, " Invalid seq number"); + lprintf(T_AXHDR,"%s\n", dama); + } else if ((type == SABM || type == UA) && length >= 2) { + /* FlexNet transmits the QSO "handle" for header + * compression in SABM and UA frame data fields + */ + lprintf(T_AXHDR," [%d]%s\n", (data[0] << 8) | data[1], dama); + } else { + lprintf(T_AXHDR,"%s\n", dama); + } +} + +static char *decode_type(int type) +{ + switch (type) { + case I: + return "I"; + case SABM: + return "C"; + case SABME: + return "CE"; + case DISC: + return "D"; + case DM: + return "DM"; + case UA: + return "UA"; + case RR: + return "RR"; + case RNR: + return "RNR"; + case REJ: + return "REJ"; + case FRMR: + return "FRMR"; + case UI: + return "UI"; + default: + return "[invalid]"; + } +} + +char *pax25(char *buf, unsigned char *data) +{ + int i, ssid; + char *s; + char c; + + s = buf; + + for (i = 0; i < ALEN; i++) { + c = (data[i] >> 1) & 0x7F; + + if (!isalnum(c) && c != ' ') { + strcpy(buf, "[invalid]"); + return buf; + } + + if (c != ' ') *s++ = c; + } + + if ((ssid = (data[ALEN] & SSID)) != 0) + sprintf(s, "-%d", ssid >> 1); + else + *s = '\0'; + + return(buf); +} + +static int ftype(unsigned char *data, int *type, int *ns, int *nr, int *pf, int extseq) +{ + if (extseq) { + if ((*data & 0x01) == 0) { /* An I frame is an I-frame ... */ + *type = I; + *ns = (*data >> 1) & 127; + data++; + *nr = (*data >> 1) & 127; + *pf = *data & EPF; + return 2; + } + if (*data & 0x02) { + *type = *data & ~PF; + *pf = *data & PF; + return 1; + } else { + *type = *data; + data++; + *nr = (*data >> 1) & 127; + *pf = *data & EPF; + return 2; + } + } else { + if ((*data & 0x01) == 0) { /* An I frame is an I-frame ... */ + *type = I; + *ns = (*data >> 1) & 7; + *nr = (*data >> 5) & 7; + *pf = *data & PF; + return 1; + } + if (*data & 0x02) { /* U-frames use all except P/F bit for type */ + *type = *data & ~PF; + *pf = *data & PF; + return 1; + } else { /* S-frames use low order 4 bits for type */ + *type = *data & 0x0F; + *nr = (*data >> 5) & 7; + *pf = *data & PF; + return 1; + } + } +} -- cgit v1.2.3