summaryrefslogtreecommitdiffstats
path: root/listen
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-07 10:23:42 +0200
committerRalf Baechle <ralf@linux-mips.org>1999-06-07 10:23:42 +0200
commit0fceb64d25ff3d9586549bb43d971c5eef904330 (patch)
treed4799d0fd53a3d8ae342c84f8ad4fb2ca2f14de0 /listen
Import ax25-apps 0.0.1 from tarballax25-apps-0.0.1
Diffstat (limited to 'listen')
-rw-r--r--listen/Makefile.am27
-rw-r--r--listen/Makefile.in379
-rw-r--r--listen/arpdump.c108
-rw-r--r--listen/ax25dump.c362
-rw-r--r--listen/flexnetdump.c149
-rw-r--r--listen/icmpdump.c196
-rw-r--r--listen/ipdump.c116
-rw-r--r--listen/kissdump.c60
-rw-r--r--listen/listen.189
-rw-r--r--listen/listen.c293
-rw-r--r--listen/listen.h65
-rw-r--r--listen/nrdump.c154
-rw-r--r--listen/ripdump.c174
-rw-r--r--listen/rosedump.c215
-rw-r--r--listen/rspfdump.c53
-rw-r--r--listen/tcpdump.c123
-rw-r--r--listen/udpdump.c44
-rw-r--r--listen/utils.c121
18 files changed, 2728 insertions, 0 deletions
diff --git a/listen/Makefile.am b/listen/Makefile.am
new file mode 100644
index 0000000..8e99155
--- /dev/null
+++ b/listen/Makefile.am
@@ -0,0 +1,27 @@
+
+installconf:
+
+bin_PROGRAMS = listen
+
+man_MANS = listen.1
+
+EXTRA_DIST = $(man_MANS)
+
+LDADD = $(AX25_LIB) $(NCURSES_LIB)
+
+listen_SOURCES = \
+ listen.c \
+ listen.h \
+ kissdump.c \
+ ax25dump.c \
+ nrdump.c \
+ arpdump.c \
+ ipdump.c \
+ icmpdump.c \
+ udpdump.c \
+ tcpdump.c \
+ rspfdump.c \
+ ripdump.c \
+ rosedump.c \
+ flexnetdump.c \
+ utils.c
diff --git a/listen/Makefile.in b/listen/Makefile.in
new file mode 100644
index 0000000..4cf3c1a
--- /dev/null
+++ b/listen/Makefile.in
@@ -0,0 +1,379 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+AWK = @AWK@
+AX25_LIB = @AX25_LIB@
+CC = @CC@
+DLLTOOL = @DLLTOOL@
+LD = @LD@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+NCURSES_LIB = @NCURSES_LIB@
+NM = @NM@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = listen
+
+man_MANS = listen.1
+
+EXTRA_DIST = $(man_MANS)
+
+LDADD = $(AX25_LIB) $(NCURSES_LIB)
+
+listen_SOURCES = listen.c listen.h kissdump.c ax25dump.c nrdump.c arpdump.c ipdump.c icmpdump.c udpdump.c tcpdump.c rspfdump.c ripdump.c rosedump.c flexnetdump.c utils.c
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+listen_OBJECTS = listen.o kissdump.o ax25dump.o nrdump.o arpdump.o \
+ipdump.o icmpdump.o udpdump.o tcpdump.o rspfdump.o ripdump.o rosedump.o \
+flexnetdump.o utils.o
+listen_LDADD = $(LDADD)
+listen_DEPENDENCIES =
+listen_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(listen_SOURCES)
+OBJECTS = $(listen_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps listen/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+listen: $(listen_OBJECTS) $(listen_DEPENDENCIES)
+ @rm -f listen
+ $(LINK) $(listen_LDFLAGS) $(listen_OBJECTS) $(listen_LDADD) $(LIBS)
+
+install-man1:
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+ done
+
+uninstall-man1:
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man1dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = listen
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+arpdump.o: arpdump.c listen.h
+ax25dump.o: ax25dump.c listen.h
+flexnetdump.o: flexnetdump.c listen.h
+icmpdump.o: icmpdump.c listen.h
+ipdump.o: ipdump.c listen.h
+kissdump.o: kissdump.c listen.h
+listen.o: listen.c ../config.h listen.h
+nrdump.o: nrdump.c listen.h
+ripdump.o: ripdump.c listen.h
+rosedump.o: rosedump.c listen.h
+rspfdump.o: rspfdump.c listen.h
+tcpdump.o: tcpdump.c listen.h
+udpdump.o: udpdump.c listen.h
+utils.o: utils.c listen.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-binPROGRAMS distclean-compile distclean-libtool \
+ distclean-tags distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool install-man1 uninstall-man1 \
+install-man uninstall-man tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+installconf:
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/listen/arpdump.c b/listen/arpdump.c
new file mode 100644
index 0000000..a80716a
--- /dev/null
+++ b/listen/arpdump.c
@@ -0,0 +1,108 @@
+/* @(#) $Header: arpdump.c,v 1.5 91/03/28 19:38:59 deyke Exp $ */
+
+/* ARP packet tracing routines
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include "listen.h"
+
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+#define REVARP_REQUEST 3
+#define REVARP_REPLY 4
+
+#define ARP_AX25 3
+
+#define AXALEN 7
+
+#define PID_IP 0xCC
+
+void arp_dump(unsigned char *data, int length)
+{
+ int is_ip = 0;
+ int hardware;
+ int protocol;
+ int hwlen;
+ int pralen;
+ int operation;
+ unsigned char *shwaddr, *sprotaddr;
+ unsigned char *thwaddr, *tprotaddr;
+ char tmp[25];
+
+ lprintf(T_PROTOCOL, "ARP: ");
+ lprintf(T_IPHDR, "len %d", length);
+ if (length < 16)
+ {
+ lprintf(T_ERROR, " bad packet\n");
+ return;
+ }
+
+ hardware = get16(data + 0);
+ protocol = get16(data + 2);
+ hwlen = data[4];
+ pralen = data[5];
+ operation = get16(data + 6);
+
+ if (hardware != ARP_AX25)
+ {
+ lprintf(T_IPHDR, " non-AX25 ARP packet\n");
+ return;
+ }
+
+ lprintf(T_IPHDR, " hwtype AX25");
+
+ /* Print hardware length only if it doesn't match
+ * the length in the known types table
+ */
+ if (hwlen != AXALEN)
+ lprintf(T_IPHDR, " hwlen %d", hwlen);
+
+ if (protocol == PID_IP)
+ {
+ lprintf(T_IPHDR, " prot IP");
+ is_ip = 1;
+ }
+ else
+ {
+ lprintf(T_IPHDR, " prot 0x%x prlen %d", protocol, pralen);
+ }
+
+ switch (operation)
+ {
+ case ARP_REQUEST:
+ lprintf(T_IPHDR, " op REQUEST");
+ break;
+ case ARP_REPLY:
+ lprintf(T_IPHDR, " op REPLY");
+ break;
+ case REVARP_REQUEST:
+ lprintf(T_IPHDR, " op REVERSE REQUEST");
+ break;
+ case REVARP_REPLY:
+ lprintf(T_IPHDR, " op REVERSE REPLY");
+ break;
+ default:
+ lprintf(T_IPHDR, " op %d", operation);
+ break;
+ }
+
+ shwaddr = data + 8;
+ sprotaddr = shwaddr + hwlen;
+
+ thwaddr = sprotaddr + pralen;
+ tprotaddr = thwaddr + hwlen;
+
+ lprintf(T_IPHDR, "\nsender");
+ if (is_ip) lprintf(T_ADDR, " IPaddr %d.%d.%d.%d",
+ sprotaddr[0], sprotaddr[1],
+ sprotaddr[2], sprotaddr[3]);
+ lprintf(T_IPHDR, " hwaddr %s\n", pax25(tmp, shwaddr));
+
+ lprintf(T_IPHDR,"target");
+ if (is_ip) lprintf(T_ADDR, " IPaddr %d.%d.%d.%d",
+ tprotaddr[0], tprotaddr[1],
+ tprotaddr[2], tprotaddr[3]);
+ if (*thwaddr != 0)
+ lprintf(T_ADDR, " hwaddr %s", pax25(tmp, thwaddr));
+ lprintf(T_IPHDR, "\n");
+}
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 <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#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;
+ }
+ }
+}
diff --git a/listen/flexnetdump.c b/listen/flexnetdump.c
new file mode 100644
index 0000000..3269390
--- /dev/null
+++ b/listen/flexnetdump.c
@@ -0,0 +1,149 @@
+/*
+ * FlexNet internode communication dump
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "listen.h"
+
+/*
+ * This was hacked by Thomas Sailer, sailer@ife.ee.ethz.ch, HB9JNX/AE4WA, with
+ * some bits stolen from Dieter Deyke (Wampes), such as these defines :-)
+ */
+
+#define FLEX_INIT '0' /* Link initialization */
+#define FLEX_RPRT '1' /* Poll answer */
+#define FLEX_POLL '2' /* Poll */
+#define FLEX_ROUT '3' /* Routing information */
+#define FLEX_QURY '6' /* Path query */
+#define FLEX_RSLT '7' /* Query result */
+
+static int flx_get_number(unsigned char **data, int *length)
+{
+ int l = *length;
+ unsigned char *d = *data;
+ int res = 0;
+
+ if (l <= 0 || *d < '0' || *d > '9')
+ return -1;
+ while (l > 0 && *d >= '0' && *d <= '9') {
+ res = res * 10 + (*d++) - '0';
+ l--;
+ }
+ *data = d;
+ *length = l;
+ return res;
+}
+
+static void dump_end(unsigned char *data, int length)
+{
+ if (length <= 0)
+ return;
+ for (; length > 0; length--, data++)
+ lprintf(T_FLEXNET, " %02x", *data);
+ lprintf(T_FLEXNET, "\n");
+}
+
+void flexnet_dump(unsigned char *data, int length, int hexdump)
+{
+ int i;
+ int hopcnt, qsonr;
+ unsigned char *cp;
+
+ lprintf(T_PROTOCOL, "FlexNet:");
+
+ if (length < 1) {
+ lprintf(T_ERROR, " bad packet\n");
+ return;
+ }
+ switch (data[0]) {
+ default:
+ lprintf(T_ERROR, " unknown packet type\n");
+ data_dump(data, length, hexdump);
+ return;
+
+ case FLEX_INIT:
+ if (length < 2) {
+ lprintf(T_ERROR, " bad packet\n");
+ dump_end(data+1, length-1);
+ return;
+ }
+ lprintf(T_FLEXNET, " Link setup - max SSID %d ", data[1] & 0xf);
+ dump_end(data+1, length-1);
+ return;
+
+ case FLEX_RPRT:
+ lprintf(T_FLEXNET, " Poll response -");
+ data++;
+ length--;
+ i = flx_get_number(&data, &length);
+ data++;
+ length--;
+ if (i < 0)
+ goto too_short;
+ lprintf(T_FLEXNET, " delay: %d\n", i);
+ dump_end(data, length);
+ return;
+
+ case FLEX_POLL:
+ lprintf(T_FLEXNET, " Poll");
+ return;
+
+ case FLEX_ROUT:
+ data++;
+ length--;
+ lprintf(T_FLEXNET, " Routing\n");
+ while (length > 0) {
+ if (isdigit(*data) || isupper(*data)) {
+ if (length < 10)
+ goto too_short;
+ lprintf(T_FLEXNET, " %.6s %2d-%2d ", data, data[6]-'0', data[7]-'0');
+ data += 8;
+ length -= 8;
+ i = flx_get_number(&data, &length);
+ data++;
+ length--;
+ if (!i)
+ lprintf(T_FLEXNET, "link down\n");
+ else
+ lprintf(T_FLEXNET, "delay: %d\n", i);
+ } else {
+ if (*data == '+')
+ lprintf(T_FLEXNET, " Request token\n");
+ else if (*data == '-')
+ lprintf(T_FLEXNET, " Release token\n");
+ else if (*data != '\r')
+ lprintf(T_FLEXNET, " invalid char: %02x\n", *data);
+ data++;
+ length--;
+ }
+ }
+ return;
+
+ case FLEX_QURY:
+ case FLEX_RSLT:
+ lprintf(T_FLEXNET, " Route query");
+ if (*data == FLEX_RSLT)
+ lprintf(T_FLEXNET, " response");
+ if (length < 2)
+ goto too_short;
+ hopcnt = data[1] - ' ';
+ data += 2;
+ length -= 2;
+ qsonr = flx_get_number(&data, &length);
+ data++;
+ length--;
+ lprintf(T_FLEXNET, " - hop count: %d QSO number: %d\n", hopcnt, qsonr);
+ cp = memchr(data, '\r', length);
+ if (cp)
+ *cp = 0;
+ lprintf(T_FLEXNET, " data");
+ return;
+ }
+
+too_short:
+ lprintf(T_ERROR, " packet too short\n");
+ dump_end(data, length);
+}
+
diff --git a/listen/icmpdump.c b/listen/icmpdump.c
new file mode 100644
index 0000000..655d2fc
--- /dev/null
+++ b/listen/icmpdump.c
@@ -0,0 +1,196 @@
+/* @(#) $Header: icmpdump.c,v 1.4 91/02/24 20:16:55 deyke Exp $ */
+
+/* ICMP header tracing
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include "listen.h"
+
+#define ICMP_DEST_UNREACH 3
+#define ICMP_REDIRECT 5
+#define ICMP_TIME_EXCEED 11
+#define ICMP_PARAM_PROB 12
+#define ICMP_ECHO 8
+#define ICMP_ECHO_REPLY 0
+#define ICMP_INFO_RQST 15
+#define ICMP_INFO_REPLY 16
+#define ICMP_TIMESTAMP 13
+#define ICMP_TIME_REPLY 14
+#define ICMP_QUENCH 4
+
+#define ICMPLEN 8
+
+/* Dump an ICMP header */
+void icmp_dump(unsigned char *data, int length, int hexdump)
+{
+ int type;
+ int code;
+ int pointer;
+ unsigned char *address;
+ int id, seq;
+
+ type = data[0];
+ code = data[1];
+ pointer = data[4];
+ address = data + 4;
+ id = get16(data + 4);
+ seq = get16(data + 6);
+
+ data += ICMPLEN;
+ length -= ICMPLEN;
+
+ lprintf(T_IPHDR, "ICMP: type ");
+
+ switch (type) {
+ case ICMP_DEST_UNREACH:
+ lprintf(T_ERROR, "Unreachable ");
+ lprintf(T_IPHDR, "code ");
+
+ switch (code) {
+ case 0:
+ lprintf(T_ERROR, "Network");
+ break;
+ case 1:
+ lprintf(T_ERROR, "Host");
+ break;
+ case 2:
+ lprintf(T_ERROR, "Protocol");
+ break;
+ case 3:
+ lprintf(T_ERROR, "Port");
+ break;
+ case 4:
+ lprintf(T_ERROR, "Fragmentation");
+ break;
+ case 5:
+ lprintf(T_ERROR, "Source route");
+ break;
+ case 6:
+ lprintf(T_ERROR, "Dest net unknown");
+ break;
+ case 7:
+ lprintf(T_ERROR, "Dest host unknown");
+ break;
+ case 8:
+ lprintf(T_ERROR, "Source host isolated");
+ break;
+ case 9:
+ lprintf(T_ERROR, "Net prohibited");
+ break;
+ case 10:
+ lprintf(T_ERROR, "Host prohibited");
+ break;
+ case 11:
+ lprintf(T_ERROR, "Net TOS");
+ break;
+ case 12:
+ lprintf(T_ERROR, "Host TOS");
+ break;
+ case 13:
+ lprintf(T_ERROR, "Administratively Prohibited");
+ break;
+ default:
+ lprintf(T_ERROR, "%d", code);
+ break;
+ }
+ lprintf(T_IPHDR, "\nReturned ");
+ ip_dump(data, length, hexdump);
+ break;
+
+ case ICMP_REDIRECT:
+ lprintf(T_ERROR, "Redirect ");
+ lprintf(T_IPHDR, "code ");
+
+ switch (code) {
+ case 0:
+ lprintf(T_ERROR, "Network");
+ break;
+ case 1:
+ lprintf(T_ERROR, "Host");
+ break;
+ case 2:
+ lprintf(T_ERROR, "TOS & Network");
+ break;
+ case 3:
+ lprintf(T_ERROR, "TOS & Host");
+ break;
+ default:
+ lprintf(T_ERROR, "%d", code);
+ break;
+ }
+ lprintf(T_IPHDR, " new gateway %d.%d.%d.%d",
+ address[0], address[1],
+ address[2], address[3]);
+ lprintf(T_IPHDR, "\nReturned ");
+ ip_dump(data, length, hexdump);
+ break;
+
+ case ICMP_TIME_EXCEED:
+ lprintf(T_ERROR, "Time Exceeded code ");
+ lprintf(T_ERROR, "Time Exceeded ");
+ lprintf(T_IPHDR, "code ");
+
+ switch (code) {
+ case 0:
+ lprintf(T_ERROR, "Time-to-live");
+ break;
+ case 1:
+ lprintf(T_ERROR, "Fragment reassembly");
+ break;
+ default:
+ lprintf(T_ERROR, "%d", code);
+ break;
+ }
+ lprintf(T_IPHDR, "\nReturned ");
+ ip_dump(data, length, hexdump);
+ break;
+
+ case ICMP_PARAM_PROB:
+ lprintf(T_ERROR, "Parameter Problem pointer %d", pointer);
+ lprintf(T_IPHDR, "\nReturned ");
+ ip_dump(data, length, hexdump);
+ break;
+
+ case ICMP_QUENCH:
+ lprintf(T_ERROR, "Source Quench");
+ lprintf(T_IPHDR, "\nReturned ");
+ ip_dump(data, length, hexdump);
+ break;
+
+ case ICMP_ECHO:
+ lprintf(T_IPHDR, "Echo Request id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ case ICMP_ECHO_REPLY:
+ lprintf(T_IPHDR, "Echo Reply id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ case ICMP_INFO_RQST:
+ lprintf(T_IPHDR, "Information Request id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ case ICMP_INFO_REPLY:
+ lprintf(T_IPHDR, "Information Reply id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ case ICMP_TIMESTAMP:
+ lprintf(T_IPHDR, "Timestamp Request id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ case ICMP_TIME_REPLY:
+ lprintf(T_IPHDR, "Timestamp Reply id %d seq %d\n", id, seq);
+ data_dump(data, length, hexdump);
+ break;
+
+ default:
+ lprintf(T_IPHDR, "%d\n", type);
+ data_dump(data, length, hexdump);
+ break;
+ }
+}
+
diff --git a/listen/ipdump.c b/listen/ipdump.c
new file mode 100644
index 0000000..aa1abae
--- /dev/null
+++ b/listen/ipdump.c
@@ -0,0 +1,116 @@
+/* @(#) $Header: ipdump.c,v 1.6 91/07/16 17:55:22 deyke Exp $ */
+
+/* IP header tracing routines
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include "listen.h"
+
+#define IPLEN 20
+
+#define MF 0x2000
+#define DF 0x4000
+#define CE 0x8000
+
+#define IPIPNEW_PTCL 4
+#define IPIPOLD_PTCL 94
+#define TCP_PTCL 6
+#define UDP_PTCL 17
+#define ICMP_PTCL 1
+#define AX25_PTCL 93
+#define RSPF_PTCL 73
+
+void ip_dump(unsigned char *data, int length, int hexdump)
+{
+ int hdr_length;
+ int tos;
+ int ip_length;
+ int id;
+ int fl_offs;
+ int flags;
+ int offset;
+ int ttl;
+ int protocol;
+ unsigned char *source, *dest;
+
+ lprintf(T_PROTOCOL, "IP:");
+
+ /* Sneak peek at IP header and find length */
+ hdr_length = (data[0] & 0xf) << 2;
+
+ if (hdr_length < IPLEN)
+ {
+ lprintf(T_ERROR, " bad header\n");
+ return;
+ }
+
+ tos = data[1];
+ ip_length = get16(data + 2);
+ id = get16(data + 4);
+ fl_offs = get16(data + 6);
+ flags = fl_offs & 0xE000;
+ offset = (fl_offs & 0x1FFF) << 3;
+ ttl = data[8];
+ protocol = data[9];
+ source = data + 12;
+ dest = data + 16;
+
+ lprintf(T_IPHDR, " len %d", ip_length);
+
+ lprintf(T_ADDR, " %d.%d.%d.%d->%d.%d.%d.%d",
+ source[0], source[1], source[2], source[3],
+ dest[0], dest[1], dest[2], dest[3]);
+
+ lprintf(T_IPHDR, " ihl %d ttl %d", hdr_length, ttl);
+
+ if (tos != 0) lprintf(T_IPHDR, " tos %d", tos);
+
+ if (offset != 0 || (flags & MF))
+ lprintf(T_IPHDR, " id %d offs %d", id, offset);
+
+ if (flags & DF) lprintf(T_IPHDR, " DF");
+ if (flags & MF) lprintf(T_IPHDR, " MF");
+ if (flags & CE) lprintf(T_IPHDR, " CE");
+
+ data += hdr_length;
+ length -= hdr_length;
+
+ if (offset != 0) {
+ lprintf(T_IPHDR, "\n");
+ if (length > 0)
+ data_dump(data, length, hexdump);
+ return;
+ }
+
+ switch (protocol) {
+ case IPIPOLD_PTCL:
+ case IPIPNEW_PTCL:
+ lprintf(T_IPHDR, " prot IP\n");
+ ip_dump(data, length, hexdump);
+ break;
+ case TCP_PTCL:
+ lprintf(T_IPHDR, " prot TCP\n");
+ tcp_dump(data, length, hexdump);
+ break;
+ case UDP_PTCL:
+ lprintf(T_IPHDR, " prot UDP\n");
+ udp_dump(data, length, hexdump);
+ break;
+ case ICMP_PTCL:
+ lprintf(T_IPHDR, " prot ICMP\n");
+ icmp_dump(data, length, hexdump);
+ break;
+ case AX25_PTCL:
+ lprintf(T_IPHDR, " prot AX25\n");
+ ax25_dump(data, length, hexdump);
+ break;
+ case RSPF_PTCL:
+ lprintf(T_IPHDR, " prot RSPF\n");
+ rspf_dump(data, length);
+ break;
+ default:
+ lprintf(T_IPHDR, " prot %d\n", protocol);
+ data_dump(data, length, hexdump);
+ break;
+ }
+}
diff --git a/listen/kissdump.c b/listen/kissdump.c
new file mode 100644
index 0000000..38bf6e6
--- /dev/null
+++ b/listen/kissdump.c
@@ -0,0 +1,60 @@
+/* @(#) $Header: kissdump.c,v 1.7 92/11/29 17:37:52 deyke Exp $ */
+
+/* Tracing routines for KISS TNC
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include "listen.h"
+
+#define PARAM_DATA 0
+#define PARAM_TXDELAY 1
+#define PARAM_PERSIST 2
+#define PARAM_SLOTTIME 3
+#define PARAM_TXTAIL 4
+#define PARAM_FULLDUP 5
+#define PARAM_HW 6
+#define PARAM_RETURN 15 /* Should be 255, but is ANDed with 0x0F */
+
+void ki_dump(unsigned char *data, int length, int hexdump)
+{
+ int type;
+ int val;
+
+ type = data[0] & 0xf;
+
+ if (type == PARAM_DATA)
+ {
+ ax25_dump(data + 1, length - 1, hexdump);
+ return;
+ }
+
+ val = data[1];
+
+ switch (type)
+ {
+ case PARAM_TXDELAY:
+ lprintf(T_KISS, "TX Delay: %lu ms\n", val * 10L);
+ break;
+ case PARAM_PERSIST:
+ lprintf(T_KISS, "Persistence: %u/256\n", val + 1);
+ break;
+ case PARAM_SLOTTIME:
+ lprintf(T_KISS, "Slot time: %lu ms\n", val * 10L);
+ break;
+ case PARAM_TXTAIL:
+ lprintf(T_KISS, "TX Tail time: %lu ms\n", val * 10L);
+ break;
+ case PARAM_FULLDUP:
+ lprintf(T_KISS, "Duplex: %s\n", val == 0 ? "Half" : "Full");
+ break;
+ case PARAM_HW:
+ lprintf(T_KISS, "Hardware %u\n", val);
+ break;
+ case PARAM_RETURN:
+ lprintf(T_KISS, "RETURN\n");
+ break;
+ default:
+ lprintf(T_KISS, "code %u arg %u\n", type, val);
+ break;
+ }
+}
diff --git a/listen/listen.1 b/listen/listen.1
new file mode 100644
index 0000000..99e1f8b
--- /dev/null
+++ b/listen/listen.1
@@ -0,0 +1,89 @@
+.TH LISTEN 1 "27 August 1996" Linux "Linux Programmer's Manual"
+.SH NAME
+listen \- monitor AX.25 traffic
+.SH SYNOPSIS
+.B listen [-8] [-a] [-c] [-h] [-i] [-p port] [-r] [-t] [-v]
+.SH DESCRIPTION
+.LP
+.B Listen
+uses SOCK_PACKET facilities to provide a network monitor of all AX.25
+traffic heard by the system. Since KISS is implicitly promiscuous no
+special driver configurations are needed.
+.LP
+This version displays standard AX.25, PE1CHL extended AX.25, NET/ROM, Rose, ARP,
+IP, ICMP, TCP and UDP. It also displays IP, TCP, ICMP, TCP and UDP
+encapsulated within NET/ROM frames. The program also displays AX.25 and IP
+encapsulated within an IP frame, but see RFC1326 for reasons not to do so.
+.LP
+.B Listen
+makes an attempt at decoding some of the more common routing protocols. RSPF
+and RIP (both \(lqnormal\(rq and G8BPQs RIP98) are traced. JNOS style
+NET/ROM node polls are also displayed.
+.LP
+.B Listen
+can use colors to make the output more readable. The ncurses library is used
+to accomplish this.
+.B Color support defaults to being disabled,
+and the
+.BR -c
+parameter is used to enable it.
+.SH OPTIONS
+.TP 10
+.BI \-8
+Indicates that the terminal is capable of printing 8-bit characters. This
+parameter is required for the -i parameter to work.
+.TP 10
+.BI \-a
+Allow for the monitoring of outgoing frames as well as incoming ones.
+.TP 10
+.BI \-c
+Enable color support.
+.TP 10
+.BI \-h
+Dump the data portion of the packet in both hexadecimal and ASCII. The
+default is to display data as ASCII only.
+.TP 10
+.BI \-i
+Map IBM codepage 437 characters 128-158 to their ISO-Latin-1 equivalents.
+This is a hack for scandinavian users. This parameter is only valid
+when used with the -8 and -c parameters.
+.TP 10
+.BI "\-p port"
+Monitor only those frames received on a particular port, by default all
+AX.25 devices are monitored.
+.TP 10
+.BI \-r
+Dump the data portion in a "readable" fashion, which is more suitable
+for tracing plaintext AX.25 traffic. CR-LF conversion is done.
+.TP 10
+.BI \-t
+Displays a timestamp with each packet received.
+.TP 10
+.BI \-v
+Display the version.
+.SH FILES
+/etc/ax25/axports
+.SH "SEE ALSO"
+.BR call (1),
+.BR mheard (1),
+.BR beacon (1),
+.BR ax25 (4),
+.BR netrom (4),
+.BR rose (4),
+.BR kissattach (8).
+.LP
+.SH BUGS
+.B Listen
+does not validate the checksums of frames that support them (ie IP),
+therefore corrupt frames will be displayed with bogus values. The MSS
+of a TCP frame that contains that option is not displayed.
+.SH AUTHORS
+.nf
+Alan Cox GW4PTS <alan@cymru.net>
+.br
+Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
+.br
+Phil Karn KA9Q <karn@qualcomm.com>
+.br
+Heikki Hannikainen OH7LZB <hessu@pspt.fi>
+.fi
diff --git a/listen/listen.c b/listen/listen.c
new file mode 100644
index 0000000..df6f770
--- /dev/null
+++ b/listen/listen.c
@@ -0,0 +1,293 @@
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <curses.h>
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netax25/ax25.h>
+#include <netax25/axconfig.h>
+
+#include <config.h>
+#include "listen.h"
+
+static void display_port(char *dev)
+{
+ char *port;
+
+ if ((port = ax25_config_get_name(dev)) == NULL)
+ port = dev;
+
+ lprintf(T_PORT, "Port %s: ", port);
+}
+
+static void display_timestamp(void)
+{
+ time_t timenow;
+ char *timestring;
+
+ time(&timenow);
+
+ timestring = ctime(&timenow);
+ timestring[24] = '\0';
+
+ lprintf(T_TIMESTAMP, "[%s]\n", timestring);
+}
+
+#define ASCII 0
+#define HEX 1
+#define READABLE 2
+
+#define BUFSIZE 1500
+
+int main(int argc, char **argv)
+{
+ unsigned char buffer[BUFSIZE];
+ int timestamp = 0;
+ int dumpstyle = ASCII;
+ int size;
+ int s;
+ char *port = NULL, *dev = NULL;
+ struct sockaddr sa;
+ int asize = sizeof(sa);
+ struct ifreq ifr;
+ int proto = ETH_P_AX25;
+
+ while ((s = getopt(argc, argv, "8achip:rtv")) != -1) {
+ switch (s) {
+ case '8':
+ sevenbit = 0;
+ break;
+ case 'a':
+ proto = ETH_P_ALL;
+ break;
+ case 'c':
+ color = 1;
+ break;
+ case 'h':
+ dumpstyle = HEX;
+ break;
+ case 'i':
+ ibmhack = 1;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'r':
+ dumpstyle = READABLE;
+ break;
+ case 't':
+ timestamp = 1;
+ break;
+ case 'v':
+ printf("listen: %s\n", VERSION);
+ return 0;
+ case ':':
+ fprintf(stderr, "listen: option -p needs a port name\n");
+ return 1;
+ case '?':
+ fprintf(stderr, "Usage: listen [-8] [-a] [-c] [-h] [-i] [-p port] [-r] [-t] [-v]\n");
+ return 1;
+ }
+ }
+
+ if (ax25_config_load_ports() == 0)
+ fprintf(stderr, "listen: no AX.25 port data configured\n");
+
+ if (port != NULL) {
+ if ((dev = ax25_config_get_dev(port)) == NULL) {
+ fprintf(stderr, "listen: invalid port name - %s\n", port);
+ return 1;
+ }
+ }
+
+ if ((s = socket(AF_INET, SOCK_PACKET, htons(proto))) == -1) {
+ perror("socket");
+ return 1;
+ }
+
+ if (color) {
+ color = initcolor(); /* Initialize color support */
+ if (!color)
+ printf("Could not initialize color support.\n");
+ }
+
+ setservent(1);
+
+ for (;;) {
+ asize = sizeof(sa);
+
+ if ((size = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &asize)) == -1) {
+ perror("recv");
+ return 1;
+ }
+
+ if (dev != NULL && strcmp(dev, sa.sa_data) != 0)
+ continue;
+
+ if (proto == ETH_P_ALL) {
+ strcpy(ifr.ifr_name, sa.sa_data);
+ if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
+ perror("GIFADDR");
+
+ if (ifr.ifr_hwaddr.sa_family == AF_AX25) {
+ if (timestamp)
+ display_timestamp();
+ display_port(sa.sa_data);
+ ki_dump(buffer, size, dumpstyle);
+ lprintf(T_DATA, "\n");
+ }
+ } else {
+ if (timestamp)
+ display_timestamp();
+ display_port(sa.sa_data);
+ ki_dump(buffer, size, dumpstyle);
+ lprintf(T_DATA, "\n");
+ }
+ if (color)
+ refresh();
+ }
+}
+
+static void ascii_dump(unsigned char *data, int length)
+{
+ unsigned char c;
+ int i, j;
+ char buf[100];
+
+ for (i = 0; length > 0; i += 64) {
+ sprintf(buf, "%04X ", i);
+
+ for (j = 0; j < 64 && length > 0; j++) {
+ c = *data++;
+ length--;
+
+ if ((c != '\0') && (c != '\n'))
+ strncat(buf, &c, 1);
+ else
+ strcat(buf, ".");
+ }
+
+ lprintf(T_DATA, "%s\n", buf);
+ }
+}
+
+static void readable_dump(unsigned char *data, int length)
+{
+ unsigned char c;
+ int i;
+ int cr = 1;
+ char buf[BUFSIZE];
+
+ for (i = 0; length > 0; i++) {
+
+ c = *data++;
+ length--;
+
+ switch (c) {
+ case 0x00:
+ buf[i] = ' ';
+ case 0x0A: /* hum... */
+ case 0x0D:
+ if (cr)
+ buf[i] = '\n';
+ else
+ i--;
+ break;
+ default:
+ buf[i] = c;
+ }
+ cr = (buf[i] != '\n');
+ }
+ if (cr)
+ buf[i++] = '\n';
+ buf[i++] = '\0';
+ lprintf(T_DATA, "%s", buf);
+}
+
+static void hex_dump(unsigned char *data, int length)
+{
+ int i, j, length2;
+ unsigned char c;
+ char *data2;
+
+ char buf[4], hexd[49], ascd[17];
+
+ length2 = length;
+ data2 = data;
+
+ for (i = 0; length > 0; i += 16) {
+
+ hexd[0] = '\0';
+ for (j = 0; j < 16; j++) {
+ c = *data2++;
+ length2--;
+
+ if (length2 >= 0)
+ sprintf(buf, "%2.2X ", c);
+ else
+ strcpy(buf, " ");
+ strcat(hexd, buf);
+ }
+
+ ascd[0] = '\0';
+ for (j = 0; j < 16 && length > 0; j++) {
+ c = *data++;
+ length--;
+
+ sprintf(buf, "%c", ((c != '\0') && (c != '\n')) ? c : '.');
+ strcat(ascd, buf);
+ }
+
+ lprintf(T_DATA, "%04X %s | %s\n", i, hexd, ascd);
+ }
+}
+
+void data_dump(unsigned char *data, int length, int dumpstyle)
+{
+ switch (dumpstyle) {
+
+ case READABLE:
+ readable_dump(data, length);
+ break;
+ case HEX:
+ hex_dump(data, length);
+ break;
+ default:
+ ascii_dump(data, length);
+ }
+}
+
+int get16(unsigned char *cp)
+{
+ int x;
+
+ x = *cp++;
+ x <<= 8;
+ x |= *cp++;
+
+ return(x);
+}
+
+int get32(unsigned char *cp)
+{
+ int x;
+
+ x = *cp++;
+ x <<= 8;
+ x |= *cp++;
+ x <<= 8;
+ x |= *cp++;
+ x <<= 8;
+ x |= *cp;
+
+ return(x);
+}
diff --git a/listen/listen.h b/listen/listen.h
new file mode 100644
index 0000000..cff051d
--- /dev/null
+++ b/listen/listen.h
@@ -0,0 +1,65 @@
+
+#define T_ERROR 1
+#define T_PORT 2
+#define T_KISS 3
+#define T_BPQ 4
+#define T_DATA 5
+#define T_PROTOCOL 6
+#define T_AXHDR 7
+#define T_ADDR 8
+#define T_IPHDR 9
+#define T_TCPHDR 10
+#define T_ROSEHDR 11
+#define T_TIMESTAMP 12
+#define T_FLEXNET 3 /* for now */
+
+/* In utils.c */
+extern int color; /* Colorized mode */
+extern int sevenbit; /* Are we on a 7-bit terminal? */
+extern int ibmhack; /* IBM mapping? */
+
+void lprintf(int dtype, char *fmt, ...);
+int initcolor(void);
+char *servname(int port, char *proto);
+
+/* In listen.c */
+void data_dump(unsigned char *, int, int);
+int get16(unsigned char *);
+int get32(unsigned char *);
+
+/* In kissdump.c */
+void ki_dump(unsigned char *, int, int);
+
+/* ax25dump.c */
+void ax25_dump(unsigned char *, int, int);
+char *pax25(char *, unsigned char *);
+
+/* In nrdump.c */
+void netrom_dump(unsigned char *, int, int);
+
+/* In arpdump.c */
+void arp_dump(unsigned char *, int);
+
+/* In ipdump.c */
+void ip_dump(unsigned char *, int, int);
+
+/* In icmpdump.c */
+void icmp_dump(unsigned char *, int, int);
+
+/* In udpdump.c */
+void udp_dump(unsigned char *, int, int);
+
+/* In tcpdump.c */
+void tcp_dump(unsigned char *, int, int);
+
+/* In rspfdump.c */
+void rspf_dump(unsigned char *, int);
+
+/* In ripdump.c */
+void rip_dump(unsigned char *, int);
+
+/* In rosedump.c */
+void rose_dump(unsigned char *, int, int);
+
+/* In flexnetdump.c */
+void flexnet_dump(unsigned char *, int, int);
diff --git a/listen/nrdump.c b/listen/nrdump.c
new file mode 100644
index 0000000..9d50864
--- /dev/null
+++ b/listen/nrdump.c
@@ -0,0 +1,154 @@
+/* @(#) $Header: nrdump.c,v 1.2 91/02/24 20:17:28 deyke Exp $ */
+
+/* NET/ROM header tracing routines
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#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: ckt %d/%d", 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 %d/%d my ckt %d/%d", 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: ckt %d/%d\n", data[0], data[1]);
+ break;
+
+ case NR4OPDISAK: /* Disconnect acknowledgement */
+ lprintf(T_AXHDR, " disc ack: ckt %d/%d\n", data[0], data[1]);
+ break;
+
+ case NR4OPINFO: /* Information (data) */
+ lprintf(T_AXHDR, " info: ckt %d/%d", 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: ckt %d/%d", 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");
+}
+
+
diff --git a/listen/ripdump.c b/listen/ripdump.c
new file mode 100644
index 0000000..9f3a799
--- /dev/null
+++ b/listen/ripdump.c
@@ -0,0 +1,174 @@
+/* RIP packet tracing
+ * Copyright 1991 Phil Karn, KA9Q
+ *
+ * Changes Copyright (c) 1993 Jeff White - N0POY, All Rights Reserved.
+ * Permission granted for non-commercial copying and use, provided
+ * this notice is retained.
+ *
+ * Rehack for RIP-2 (RFC1388) by N0POY 4/1993
+ *
+ * Beta release 11/10/93 V0.91
+ *
+ * 2/19/94 release V1.0
+ *
+ */
+
+#include <stdio.h>
+
+#include "listen.h"
+
+#define RIP_VERSION_2 2
+#define RIP_VERSION_98 98
+
+#define RIP_HEADER 4
+#define RIP_ENTRY 20
+
+#define RIP_AF_INET 2 /* IP Family */
+
+#define RIPCMD_REQUEST 1 /* want info */
+#define RIPCMD_RESPONSE 2 /* responding to request */
+
+#define RIP98_ENTRY 6
+
+static struct mask_struct
+{
+ unsigned int mask;
+ unsigned int width;
+}
+mask_table[] =
+{
+ {0xFFFFFFFF, 32},
+ {0xFFFFFFFE, 31},
+ {0xFFFFFFFC, 30},
+ {0xFFFFFFF8, 29},
+ {0xFFFFFFF0, 28},
+ {0xFFFFFFE0, 27},
+ {0xFFFFFFC0, 26},
+ {0xFFFFFF80, 25},
+ {0xFFFFFF00, 24},
+ {0xFFFFFE00, 23},
+ {0xFFFFFC00, 22},
+ {0xFFFFF800, 21},
+ {0xFFFFF000, 20},
+ {0xFFFFE000, 19},
+ {0xFFFFC000, 18},
+ {0xFFFF8000, 17},
+ {0xFFFF0000, 16},
+ {0xFFFE0000, 15},
+ {0xFFFC0000, 14},
+ {0xFFF80000, 13},
+ {0xFFF00000, 12},
+ {0xFFE00000, 11},
+ {0xFFC00000, 10},
+ {0xFF800000, 9},
+ {0xFF000000, 8},
+ {0xFE000000, 7},
+ {0xFC000000, 6},
+ {0xF8000000, 5},
+ {0xF0000000, 4},
+ {0xE0000000, 3},
+ {0xC0000000, 2},
+ {0x80000000, 1},
+ {0x00000000, 0},
+};
+
+static unsigned int mask2width(unsigned int mask)
+{
+ struct mask_struct *t;
+
+ for (t = mask_table; t->mask != 0; t++)
+ if (mask == t->mask)
+ return t->width;
+
+ return 0;
+}
+
+void rip_dump(unsigned char *data, int length)
+{
+ int i;
+ int cmd;
+ int version;
+ int domain;
+ char ipaddmask[25];
+
+ lprintf(T_PROTOCOL, "RIP: ");
+
+ cmd = data[0];
+ version = data[1];
+ domain = get16(data + 2);
+
+ length -= RIP_HEADER;
+ data += RIP_HEADER;
+
+ switch (cmd)
+ {
+ case RIPCMD_REQUEST:
+ lprintf(T_IPHDR, "REQUEST");
+ break;
+
+ case RIPCMD_RESPONSE:
+ lprintf(T_IPHDR, "RESPONSE");
+ break;
+
+ default:
+ lprintf(T_IPHDR, " cmd %u", cmd);
+ break;
+ }
+
+ switch (version)
+ {
+ case RIP_VERSION_98: /* IPGATE **/
+ lprintf(T_IPHDR, " vers %u entries %u\n", version, length / RIP98_ENTRY);
+
+ i = 0;
+ while (length >= RIP98_ENTRY)
+ {
+ sprintf(ipaddmask, "%u.%u.%u.%u/%-2u", data[0], data[1], data[2], data[3], data[4]);
+ lprintf(T_ADDR, "%-16s %-3u ", ipaddmask, data[5]);
+
+ if ((++i % 3) == 0) lprintf(T_IPHDR, "\n");
+
+ length -= RIP98_ENTRY;
+ data += RIP98_ENTRY;
+ }
+
+ if ((i % 3) != 0) lprintf(T_IPHDR, "\n");
+ break;
+
+ default:
+ lprintf(T_IPHDR, " vers %u entries %u domain %u:\n", version, length / RIP_ENTRY, domain);
+
+ i = 0;
+ while (length >= RIP_ENTRY)
+ {
+ if (get16(data + 0) != RIP_AF_INET)
+ {
+ /* Skip non-IP addresses */
+ length -= RIP_ENTRY;
+ data += RIP_ENTRY;
+ continue;
+ }
+
+ if (version >= RIP_VERSION_2)
+ {
+ sprintf(ipaddmask, "%u.%u.%u.%u/%-4d", data[4], data[5], data[6], data[7],
+ mask2width(get32(data + 8)));
+ }
+ else
+ {
+ sprintf(ipaddmask, "%u.%u.%u.%u/??", data[4], data[5], data[6], data[7]);
+ }
+
+ lprintf(T_ADDR, "%-20s%-3u", ipaddmask, get32(data + 16));
+
+ if ((++i % 3) == 0) lprintf(T_IPHDR, "\n");
+
+ length -= RIP_ENTRY;
+ data += RIP_ENTRY;
+ }
+
+ if ((i % 3) != 0) lprintf(T_IPHDR, "\n");
+ break;
+ }
+}
+
diff --git a/listen/rosedump.c b/listen/rosedump.c
new file mode 100644
index 0000000..aff16aa
--- /dev/null
+++ b/listen/rosedump.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 1996 Jonathan Naylor G4KLX
+ */
+#include <stdio.h>
+#include <string.h>
+#include "listen.h"
+
+#define ROSE_ADDR_LEN 5
+
+#define CALL_REQUEST 0x0B
+#define CALL_ACCEPTED 0x0F
+#define CLEAR_REQUEST 0x13
+#define CLEAR_CONFIRMATION 0x17
+#define INTERRUPT 0x23
+#define INTERRUPT_CONFIRMATION 0x27
+#define RESET_REQUEST 0x1B
+#define RESET_CONFIRMATION 0x1F
+#define RESTART_REQUEST 0xFB
+#define RESTART_CONFIRMATION 0xFF
+#define REGISTRATION_REQUEST 0xF3
+#define REGISTRATION_CONFIRMATION 0xF7
+#define DIAGNOSTIC 0xF1
+#define RR 0x01
+#define RNR 0x05
+#define REJ 0x09
+#define DATA 0x00
+
+#define QBIT 0x80
+#define DBIT 0x40
+#define MBIT 0x10
+
+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);
+
+void rose_dump(unsigned char *data, int length, int hexdump)
+{
+ lprintf(T_ROSEHDR, "X.25: LCI %3.3X : ", (data[0] & 0x0F) + data[1]);
+
+ switch (data[2]) {
+ case CALL_REQUEST:
+ data += 4;
+ length -= 4;
+ 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);
+ return;
+
+ case CALL_ACCEPTED:
+ lprintf(T_ROSEHDR, "CALL ACCEPTED\n");
+ return;
+
+ case CLEAR_REQUEST:
+ lprintf(T_ROSEHDR, "CLEAR REQUEST - Cause %s - Diag %d\n",
+ clear_code(data[3]), data[4]);
+ return;
+
+ case CLEAR_CONFIRMATION:
+ lprintf(T_ROSEHDR, "CLEAR CONFIRMATION\n");
+ return;
+
+ case DIAGNOSTIC:
+ lprintf(T_ROSEHDR, "DIAGNOSTIC - Diag %d\n", data[3]);
+ return;
+
+ case INTERRUPT:
+ lprintf(T_ROSEHDR, "INTERRUPT\n");
+ data_dump(data + 3, length - 3, hexdump);
+ return;
+
+ case INTERRUPT_CONFIRMATION:
+ lprintf(T_ROSEHDR, "INTERRUPT CONFIRMATION\n");
+ return;
+
+ case RESET_REQUEST:
+ lprintf(T_ROSEHDR, "RESET REQUEST - Cause %s - Diag %d\n",
+ reset_code(data[3]), data[4]);
+ return;
+
+ case RESET_CONFIRMATION:
+ lprintf(T_ROSEHDR, "RESET CONFIRMATION\n");
+ return;
+
+ case RESTART_REQUEST:
+ lprintf(T_ROSEHDR, "RESTART REQUEST - Cause %s - Diag %d\n",
+ restart_code(data[3]), data[4]);
+ return;
+
+ case RESTART_CONFIRMATION:
+ lprintf(T_ROSEHDR, "RESTART CONFIRMATION\n");
+ return;
+
+ case REGISTRATION_REQUEST:
+ lprintf(T_ROSEHDR, "REGISTRATION REQUEST\n");
+ return;
+
+ case REGISTRATION_CONFIRMATION:
+ lprintf(T_ROSEHDR, "REGISTRATION CONFIRMATION\n");
+ return;
+ }
+
+ if ((data[2] & 0x01) == DATA) {
+ lprintf(T_ROSEHDR, "DATA R%d S%d %s%s%s\n",
+ (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);
+ return;
+ }
+
+ switch (data[2] & 0x1F) {
+ case RR:
+ lprintf(T_ROSEHDR, "RR R%d\n", (data[2] >> 5) & 0x07);
+ return;
+ case RNR:
+ lprintf(T_ROSEHDR, "RNR R%d\n", (data[2] >> 5) & 0x07);
+ return;
+ case REJ:
+ lprintf(T_ROSEHDR, "REJ R%d\n", (data[2] >> 5) & 0x07);
+ return;
+ }
+
+ lprintf(T_ROSEHDR, "UNKNOWN\n");
+ data_dump(data, length, 1);
+}
+
+static char *clear_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x01)
+ return "Number Busy";
+ if (code == 0x09)
+ return "Out Of Order";
+ if (code == 0x11)
+ return "Remote Procedure Error";
+ if (code == 0x19)
+ return "Reverse Charging Acceptance Not Subscribed";
+ if (code == 0x21)
+ return "Incompatible Destination";
+ if (code == 0x29)
+ return "Fast Select Acceptance Not Subscribed";
+ if (code == 0x39)
+ return "Destination Absent";
+ if (code == 0x03)
+ return "Invalid Facility Requested";
+ if (code == 0x0B)
+ return "Access Barred";
+ if (code == 0x13)
+ return "Local Procedure Error";
+ if (code == 0x05)
+ return "Network Congestion";
+ if (code == 0x0D)
+ return "Not Obtainable";
+ if (code == 0x15)
+ return "RPOA Out Of Order";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static char *reset_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x03)
+ return "Remote Procedure Error";
+ if (code == 0x11)
+ return "Incompatible Destination";
+ if (code == 0x05)
+ return "Local Procedure Error";
+ if (code == 0x07)
+ return "Network Congestion";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static char *restart_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x01)
+ return "Local Procedure Error";
+ if (code == 0x03)
+ return "Network Congestion";
+ if (code == 0x07)
+ return "Network Operational";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+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]);
+
+ return buffer;
+}
diff --git a/listen/rspfdump.c b/listen/rspfdump.c
new file mode 100644
index 0000000..e05e0fa
--- /dev/null
+++ b/listen/rspfdump.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "listen.h"
+
+void rspf_dump(unsigned char *data, int length)
+{
+ int bptr, nodes, links, adjs;
+
+ lprintf(T_IPHDR, "RSPF: version %u ", data[0]);
+
+ switch(data[1])
+ {
+ case 3: /* RRH */
+ lprintf(T_IPHDR, "type RRH seq %#04x flags %d\n",ntohs(*((u_short*)(&data[8]))), data[10]);
+ bptr = 11;
+ while (bptr < length)
+ lprintf(T_IPHDR, "%c", data[bptr++]);
+ lprintf(T_IPHDR, "\n");
+ break;
+ case 1: /*Routing update*/
+ lprintf(T_IPHDR, "type ROUTING UPDATE ");
+ lprintf(T_IPHDR, "fragment %u frag total %u sync %u #nodes %u env_id %u\n", data[2], data[3], data[6], data[7], ntohs(*((u_short*)(&data[8]))));
+
+ bptr = data[6] + 6;
+ nodes = data[7];
+ while(nodes-- && (length - bptr) > 7)
+ {
+ lprintf(T_DATA, " Reporting Router: %s Seq %u Subseq %u #links %u\n", inet_ntoa(*((struct in_addr*)(&data[bptr]))), ntohs(*((u_short*)(&data[bptr+4]))), data[bptr+6], data[bptr+7]);
+ links = data[bptr+7];
+ bptr += 8;
+ while(links-- && (length - bptr) > 4)
+ {
+ lprintf(T_DATA, " horizon %u ERP factor %u cost %u #adjacencies %u\n", data[bptr], data[bptr+1], data[bptr+2], data[bptr+3]);
+ adjs = data[bptr+3];
+ bptr += 4;
+ while(adjs-- && (length - bptr) > 4)
+ {
+ lprintf(T_DATA, " %s/%d \n", inet_ntoa(*((struct in_addr*)(&data[bptr+1]))), data[bptr] & 0x3f);
+ bptr += 5;
+ }
+ }
+ }
+ break;
+ default:
+ lprintf(T_ERROR, "Unknown packet type %d\n", data[1]);
+ break;
+ }
+}
+
diff --git a/listen/tcpdump.c b/listen/tcpdump.c
new file mode 100644
index 0000000..7939f41
--- /dev/null
+++ b/listen/tcpdump.c
@@ -0,0 +1,123 @@
+/* @(#) $Header: tcpdump.c,v 1.5 91/05/09 07:38:56 deyke Exp $ */
+
+/* TCP header tracing routines
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include <string.h>
+#include "listen.h"
+
+#define FIN 0x01
+#define SYN 0x02
+#define RST 0x04
+#define PSH 0x08
+#define ACK 0x10
+#define URG 0x20
+#define CE 0x40
+
+/* TCP options */
+#define EOL_KIND 0
+#define NOOP_KIND 1
+#define MSS_KIND 2
+#define MSS_LENGTH 4
+
+#define TCPLEN 20
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+/* Dump a TCP segment header. Assumed to be in network byte order */
+void tcp_dump(unsigned char *data, int length, int hexdump)
+{
+ int source, dest;
+ int seq;
+ int ack;
+ int flags;
+ int wnd;
+ int up;
+ int hdrlen;
+ int mss = 0;
+
+ source = get16(data + 0);
+ dest = get16(data + 2);
+ seq = get32(data + 4);
+ ack = get32(data + 8);
+ hdrlen = (data[12] & 0xF0) >> 2;
+ flags = data[13];
+ wnd = get16(data + 14);
+ up = get16(data + 18);
+
+ lprintf(T_PROTOCOL, "TCP:");
+ lprintf(T_TCPHDR, " %s->", servname(source, "tcp"));
+ lprintf(T_TCPHDR, "%s Seq x%x", servname(dest, "tcp"), seq);
+
+ if (flags & ACK) lprintf(T_TCPHDR, " Ack x%x", ack);
+
+ if (flags & CE) lprintf(T_TCPHDR, " CE");
+
+ if (flags & URG) lprintf(T_TCPHDR, " URG");
+
+ if (flags & ACK) lprintf(T_TCPHDR, " ACK");
+
+ if (flags & PSH) lprintf(T_TCPHDR, " PSH");
+
+ if (flags & RST) lprintf(T_TCPHDR, " RST");
+
+ if (flags & SYN) lprintf(T_TCPHDR, " SYN");
+
+ if (flags & FIN) lprintf(T_TCPHDR, " FIN");
+
+ lprintf(T_TCPHDR, " Wnd %d", wnd);
+
+ if (flags & URG) lprintf(T_TCPHDR, " UP x%x", up);
+
+ /* Process options, if any */
+ if (hdrlen > TCPLEN && length >= hdrlen) {
+ unsigned char *cp = data + TCPLEN;
+ int i = hdrlen - TCPLEN;
+ int kind, optlen;
+
+ while (i > 0) {
+ kind = *cp++;
+
+ /* Process single-byte options */
+ switch (kind) {
+ case EOL_KIND:
+ i--;
+ cp++;
+ break;
+ case NOOP_KIND:
+ i--;
+ cp++;
+ continue;
+ }
+
+ /* All other options have a length field */
+ optlen = *cp++;
+
+ /* Process valid multi-byte options */
+ switch (kind) {
+ case MSS_KIND:
+ if (optlen == MSS_LENGTH)
+ mss = get16(cp);
+ break;
+ }
+
+ optlen = max(2, optlen); /* Enforce legal minimum */
+ i -= optlen;
+ cp += optlen - 2;
+ }
+ }
+
+ if (mss != 0) lprintf(T_TCPHDR," MSS %d", mss);
+
+ length -= hdrlen;
+ data += hdrlen;
+
+ if (length > 0) {
+ lprintf(T_TCPHDR, " Data %d\n", length);
+ data_dump(data, length, hexdump);
+ return;
+ }
+
+ lprintf(T_TCPHDR, "\n");
+}
diff --git a/listen/udpdump.c b/listen/udpdump.c
new file mode 100644
index 0000000..7b1c184
--- /dev/null
+++ b/listen/udpdump.c
@@ -0,0 +1,44 @@
+/* @(#) $Header: udpdump.c,v 1.5 91/05/09 07:39:11 deyke Exp $ */
+
+/* UDP packet tracing
+ * Copyright 1991 Phil Karn, KA9Q
+ */
+#include <stdio.h>
+#include "listen.h"
+
+#define RIP_PORT 520
+
+#define UDPHDR 8
+
+/* Dump a UDP header */
+void udp_dump(unsigned char *data, int length, int hexdump)
+{
+ int hdr_length;
+ int source;
+ int dest;
+
+ hdr_length = get16(data + 4);
+ source = get16(data + 0);
+ dest = get16(data + 2);
+
+ lprintf(T_PROTOCOL, "UDP:");
+
+ lprintf(T_TCPHDR, " len %d %s->", hdr_length, servname(source, "udp"));
+ lprintf(T_TCPHDR, "%s", servname(dest, "udp"));
+
+ if (hdr_length > UDPHDR) {
+ length -= UDPHDR;
+ data += UDPHDR;
+
+ switch (dest) {
+ case RIP_PORT:
+ lprintf(T_TCPHDR, "\n");
+ rip_dump(data, length);
+ break;
+ default:
+ lprintf(T_TCPHDR, " Data %d\n", length);
+ data_dump(data, length, hexdump);
+ break;
+ }
+ }
+}
diff --git a/listen/utils.c b/listen/utils.c
new file mode 100644
index 0000000..7b7cc5d
--- /dev/null
+++ b/listen/utils.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 1996, 1997 Heikki Hannikainen OH7LZB <hessu@pspt.fi>
+ *
+ * Portions and ideas (like the ibm character mapping) from
+ * Tomi Manninen OH2BNS <Tomi.Manninen@hut.fi>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <curses.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include "listen.h"
+
+int color = 0; /* Colorized? */
+int sevenbit = 1; /* Are we on a 7-bit terminal? */
+int ibmhack = 0; /* IBM mapping? */
+
+/* mapping of IBM codepage 437 chars 128-159 to ISO latin1 equivalents
+ * (158 and 159 are mapped to space)
+ */
+
+unsigned char ibm_map[32] =
+{
+ 199, 252, 233, 226, 228, 224, 229, 231,
+ 234, 235, 232, 239, 238, 236, 196, 197,
+ 201, 230, 198, 244, 246, 242, 251, 249,
+ 255, 214, 220, 162, 163, 165, 32, 32
+};
+
+/*
+ * Printf in Technicolor (TM) (available in selected theatres only)
+ */
+
+void lprintf(int dtype, char *fmt, ...)
+{
+ va_list args;
+ char str[1024];
+ unsigned char *p;
+ chtype ch;
+
+ va_start(args, fmt);
+ vsnprintf(str, 1024, fmt, args);
+ va_end(args);
+
+ if (color) {
+ for (p = str; *p != '\0'; p++) {
+ ch = *p;
+
+ if (sevenbit && ch > 127)
+ ch = '.';
+
+ if ((ch > 127 && ch < 160) && ibmhack)
+ ch = ibm_map[ch - 128] | A_BOLD;
+ else if ((ch < 32) && (ch != '\n'))
+ ch = (ch + 64) | A_REVERSE;
+
+ if ((dtype == T_ADDR) || (dtype == T_PROTOCOL)
+ || (dtype == T_AXHDR) || (dtype == T_IPHDR)
+ || (dtype == T_ROSEHDR))
+ ch |= A_BOLD;
+
+ ch |= COLOR_PAIR(dtype);
+
+ addch(ch);
+ }
+ } else {
+ for (p = str; *p != '\0'; p++)
+ if ((*p < 32 && *p != '\n')
+ || (*p > 126 && *p < 160 && sevenbit))
+ *p = '.';
+ fputs(str, stdout);
+ fflush(stdout);
+ }
+}
+
+int initcolor(void)
+{
+ if (!has_colors)
+ return 0;
+ initscr(); /* Start ncurses */
+ start_color(); /* Initialize color support */
+ refresh(); /* Clear screen */
+ noecho(); /* Don't echo */
+ wattrset(stdscr, 0); /* Clear attributes */
+ scrollok(stdscr, TRUE); /* Like a scrolling Stone... */
+ leaveok(stdscr, TRUE); /* Cursor position doesn't really matter */
+ idlok(stdscr, TRUE); /* Use hardware ins/del of the terminal */
+ nodelay(stdscr, TRUE); /* Make getch() nonblocking */
+
+ /* Pick colors for each type */
+ init_pair(T_PORT, COLOR_GREEN, COLOR_BLACK);
+ init_pair(T_DATA, COLOR_WHITE, COLOR_BLACK);
+ init_pair(T_ERROR, COLOR_RED, COLOR_BLACK);
+ init_pair(T_PROTOCOL, COLOR_CYAN, COLOR_BLACK);
+ init_pair(T_AXHDR, COLOR_WHITE, COLOR_BLACK);
+ init_pair(T_IPHDR, COLOR_WHITE, COLOR_BLACK);
+ init_pair(T_ADDR, COLOR_GREEN, COLOR_BLACK);
+ init_pair(T_ROSEHDR, COLOR_WHITE, COLOR_BLACK);
+ init_pair(T_TIMESTAMP, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(T_KISS, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(T_BPQ, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(T_TCPHDR, COLOR_BLUE, COLOR_BLACK);
+
+ return 1;
+}
+
+char *servname(int port, char *proto)
+{
+ struct servent *serv;
+ static char str[16];
+
+ if ((serv = getservbyport(htons(port), proto)))
+ strncpy(str, serv->s_name, 16);
+ else
+ snprintf(str, 16, "%i", port);
+
+ return str;
+}