/* @(#) $Header: /cvsroot/ax25/ax25-apps/listen/nrdump.c,v 1.1.1.1 2001/04/10 01:58:54 csmall Exp $ */ /* NET/ROM header tracing routines * Copyright 1991 Phil Karn, KA9Q */ #include #include #include "listen.h" #define AXLEN 7 #define ALEN 6 #define NRPROTO_IP 0x0C #define NR4OPCODE 0x0F #define NR4OPPID 0 #define NR4OPCONRQ 1 #define NR4OPCONAK 2 #define NR4OPDISRQ 3 #define NR4OPDISAK 4 #define NR4OPINFO 5 #define NR4OPACK 6 #define NR4MORE 0x20 #define NR4NAK 0x40 #define NR4CHOKE 0x80 #define NRDESTPERPACK 11 #define NR3NODESIG 0xFF #define NR3POLLSIG 0xFE static void netrom_flags(int); /* Display NET/ROM network and transport headers */ void netrom_dump(unsigned char *data, int length, int hexdump) { char tmp[15]; register int i; /* See if it is a routing broadcast */ if (data[0] == NR3NODESIG) { memcpy(tmp, data + 1, ALEN); tmp[ALEN] = '\0'; lprintf(T_AXHDR, "NET/ROM Routing: %s\n", tmp); data += (ALEN + 1); length -= (ALEN + 1); for(i = 0;i < NRDESTPERPACK;i++) { if (length < AXLEN) break; lprintf(T_DATA," %12s", pax25(tmp, data)); memcpy(tmp, data + AXLEN, ALEN); tmp[ALEN] = '\0'; lprintf(T_DATA, "%8s", tmp); lprintf(T_DATA, " %12s", pax25(tmp, data + AXLEN + ALEN)); lprintf(T_DATA, " %3u\n", data[AXLEN + ALEN + AXLEN]); data += (AXLEN + ALEN + AXLEN + 1); length -= (AXLEN + ALEN + AXLEN + 1); } return; } /* See if it is a JNOS style node poll */ if (data[0] == NR3POLLSIG) { memcpy(tmp, data + 1, ALEN); tmp[ALEN] = '\0'; lprintf(T_AXHDR, "NET/ROM Poll: %s\n", tmp); return; } /* Decode network layer */ lprintf(T_AXHDR, "NET/ROM: "); lprintf(T_ADDR, "%s->", pax25(tmp, data)); lprintf(T_ADDR, "%s", pax25(tmp, data + AXLEN)); lprintf(T_AXHDR," ttl %d\n", data[AXLEN + AXLEN]); data += (AXLEN + AXLEN + 1); length -= (AXLEN + AXLEN + 1); switch (data[4] & NR4OPCODE) { case NR4OPPID: /* network PID extension */ if (data[0] == NRPROTO_IP && data[1] == NRPROTO_IP) { ip_dump(data + 5, length - 5, hexdump); return; } else { lprintf(T_AXHDR, " protocol family %x, proto %x", data[0], data[1]); } break; case NR4OPCONRQ: /* Connect request */ lprintf(T_AXHDR, " conn rqst: my ckt %02X/%02X", data[0], data[1]); lprintf(T_AXHDR, " wnd %d", data[5]); lprintf(T_ADDR, " %s", pax25(tmp, data + 6)); lprintf(T_ADDR, "@%s", pax25(tmp, data + 6 + AXLEN)); data += AXLEN + AXLEN + 6; length -= AXLEN + AXLEN + 6; if (length > 0) lprintf(T_AXHDR, " timeout %d", data[1] * 256 + data[0]); lprintf(T_AXHDR, "\n"); break; case NR4OPCONAK: /* Connect acknowledgement */ lprintf(T_AXHDR," conn ack: ur ckt %02X/%02X my ckt %02X/%02X", data[0], data[1], data[2], data[3]); lprintf(T_AXHDR, " wnd %d", data[5]); netrom_flags(data[4]); break; case NR4OPDISRQ: /* Disconnect request */ lprintf(T_AXHDR, " disc: ur ckt %02X/%02X\n", data[0], data[1]); break; case NR4OPDISAK: /* Disconnect acknowledgement */ lprintf(T_AXHDR, " disc ack: ur ckt %02X/%02X\n", data[0], data[1]); break; case NR4OPINFO: /* Information (data) */ lprintf(T_AXHDR, " info: ur ckt %02X/%02X", data[0], data[1]); lprintf(T_AXHDR, " txseq %d rxseq %d", data[2], data[3]); netrom_flags(data[4]); data_dump(data + 5, length - 5, hexdump); break; case NR4OPACK: /* Information acknowledgement */ lprintf(T_AXHDR, " info ack: ur ckt %02X/%02X", data[0], data[1]); lprintf(T_AXHDR, " rxseq %d", data[3]); netrom_flags(data[4]); break; default: lprintf(T_AXHDR, " unknown transport type %d\n", data[4] & 0x0f) ; break; } } static void netrom_flags(int flags) { if (flags & NR4CHOKE) lprintf(T_AXHDR," CHOKE"); if (flags & NR4NAK) lprintf(T_AXHDR," NAK"); if (flags & NR4MORE) lprintf(T_AXHDR," MORE"); lprintf(T_AXHDR, "\n"); }