Wireshark-dev: [Wireshark-dev] [PATCH 2/2] plugins: New MPEG dissector

From: "Shaun Jackman" <sjackman@xxxxxxxxx>
Date: Fri, 25 Aug 2006 14:45:33 -0600
I've created an MPEG stream decoder for Wireshark. It's useful for
decoding streaming audio. It currently supports MPEG-1, MPEG-2,
MPEG-2.5 audio, layers 1, 2, 3. To test out the protocol decoder, the
first half of the patch adds a wiretap file format to allow opening
your favourite MPEG audio file (mp3 for example). The second half of
the patch adds the protocol decoder. This patch is generated against
wireshark 0.99.2.

Cheers,
Shaun

Signed-off-by: Shaun Jackman <sjackman@xxxxxxxxx>

2006-08-25  Shaun Jackman  <sjackman@xxxxxxxxx>

	* asn1/mpeg/Makefile: New file.
	* asn1/mpeg/mpeg.asn: Ditto.
	* asn1/mpeg/packet-mpeg-template.c: Ditto.
	* configure.in (AC_OUTPUT): Add plugins/mpeg/Makefile.
	* plugins/Makefile.am (SUBDIRS): Add mpeg.
	* plugins/Makefile.in: Regenerate.
	* plugins/mpeg/Makefile.am: New file.
	* plugins/mpeg/Makefile.in: Regenerate.
	* plugins/mpeg/Makefile.common: Ditto.
	* plugins/mpeg/moduleinfo.h: Ditto.
	* plugins/mpeg/packet-mpeg.c: Regenerate.

diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/asn1/mpeg/Makefile
wireshark-0.99.2/asn1/mpeg/Makefile
--- wireshark-0.99.2.orig/asn1/mpeg/Makefile	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/Makefile	2006-08-15 15:58:43.000000000 -0600
@@ -0,0 +1,14 @@
+DISSECTOR_FILES=packet-mpeg.c packet-mpeg.h
+
+all: generate_dissector
+
+generate_dissector: $(DISSECTOR_FILES)
+
+$(DISSECTOR_FILES): ../../tools/asn2wrs.py mpeg.asn packet-mpeg-template.c
+	python ../../tools/asn2wrs.py -e -p mpeg -s packet-mpeg-template mpeg.asn
+
+clean:
+	rm -f parsetab.py parsetab.pyc $(DISSECTOR_FILES)
+
+copy_files: generate_dissector
+	cp $(DISSECTOR_FILES) ../../epan/dissectors
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/asn1/mpeg/mpeg.asn
wireshark-0.99.2/asn1/mpeg/mpeg.asn
--- wireshark-0.99.2.orig/asn1/mpeg/mpeg.asn	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/mpeg.asn	2006-08-24 17:09:03.000000000 -0600
@@ -0,0 +1,35 @@
+MPEG DEFINITIONS ::= BEGIN
+
+Audio ::= SEQUENCE {
+	sync           BIT STRING (SIZE (11)),
+	version        ENUMERATED
+		{ mpeg-2-5(0), reserved(1), mpeg-2(2), mpeg-1(3) },
+	layer          ENUMERATED
+		{ reserved(0), layer-3(1), layer-2(2), layer-1(3) },
+	protection     ENUMERATED { crc(0), none(1) },
+	bitrate        INTEGER (0..15),
+	frequency      INTEGER (0..3),
+	padding        BOOLEAN,
+	private        BOOLEAN,
+	channel-mode   ENUMERATED
+		{ stereo(0), joint-stereo(1), dual-channel(2), single-channel(3) },
+	mode-extension INTEGER (0..3),
+	copyright      BOOLEAN,
+	original       BOOLEAN,
+	emphasis       ENUMERATED
+		{ none(0), em-50-15-ms(1), reserved(2), ccit-j-17(3) }
+}
+
+ID3v1 ::= SEQUENCE {
+	tag     OCTET STRING (SIZE (3)),
+	title   OCTET STRING (SIZE (30)),
+	artist  OCTET STRING (SIZE (30)),
+	album   OCTET STRING (SIZE (30)),
+	year    OCTET STRING (SIZE (4)),
+	comment OCTET STRING (SIZE (28)),
+	zero    INTEGER (0..255),
+	track   INTEGER (0..255),
+	genre   INTEGER (0..255)
+}
+
+END
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/asn1/mpeg/packet-mpeg-template.c
wireshark-0.99.2/asn1/mpeg/packet-mpeg-template.c
--- wireshark-0.99.2.orig/asn1/mpeg/packet-mpeg-template.c	1969-12-31
17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/packet-mpeg-template.c	2006-08-24
17:23:57.000000000 -0600
@@ -0,0 +1,235 @@
+/* MPEG packet decoder.
+ * Written by Shaun Jackman <sjackman@xxxxxxxxx>.
+ * Copyright 2006 Shaun Jackman.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+#include "packet-per.h"
+
+#include "packet-mpeg-hf.c"
+#include "packet-mpeg-ett.c"
+#include "packet-mpeg-fn.c"
+
+static int hf_mpeg_audio = -1;
+static int hf_mpeg_data = -1;
+static int hf_mpeg_padbytes = -1;
+static int hf_id3v1 = -1;
+static int hf_id3v2 = -1;
+
+struct header {
+	unsigned emphasis   :2;
+	unsigned original   :1;
+	unsigned copyright  :1;
+	unsigned mode_ext   :2;
+	unsigned mode       :2;
+	unsigned private    :1;
+	unsigned padding    :1;
+	unsigned frequency  :2;
+	unsigned bitrate    :4;
+	unsigned protection :1;
+	unsigned layer      :2;
+	unsigned version    :2;
+	unsigned sync       :11;
+};
+
+enum { SYNC = 0x7ff };
+static const int versions[4] = { 2, -1, 1, 0 };
+static const int layers[4] = { -1, 2, 1, 0 };
+
+static const unsigned samples_per_frame[3][3] = {
+	{ 384, 1152, 1152 },
+	{ 384, 1152, 576 },
+	{ 384, 1152, 576 },
+};
+
+static const unsigned bitrates[3][3][16] = { /* kb/s */
+  {
+	{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384 },
+	{ 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320 },
+  },
+  {
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+  },
+  {
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+  },
+};
+
+static const unsigned frequencies[3][4] = {
+	{ 44100, 48000, 32000 },
+	{ 22050, 24000, 16000 },
+	{ 11025, 12000, 8000 },
+};
+static const unsigned padding[3] = { 4, 1, 1 };
+
+static size_t
+read_header(tvbuff_t *tvb, packet_info *pinfo, struct header *header)
+{
+	size_t data_size = 0;
+	uint32_t h = tvb_get_ntohl(tvb, 0);
+	memcpy(header, &h, sizeof *header);
+	if (header->sync == SYNC) {
+		int version = versions[header->version];
+		int layer = layers[header->layer];
+		if (version >= 0 && layer >= 0) {
+			unsigned bitrate = bitrates[version][layer][header->bitrate] * 1000;
+			unsigned frequency = frequencies[version][header->frequency];
+			if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+				static const char *version_names[] = { "1", "2", "2.5" };
+				col_add_fstr(pinfo->cinfo, COL_PROTOCOL,
+						"MPEG-%s", version_names[version]);
+			}
+			if (check_col(pinfo->cinfo, COL_INFO))
+				col_add_fstr(pinfo->cinfo, COL_INFO,
+						"Audio Layer %d", layer+1);
+			if (bitrate > 0 && frequency > 0) {
+				unsigned samples = samples_per_frame[version][layer];
+				data_size = bitrate * samples / frequency / 8 - sizeof header;
+				if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
+					SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
+					col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
+							"%d kb/s", bitrate / 1000);
+				}
+				if (check_col(pinfo->cinfo, COL_DEF_DST)) {
+					SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
+					col_add_fstr(pinfo->cinfo, COL_DEF_DST,
+							"%g kHz", frequency / (float)1000);
+				}
+			}
+		} else {
+			if (check_col(pinfo->cinfo, COL_PROTOCOL))
+				col_add_str(pinfo->cinfo, COL_PROTOCOL, "MPEG");
+		}
+	}
+	return data_size;
+}
+
+static void
+dissect_mpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	struct header header;
+	size_t data_size = read_header(tvb, pinfo, &header);
+	if (tree == NULL)
+		return;
+
+	if (header.sync != SYNC)
+		return;
+	asn1_ctx_t asn1_ctx;
+	asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
+	int offset = 0;
+	offset = dissect_mpeg_Audio(tvb, offset, &asn1_ctx,
+			tree, hf_mpeg_audio);
+	if (data_size > 0) {
+		proto_tree_add_item(tree, hf_mpeg_data, tvb,
+				offset / 8, data_size, FALSE);
+		offset += data_size * 8;
+		if (header.padding)
+			proto_tree_add_item(tree, hf_mpeg_padbytes, tvb,
+					offset / 8, 1, FALSE);
+	}
+}
+
+static void
+dissect_id3v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "ID3v1");
+	if (tree == NULL)
+		return;
+	asn1_ctx_t asn1_ctx;
+	asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
+	dissect_mpeg_ID3v1(tvb, 0, &asn1_ctx,
+			tree, hf_id3v1);
+}
+
+static void
+dissect_id3v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "ID3v2");
+	proto_tree_add_item(tree, hf_id3v2, tvb,
+			0, -1, FALSE);
+}
+
+static void
+dissect_mpeg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_clear(pinfo->cinfo, COL_PROTOCOL);
+	if (check_col(pinfo->cinfo, COL_INFO))
+		col_clear(pinfo->cinfo, COL_INFO);
+
+	int magic = tvb_get_ntoh24(tvb, 0);
+	switch (magic) {
+		case 0x544147:
+			dissect_id3v1(tvb, pinfo, tree);
+			break;
+		case 0x494433:
+			dissect_id3v2(tvb, pinfo, tree);
+			break;
+		default:
+			dissect_mpa(tvb, pinfo, tree);
+	}
+}
+
+static int proto_mpeg = -1;
+
+void
+proto_register_mpeg(void)
+{
+	static hf_register_info hf[] = {
+#include "packet-mpeg-hfarr.c"
+		{ &hf_mpeg_audio,
+			{ "MPEG Audio", "mpeg.audio",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_mpeg_data,
+			{ "Data", "mpeg.data",
+				FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_mpeg_padbytes,
+			{ "Padding", "mpeg.padbytes",
+				FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+		{ &hf_id3v1,
+			{ "ID3v1", "id3v1",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_id3v2,
+			{ "ID3v2", "id3v2",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+	};
+
+	static gint *ett[] = {
+#include "packet-mpeg-ettarr.c"
+	};
+
+	if (proto_mpeg != -1)
+		return;
+
+	proto_mpeg = proto_register_protocol(
+			"Moving Picture Experts Group", "MPEG", "mpeg");
+	proto_register_field_array(proto_mpeg, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mpeg(void)
+{
+	dissector_handle_t mpeg_handle = create_dissector_handle(
+			dissect_mpeg, proto_mpeg);
+	dissector_add("wtap_encap", WTAP_ENCAP_MPEG, mpeg_handle);
+}
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/configure.in wireshark-0.99.2/configure.in
--- wireshark-0.99.2.orig/configure.in	2006-07-17 14:00:03.000000000 -0600
+++ wireshark-0.99.2/configure.in	2006-08-25 13:14:12.000000000 -0600
@@ -1350,6 +1350,7 @@
  plugins/mate/Makefile
  plugins/megaco/Makefile
  plugins/mgcp/Makefile
+  plugins/mpeg/Makefile
  plugins/opsi/Makefile
  plugins/pcli/Makefile
  plugins/profinet/Makefile
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/plugins/Makefile.am
wireshark-0.99.2/plugins/Makefile.am
--- wireshark-0.99.2.orig/plugins/Makefile.am	2006-07-17
13:57:16.000000000 -0600
+++ wireshark-0.99.2/plugins/Makefile.am	2006-08-15 16:00:45.000000000 -0600
@@ -45,6 +45,7 @@
	mate \
	megaco \
	mgcp \
+	mpeg \
	opsi \
	pcli \
	profinet \
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/plugins/mpeg/Makefile.am
wireshark-0.99.2/plugins/mpeg/Makefile.am
--- wireshark-0.99.2.orig/plugins/mpeg/Makefile.am	1969-12-31
17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/Makefile.am	2006-08-15
16:14:12.000000000 -0600
@@ -0,0 +1,118 @@
+# Makefile.am
+# Automake file for MPEG plugin
+#
+# $Id: Makefile.am 18312 2006-06-02 06:53:30Z jmayer $
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@xxxxxxxxxxxxx>
+# 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.
+#
+
+INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/epan/dissectors
+
+include Makefile.common
+
+plugindir = @plugindir@
+
+plugin_LTLIBRARIES = mpeg.la
+mpeg_la_SOURCES = \
+	plugin.c \
+	moduleinfo.h \
+	$(DISSECTOR_SRC) \
+	$(DISSECTOR_INCLUDES)
+mpeg_la_LDFLAGS = -module -avoid-version
+mpeg_la_LIBADD = @PLUGIN_LIBS@
+
+# Libs must be cleared, or else libtool won't create a shared module.
+# If your module needs to be linked against any particular libraries,
+# add them here.
+LIBS =
+
+#
+# Build plugin.c, which contains the plugin version[] string, a
+# function plugin_register() that calls the register routines for all
+# protocols, and a function plugin_reg_handoff() that calls the handoff
+# registration routines for all protocols.
+#
+# We do this by scanning sources.  If that turns out to be too slow,
+# maybe we could just require every .o file to have an register routine
+# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
+#
+# Formatting conventions:  The name of the proto_register_* routines an
+# proto_reg_handoff_* routines must start in column zero, or must be
+# preceded only by "void " starting in column zero, and must not be
+# inside #if.
+#
+# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
+#
+# For some unknown reason, having a big "for" loop in the Makefile
+# to scan all the files doesn't work with some "make"s; they seem to
+# pass only the first few names in the list to the shell, for some
+# reason.
+#
+# Therefore, we have a script to generate the plugin.c file.
+# The shell script runs slowly, as multiple greps and seds are run
+# for each input file; this is especially slow on Windows.  Therefore,
+# if Python is present (as indicated by PYTHON being defined), we run
+# a faster Python script to do that work instead.
+#
+# The first argument is the directory in which the source files live.
+# The second argument is "plugin", to indicate that we should build
+# a plugin.c file for a plugin.
+# All subsequent arguments are the files to scan.
+#
+plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \
+    $(top_srcdir)/tools/make-dissector-reg.py
+	@if test -n $(PYTHON); then \
+		echo Making plugin.c with python ; \
+		$(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
+		    plugin $(DISSECTOR_SRC) ; \
+	else \
+		echo Making plugin.c with shell script ; \
+		$(top_srcdir)/tools/make-dissector-reg $(srcdir) \
+		    $(plugin_src) plugin $(DISSECTOR_SRC) ; \
+	fi
+
+#
+# Currently plugin.c can be included in the distribution because
+# we always build all protocol dissectors. We used to have to check
+# whether or not to build the snmp dissector. If we again need to
+# variably build something, making plugin.c non-portable, uncomment
+# the dist-hook line below.
+#
+# Oh, yuk.  We don't want to include "plugin.c" in the distribution, as
+# its contents depend on the configuration, and therefore we want it
+# to be built when the first "make" is done; however, Automake insists
+# on putting *all* source into the distribution.
+#
+# We work around this by having a "dist-hook" rule that deletes
+# "plugin.c", so that "dist" won't pick it up.
+#
+#dist-hook:
+#	@rm -f $(distdir)/plugin.c
+
+CLEANFILES = \
+	mpeg \
+	*~
+
+MAINTAINERCLEANFILES = \
+	Makefile.in	\
+	plugin.c
+
+EXTRA_DIST = \
+	Makefile.common		\
+	Makefile.nmake
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/plugins/mpeg/Makefile.common
wireshark-0.99.2/plugins/mpeg/Makefile.common
--- wireshark-0.99.2.orig/plugins/mpeg/Makefile.common	1969-12-31
17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/Makefile.common	2006-08-15
16:03:34.000000000 -0600
@@ -0,0 +1,31 @@
+# Makefile.common for MPEG plugin
+#     Contains the stuff from Makefile.am and Makefile.nmake that is
+#     a) common to both files and
+#     b) portable between both files
+#
+# $Id: Makefile.common 18197 2006-05-21 05:12:17Z sahlberg $
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@xxxxxxxxxxxxx>
+# 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.
+
+# the name of the plugin
+PLUGIN_NAME = mpeg
+
+# the dissector sources (without any helpers)
+DISSECTOR_SRC = \
+	packet-mpeg.c
diff --unidirectional-new-file -urXX
wireshark-0.99.2.orig/plugins/mpeg/moduleinfo.h
wireshark-0.99.2/plugins/mpeg/moduleinfo.h
--- wireshark-0.99.2.orig/plugins/mpeg/moduleinfo.h	1969-12-31
17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/moduleinfo.h	2006-08-15
16:04:48.000000000 -0600
@@ -0,0 +1,16 @@
+/* Included *after* config.h, in order to re-define these macros */
+
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+
+/* Name of package */
+#define PACKAGE "mpeg"
+
+
+#ifdef VERSION
+#undef VERSION
+#endif
+
+/* Version number of package */
+#define VERSION "0.1.0"
[PATCH 2/2] plugins: New MPEG dissector
Signed-off-by: Shaun Jackman <sjackman@xxxxxxxxx>

2006-08-25  Shaun Jackman  <sjackman@xxxxxxxxx>

	* asn1/mpeg/Makefile: New file.
	* asn1/mpeg/mpeg.asn: Ditto.
	* asn1/mpeg/packet-mpeg-template.c: Ditto.
	* configure.in (AC_OUTPUT): Add plugins/mpeg/Makefile.
	* plugins/Makefile.am (SUBDIRS): Add mpeg.
	* plugins/Makefile.in: Regenerate.
	* plugins/mpeg/Makefile.am: New file.
	* plugins/mpeg/Makefile.in: Regenerate.
	* plugins/mpeg/Makefile.common: Ditto.
	* plugins/mpeg/moduleinfo.h: Ditto.
	* plugins/mpeg/packet-mpeg.c: Regenerate.

diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/asn1/mpeg/Makefile wireshark-0.99.2/asn1/mpeg/Makefile
--- wireshark-0.99.2.orig/asn1/mpeg/Makefile	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/Makefile	2006-08-15 15:58:43.000000000 -0600
@@ -0,0 +1,14 @@
+DISSECTOR_FILES=packet-mpeg.c packet-mpeg.h
+
+all: generate_dissector
+
+generate_dissector: $(DISSECTOR_FILES)
+
+$(DISSECTOR_FILES): ../../tools/asn2wrs.py mpeg.asn packet-mpeg-template.c
+	python ../../tools/asn2wrs.py -e -p mpeg -s packet-mpeg-template mpeg.asn
+
+clean:
+	rm -f parsetab.py parsetab.pyc $(DISSECTOR_FILES)
+
+copy_files: generate_dissector
+	cp $(DISSECTOR_FILES) ../../epan/dissectors
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/asn1/mpeg/mpeg.asn wireshark-0.99.2/asn1/mpeg/mpeg.asn
--- wireshark-0.99.2.orig/asn1/mpeg/mpeg.asn	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/mpeg.asn	2006-08-24 17:09:03.000000000 -0600
@@ -0,0 +1,35 @@
+MPEG DEFINITIONS ::= BEGIN
+
+Audio ::= SEQUENCE {
+	sync           BIT STRING (SIZE (11)),
+	version        ENUMERATED
+		{ mpeg-2-5(0), reserved(1), mpeg-2(2), mpeg-1(3) },
+	layer          ENUMERATED
+		{ reserved(0), layer-3(1), layer-2(2), layer-1(3) },
+	protection     ENUMERATED { crc(0), none(1) },
+	bitrate        INTEGER (0..15),
+	frequency      INTEGER (0..3),
+	padding        BOOLEAN,
+	private        BOOLEAN,
+	channel-mode   ENUMERATED
+		{ stereo(0), joint-stereo(1), dual-channel(2), single-channel(3) },
+	mode-extension INTEGER (0..3),
+	copyright      BOOLEAN,
+	original       BOOLEAN,
+	emphasis       ENUMERATED
+		{ none(0), em-50-15-ms(1), reserved(2), ccit-j-17(3) }
+}
+
+ID3v1 ::= SEQUENCE {
+	tag     OCTET STRING (SIZE (3)),
+	title   OCTET STRING (SIZE (30)),
+	artist  OCTET STRING (SIZE (30)),
+	album   OCTET STRING (SIZE (30)),
+	year    OCTET STRING (SIZE (4)),
+	comment OCTET STRING (SIZE (28)),
+	zero    INTEGER (0..255),
+	track   INTEGER (0..255),
+	genre   INTEGER (0..255)
+}
+
+END
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/asn1/mpeg/packet-mpeg-template.c wireshark-0.99.2/asn1/mpeg/packet-mpeg-template.c
--- wireshark-0.99.2.orig/asn1/mpeg/packet-mpeg-template.c	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/asn1/mpeg/packet-mpeg-template.c	2006-08-24 17:23:57.000000000 -0600
@@ -0,0 +1,235 @@
+/* MPEG packet decoder.
+ * Written by Shaun Jackman <sjackman@xxxxxxxxx>.
+ * Copyright 2006 Shaun Jackman.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+#include "packet-per.h"
+
+#include "packet-mpeg-hf.c"
+#include "packet-mpeg-ett.c"
+#include "packet-mpeg-fn.c"
+
+static int hf_mpeg_audio = -1;
+static int hf_mpeg_data = -1;
+static int hf_mpeg_padbytes = -1;
+static int hf_id3v1 = -1;
+static int hf_id3v2 = -1;
+
+struct header {
+	unsigned emphasis   :2;
+	unsigned original   :1;
+	unsigned copyright  :1;
+	unsigned mode_ext   :2;
+	unsigned mode       :2;
+	unsigned private    :1;
+	unsigned padding    :1;
+	unsigned frequency  :2;
+	unsigned bitrate    :4;
+	unsigned protection :1;
+	unsigned layer      :2;
+	unsigned version    :2;
+	unsigned sync       :11;
+};
+
+enum { SYNC = 0x7ff };
+static const int versions[4] = { 2, -1, 1, 0 };
+static const int layers[4] = { -1, 2, 1, 0 };
+
+static const unsigned samples_per_frame[3][3] = {
+	{ 384, 1152, 1152 },
+	{ 384, 1152, 576 },
+	{ 384, 1152, 576 },
+};
+
+static const unsigned bitrates[3][3][16] = { /* kb/s */
+  {
+	{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384 },
+	{ 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320 },
+  },
+  {
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+  },
+  {
+	{ 0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+	{ 0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160 },
+  },
+};
+
+static const unsigned frequencies[3][4] = {
+	{ 44100, 48000, 32000 },
+	{ 22050, 24000, 16000 },
+	{ 11025, 12000, 8000 },
+};
+static const unsigned padding[3] = { 4, 1, 1 };
+
+static size_t
+read_header(tvbuff_t *tvb, packet_info *pinfo, struct header *header)
+{
+	size_t data_size = 0;
+	uint32_t h = tvb_get_ntohl(tvb, 0);
+	memcpy(header, &h, sizeof *header);
+	if (header->sync == SYNC) {
+		int version = versions[header->version];
+		int layer = layers[header->layer];
+		if (version >= 0 && layer >= 0) {
+			unsigned bitrate = bitrates[version][layer][header->bitrate] * 1000;
+			unsigned frequency = frequencies[version][header->frequency];
+			if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+				static const char *version_names[] = { "1", "2", "2.5" };
+				col_add_fstr(pinfo->cinfo, COL_PROTOCOL,
+						"MPEG-%s", version_names[version]);
+			}
+			if (check_col(pinfo->cinfo, COL_INFO))
+				col_add_fstr(pinfo->cinfo, COL_INFO,
+						"Audio Layer %d", layer+1);
+			if (bitrate > 0 && frequency > 0) {
+				unsigned samples = samples_per_frame[version][layer];
+				data_size = bitrate * samples / frequency / 8 - sizeof header;
+				if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
+					SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
+					col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
+							"%d kb/s", bitrate / 1000);
+				}
+				if (check_col(pinfo->cinfo, COL_DEF_DST)) {
+					SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
+					col_add_fstr(pinfo->cinfo, COL_DEF_DST,
+							"%g kHz", frequency / (float)1000);
+				}
+			}
+		} else {
+			if (check_col(pinfo->cinfo, COL_PROTOCOL))
+				col_add_str(pinfo->cinfo, COL_PROTOCOL, "MPEG");
+		}
+	}
+	return data_size;
+}
+
+static void
+dissect_mpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	struct header header;
+	size_t data_size = read_header(tvb, pinfo, &header);
+	if (tree == NULL)
+		return;
+
+	if (header.sync != SYNC)
+		return;
+	asn1_ctx_t asn1_ctx;
+	asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
+	int offset = 0;
+	offset = dissect_mpeg_Audio(tvb, offset, &asn1_ctx,
+			tree, hf_mpeg_audio);
+	if (data_size > 0) {
+		proto_tree_add_item(tree, hf_mpeg_data, tvb,
+				offset / 8, data_size, FALSE);
+		offset += data_size * 8;
+		if (header.padding)
+			proto_tree_add_item(tree, hf_mpeg_padbytes, tvb,
+					offset / 8, 1, FALSE);
+	}
+}
+
+static void
+dissect_id3v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "ID3v1");
+	if (tree == NULL)
+		return;
+	asn1_ctx_t asn1_ctx;
+	asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
+	dissect_mpeg_ID3v1(tvb, 0, &asn1_ctx,
+			tree, hf_id3v1);
+}
+
+static void
+dissect_id3v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_set_str(pinfo->cinfo, COL_PROTOCOL, "ID3v2");
+	proto_tree_add_item(tree, hf_id3v2, tvb,
+			0, -1, FALSE);
+}
+
+static void
+dissect_mpeg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	if (check_col(pinfo->cinfo, COL_PROTOCOL))
+		col_clear(pinfo->cinfo, COL_PROTOCOL);
+	if (check_col(pinfo->cinfo, COL_INFO))
+		col_clear(pinfo->cinfo, COL_INFO);
+
+	int magic = tvb_get_ntoh24(tvb, 0);
+	switch (magic) {
+		case 0x544147:
+			dissect_id3v1(tvb, pinfo, tree);
+			break;
+		case 0x494433:
+			dissect_id3v2(tvb, pinfo, tree);
+			break;
+		default:
+			dissect_mpa(tvb, pinfo, tree);
+	}
+}
+
+static int proto_mpeg = -1;
+
+void
+proto_register_mpeg(void)
+{
+	static hf_register_info hf[] = {
+#include "packet-mpeg-hfarr.c"
+		{ &hf_mpeg_audio,
+			{ "MPEG Audio", "mpeg.audio",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_mpeg_data,
+			{ "Data", "mpeg.data",
+				FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_mpeg_padbytes,
+			{ "Padding", "mpeg.padbytes",
+				FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+		{ &hf_id3v1,
+			{ "ID3v1", "id3v1",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+		{ &hf_id3v2,
+			{ "ID3v2", "id3v2",
+				FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+	};
+
+	static gint *ett[] = {
+#include "packet-mpeg-ettarr.c"
+	};
+
+	if (proto_mpeg != -1)
+		return;
+
+	proto_mpeg = proto_register_protocol(
+			"Moving Picture Experts Group", "MPEG", "mpeg");
+	proto_register_field_array(proto_mpeg, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mpeg(void)
+{
+	dissector_handle_t mpeg_handle = create_dissector_handle(
+			dissect_mpeg, proto_mpeg);
+	dissector_add("wtap_encap", WTAP_ENCAP_MPEG, mpeg_handle);
+}
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/configure.in wireshark-0.99.2/configure.in
--- wireshark-0.99.2.orig/configure.in	2006-07-17 14:00:03.000000000 -0600
+++ wireshark-0.99.2/configure.in	2006-08-25 13:14:12.000000000 -0600
@@ -1350,6 +1350,7 @@
   plugins/mate/Makefile
   plugins/megaco/Makefile
   plugins/mgcp/Makefile
+  plugins/mpeg/Makefile
   plugins/opsi/Makefile
   plugins/pcli/Makefile
   plugins/profinet/Makefile
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/plugins/Makefile.am wireshark-0.99.2/plugins/Makefile.am
--- wireshark-0.99.2.orig/plugins/Makefile.am	2006-07-17 13:57:16.000000000 -0600
+++ wireshark-0.99.2/plugins/Makefile.am	2006-08-15 16:00:45.000000000 -0600
@@ -45,6 +45,7 @@
 	mate \
 	megaco \
 	mgcp \
+	mpeg \
 	opsi \
 	pcli \
 	profinet \
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/plugins/mpeg/Makefile.am wireshark-0.99.2/plugins/mpeg/Makefile.am
--- wireshark-0.99.2.orig/plugins/mpeg/Makefile.am	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/Makefile.am	2006-08-15 16:14:12.000000000 -0600
@@ -0,0 +1,118 @@
+# Makefile.am
+# Automake file for MPEG plugin
+#
+# $Id: Makefile.am 18312 2006-06-02 06:53:30Z jmayer $
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@xxxxxxxxxxxxx>
+# 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.
+#
+
+INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/epan/dissectors
+
+include Makefile.common
+
+plugindir = @plugindir@
+
+plugin_LTLIBRARIES = mpeg.la
+mpeg_la_SOURCES = \
+	plugin.c \
+	moduleinfo.h \
+	$(DISSECTOR_SRC) \
+	$(DISSECTOR_INCLUDES)
+mpeg_la_LDFLAGS = -module -avoid-version
+mpeg_la_LIBADD = @PLUGIN_LIBS@
+
+# Libs must be cleared, or else libtool won't create a shared module.
+# If your module needs to be linked against any particular libraries,
+# add them here.
+LIBS =
+
+#
+# Build plugin.c, which contains the plugin version[] string, a
+# function plugin_register() that calls the register routines for all
+# protocols, and a function plugin_reg_handoff() that calls the handoff
+# registration routines for all protocols.
+#
+# We do this by scanning sources.  If that turns out to be too slow,
+# maybe we could just require every .o file to have an register routine
+# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
+#
+# Formatting conventions:  The name of the proto_register_* routines an
+# proto_reg_handoff_* routines must start in column zero, or must be
+# preceded only by "void " starting in column zero, and must not be
+# inside #if.
+#
+# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
+#
+# For some unknown reason, having a big "for" loop in the Makefile
+# to scan all the files doesn't work with some "make"s; they seem to
+# pass only the first few names in the list to the shell, for some
+# reason.
+#
+# Therefore, we have a script to generate the plugin.c file.
+# The shell script runs slowly, as multiple greps and seds are run
+# for each input file; this is especially slow on Windows.  Therefore,
+# if Python is present (as indicated by PYTHON being defined), we run
+# a faster Python script to do that work instead.
+#
+# The first argument is the directory in which the source files live.
+# The second argument is "plugin", to indicate that we should build
+# a plugin.c file for a plugin.
+# All subsequent arguments are the files to scan.
+#
+plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \
+    $(top_srcdir)/tools/make-dissector-reg.py
+	@if test -n $(PYTHON); then \
+		echo Making plugin.c with python ; \
+		$(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
+		    plugin $(DISSECTOR_SRC) ; \
+	else \
+		echo Making plugin.c with shell script ; \
+		$(top_srcdir)/tools/make-dissector-reg $(srcdir) \
+		    $(plugin_src) plugin $(DISSECTOR_SRC) ; \
+	fi
+
+#
+# Currently plugin.c can be included in the distribution because
+# we always build all protocol dissectors. We used to have to check
+# whether or not to build the snmp dissector. If we again need to
+# variably build something, making plugin.c non-portable, uncomment
+# the dist-hook line below.
+#
+# Oh, yuk.  We don't want to include "plugin.c" in the distribution, as
+# its contents depend on the configuration, and therefore we want it
+# to be built when the first "make" is done; however, Automake insists
+# on putting *all* source into the distribution.
+#
+# We work around this by having a "dist-hook" rule that deletes
+# "plugin.c", so that "dist" won't pick it up.
+#
+#dist-hook:
+#	@rm -f $(distdir)/plugin.c
+
+CLEANFILES = \
+	mpeg \
+	*~
+
+MAINTAINERCLEANFILES = \
+	Makefile.in	\
+	plugin.c
+
+EXTRA_DIST = \
+	Makefile.common		\
+	Makefile.nmake
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/plugins/mpeg/Makefile.common wireshark-0.99.2/plugins/mpeg/Makefile.common
--- wireshark-0.99.2.orig/plugins/mpeg/Makefile.common	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/Makefile.common	2006-08-15 16:03:34.000000000 -0600
@@ -0,0 +1,31 @@
+# Makefile.common for MPEG plugin
+#     Contains the stuff from Makefile.am and Makefile.nmake that is
+#     a) common to both files and
+#     b) portable between both files
+#
+# $Id: Makefile.common 18197 2006-05-21 05:12:17Z sahlberg $
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@xxxxxxxxxxxxx>
+# 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.
+
+# the name of the plugin
+PLUGIN_NAME = mpeg
+
+# the dissector sources (without any helpers)
+DISSECTOR_SRC = \
+	packet-mpeg.c
diff --unidirectional-new-file -urXX wireshark-0.99.2.orig/plugins/mpeg/moduleinfo.h wireshark-0.99.2/plugins/mpeg/moduleinfo.h
--- wireshark-0.99.2.orig/plugins/mpeg/moduleinfo.h	1969-12-31 17:00:00.000000000 -0700
+++ wireshark-0.99.2/plugins/mpeg/moduleinfo.h	2006-08-15 16:04:48.000000000 -0600
@@ -0,0 +1,16 @@
+/* Included *after* config.h, in order to re-define these macros */
+
+#ifdef PACKAGE
+#undef PACKAGE
+#endif
+
+/* Name of package */
+#define PACKAGE "mpeg"
+
+
+#ifdef VERSION
+#undef VERSION
+#endif
+
+/* Version number of package */
+#define VERSION "0.1.0"