aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS11
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.in97
-rw-r--r--VERSION1
-rw-r--r--config.h.in2
-rw-r--r--configure.in4
-rw-r--r--doc/ethereal.pod29
-rw-r--r--ethereal.144
-rw-r--r--packet-llc.c5
-rw-r--r--packet-osi.c1617
-rw-r--r--packet.h7
11 files changed, 1749 insertions, 69 deletions
diff --git a/AUTHORS b/AUTHORS
index d2f4f82996..15a3e9059a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,13 +22,22 @@ Mike Hall <mlh@io.com>{
}
Bobo Rajec <bobo@bsp-consulting.sk> {
- /* add your info here */
+ DNS protocol support
}
Laurent Deniel <deniel@worldnet.fr> {
+ http://www.worldnet.fr/~deniel
+
+ Name resolution
+ ISO/OSI CLNP/COTP support
+ Miscellaneous enhancements and fixes
+}
+
+Don Lafontaine <lafont02@cn.ca> {
/* add your info here */
}
+
Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to
give his permission to use his version of snprintf.c.
diff --git a/Makefile.am b/Makefile.am
index 2c148261ab..67761fd9f0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,6 +20,7 @@ ethereal_SOURCES = \
packet-ip.c \
packet-ipv6.c \
packet-ipx.c \
+ packet-osi.c \
packet-ospf.c \
packet-ppp.c \
packet-raw.c \
diff --git a/Makefile.in b/Makefile.in
index 9881ae67d1..e1139a4f27 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -89,6 +89,7 @@ ethereal_SOURCES = \
packet-ip.c \
packet-ipv6.c \
packet-ipx.c \
+ packet-osi.c \
packet-ospf.c \
packet-ppp.c \
packet-raw.c \
@@ -144,9 +145,9 @@ LIBS = @LIBS@
ethereal_OBJECTS = capture.o ethereal.o ethertype.o file.o filter.o \
menu.o packet.o packet-arp.o packet-bootp.o packet-data.o packet-dns.o \
packet-eth.o packet-llc.o packet-lpd.o packet-ip.o packet-ipv6.o \
-packet-ipx.o packet-ospf.o packet-ppp.o packet-raw.o packet-rip.o \
-packet-tcp.o packet-tr.o packet-trmac.o packet-udp.o print.o ps.o \
-resolv.o util.o
+packet-ipx.o packet-osi.o packet-ospf.o packet-ppp.o packet-raw.o \
+packet-rip.o packet-tcp.o packet-tr.o packet-trmac.o packet-udp.o \
+print.o ps.o resolv.o util.o
ethereal_LDADD = $(LDADD)
ethereal_LDFLAGS =
CFLAGS = @CFLAGS@
@@ -165,6 +166,15 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
+DEP_FILES = .deps/capture.P .deps/ethereal.P .deps/ethertype.P \
+.deps/file.P .deps/filter.P .deps/menu.P .deps/packet-arp.P \
+.deps/packet-bootp.P .deps/packet-data.P .deps/packet-dns.P \
+.deps/packet-eth.P .deps/packet-ip.P .deps/packet-ipv6.P \
+.deps/packet-ipx.P .deps/packet-llc.P .deps/packet-lpd.P \
+.deps/packet-osi.P .deps/packet-ospf.P .deps/packet-ppp.P \
+.deps/packet-raw.P .deps/packet-rip.P .deps/packet-tcp.P \
+.deps/packet-tr.P .deps/packet-trmac.P .deps/packet-udp.P \
+.deps/packet.P .deps/print.P .deps/ps.P .deps/resolv.P .deps/util.P
SOURCES = $(ethereal_SOURCES) $(EXTRA_ethereal_SOURCES)
OBJECTS = $(ethereal_OBJECTS)
@@ -173,9 +183,9 @@ all: Makefile $(PROGRAMS) $(MANS) config.h
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
@@ -233,9 +243,6 @@ uninstall-binPROGRAMS:
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
done
-.c.o:
- $(COMPILE) -c $<
-
.s.o:
$(COMPILE) -c $<
@@ -356,6 +363,11 @@ distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu Makefile
$(mkinstalldirs) $(distdir)/doc $(distdir)/image
@for file in $(DISTFILES); do \
d=$(srcdir); \
@@ -363,41 +375,30 @@ distdir: $(DISTFILES)
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
-capture.o: capture.c config.h packet.h file.h capture.h etypes.h util.h \
- image/icon-excl.xpm
-ethereal.o: ethereal.c config.h packet.h file.h ethereal.h menu.h \
- etypes.h print.h resolv.h
-ethertype.o: ethertype.c config.h packet.h ethereal.h etypes.h
-file.o: file.c config.h packet.h file.h ethereal.h util.h \
- image/icon-excl.xpm
-filter.o: filter.c config.h filter.h packet.h file.h menu.h
-menu.o: menu.c config.h menu.h ethereal.h capture.h filter.h packet.h \
- print.h
-packet-arp.o: packet-arp.c config.h ethereal.h packet.h etypes.h
-packet-bootp.o: packet-bootp.c config.h packet.h ethereal.h etypes.h
-packet-data.o: packet-data.c config.h ethereal.h packet.h
-packet-dns.o: packet-dns.c config.h packet.h
-packet-eth.o: packet-eth.c config.h packet.h ethereal.h etypes.h
-packet-ip.o: packet-ip.c config.h ethereal.h packet.h etypes.h resolv.h
-packet-ipv6.o: packet-ipv6.c config.h ethereal.h packet.h packet-ipv6.h \
- etypes.h
-packet-ipx.o: packet-ipx.c config.h ethereal.h packet.h
-packet-llc.o: packet-llc.c config.h packet.h ethereal.h etypes.h
-packet-lpd.o: packet-lpd.c config.h packet.h ethereal.h etypes.h
-packet-ospf.o: packet-ospf.c config.h ethereal.h packet.h packet-ospf.h
-packet-ppp.o: packet-ppp.c config.h packet.h ethereal.h
-packet-raw.o: packet-raw.c config.h packet.h ethereal.h
-packet-rip.o: packet-rip.c config.h ethereal.h packet.h packet-rip.h
-packet-tcp.o: packet-tcp.c config.h ethereal.h packet.h
-packet-tr.o: packet-tr.c config.h packet.h ethereal.h etypes.h
-packet-trmac.o: packet-trmac.c config.h packet.h ethereal.h etypes.h
-packet-udp.o: packet-udp.c config.h ethereal.h packet.h resolv.h
-packet.o: packet.c config.h packet.h ethereal.h etypes.h file.h
-print.o: print.c config.h packet.h print.h
-ps.o: ps.c ps.h
-resolv.o: resolv.c config.h packet.h resolv.h
-util.o: util.c config.h util.h image/icon-excl.xpm
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+
+maintainer-clean-depend:
+ -rm -rf .deps
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).P -c $<
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).p -c $<
+ @-sed -e 's/^\([^:]*\)\.o:/\1.lo \1.o:/' \
+ < .deps/$(*F).p > .deps/$(*F).P
+ @-rm -f .deps/$(*F).p
info:
dvi:
check: all
@@ -435,19 +436,20 @@ maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-hdr mostlyclean-binPROGRAMS \
- mostlyclean-compile mostlyclean-tags \
+ mostlyclean-compile mostlyclean-tags mostlyclean-depend \
mostlyclean-generic
clean: clean-hdr clean-binPROGRAMS clean-compile clean-tags \
- clean-generic mostlyclean
+ clean-depend clean-generic mostlyclean
distclean: distclean-hdr distclean-binPROGRAMS distclean-compile \
- distclean-tags distclean-generic clean
+ distclean-tags distclean-depend distclean-generic clean
-rm -f config.status
maintainer-clean: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
- maintainer-clean-generic distclean
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
-rm -f config.status
@@ -458,7 +460,8 @@ maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile install-man1 uninstall-man1 install-man \
uninstall-man tags mostlyclean-tags distclean-tags clean-tags \
-maintainer-clean-tags distdir info dvi installcheck install-exec \
+maintainer-clean-tags distdir mostlyclean-depend distclean-depend \
+clean-depend maintainer-clean-depend info dvi installcheck install-exec \
install-data install uninstall all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000000..ec96a6218d
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.3.16
diff --git a/config.h.in b/config.h.in
index 228e988bb2..67cd0c40ae 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,7 +1,5 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
-/* $Id: config.h.in,v 1.2 1998/09/16 03:21:53 gerald Exp $ */
-
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
diff --git a/configure.in b/configure.in
index b4994af886..b881a69958 100644
--- a/configure.in
+++ b/configure.in
@@ -1,8 +1,8 @@
-# $Id: configure.in,v 1.2 1998/09/16 03:21:53 gerald Exp $
+# $Id: configure.in,v 1.3 1998/09/17 02:01:46 gerald Exp $
dnl Process this file with autoconf to produce a configure script.
AC_INIT(etypes.h)
-AM_INIT_AUTOMAKE(ethereal, 0.3.15)
+AM_INIT_AUTOMAKE(ethereal, 0.3.16)
dnl Checks for programs.
AC_PROG_CC
diff --git a/doc/ethereal.pod b/doc/ethereal.pod
index f987e7103a..61cab06ac9 100644
--- a/doc/ethereal.pod
+++ b/doc/ethereal.pod
@@ -6,14 +6,18 @@ Ethereal - Interactively browse network traffic
=head1 SYNOPSYS
B<ethereal>
-S<[ B<-v> ]>
S<[ B<-B> byte view height ]>
+S<[ B<-b> bold font ]>
S<[ B<-c> count ]>
+S<[ B<-h> ]>
S<[ B<-i> interface ]>
+S<[ B<-m> font ]>
+S<[ B<-n> ]>
S<[ B<-P> packet list height ]>
S<[ B<-r> infile ]>
S<[ B<-s> snaplen ]>
S<[ B<-T> tree view height ]>
+S<[ B<-v> ]>
S<[ B<-w> savefile]>
=head1 DESCRIPTION
@@ -30,15 +34,32 @@ you interactively browse packet data from a live network or from a B<pcap>
Sets the initial height of the byte view (bottom) pane
+=item -b
+
+The bold font name used for packet fied display.
+
=item -c
The default number of packets to read when capturing live data.
+=item -h
+
+Prints the version and options and exits.
+
=item -i
The name of the interface to use for live packet capture. It should match
one of the names listed in "B<netstat -i>" or "B<ifconfig -a>".
+=item -m
+
+The font name used by B<Ethereal>.
+
+=item -n
+
+Disable network object name resolution (such as hostname, TCP and UDP port
+names).
+
=item -P
Sets the initial height of the packet list (top) pane
@@ -223,10 +244,12 @@ B<http://ethereal.zing.org>.
Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>
Hannes R. Boehm <hannes@boehm.org>
Mike Hall <mlh@io.com>
- cpg <cpg@rocketmail.com>
+ Bobo Rajec <bobo@bsp-consulting.sk>
+ Laurent Deniel <deniel@worldnet.fr>
+ Don Lafontaine <lafont02@cn.ca>
-Theo de Raadt <deraadt@cvs.openbsd.org> was kind enough to give his
+Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his
permission to use his version of snprintf.c.
Dan Lasley <dlasley@promus.com> gave permission for his dumpit() hex-dump
diff --git a/ethereal.1 b/ethereal.1
index 9381c89c5b..bfa4d13387 100644
--- a/ethereal.1
+++ b/ethereal.1
@@ -1,12 +1,11 @@
.rn '' }`
-''' $RCSfile: ethereal.1,v $$Revision: 1.1 $$Date: 1998/09/16 02:39:18 $
+''' $RCSfile: ethereal.1,v $$Revision: 1.2 $$Date: 1998/09/17 02:01:47 $
'''
''' $Log: ethereal.1,v $
-''' Revision 1.1 1998/09/16 02:39:18 gerald
-''' Initial revision
-'''
-''' Revision 1.1.1.1 1998/08/30 17:53:24 gerald
-''' Imported sources
+''' Revision 1.2 1998/09/17 02:01:47 gerald
+''' * Added in Laurent's OSI/ISO CNLP and COTP support.
+''' * Added Laurent's changes to the man (actually pod) page.
+''' * Copied in VERSION file so that others can make doc/Makefile
'''
'''
.de Sh
@@ -99,7 +98,7 @@
.nr % 0
.rr F
.\}
-.TH ETHEREAL 1 "0.3.8" "24/Aug/98" "The Ethereal Network Analyzer"
+.TH ETHEREAL 1 "0.3.16" "16/Sep/98" "The Ethereal Network Analyzer"
.UC
.if n .hy 0
.if n .na
@@ -197,14 +196,18 @@
Ethereal \- Interactively browse network traffic
.SH "SYNOPSYS"
\fBethereal\fR
-[\ \fB\-v\fR\ ]
[\ \fB\-B\fR\ byte\ view\ height\ ]
+[\ \fB\-b\fR\ bold\ font\ ]
[\ \fB\-c\fR\ count\ ]
+[\ \fB\-h\fR\ ]
[\ \fB\-i\fR\ interface\ ]
+[\ \fB\-m\fR\ font\ ]
+[\ \fB\-n\fR\ ]
[\ \fB\-P\fR\ packet\ list\ height\ ]
[\ \fB\-r\fR\ infile\ ]
[\ \fB\-s\fR\ snaplen\ ]
[\ \fB\-T\fR\ tree\ view\ height\ ]
+[\ \fB\-v\fR\ ]
[\ \fB\-w\fR\ savefile]
.SH "DESCRIPTION"
\fBEthereal\fR is a network protocol analyzer based on the \fBGTK+\fR GUI toolkit. It lets
@@ -213,11 +216,20 @@ you interactively browse packet data from a live network or from a \fBpcap\fR
.SH "OPTIONS"
.Ip "-B" 4
Sets the initial height of the byte view (bottom) pane
+.Ip "-b" 4
+The bold font name used for packet fied display.
.Ip "-c" 4
The default number of packets to read when capturing live data.
+.Ip "-h" 4
+Prints the version and options and exits.
.Ip "-i" 4
The name of the interface to use for live packet capture. It should match
one of the names listed in \*(L"\fBnetstat \-i\fR\*(R" or \*(L"\fBifconfig \-a\fR\*(R".
+.Ip "-m" 4
+The font name used by \fBEthereal\fR.
+.Ip "-n" 4
+Disable network object name resolution (such as hostname, \s-1TCP\s0 and \s-1UDP\s0 port
+names).
.Ip "-P" 4
Sets the initial height of the packet list (top) pane
.Ip "-r" 4
@@ -335,15 +347,17 @@ The latest version of \fBethereal\fR can be found at
\& -------- ------
\& Gerald Combs <gerald@zing.org>
.Ve
-.Vb 6
+.Vb 8
\& Contributors
\& ------------
\& Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>
\& Hannes R. Boehm <hannes@boehm.org>
\& Mike Hall <mlh@io.com>
-\& cpg <cpg@rocketmail.com>
+\& Bobo Rajec <bobo@bsp-consulting.sk>
+\& Laurent Deniel <deniel@worldnet.fr>
+\& Don Lafontaine <lafont02@cn.ca>
.Ve
-Theo de Raadt <deraadt@cvs.openbsd.org> was kind enough to give his
+Alain Magloire <alainm@rcsm.ece.mcgill.ca> was kind enough to give his
permission to use his version of snprintf.c.
.Sp
Dan Lasley <dlasley@promus.com> gave permission for his \fIdumpit()\fR hex-dump
@@ -363,10 +377,18 @@ routine to be used.
.IX Item "-B"
+.IX Item "-b"
+
.IX Item "-c"
+.IX Item "-h"
+
.IX Item "-i"
+.IX Item "-m"
+
+.IX Item "-n"
+
.IX Item "-P"
.IX Item "-r"
diff --git a/packet-llc.c b/packet-llc.c
index beaff6a018..c5a7cff859 100644
--- a/packet-llc.c
+++ b/packet-llc.c
@@ -2,7 +2,7 @@
* Routines for IEEE 802.2 LLC layer
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
*
- * $Id: packet-llc.c,v 1.2 1998/09/16 03:22:06 gerald Exp $
+ * $Id: packet-llc.c,v 1.3 1998/09/17 02:01:47 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@@ -157,6 +157,9 @@ dissect_llc(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
case 0xe0: /* NetWare (IPX) */
dissect_ipx(pd, offset, fd, tree);
break;
+ case 0xfe: /* ISO Network Layer */
+ dissect_osi(pd, offset, fd, tree);
+ break;
default:
dissect_data(pd, offset, fd, tree);
break;
diff --git a/packet-osi.c b/packet-osi.c
new file mode 100644
index 0000000000..3d75769630
--- /dev/null
+++ b/packet-osi.c
@@ -0,0 +1,1617 @@
+/* packet-osi.c
+ * Routines for ISO/OSI network and transport protocol packet disassembly
+ *
+ * $Id: packet-osi.c,v 1.1 1998/09/17 02:01:48 gerald Exp $
+ * Laurent Deniel <deniel@worldnet.fr>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * To do:
+ *
+ * - add other network protocols (ES,IS-IS)
+ * - add NSAP decoding & resolution
+ * - complete CLNP decoding (options)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <pcap.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include "ethereal.h"
+#include "packet.h"
+
+/* Network layer protocol identifiers */
+
+#define ISO8473_CLNP 0x81
+#define ISO9542_ESIS 0x82
+#define ISO10589_ISIS 0x83
+#define ISO9542X25_ESIS 0x8a
+
+/*
+ * ISO8473 OSI CLNP definition (see RFC994)
+ *
+ * _________________________________
+ * | Fixed Part |
+ * |_________________________________|
+ * | Address Part |
+ * |_________________________________|
+ * | Segmentation Part (optional) |
+ * |_________________________________|
+ * | Options Part (optional) |
+ * |_________________________________|
+ * | Data (optional) |
+ * |_________________________________|
+ */
+
+#define ISO8473_V1 0x01 /* CLNP version 1 */
+
+/* Fixed part */
+
+struct clnp_header {
+ u_char cnf_proto_id; /* network layer protocol identifier */
+ u_char cnf_hdr_len; /* length indicator (octets) */
+ u_char cnf_vers; /* version/protocol identifier extension */
+ u_char cnf_ttl; /* lifetime (500 milliseconds) */
+ u_char cnf_type; /* type code */
+ u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
+ u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
+ u_char cnf_cksum_msb; /* checksum high byte */
+ u_char cnf_cksum_lsb; /* checksum low byte */
+};
+
+#define CNF_TYPE 0x1f
+#define CNF_ERR_OK 0x20
+#define CNF_MORE_SEGS 0x40
+#define CNF_SEG_OK 0x80
+
+#define ER_NPDU 0x01
+#define DT_NPDU 0x1C
+
+/* field position */
+
+#define P_ADDRESS_PART 9
+
+/* Segmentation part */
+
+struct clnp_segment {
+ u_short cng_id; /* data unit identifier */
+ u_short cng_off; /* segment offset */
+ u_short cng_tot_len; /* total length */
+};
+
+/* NSAP selector */
+
+#define NSEL_NET 0x00
+#define NSEL_NP 0x20
+#define NSEL_TP 0x21
+
+/*
+ * ISO8073 OSI COTP definition (see RFC905)
+ */
+
+/* don't use specific TPDU types to avoid alignment problems & copy overhead */
+
+/* TPDU definition */
+
+#define ED_TPDU 0x1
+#define EA_TPDU 0x2
+#define RJ_TPDU 0x5
+#define AK_TPDU 0x6
+#define ER_TPDU 0x7
+#define DR_TPDU 0x8
+#define DC_TPDU 0xC
+#define CC_TPDU 0xD
+#define CR_TPDU 0xE
+#define DT_TPDU 0xF
+
+/* field position */
+
+#define P_LI 0
+#define P_TPDU 1
+#define P_CDT 1
+#define P_DST_REF 2
+#define P_SRC_REF 4
+#define P_TPDU_NR_0_1 2
+#define P_TPDU_NR_234 4
+#define P_VAR_PART_NDT 5
+#define P_VAR_PART_EDT 8
+#define P_VAR_PART_NAK 5
+#define P_VAR_PART_CC 7
+#define P_VAR_PART_EAK 10
+#define P_VAR_PART_DC 6
+#define P_VAR_PART_DR 7
+#define P_CDT_IN_AK 8
+#define P_CDT_IN_RJ 8
+#define P_REJECT_ER 4
+#define P_REASON_IN_DR 6
+#define P_CLASS_OPTION 6
+
+/* TPDU length indicator */
+
+#define LI_NORMAL_DT_CLASS_01 2
+#define LI_NORMAL_DT_WITH_CHECKSUM 8
+#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_DT_WITH_CHECKSUM 11
+#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_EA_WITH_CHECKSUM 8
+#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_EA_WITH_CHECKSUM 11
+#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_RJ 4
+#define LI_EXTENDED_RJ 9
+#define LI_MIN_DR 6
+#define LI_MAX_DC 9
+#define LI_MAX_AK 27
+#define LI_MAX_EA 11
+#define LI_MAX_ER 8
+#define LI_DC_WITH_CHECKSUM 9
+#define LI_DC_WITHOUT_CHECKSUM 5
+#define is_LI_NORMAL_AK(p) ( p & 0x01 )
+
+/* variant part */
+
+#define VP_ACK_TIME 0x85
+#define VP_RES_ERROR 0x86
+#define VP_PRIORITY 0x87
+#define VP_TRANSIT_DEL 0x88
+#define VP_THROUGHPUT 0x89
+#define VP_SEQ_NR 0x8A /* in AK */
+#define VP_REASSIGNMENT 0x8B
+#define VP_FLOW_CNTL 0x8C /* in AK */
+#define VP_TPDU_SIZE 0xC0
+#define VP_SRC_TSAP 0xC1 /* in CR/CC */
+#define VP_DST_TSAP 0xC2
+#define VP_CHECKSUM 0xC3
+#define VP_VERSION_NR 0xC4
+#define VP_PROTECTION 0xC5
+#define VP_OPT_SEL 0xC6
+#define VP_PROTO_CLASS 0xC7
+
+/* misc */
+
+#define EXTRACT_SHORT(p) pntohs(p)
+#define EXTRACT_LONG(p) pntohl(p)
+
+/* global variables */
+
+static u_char li, tpdu, cdt; /* common fields */
+static u_short dst_ref;
+
+/* function definitions */
+
+static int osi_decode_DR(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_short src_ref;
+ u_char reason;
+ char *str;
+
+ if (li < LI_MIN_DR)
+ return -1;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+ reason = pd[offset + P_REASON_IN_DR];
+
+ switch(reason) {
+ case (128+0): str = "Normal Disconnect"; break;
+ case (128+1): str = "Remote transport enity congestion"; break;
+ case (128+2): str = "Connection negotiation failed"; break;
+ case (128+3): str = "Duplicate source reference"; break;
+ case (128+4): str = "Mismatched references"; break;
+ case (128+5): str = "Protocol error"; break;
+ case (128+7): str = "Reference overflow"; break;
+ case (128+8): str = "Connection requestion refused"; break;
+ case (128+10):str = "Header or parameter length invalid"; break;
+ case (0): str = "Reason not specified"; break;
+ case (1): str = "Congestion at TSAP"; break;
+ case (2): str = "Session entity not attached to TSAP"; break;
+ case (3): str = "Address unknown"; break;
+ default: return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x %s",
+ src_ref, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (DR)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ add_item_to_tree(cotp_tree, offset + 6, 1,
+ "Cause: %s", str);
+ }
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_DR */
+
+static int osi_decode_DT(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_int tpdu_nr ;
+ u_short checksum;
+ u_char code, length;
+ u_int fragment = 0;
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ code = pd[offset + P_VAR_PART_NDT];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ fragment = 1;
+ code = pd[offset + P_VAR_PART_EDT];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ fragment = 1;
+ break;
+ case LI_NORMAL_DT_CLASS_01 :
+ tpdu_nr = pd[offset + P_TPDU_NR_0_1];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "DT TPDU (%d) dst-ref: 0x%04x %s",
+ tpdu_nr,
+ dst_ref,
+ (fragment)? "(fragment)" : "");
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (DT)", tpdu);
+
+ if (li != LI_NORMAL_DT_CLASS_01)
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%08x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%08x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ case LI_NORMAL_DT_CLASS_01 :
+ add_item_to_tree(cotp_tree, offset + 2, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ break;
+ }
+ } /* tree */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_DT */
+
+static int osi_decode_ED(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_int tpdu_nr ;
+ u_short checksum;
+ u_char code, length;
+
+ /* ED TPDUs are never fragmented */
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ return -1;
+ code = pd[offset + P_VAR_PART_NDT];
+ length = pd[offset + P_VAR_PART_NDT + 1];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ return -1;
+ code = pd[offset + P_VAR_PART_EDT];
+ length = pd[offset + P_VAR_PART_EDT + 1];
+ if (code == VP_CHECKSUM)
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ else
+ return -1;
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ return -1;
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "ED TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (ED)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x", tpdu_nr);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "TPDU number: 0x%02x", tpdu_nr);
+ break;
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%02x", tpdu_nr);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EDT + 2, length,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "TPDU number: 0x%02x", tpdu_nr);
+ break;
+ }
+ } /* tree */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_ED */
+
+static int osi_decode_RJ(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_int tpdu_nr ;
+ u_short credit;
+
+ switch(li) {
+ case LI_NORMAL_RJ :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ break;
+ case LI_EXTENDED_RJ :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
+ break;
+ default :
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "RJ TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (RJ)", tpdu);
+ if (li == LI_NORMAL_RJ)
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "Credit: %d", cdt);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ if (li == LI_NORMAL_RJ)
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ else {
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ add_item_to_tree(cotp_tree, offset + 8, 2,
+ "Credit: 0x%02x", credit);
+ }
+ }
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_RJ */
+
+#define MAX_TSAP_LEN 32
+
+static gchar *print_tsap(const u_char *tsap, int length)
+{
+
+ static gchar str[3][MAX_TSAP_LEN * 2 + 1];
+ static gchar *cur;
+ gchar tmp[3];
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ /* to do: test if all bytes are printable */
+
+ cur[0] = '\0';
+ if (length <= 0 || length > MAX_TSAP_LEN)
+ sprintf(cur, "<unsupported TSAP length>");
+ else {
+ while (length != 0) {
+ sprintf(tmp, "%02x", *tsap ++);
+ strcat(cur, tmp);
+ length --;
+ }
+ }
+ return cur;
+
+} /* print_tsap */
+
+static int osi_decode_CC(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+
+ /* CC & CR decoding in the same function */
+
+ GtkWidget *cotp_tree, *ti;
+ u_short src_ref, checksum;
+ u_char class_option, code, length;
+ u_int i = 0;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+ class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
+ if (class_option > 4)
+ return -1;
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ (tpdu == CR_TPDU) ? "CR" : "CC",
+ src_ref,
+ dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (%s)", tpdu,
+ (tpdu == CR_TPDU) ? "CR" : "CC");
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ add_item_to_tree(cotp_tree, offset + 6, 1,
+ "Class option: 0x%02x", class_option);
+ }
+
+ if (tree)
+ while(li > P_VAR_PART_CC + i - 1) {
+
+ u_char c1,c2;
+ u_short s, s1,s2,s3,s4;
+ u_int t1,t2,t3,t4;
+
+ switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Checksum: 0x%04x", checksum);
+ i += length + 2;
+ break;
+ case VP_SRC_TSAP :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (src-tsap)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Calling TSAP: 0x%s",
+ print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
+ length));
+ i += length + 2;
+ break;
+ case VP_DST_TSAP :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (dst-tsap)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Called TSAP: 0x%s",
+ print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
+ length));
+ i += length + 2;
+ break;
+ case VP_TPDU_SIZE :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (tpdu-size)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "TPDU size: %d", 2 << c1);
+ i += length + 2;
+ break;
+ case VP_OPT_SEL :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (options)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ if (class_option == 1) {
+ if (c1 & 0x8)
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of network expedited data");
+ else
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non use of network expedited data");
+ if (c1 & 0x4)
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of Receipt confirmation");
+ else
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of explicit AK variant");
+ } else if (class_option == 4) {
+ if (c1 & 0x2)
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use 16 bit checksum ");
+ else
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non-use 16 bit checksum in class 4");
+ }
+ if (c1 & 0x1)
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Use of transport expedited data transfer\n");
+ else
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 1,
+ "Non-use of transport expedited data transfer");
+ i += length + 2;
+ break;
+ case VP_ACK_TIME :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (ack time)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Ack time (ms): %d", s);
+ i += length + 2;
+ break;
+ case VP_THROUGHPUT :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
+ t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
+ t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
+ t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (throughput)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 4,
+ "Target value / calling-called: %d o/s", t1);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 6, 4,
+ "Minimum / calling-called: %d o/s", t2);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 10, 4,
+ "Target value / called-calling: %d o/s", t3);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 14, 4,
+ "Minimum / called-calling: %d o/s", t4);
+ i += length + 2;
+ break;
+ case VP_TRANSIT_DEL :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
+ s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
+ s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (transit delay)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, 2,
+ "Target value / calling-called: %d ms", s1);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 4, 2,
+ "Minimum / calling-called: %d ms", s2);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 6, 2,
+ "Target value / called-calling: %d ms", s3);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 8, 2,
+ "Minimum / called-calling: %d ms", s4);
+ i += length + 2;
+ break;
+ case VP_PRIORITY :
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i, 1,
+ "Parameter code: 0x%02x (priority)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Priority: %d", s);
+ i += length + 2;
+ break;
+
+ case VP_REASSIGNMENT: /* todo */
+ case VP_RES_ERROR :
+ case VP_VERSION_NR :
+ case VP_PROTECTION :
+ case VP_PROTO_CLASS :
+ default : /* no decoding */
+ length = pd[offset + P_VAR_PART_CC + i + 1];
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 0, 1,
+ "Parameter code: 0x%02x", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_CC + i + 2, length,
+ "Parameter value: <not shown>");
+ i += length + 2;
+ break;
+ }
+ } /* while */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_CC */
+
+static int osi_decode_DC(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_short src_ref, checksum;
+ u_char length, code = 0;
+
+ if (li > LI_MAX_DC)
+ return -1;
+
+ src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
+
+ switch(li) {
+ case LI_DC_WITHOUT_CHECKSUM :
+ break;
+ case LI_DC_WITH_CHECKSUM :
+ if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
+ return -1;
+ length = pd[offset + P_VAR_PART_DC + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
+ break;
+ default :
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ src_ref,
+ dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (DC)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 2,
+ "Source reference: 0x%04x", src_ref);
+ if (code) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_DC + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_DC + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_DC + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ }
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_DC */
+
+static int osi_decode_AK(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_int tpdu_nr,i =0, r_lower_window_edge ;
+ u_short cdt_in_ak;
+ u_short checksum, seq_nr, r_seq_nr, r_cdt;
+ u_char code, length;
+
+ if (li > LI_MAX_AK)
+ return -1;
+
+ if (!is_LI_NORMAL_AK(li)) {
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "AK TPDU (%d) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (AK)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "Credit: %d", cdt);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ }
+
+ while(li > P_VAR_PART_NAK + i - 1) {
+ switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ i += length + 2;
+ break;
+ case VP_FLOW_CNTL :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ r_lower_window_edge =
+ EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
+ r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (flow control)",
+ code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 4,
+ "Lower window edge: 0x%08x",
+ r_lower_window_edge);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 6, 2,
+ "Sequence number: 0x%04x",
+ r_seq_nr);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 8, 2,
+ "Credit: 0x%04x",
+ r_cdt);
+ }
+ i += length + 2;
+ break;
+ case VP_SEQ_NR :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (seq number)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, 2,
+ "Sequence number: 0x%04x", seq_nr);
+ }
+ i += length + 2;
+ break;
+ default :
+ length = pd[offset + P_VAR_PART_NAK + i + 1];
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 0, 1,
+ "Parameter code: 0x%02x (unknown)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_NAK + i + 2, length,
+ "Parameter value: <not shown>");
+ }
+ i += length + 2;
+ break;
+ } /* code */
+ }
+ } else { /* extended format */
+
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "AK TPDU (%d) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (AK)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ add_item_to_tree(cotp_tree, offset + 8, 2,
+ "Credit: 0x%04x", cdt_in_ak);
+ }
+
+ while(li > P_VAR_PART_EAK + i - 1) {
+ switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
+ case VP_CHECKSUM :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 2,
+ "Checksum: 0x%04x", checksum);
+ }
+ i += length + 2;
+ break;
+ case VP_FLOW_CNTL :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ r_lower_window_edge =
+ EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
+ r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (flow control)",
+ code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 4,
+ "Lower window edge: 0x%08x",
+ r_lower_window_edge);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 6, 2,
+ "Sequence number: 0x%04x",
+ r_seq_nr);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 8, 2,
+ "Credit: 0x%04x",
+ r_cdt);
+ }
+ i += length + 2;
+ break;
+ case VP_SEQ_NR :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (seq number)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, 2,
+ "Sequence number: 0x%04x", seq_nr);
+ }
+ i += length + 2;
+ break;
+ default :
+ length = pd[offset + P_VAR_PART_EAK + i + 1];
+ if (tree) {
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 0, 1,
+ "Parameter code: 0x%02x (unknown)", code);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 1, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree,
+ offset + P_VAR_PART_EAK + i + 2, length,
+ "Parameter value: <not shown>");
+ }
+ i += length + 2;
+ break;
+ } /* code */
+ }
+
+ } /* is_LI_NORMAL_AK */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_AK */
+
+static int osi_decode_EA(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_int tpdu_nr ;
+ u_short checksum;
+ u_char code;
+ u_char length;
+
+ if (li > LI_MAX_EA)
+ return -1;
+
+ switch (li) {
+ case LI_NORMAL_EA_WITH_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ code = pd[offset + P_VAR_PART_NDT];
+ length = pd[offset + P_VAR_PART_NDT + 1];
+ if (code != VP_CHECKSUM || length != 1)
+ return -1;
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
+ break;
+ case LI_NORMAL_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = pd[offset + P_TPDU_NR_234];
+ break;
+ case LI_EXTENDED_EA_WITH_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ code = pd[offset + P_VAR_PART_EDT];
+ length = pd[offset + P_VAR_PART_EDT + 1];
+ if (code != VP_CHECKSUM || length != 1)
+ return -1;
+ checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
+ break;
+ case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
+ break;
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (EA)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+
+ switch (li) {
+ case LI_NORMAL_EA_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ add_item_to_tree(cotp_tree, offset + 5, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree, offset + 6, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree, offset + 7, 2,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_NORMAL_EA_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ break;
+ case LI_EXTENDED_EA_WITH_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ add_item_to_tree(cotp_tree, offset + 8, 1,
+ "Parameter code: 0x%02x (checksum)", code);
+ add_item_to_tree(cotp_tree, offset + 9, 1,
+ "Parameter length: 0x%02x", length);
+ add_item_to_tree(cotp_tree, offset + 10, 2,
+ "Checksum: 0x%04x", checksum);
+ break;
+ case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
+ add_item_to_tree(cotp_tree, offset + 4, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ break;
+ default :
+ break;
+ } /* li */
+ } /* tree */
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_EA */
+
+static int osi_decode_ER(const u_char *pd, int offset,
+ frame_data *fd, GtkTree *tree)
+{
+ GtkWidget *cotp_tree, *ti;
+ u_char *str;
+
+ if (li > LI_MAX_ER)
+ return -1;
+
+ switch(pd[offset + P_REJECT_ER]) {
+ case 0 :
+ str = "Reason not specified";
+ break;
+ case 1 :
+ str = "Invalid parameter code";
+ break;
+ case 2 :
+ str = "Invalid TPDU type";
+ break;
+ case 3 :
+ str = "Invalid parameter value";
+ break;
+ default:
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (fd->win_info[0]) {
+ strcpy(fd->win_info[3], "COTP");
+ sprintf(fd->win_info[4], "ER TPDU dst-ref: 0x%04x", dst_ref);
+ }
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
+ "ISO COTP");
+ cotp_tree = gtk_tree_new();
+ add_subtree(ti, cotp_tree, ETT_COTP);
+ add_item_to_tree(cotp_tree, offset, 1,
+ "Length indicator: %d", li);
+ add_item_to_tree(cotp_tree, offset + 1, 1,
+ "TPDU code: Ox%x (ER)", tpdu);
+ add_item_to_tree(cotp_tree, offset + 2, 2,
+ "Destination reference: 0x%04x", dst_ref);
+ add_item_to_tree(cotp_tree, offset + 4, 1,
+ "Reject cause: %s", str);
+ }
+
+ offset += li + 1;
+ dissect_data(pd, offset, fd, tree);
+
+ return 0;
+
+} /* osi_decode_ER */
+
+void dissect_cotp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
+{
+
+ int status = -1;
+
+ if (((li = pd[offset + P_LI]) == 0) ||
+ (offset + P_LI + li + 1 > fd->cap_len)) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
+ cdt = pd[offset + P_CDT] & 0x0F;
+ dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
+
+ switch (tpdu) {
+ case CC_TPDU :
+ case CR_TPDU :
+ status = osi_decode_CC(pd, offset, fd, tree);
+ break;
+ case DR_TPDU :
+ status = osi_decode_DR(pd, offset, fd, tree);
+ break;
+ case DT_TPDU :
+ status = osi_decode_DT(pd, offset, fd, tree);
+ break;
+ case ED_TPDU :
+ status = osi_decode_ED(pd, offset, fd, tree);
+ break;
+ case RJ_TPDU :
+ status = osi_decode_RJ(pd, offset, fd, tree);
+ break;
+ case DC_TPDU :
+ status = osi_decode_DC(pd, offset, fd, tree);
+ break;
+ case AK_TPDU :
+ status = osi_decode_AK(pd, offset, fd, tree);
+ break;
+ case EA_TPDU :
+ status = osi_decode_EA(pd, offset, fd, tree);
+ break;
+ case ER_TPDU :
+ status = osi_decode_ER(pd, offset, fd, tree);
+ break;
+ default :
+ break;
+ }
+
+ if (status == -1) /* incorrect TPDU */
+ dissect_data(pd, offset, fd, tree);
+
+} /* dissect_cotp */
+
+
+/*
+ * CLNP part
+ */
+
+#define MAX_NSAP_LEN 20
+
+static gchar *print_nsap(const u_char *nsap, int length)
+{
+
+ /* to do : real NSAP decoding */
+
+ static gchar str[3][MAX_NSAP_LEN * 3 + 1];
+ static gchar *cur;
+ gchar tmp[5];
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ cur[0] = '\0';
+ if (length <= 0 || length > MAX_NSAP_LEN)
+ sprintf(cur, "<invalid NSAP>");
+ else
+ while (length != 1) {
+ sprintf(tmp, "%02x:", *nsap ++);
+ strcat(cur, tmp);
+ length --;
+ }
+ sprintf(tmp, "%02x", *nsap);
+ strcat(cur, tmp);
+ return cur;
+
+} /* print_nsap */
+
+void dissect_clnp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
+{
+
+ struct clnp_header clnp;
+ GtkWidget *clnp_tree, *ti;
+ u_char src_len, dst_len, nsel;
+ u_int first_offset = offset;
+
+ if (fd->cap_len < offset + sizeof(clnp)) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* avoid alignment problem */
+ memcpy(&clnp, &pd[offset], sizeof(clnp));
+
+ /* return if version not known */
+ if (clnp.cnf_vers != ISO8473_V1) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* fixed part decoding */
+
+ if (tree) {
+ ti = add_item_to_tree(GTK_WIDGET(tree), offset, clnp.cnf_hdr_len,
+ "ISO CLNP");
+ clnp_tree = gtk_tree_new();
+ add_subtree(ti, clnp_tree, ETT_CLNP);
+ add_item_to_tree(clnp_tree, offset, 1,
+ "Protocol identifier: 0x%02x", clnp.cnf_proto_id);
+ add_item_to_tree(clnp_tree, offset + 1, 1,
+ "Length: %d", clnp.cnf_hdr_len);
+ add_item_to_tree(clnp_tree, offset + 2, 1,
+ "Version: %d", clnp.cnf_vers);
+ add_item_to_tree(clnp_tree, offset + 3, 1,
+ "TTL: %d (%d secs)",
+ clnp.cnf_ttl, clnp.cnf_ttl / 2);
+ add_item_to_tree(clnp_tree, offset + 4, 1,
+ "Type code: 0x%02x (%s%s%s%s)",
+ clnp.cnf_type,
+ (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
+ (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
+ (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
+ (clnp.cnf_type & CNF_TYPE) == DT_NPDU ? "DT" : "ER");
+ add_item_to_tree(clnp_tree, offset + 5, 2,
+ "PDU segment length: %d",
+ EXTRACT_SHORT(&clnp.cnf_seglen_msb));
+ add_item_to_tree(clnp_tree, offset + 7, 2,
+ "Checksum: 0x%04x",
+ EXTRACT_SHORT(&clnp.cnf_cksum_msb));
+ } /* tree */
+
+ /* stop here if header is not complete */
+
+ if (fd->cap_len < offset + clnp.cnf_hdr_len) {
+ dissect_data(pd, offset, fd, tree);
+ return;
+ }
+
+ /* address part */
+
+ offset += P_ADDRESS_PART;
+ dst_len = pd[offset];
+ nsel = pd[offset + dst_len];
+ src_len = pd[offset + dst_len + 1];
+
+ if (tree) {
+ add_item_to_tree(clnp_tree, offset, 1,
+ "Destination address length: 0x%02x", dst_len);
+ add_item_to_tree(clnp_tree, offset + 1 , dst_len,
+ "Destination address: %s",
+ print_nsap(&pd[offset + 1], dst_len));
+ add_item_to_tree(clnp_tree, offset + 1 + dst_len, 1,
+ "Source address length: 0x%02x", src_len);
+ add_item_to_tree(clnp_tree, offset + dst_len + 2, src_len,
+ "Source address: %s",
+ print_nsap(&pd[offset + dst_len + 2], src_len));
+ }
+
+ if (fd->win_info[0]) {
+ sprintf(fd->win_info[1], "%s",
+ print_nsap(&pd[offset + dst_len + 2], src_len));
+ sprintf(fd->win_info[2], "%s",
+ print_nsap(&pd[offset + 1], dst_len));
+ }
+
+ /* Segmentation Part */
+
+ offset += dst_len + src_len + 2;
+
+ if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
+ struct clnp_segment seg;
+ memcpy(&seg, &pd[offset], sizeof(seg));
+
+ add_item_to_tree(clnp_tree, offset, 2,
+ "Data unit identifier: 0x%04x",
+ EXTRACT_SHORT(&pd[offset]));
+ add_item_to_tree(clnp_tree, offset + 2 , 2,
+ "Segment offset: 0x%04x",
+ EXTRACT_SHORT(&pd[offset + 2]));
+ add_item_to_tree(clnp_tree, offset + 4 , 2,
+ "Total length: 0x%04x",
+ EXTRACT_SHORT(&pd[offset + 4]));
+
+ offset += 6;
+ }
+
+ if (tree) {
+ /* To do : decode options */
+
+ add_item_to_tree(clnp_tree, offset,
+ clnp.cnf_hdr_len + first_offset - offset,
+ "Options/Data: <not shown>");
+ }
+
+
+ offset = first_offset + clnp.cnf_hdr_len;
+
+ if (offset == fd->cap_len)
+ return;
+
+ /* continue with COTP if any */
+
+ if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
+ dissect_cotp(pd, offset, fd, tree);
+ else
+ dissect_data(pd, offset, fd, tree);
+
+} /* dissect_clnp */
+
+
+/* main entry point */
+
+void dissect_osi(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
+{
+
+ switch (pd[offset]) {
+
+ /* only CLNP is currently decoded */
+
+ case ISO8473_CLNP:
+ if (fd->win_info[0])
+ {
+ strcpy(fd->win_info[3], "CLNP");
+ }
+ dissect_clnp(pd, offset, fd, tree);
+ break;
+ case ISO9542_ESIS:
+ if (fd->win_info[0])
+ {
+ strcpy(fd->win_info[3], "ESIS");
+ }
+ dissect_data(pd, offset, fd, tree);
+ break;
+ case ISO9542X25_ESIS:
+ if (fd->win_info[0])
+ {
+ strcpy(fd->win_info[3], "ESIS(X25)");
+ }
+ dissect_data(pd, offset, fd, tree);
+ break;
+ case ISO10589_ISIS:
+ if (fd->win_info[0])
+ {
+ strcpy(fd->win_info[3], "ISIS");
+ }
+ dissect_data(pd, offset, fd, tree);
+ break;
+ default:
+ if (fd->win_info[0])
+ {
+ strcpy(fd->win_info[3], "ISO");
+ sprintf(fd->win_info[4], "Unknown ISO protocol (%02x)", pd[offset]);
+ }
+ dissect_data(pd, offset, fd, tree);
+ break;
+ }
+
+} /* dissect_osi */
+
diff --git a/packet.h b/packet.h
index 71b195e1a8..7e98bb5bea 100644
--- a/packet.h
+++ b/packet.h
@@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
- * $Id: packet.h,v 1.2 1998/09/16 03:22:14 gerald Exp $
+ * $Id: packet.h,v 1.3 1998/09/17 02:01:49 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -282,9 +282,11 @@ typedef struct _e_udphdr {
#define ETT_BOOTP 31
#define ETT_BOOTP_OPTION 32
#define ETT_IPv6 33
+#define ETT_CLNP 34
+#define ETT_COTP 35
/* Should be the last item number plus one */
-#define NUM_TREE_TYPES 34
+#define NUM_TREE_TYPES 36
/* The version of pcap.h that comes with some systems is missing these
* #defines.
@@ -342,6 +344,7 @@ void dissect_ipv6(const u_char *, int, frame_data *, GtkTree *);
void dissect_ipx(const u_char *, int, frame_data *, GtkTree *);
void dissect_llc(const u_char *, int, frame_data *, GtkTree *);
void dissect_lpd(const u_char *, int, frame_data *, GtkTree *);
+void dissect_osi(const u_char *, int, frame_data *, GtkTree *);
void dissect_ospf(const u_char *, int, frame_data *, GtkTree *);
void dissect_ospf_hello(const u_char *, int, frame_data *, GtkTree *);
void dissect_tcp(const u_char *, int, frame_data *, GtkTree *);