Ethereal-dev: [Ethereal-dev] Serial Infrared (SIR) [PATCH]

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Shaun Jackman <sjackman@xxxxxxxxx>
Date: Wed, 23 Jun 2004 13:00:04 -0700
Here's a patch to add Serial Infrared (SIR) to the IrDA plugin.

Cheers,
Shaun


2004-06-23  Shaun Jackman  <sjackman@xxxxxxxxxx>

        * plugins/irda/packet-sir.c: New. Dissect serial infrared (SIR) packets.
        * plugins/irda/moduleinfo.h: Bump version to 0.0.6.
	* plugins/irda/irda-appl.h: Call proto_register_irsir().
        * plugins/irda/Makefile.am: Add packet-sir.c.
	* plugins/irda/Makefile.in: Regenerate.
	* plugins/irda/Makefile: Regenerate.
	* plugins/irda/Makefile.nmake: Add packet-sir.obj.


diff -urN plugins/irda-/Makefile plugins/irda/Makefile
--- plugins/irda-/Makefile	2004-06-22 15:18:06.000000000 -0700
+++ plugins/irda/Makefile	2004-06-23 09:05:37.000000000 -0700
@@ -186,7 +186,9 @@
 INCLUDES = -I$(top_srcdir)
 
 plugin_LTLIBRARIES = irda.la
-irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c
+irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c \
+	packet-sir.c
+
 irda_la_LDFLAGS = -module -avoid-version
 irda_la_LIBADD = -L../../epan -lethereal -Wl,--export-dynamic -lgmodule-2.0 -ldl -lglib-2.0  
 
@@ -210,7 +212,7 @@
 LTLIBRARIES = $(plugin_LTLIBRARIES)
 
 irda_la_DEPENDENCIES =
-am_irda_la_OBJECTS = packet-irda.lo packet-ircomm.lo
+am_irda_la_OBJECTS = packet-irda.lo packet-ircomm.lo packet-sir.lo
 irda_la_OBJECTS = $(am_irda_la_OBJECTS)
 
 DEFS = -DHAVE_CONFIG_H
@@ -220,7 +222,8 @@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
 DEP_FILES = ./$(DEPDIR)/packet-ircomm.Plo \
-	./$(DEPDIR)/packet-irda.Plo
+	./$(DEPDIR)/packet-irda.Plo \
+	./$(DEPDIR)/packet-sir.Plo
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
@@ -281,6 +284,7 @@
 
 include ./$(DEPDIR)/packet-ircomm.Plo
 include ./$(DEPDIR)/packet-irda.Plo
+include ./$(DEPDIR)/packet-sir.Plo
 
 distclean-depend:
 	-rm -rf ./$(DEPDIR)
diff -urN plugins/irda-/Makefile.am plugins/irda/Makefile.am
--- plugins/irda-/Makefile.am	2004-06-22 15:18:06.000000000 -0700
+++ plugins/irda/Makefile.am	2004-06-23 09:05:34.000000000 -0700
@@ -27,7 +27,8 @@
 plugindir = @plugindir@
 
 plugin_LTLIBRARIES = irda.la
-irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c
+irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c \
+	packet-sir.c
 irda_la_LDFLAGS = -module -avoid-version
 irda_la_LIBADD = @PLUGIN_LIBS@
 
diff -urN plugins/irda-/Makefile.in plugins/irda/Makefile.in
--- plugins/irda-/Makefile.in	2004-06-23 09:02:51.000000000 -0700
+++ plugins/irda/Makefile.in	2004-06-23 09:05:36.000000000 -0700
@@ -186,7 +186,9 @@
 INCLUDES = -I$(top_srcdir)
 
 plugin_LTLIBRARIES = irda.la
-irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c
+irda_la_SOURCES = packet-irda.c moduleinfo.h irda-appl.h packet-ircomm.c \
+	packet-sir.c
+
 irda_la_LDFLAGS = -module -avoid-version
 irda_la_LIBADD = @PLUGIN_LIBS@
 
@@ -210,7 +212,7 @@
 LTLIBRARIES = $(plugin_LTLIBRARIES)
 
 irda_la_DEPENDENCIES =
-am_irda_la_OBJECTS = packet-irda.lo packet-ircomm.lo
+am_irda_la_OBJECTS = packet-irda.lo packet-ircomm.lo packet-sir.lo
 irda_la_OBJECTS = $(am_irda_la_OBJECTS)
 
 DEFS = @DEFS@
@@ -220,7 +222,8 @@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
 @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/packet-ircomm.Plo \
-@AMDEP_TRUE@	./$(DEPDIR)/packet-irda.Plo
+@AMDEP_TRUE@	./$(DEPDIR)/packet-irda.Plo \
+@AMDEP_TRUE@	./$(DEPDIR)/packet-sir.Plo
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
@@ -281,6 +284,7 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-ircomm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-irda.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet-sir.Plo@am__quote@
 
 distclean-depend:
 	-rm -rf ./$(DEPDIR)
diff -urN plugins/irda-/Makefile.nmake plugins/irda/Makefile.nmake
--- plugins/irda-/Makefile.nmake	2004-06-22 15:18:06.000000000 -0700
+++ plugins/irda/Makefile.nmake	2004-06-22 15:27:26.000000000 -0700
@@ -9,7 +9,7 @@
 CFLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \
 	/I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
 
-OBJECTS=packet-irda.obj packet-ircomm.obj
+OBJECTS=packet-irda.obj packet-ircomm.obj packet-sir.obj
 
 irda.dll irda.exp irda.lib : $(OBJECTS) ..\plugin_api.obj
 	link -dll /out:irda.dll $(OBJECTS) ..\plugin_api.obj \
diff -urN plugins/irda-/irda-appl.h plugins/irda/irda-appl.h
--- plugins/irda-/irda-appl.h	2004-06-22 15:18:06.000000000 -0700
+++ plugins/irda/irda-appl.h	2004-06-23 10:24:25.000000000 -0700
@@ -87,6 +87,9 @@
 extern ias_attr_dissector_t ircomm_attr_dissector[];
 extern ias_attr_dissector_t irlpt_attr_dissector[];
 
+/* Serial Infrared (SIR) */
+extern void proto_register_irsir(void);
+
 
 /*
  * Protocol hooks
@@ -102,6 +105,7 @@
 /* Protocol initialisation */
 #define REGISTER_SUB_PROTOCOLS()    do {                    \
         proto_register_ircomm();                            \
+        proto_register_irsir();                             \
     } while (0)
 
 #endif /* __IRDA_APPL_H__ */
diff -urN plugins/irda-/moduleinfo.h plugins/irda/moduleinfo.h
--- plugins/irda-/moduleinfo.h	2004-06-22 15:18:06.000000000 -0700
+++ plugins/irda/moduleinfo.h	2004-06-22 15:19:48.000000000 -0700
@@ -13,5 +13,5 @@
 #endif
 
 /* Version number of package */
-#define VERSION "0.0.5"
+#define VERSION "0.0.6"
 
diff -urN plugins/irda-/packet-sir.c plugins/irda/packet-sir.c
--- plugins/irda-/packet-sir.c	1969-12-31 16:00:00.000000000 -0800
+++ plugins/irda/packet-sir.c	2004-06-23 10:23:32.000000000 -0700
@@ -0,0 +1,280 @@
+/** Decode IrDA Serial Infrared (SIR) wrapped packets.
+ * @author Shaun Jackman <sjackman@xxxxxxxxxx>
+ * @copyright Copyright 2004 Shaun Jackman
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "moduleinfo.h"
+#include "plugins/plugin_api.h"
+
+#include <gmodule.h>
+
+
+/** Serial infrared port. */
+#define TCP_PORT_SIR 6417
+
+
+/** Beginning of frame. */
+#define SIR_BOF 0xc0
+
+/** End of frame. */
+#define SIR_EOF 0xc1
+
+/** Control escape. */
+#define SIR_CE 0x7d
+
+/** Escapes this character. */
+#define SIR_ESCAPE(x) ((x)^0x20)
+
+
+/** Protocol handles. */
+dissector_handle_t data_handle;
+dissector_handle_t irda_handle;
+
+/** Protocol fields. */
+static int proto_sir = -1;
+static int ett_sir = -1;
+static int hf_sir_bof = -1;
+static int hf_sir_ce = -1;
+static int hf_sir_eof = -1;
+static int hf_sir_fcs = -1;
+static int hf_sir_fcs_bad = -1;
+static int hf_sir_length = -1;
+static int hf_sir_preamble = -1;
+
+
+/** CRC of each possible byte. It can be computed using the standard
+ * bit-at-a-time methods. The polynomial can be seen in entry 128,
+ * 0x8408. This corresponds to x^0 + x^5 + x^12. Add the implicit
+ * x^16, and you have the standard CRC-CCITT.
+ */
+static const guint16
+crc16_table[] = {
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+
+/** Incrementally calculates the CRC-16 checksum. */
+static guint16
+crc16_incremental( guint16 fcs, guint8 c)
+{
+   return (fcs >> 8) ^ crc16_table[(fcs ^ c) & 0xff];
+}
+
+
+/** Calculates the CRC-16 checksum of the specified buffer. */
+static guint16
+crc16( const void* buf, unsigned len)
+{
+	const guint8* p = buf;
+	guint16 fcs = 0xffff;
+	while( len--)
+		fcs = crc16_incremental( fcs, *p++);
+	return ~fcs;
+}
+
+
+/** Unescapes the data. */
+static tvbuff_t*
+unescape_data( tvbuff_t* tvb, packet_info* pinfo)
+{
+	if( tvb_find_guint8( tvb, 0, -1, SIR_CE) == -1) {
+		return tvb;
+	} else {
+		guint8* data = g_malloc( tvb_length( tvb));
+		const guint8* src = tvb_get_ptr( tvb, 0, -1);
+		const guint8* end = src + tvb_length( tvb);
+		guint8* dst = data;
+		while( src < end) {
+			guint8 c = *src++;
+			switch( c) {
+				case SIR_CE:
+					if( src < end)
+						c = SIR_ESCAPE( *src++);
+				default:
+					*dst++ = c;
+			}
+		}
+		{
+			tvbuff_t* next_tvb = tvb_new_real_data(
+					data, dst-data, dst-data);
+			tvb_set_free_cb( next_tvb, g_free);
+			tvb_set_child_real_data_tvbuff( tvb, next_tvb);
+			add_new_data_source( pinfo, next_tvb, "Unescaped SIR");
+			return next_tvb;
+		}
+	}
+}
+
+
+/** Checksums the data. */
+static tvbuff_t*
+checksum_data( tvbuff_t* tvb, proto_tree* tree)
+{
+	int data_len = tvb_length( tvb) - 2;
+	if( data_len < 0)
+		return tvb;
+	if( tree) {
+		guint16 actual_fcs = tvb_get_letohs( tvb, data_len);
+		const guint8* data = tvb_get_ptr( tvb, 0, data_len);
+		guint16 calculated_fcs = crc16( data, data_len);
+		if( calculated_fcs == actual_fcs) {
+			proto_tree_add_uint_format( tree, hf_sir_fcs,
+					tvb, data_len, 2, actual_fcs,
+					"Frame check sequence: 0x%04x (correct)",
+					actual_fcs);
+		} else {
+			proto_tree_add_boolean_hidden( tree,
+					hf_sir_fcs_bad, tvb,
+					data_len, 2, TRUE);
+			proto_tree_add_uint_format( tree, hf_sir_fcs,
+					tvb, data_len, 2, actual_fcs,
+					"Frame check sequence: 0x%04x "
+					"(incorrect, should be 0x%04x)",
+					actual_fcs, calculated_fcs);
+		}
+	}
+	return tvb_new_subset( tvb, 0, data_len, data_len);
+}
+
+
+/** Dissects an SIR packet. */
+static void
+dissect_sir( tvbuff_t* tvb, packet_info* pinfo, proto_tree* root)
+{
+	gint offset = 0;
+	while( tvb_length_remaining( tvb, offset) > 0) {
+		gint bof_offset = tvb_find_guint8( tvb, offset, -1, SIR_BOF);
+		guint preamble_len = bof_offset - offset;
+		gint eof_offset = bof_offset == -1 ? -1 :
+			tvb_find_guint8( tvb, bof_offset, -1, SIR_EOF);
+		gint data_offset = bof_offset + 1;
+		guint data_len = eof_offset - data_offset;
+		tvbuff_t* next_tvb = tvb_new_subset( tvb,
+				data_offset, data_len, -1);
+		if( bof_offset == -1 || eof_offset == -1) {
+			if( pinfo->can_desegment) {
+				pinfo->desegment_offset = offset;
+				pinfo->desegment_len = 1;
+			}
+			return;
+		} else {
+			next_tvb = unescape_data( next_tvb, pinfo);
+			if( root) {
+				unsigned data_len = tvb_length( next_tvb) < 2 ? 0 :
+					tvb_length( next_tvb) - 2;
+				proto_tree* ti = proto_tree_add_protocol_format( root,
+						proto_sir, tvb, offset, eof_offset - offset + 1,
+						"Serial Infrared, Len: %d", data_len);
+				proto_tree* tree = proto_item_add_subtree( ti, ett_sir);
+				if( preamble_len > 0)
+					proto_tree_add_item( tree, hf_sir_preamble, tvb,
+							offset, preamble_len, FALSE);
+				proto_tree_add_item( tree, hf_sir_bof, tvb,
+						bof_offset, 1, FALSE);
+				proto_tree_add_uint( tree, hf_sir_length,
+						next_tvb, 0, data_len, data_len);
+				next_tvb = checksum_data( next_tvb, tree);
+				proto_tree_add_item( tree, hf_sir_eof, tvb,
+						eof_offset, 1, FALSE);
+			} else
+				next_tvb = checksum_data( next_tvb, NULL);
+			call_dissector( irda_handle, next_tvb, pinfo, root);
+		}
+		offset = eof_offset + 1;
+	}
+}
+
+
+/** Registers this dissector with the parent dissector. */
+static void
+proto_reg_handoff_sir( void)
+{
+	dissector_add( "tcp.port", TCP_PORT_SIR, find_dissector( "sir"));
+
+	data_handle = find_dissector( "data");
+	irda_handle = find_dissector( "irda");
+	if( irda_handle == 0)
+		irda_handle = data_handle;
+}
+
+
+/** Initializes this protocol. */
+void
+proto_register_irsir( void)
+{
+	static gint* ett[] = { &ett_sir };
+
+	static hf_register_info hf_sir[] = {
+		{ &hf_sir_bof,
+			{ "Beginning of frame", "sir.bof",
+				FT_UINT8, BASE_HEX, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_ce,
+			{ "Command escape", "sir.ce",
+				FT_UINT8, BASE_HEX, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_eof,
+			{ "End of frame", "sir.eof",
+				FT_UINT8, BASE_HEX, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_fcs,
+			{ "Frame check sequence", "sir.fcs",
+				FT_UINT16, BASE_HEX, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_fcs_bad,
+			{ "Bad frame check sequence", "sir.fcs_bad",
+				FT_BOOLEAN, BASE_NONE, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_length,
+			{ "Length", "sir.length",
+				FT_UINT16, BASE_DEC, NULL, 0,
+				"", HFILL }},
+		{ &hf_sir_preamble,
+			{ "Preamble", "sir.preamble",
+				FT_BYTES, BASE_NONE, NULL, 0,
+				"", HFILL }},
+	};
+
+	proto_sir = proto_register_protocol(
+			"Serial Infrared", "SIR", "sir");
+	register_dissector( "sir", dissect_sir, proto_sir);
+	proto_register_subtree_array( ett, array_length( ett));
+	proto_register_field_array(
+			proto_sir, hf_sir, array_length( hf_sir));
+
+	proto_reg_handoff_sir();
+}