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/Makefile.am | 27 ++++ listen/Makefile.in | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++ listen/arpdump.c | 108 +++++++++++++++ listen/ax25dump.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ listen/flexnetdump.c | 149 ++++++++++++++++++++ listen/icmpdump.c | 196 ++++++++++++++++++++++++++ listen/ipdump.c | 116 ++++++++++++++++ listen/kissdump.c | 60 ++++++++ listen/listen.1 | 89 ++++++++++++ listen/listen.c | 293 +++++++++++++++++++++++++++++++++++++++ listen/listen.h | 65 +++++++++ listen/nrdump.c | 154 +++++++++++++++++++++ listen/ripdump.c | 174 +++++++++++++++++++++++ listen/rosedump.c | 215 +++++++++++++++++++++++++++++ listen/rspfdump.c | 53 +++++++ listen/tcpdump.c | 123 +++++++++++++++++ listen/udpdump.c | 44 ++++++ listen/utils.c | 121 ++++++++++++++++ 18 files changed, 2728 insertions(+) create mode 100644 listen/Makefile.am create mode 100644 listen/Makefile.in create mode 100644 listen/arpdump.c create mode 100644 listen/ax25dump.c create mode 100644 listen/flexnetdump.c create mode 100644 listen/icmpdump.c create mode 100644 listen/ipdump.c create mode 100644 listen/kissdump.c create mode 100644 listen/listen.1 create mode 100644 listen/listen.c create mode 100644 listen/listen.h create mode 100644 listen/nrdump.c create mode 100644 listen/ripdump.c create mode 100644 listen/rosedump.c create mode 100644 listen/rspfdump.c create mode 100644 listen/tcpdump.c create mode 100644 listen/udpdump.c create mode 100644 listen/utils.c (limited to 'listen') 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 +#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 +#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; + } + } +} 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 +#include +#include +#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 +#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 +#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 +#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 +.br +Jonathan Naylor G4KLX +.br +Phil Karn KA9Q +.br +Heikki Hannikainen OH7LZB +.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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#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 +#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 + +#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 +#include +#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 +#include +#include +#include +#include + +#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 +#include +#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 +#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 + * + * Portions and ideas (like the ibm character mapping) from + * Tomi Manninen OH2BNS + */ + +#include +#include +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3