diff options
Diffstat (limited to 'listen/rosedump.c')
-rw-r--r-- | listen/rosedump.c | 295 |
1 files changed, 284 insertions, 11 deletions
diff --git a/listen/rosedump.c b/listen/rosedump.c index aff16aa..c4d26b0 100644 --- a/listen/rosedump.c +++ b/listen/rosedump.c @@ -1,10 +1,24 @@ /* * Copyright 1996 Jonathan Naylor G4KLX + * + * Added ROSE new facilities : Jean-Paul ROUBELAT 04-1998 + * Added ROSE multi-digi : Jean-Paul ROUBELAT 05-1998 + * Added ROSE PID transport : Jean-Paul ROUBELAT 07-1998 */ + #include <stdio.h> #include <string.h> #include "listen.h" +#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 ROSE_ADDR_LEN 5 #define CALL_REQUEST 0x0B @@ -29,25 +43,49 @@ #define DBIT 0x40 #define MBIT 0x10 +#define AX25_HBIT 0x80 + static char *dump_x25_addr(unsigned char *); static char *clear_code(unsigned char); static char *reset_code(unsigned char); static char *restart_code(unsigned char); +static void facility(unsigned char *, int len); void rose_dump(unsigned char *data, int length, int hexdump) { - lprintf(T_ROSEHDR, "X.25: LCI %3.3X : ", (data[0] & 0x0F) + data[1]); + unsigned char *source = NULL; + unsigned char *dest = NULL; + unsigned int len, hlen; + unsigned int lci = ((unsigned)(data[0] & 0x0F) << 8) + data[1]; + lprintf(T_ROSEHDR, "X.25: LCI %3.3X : ", lci); switch (data[2]) { case CALL_REQUEST: - data += 4; - length -= 4; + len = 4; + hlen = (((data[3] >> 4) & 0x0F) + 1) / 2; + hlen += (((data[3] >> 0) & 0x0F) + 1) / 2; + if (hlen == 10) + { + dest = data+4; + source = data+9; + } + len += hlen; + data += len; + length -= len; lprintf(T_ROSEHDR, "CALL REQUEST - "); - lprintf(T_ADDR, "%s -> ", dump_x25_addr(data + ROSE_ADDR_LEN)); - lprintf(T_ADDR, "%s\n", dump_x25_addr(data + 0)); - data += ROSE_ADDR_LEN + ROSE_ADDR_LEN; - length -= ROSE_ADDR_LEN + ROSE_ADDR_LEN; - data_dump(data, length, 1); + if (length) + { + unsigned int flen = data[0]+1; + facility(data, length); + length -= flen; + data += flen; + if (length > 0) + data_dump(data, length, 1); + } + else + { + lprintf(T_ROSEHDR, "\n"); + } return; case CALL_ACCEPTED: @@ -57,6 +95,10 @@ void rose_dump(unsigned char *data, int length, int hexdump) case CLEAR_REQUEST: lprintf(T_ROSEHDR, "CLEAR REQUEST - Cause %s - Diag %d\n", clear_code(data[3]), data[4]); + if (length > 6) + { + facility(data+6, length-6); + } return; case CLEAR_CONFIRMATION: @@ -104,12 +146,61 @@ void rose_dump(unsigned char *data, int length, int hexdump) } if ((data[2] & 0x01) == DATA) { - lprintf(T_ROSEHDR, "DATA R%d S%d %s%s%s\n", + lprintf(T_ROSEHDR, "DATA R%d S%d %s%s%s", (data[2] >> 5) & 0x07, (data[2] >> 1) & 0x07, (data[0] & QBIT) ? "Q" : "", (data[0] & DBIT) ? "D" : "", (data[2] & MBIT) ? "M" : ""); - data_dump(data + 3, length - 3, hexdump); + if ((length >= 5) && (data[0] & QBIT) && (data[3] == 0x7f)) + { + /* pid transport */ + int pid = data[4]; + data += 5; + length -= 5; + switch (pid) { + case PID_SEGMENT: + lprintf(T_ROSEHDR," len %d\n", length - 5); + data_dump(data, length, hexdump); + break; + case PID_ARP: + lprintf(T_ROSEHDR," pid=ARP len %d\n", length - 5); + arp_dump(data, length); + break; + case PID_NETROM: + lprintf(T_ROSEHDR," pid=NET/ROM len %d\n", length - 5); + netrom_dump(data, length, hexdump); + break; + case PID_IP: + lprintf(T_ROSEHDR," pid=IP len %d\n", length - 5); + ip_dump(data, length, hexdump); + break; + case PID_X25: + lprintf(T_ROSEHDR, " pid=X.25 len %d\n", length - 5); + rose_dump(data, length, hexdump); + break; + case PID_TEXNET: + lprintf(T_ROSEHDR, " pid=TEXNET len %d\n", length - 5); + data_dump(data, length, hexdump); + break; + case PID_FLEXNET: + lprintf(T_ROSEHDR, " pid=FLEXNET len %d\n", length - 5); + flexnet_dump(data, length, hexdump); + break; + case PID_NO_L3: + lprintf(T_ROSEHDR, " pid=Text len %d\n", length - 5); + data_dump(data, length, hexdump); + break; + default: + lprintf(T_ROSEHDR, " pid=0x%x len %d\n", pid, length - 5); + data_dump(data, length, hexdump); + break; + } + } + else + { + lprintf(T_ROSEHDR, " len %d\n", length - 3); + data_dump(data + 3, length - 3, hexdump); + } return; } @@ -209,7 +300,189 @@ static char *dump_x25_addr(unsigned char *data) { static char buffer[25]; - sprintf(buffer, "%02X%02X%02X%02X%02X", data[0], data[1], data[2], data[3], data[4]); + sprintf(buffer, "%02X%02X,%02X%02X%02X", data[0], data[1], data[2], data[3], data[4]); return buffer; } + +static char *dump_ax25_call(unsigned char *data, int l_data) +{ + static char buffer[25]; + char *ptr = buffer; + int ssid; + + while (l_data-- > 1) + { + *ptr = *data++ >> 1; + if (*ptr != ' ') + ++ptr; + } + + *ptr++ = '-'; + ssid = (*data & 0x1F) >> 1; + if (ssid >= 10) + { + *ptr++ = '1'; + ssid -= 10; + } + *ptr++ = ssid + '0'; + *ptr = 0; + + return buffer; +} + +static void facility(unsigned char *data, int lgtot) +{ + int lgfac, l, lg, fct, lgdigi, lgaddcall; + int lgad, lgaddr, lgadind, digi_fac; + char digis[80], digid[80]; + char indorig[10], inddest[10]; + char addstorig[20], addstdest[20]; + char *d, *factot; + char buf[512]; + char *result = buf; + + factot = data; + + lgfac = *data++; + lg = lgfac; + + digi_fac = 0; + digid[0] = digis[0] = '\0'; + indorig[0] = inddest[0] = '\0'; + + while (lg > 0) + { + fct = *data++; + lg--; + switch (fct) + { + case 0: + /* Marker=0 National Fac ou Marker=15 CCITT */ + data++; + lg--; + break; + case 0x3F: + /* Used if call request via L2 digi instead of L3 */ + lprintf (T_ROSEHDR, "Facility 3F%2.2X\n", *data++); + lg--; + break; + case 0x7F: + /* Random number to avoid loops */ + lprintf (T_ROSEHDR, "NbAlea: %2.2X%2.2X\n", *data, *(data + 1)); + data += 2; + lg -= 2; + break; + case 0xE9: + /* Destination digi (for compatibility) */ + lgdigi = *data++; + if (!digi_fac) + strcpy(digid, dump_ax25_call(data, lgdigi)); + data += lgdigi; + lg -= 1 + lgdigi; + break; + case 0xEB: + /* Origin digi (for compatibility) */ + lgdigi = *data++; + if (!digi_fac) + strcpy(digis, dump_ax25_call(data, lgdigi)); + data += lgdigi; + lg -= 1 + lgdigi; + break; + case 0xED: + /* Out of order : callsign */ + lgaddcall = *data++; + lprintf(T_ROSEHDR, "at %s", dump_ax25_call(data, lgaddcall)); + data += lgaddcall; + lg -= 1 + lgaddcall; + break; + case 0xEE: + /* Out of order : address */ + lgaddcall = *data++; + ++data; /* Don't know... */ + lprintf(T_ROSEHDR, " @%s\n", dump_x25_addr(data)); + /* data_dump(data, lgaddcall, 1); */ + data += lgaddcall; + lg -= 1 + lgaddcall; + break; + case 0xEF: + lgaddcall = *data++; + for (d = data, l = 0; l < lgaddcall ; l += 7, d += 7) + { + if (l > (6 * 7)) + { + /* 6 digis maximum */ + break; + } + if (d[6] & AX25_HBIT) + { + strcat(digis, dump_ax25_call(d, 7)); + strcat(digis, " "); + } + else + { + strcat(digid, dump_ax25_call(d, 7)); + strcat(digid, " "); + } + } + data += lgaddcall; + lg -= 1 + lgaddcall; + digi_fac = 1; + break; + case 0xC9: + /* Address and callsign of the remote node */ + case 0xCB: + /* Address and callsign of the local node */ + lgaddcall = *data++; + data++; + data += 3; + lgad = *data++; + lg -= 6; + lgaddr = lgad; + + if (fct == 0xCB) + strcpy (addstorig, dump_x25_addr(data)); + else + strcpy (addstdest, dump_x25_addr(data)); + + data += (lgad + 1) / 2; + lg -= (lgad + 1) / 2; + lgadind = lgaddcall - (lgad + 1) / 2 - 5; + + if (fct == 0xCB) + { + strncpy (indorig, data, lgadind); + indorig[lgadind] = '\0'; + } + else + { + strncpy (inddest, data, lgadind); + inddest[lgadind] = '\0'; + } + + data += lgadind; + lg -= lgadind; + break; + default: + lprintf (T_ROSEHDR, "Unknown Facility Type %2.2X\n", fct); + data_dump(factot, lgtot, 1); + lg = 0; + break; + } + + result += strlen (result); + } + + if (*indorig && *inddest) + { + /* Build the displayed string */ + lprintf (T_ROSEHDR, "fm %-9s @%s", indorig, addstorig); + if (*digis) + lprintf (T_ROSEHDR, " via %s", digis); + lprintf (T_ROSEHDR, "\n"); + lprintf (T_ROSEHDR, "to %-9s @%s", inddest, addstdest); + if (*digid) + lprintf (T_ROSEHDR, " via %s", digid); + lprintf (T_ROSEHDR, "\n"); + } +} |