diff options
author | Gerald Combs <gerald@wireshark.org> | 1998-09-17 02:01:50 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 1998-09-17 02:01:50 +0000 |
commit | 19176fbb4f84cce7cac6ebe5f453837bfafa76d0 (patch) | |
tree | 73736c49df55712dd300e40f52e754b5909915dd | |
parent | 576024f9038de43ca7d0e1fce34282d0e1ec37c5 (diff) | |
download | wireshark-19176fbb4f84cce7cac6ebe5f453837bfafa76d0.tar.gz wireshark-19176fbb4f84cce7cac6ebe5f453837bfafa76d0.tar.bz2 wireshark-19176fbb4f84cce7cac6ebe5f453837bfafa76d0.zip |
* 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
svn path=/trunk/; revision=8
-rw-r--r-- | AUTHORS | 11 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | Makefile.in | 97 | ||||
-rw-r--r-- | VERSION | 1 | ||||
-rw-r--r-- | config.h.in | 2 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | doc/ethereal.pod | 29 | ||||
-rw-r--r-- | ethereal.1 | 44 | ||||
-rw-r--r-- | packet-llc.c | 5 | ||||
-rw-r--r-- | packet-osi.c | 1617 | ||||
-rw-r--r-- | packet.h | 7 |
11 files changed, 1749 insertions, 69 deletions
@@ -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 */ + @@ -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 *); |