From Michael Bernhard via bug 3398 with minor fixups:
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 1 Jun 2010 23:27:16 +0000 (23:27 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 1 Jun 2010 23:27:16 +0000 (23:27 +0000)
I've created a ASN.1 dissector for the IEC 61850 Sampled Values protocol. It
dissects ethernet frames of the IEC 61850-9-2LE specification form the UCA
International User Group.

There is also a new TAP for tshark (-R sv) which extracts the important
information of the frame and allows to create plots (with external tools) of
the sampled values.

I've developed under Linux (Ubuntu 8.10) but everything should be in place for
successful compilation under Windows.

It would be great if this dissector could be included in wireshark. I'm looking
forward for your comments.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@33039 f5534014-38df-0310-8fa8-9805f1628bb7

16 files changed:
AUTHORS
Makefile.common
asn1/Makefile.am
asn1/Makefile.nmake
asn1/sv/Makefile.am [new file with mode: 0644]
asn1/sv/Makefile.common [new file with mode: 0644]
asn1/sv/Makefile.nmake [new file with mode: 0644]
asn1/sv/packet-sv-template.c [new file with mode: 0644]
asn1/sv/packet-sv-template.h [new file with mode: 0644]
asn1/sv/sv.asn [new file with mode: 0644]
asn1/sv/sv.cnf [new file with mode: 0644]
configure.in
epan/dissectors/Makefile.common
epan/dissectors/packet-sv.c [new file with mode: 0644]
epan/dissectors/packet-sv.h [new file with mode: 0644]
tap-sv.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index ea02dad288519b7725cd39e7d59581c5ee623d1b..269cb6a3b385f2e287a8f02a24761257d739cf01 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3071,6 +3071,10 @@ Edgar Gladkich           <edgar.gladkich [AT] inacon.de> {
        Protocol help
 }
 
+Michael Bernhard       <michael.bernhard [AT] bfh.ch> {
+       IEC 61850 dissector
+}
+
 and by:
 
 Pavel Roskin            <proski [AT] gnu.org>
index bb4f4b6007d4fd8332e04c0af9d64c49cacbecef..cdb2f78b83af1f2bae1d7c0719dcb0bebe2e310d 100644 (file)
@@ -129,6 +129,7 @@ TSHARK_TAP_SRC =    \
        tap-smbsids.c   \
        tap-smbstat.c   \
        tap-stats_tree.c        \
+       tap-sv.c \
        tap-wspstat.c
 
 # wireshark specifics
index dcbe5f63d340be47ed688c9b945aa77aa7127f2a..22aa52f94e4bc635cac120bb3b05ab04fe270b07 100644 (file)
@@ -95,6 +95,7 @@ SUBDIRS =             \
        smrse           \
        snmp            \
        spnego          \
+       sv                      \
        t125            \
        t38                     \
        tcap            \
index 6f92a226220cc4e1208a1ebbe855e55b3f2d4685..f27770d8e6cd1503a3591fa287c41f18e996f9fc 100644 (file)
@@ -92,6 +92,7 @@ BER_LIST= \
        smrse                   \
        snmp                    \
        spnego                  \
+       sv                      \
        t125                    \
        tcap                    \
        wlancertextn            \
diff --git a/asn1/sv/Makefile.am b/asn1/sv/Makefile.am
new file mode 100644 (file)
index 0000000..0d2c3ef
--- /dev/null
@@ -0,0 +1,26 @@
+# $Id:$
+#
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.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.
+
+
+include ../Makefile.preinc
+include Makefile.common
+include ../Makefile.inc
+
diff --git a/asn1/sv/Makefile.common b/asn1/sv/Makefile.common
new file mode 100644 (file)
index 0000000..62bc168
--- /dev/null
@@ -0,0 +1,47 @@
+# $Id:$
+#
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.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.
+
+
+PROTOCOL_NAME=sv
+
+DISSECTOR_FILES= \
+       packet-$(PROTOCOL_NAME).c \
+       packet-$(PROTOCOL_NAME).h
+
+
+EXT_ASN_FILE_LIST =
+
+ASN_FILE_LIST = $(PROTOCOL_NAME).asn
+
+# The packet-$(PROTOCOL_NAME)-template.h and $(PROTOCOL_NAME).asn
+# files do not exist for all protocols: Please add/remove as required.
+EXTRA_DIST = \
+       Makefile.nmake \
+       $(ASN_FILE_LIST) \
+       packet-$(PROTOCOL_NAME)-template.c \
+       packet-$(PROTOCOL_NAME)-template.h \
+       $(PROTOCOL_NAME).cnf
+
+SRC_FILES = \
+       $(EXTRA_DIST) \
+       $(EXT_ASN_FILE_LIST)
+
+A2W_FLAGS= -b 
diff --git a/asn1/sv/Makefile.nmake b/asn1/sv/Makefile.nmake
new file mode 100644 (file)
index 0000000..8263722
--- /dev/null
@@ -0,0 +1,29 @@
+## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
+#
+# $Id:$
+#
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.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.
+
+
+include ../../config.nmake
+include ../Makefile.preinc.nmake
+include Makefile.common
+include ../Makefile.inc.nmake
+
diff --git a/asn1/sv/packet-sv-template.c b/asn1/sv/packet-sv-template.c
new file mode 100644 (file)
index 0000000..0096ea0
--- /dev/null
@@ -0,0 +1,335 @@
+/* packet-sv.c
+ * Routines for IEC 61850 Sampled Vales packet dissection
+ * Michael Bernhard 2008
+ *
+ * $Id:$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/asn1.h>
+#include <epan/etypes.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-ber.h"
+#include "packet-acse.h"
+
+#include "tap.h"
+
+#include "packet-sv.h"
+
+#define PNAME  "IEC61850 Sampled Values"
+#define PSNAME "SV"
+#define PFNAME "sv"
+
+/* see IEC61850-8-1 8.2 */
+#define Q_VALIDITY_GOOD                        (0x0 << 0)
+#define Q_VALIDITY_INVALID             (0x1 << 0)
+#define Q_VALIDITY_QUESTIONABLE        (0x3 << 0)
+#define Q_VALIDITY_MASK                        (0x3 << 0)
+
+#define Q_OVERFLOW                             (1 << 2)
+#define Q_OUTOFRANGE                   (1 << 3)
+#define Q_BADREFERENCE                 (1 << 4)
+#define Q_OSCILLATORY                  (1 << 5)
+#define Q_FAILURE                              (1 << 6)
+#define Q_OLDDATA                              (1 << 7)
+#define Q_INCONSISTENT                 (1 << 8)
+#define Q_INACCURATE                   (1 << 9)
+
+#define Q_SOURCE_PROCESS               (0 << 10)
+#define Q_SOURCE_SUBSTITUTED   (1 << 10)
+#define Q_SOURCE_MASK                  (1 << 10)
+
+#define Q_TEST                                 (1 << 11)
+#define Q_OPERATORBLOCKED              (1 << 12)
+
+/* see UCA Implementation Guideline for IEC 61850-9-2 */
+#define Q_DERIVED                              (1 << 13)
+
+
+/* Data for SV tap */
+static int sv_tap = -1;
+static sv_frame_data sv_data;
+
+/* Initialize the protocol and registered fields */
+static int proto_sv = -1;
+static int hf_sv_appid = -1;
+static int hf_sv_length = -1;
+static int hf_sv_reserve1 = -1;
+static int hf_sv_reserve2 = -1;
+static int hf_sv_phmeas_instmag_i = -1;
+static int hf_sv_phsmeas_q = -1;
+static int hf_sv_phsmeas_q_validity = -1;
+static int hf_sv_phsmeas_q_overflow = -1;
+static int hf_sv_phsmeas_q_outofrange = -1;
+static int hf_sv_phsmeas_q_badreference = -1;
+static int hf_sv_phsmeas_q_oscillatory = -1;
+static int hf_sv_phsmeas_q_failure = -1;
+static int hf_sv_phsmeas_q_olddata = -1;
+static int hf_sv_phsmeas_q_inconsistent = -1;
+static int hf_sv_phsmeas_q_inaccurate = -1;
+static int hf_sv_phsmeas_q_source = -1;
+static int hf_sv_phsmeas_q_test = -1;
+static int hf_sv_phsmeas_q_operatorblocked = -1;
+static int hf_sv_phsmeas_q_derived = -1;
+
+#include "packet-sv-hf.c"
+
+/* Initialize the subtree pointers */
+static int ett_sv = -1;
+static int ett_phsmeas = -1;
+static int ett_phsmeas_q = -1;
+
+#include "packet-sv-ett.c"
+
+static const value_string sv_q_validity_vals[] = {
+  {   0, "good" },
+  {   1, "invalid" },
+  {   3, "questionable" },
+  { 0, NULL }
+};
+
+static const value_string sv_q_source_vals[] = {
+  {   0, "process" },
+  {   1, "substituted" },
+  { 0, NULL }
+};
+
+static int
+dissect_PhsMeas1(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int hf_id _U_)
+{
+       gint8 class;
+       gboolean pc;
+       gint32 tag;
+       guint32 len;
+       proto_item *it;
+       proto_tree *subtree = NULL;
+       gint32 value;
+       guint32 qual;
+       guint32 i;
+
+       static const int *q_flags[] = {
+               &hf_sv_phsmeas_q_validity,
+               &hf_sv_phsmeas_q_overflow,
+               &hf_sv_phsmeas_q_outofrange,
+               &hf_sv_phsmeas_q_badreference,
+               &hf_sv_phsmeas_q_oscillatory,
+               &hf_sv_phsmeas_q_failure,
+               &hf_sv_phsmeas_q_olddata,
+               &hf_sv_phsmeas_q_inconsistent,
+               &hf_sv_phsmeas_q_inaccurate,
+               &hf_sv_phsmeas_q_source,
+               &hf_sv_phsmeas_q_test,
+               &hf_sv_phsmeas_q_operatorblocked,
+               &hf_sv_phsmeas_q_derived,
+               NULL
+               };
+
+       if (!implicit_tag) {
+               offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+               offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+       } else {
+               len=tvb_length_remaining(tvb, offset);
+       }
+
+       if (tree) {
+               it = proto_tree_add_text(tree, tvb, offset, len, "PhsMeas1");
+               subtree = proto_item_add_subtree(it, ett_phsmeas);
+       }
+
+       sv_data.num_phsMeas = 0;
+       for (i = 0; i < len/8; i++) {
+               if (tree && subtree) {
+                       value = tvb_get_ntohl(tvb, offset);
+                       qual = tvb_get_ntohl(tvb, offset + 4);
+
+                       proto_tree_add_item(subtree, hf_sv_phmeas_instmag_i, tvb, offset, 4, FALSE);
+                       proto_tree_add_bitmask(subtree, tvb, offset + 4, hf_sv_phsmeas_q, ett_phsmeas_q, q_flags, FALSE);
+
+                       if (i < IEC61850_SV_MAX_PHSMEAS_ENTRIES) {
+                               sv_data.phsMeas[i].value = value;
+                               sv_data.phsMeas[i].qual = qual;
+                               sv_data.num_phsMeas++;
+                       }
+               }
+
+               offset += 8;
+       }
+
+       return offset;
+}
+
+#include "packet-sv-fn.c"
+
+/*
+* Dissect SV PDUs inside a PPDU.
+*/
+static void
+dissect_sv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+       int offset = 0;
+       int old_offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       asn1_ctx_t asn1_ctx;
+
+       asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+
+       if (parent_tree){
+               item = proto_tree_add_item(parent_tree, proto_sv, tvb, 0, -1, FALSE);
+               tree = proto_item_add_subtree(item, ett_sv);
+       }
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, PNAME);
+       col_clear(pinfo->cinfo, COL_INFO);
+
+       /* APPID */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 2)
+               proto_tree_add_item(tree, hf_sv_appid, tvb, offset, 2, FALSE);
+
+       /* Length */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 4)
+               proto_tree_add_item(tree, hf_sv_length, tvb, offset + 2, 2, FALSE);
+
+       /* Reserved 1 */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 6)
+               proto_tree_add_item(tree, hf_sv_reserve1, tvb, offset + 4, 2, FALSE);
+
+       /* Reserved 2 */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 8)
+               proto_tree_add_item(tree, hf_sv_reserve2, tvb, offset + 6, 2, FALSE);
+
+       offset = 8;
+       while (tree && tvb_reported_length_remaining(tvb, offset) > 0){
+               old_offset = offset;
+               offset = dissect_sv_SampledValues(FALSE, tvb, offset, &asn1_ctx , tree, -1);
+               if (offset == old_offset) {
+                       proto_tree_add_text(tree, tvb, offset, -1, "Internal error, zero-byte SV PDU");
+                       offset = tvb_length(tvb);
+                       break;
+               }
+       }
+
+       if(tree)
+               tap_queue_packet(sv_tap, pinfo, &sv_data);
+}
+
+
+/*--- proto_register_sv -------------------------------------------*/
+void proto_register_sv(void) {
+
+       /* List of fields */
+       static hf_register_info hf[] = {
+               { &hf_sv_appid,
+               { "APPID",      "sv.appid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+               { &hf_sv_length,
+               { "Length",     "sv.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+               { &hf_sv_reserve1,
+               { "Reserved 1", "sv.reserve1", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
+
+               { &hf_sv_reserve2,
+               { "Reserved 2", "sv.reserve2", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }},
+
+               { &hf_sv_phmeas_instmag_i,
+               { "value", "sv.meas_value", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q,
+               { "quality", "sv.meas_quality", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_validity,
+               { "validity", "sv.meas_quality.validity", FT_UINT32, BASE_HEX, VALS(sv_q_validity_vals), Q_VALIDITY_MASK, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_overflow,
+               { "overflow", "sv.meas_quality.overflow", FT_BOOLEAN, 32, NULL, Q_OVERFLOW, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_outofrange,
+               { "out of range", "sv.meas_quality.outofrange", FT_BOOLEAN, 32, NULL, Q_OUTOFRANGE, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_badreference,
+               { "bad reference", "sv.meas_quality.badreference", FT_BOOLEAN, 32, NULL, Q_BADREFERENCE, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_oscillatory,
+               { "oscillatory", "sv.meas_quality.oscillatory", FT_BOOLEAN, 32, NULL, Q_OSCILLATORY, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_failure,
+               { "failure", "sv.meas_quality.failure", FT_BOOLEAN, 32, NULL, Q_FAILURE, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_olddata,
+               { "old data", "sv.meas_quality.olddata", FT_BOOLEAN, 32, NULL, Q_OLDDATA, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_inconsistent,
+               { "inconsistent", "sv.meas_quality.inconsistent", FT_BOOLEAN, 32, NULL, Q_INCONSISTENT, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_inaccurate,
+               { "inaccurate", "sv.meas_quality.inaccurate", FT_BOOLEAN, 32, NULL, Q_INACCURATE, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_source,
+               { "source", "sv.meas_quality.source", FT_UINT32, BASE_HEX, VALS(sv_q_source_vals), Q_SOURCE_MASK, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_test,
+               { "test", "sv.meas_quality.teset", FT_BOOLEAN, 32, NULL, Q_TEST, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_operatorblocked,
+               { "operator blocked", "sv.meas_quality.operatorblocked", FT_BOOLEAN, 32, NULL, Q_OPERATORBLOCKED, NULL, HFILL}},
+
+               { &hf_sv_phsmeas_q_derived,
+               { "derived", "sv.meas_quality.derived", FT_BOOLEAN, 32, NULL, Q_DERIVED, NULL, HFILL}},
+
+
+#include "packet-sv-hfarr.c"
+       };
+
+       /* List of subtrees */
+       static gint *ett[] = {
+               &ett_sv,
+               &ett_phsmeas,
+               &ett_phsmeas_q,
+#include "packet-sv-ettarr.c"
+       };
+
+       /* Register protocol */
+       proto_sv = proto_register_protocol(PNAME, PSNAME, PFNAME);
+       register_dissector("sv", dissect_sv, proto_sv);
+
+       /* Register fields and subtrees */
+       proto_register_field_array(proto_sv, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+
+       /* Register tap */
+       sv_tap = register_tap("sv");
+}
+
+/*--- proto_reg_handoff_sv --- */
+void proto_reg_handoff_sv(void) {
+
+       dissector_handle_t sv_handle;
+       sv_handle = find_dissector("sv");
+
+       dissector_add("ethertype", ETHERTYPE_IEC61850_SV, sv_handle);
+}
diff --git a/asn1/sv/packet-sv-template.h b/asn1/sv/packet-sv-template.h
new file mode 100644 (file)
index 0000000..557a026
--- /dev/null
@@ -0,0 +1,43 @@
+/* packet-sv.h
+ * Routines for IEC 61850 Sampled Vales packet dissection
+ * Michael Bernhard 2008
+ *
+ * $Id:$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+#ifndef __PACKET_SV_H__
+#define __PACKET_SV_H__
+
+#define IEC61850_SV_MAX_PHSMEAS_ENTRIES 20
+
+typedef struct _sv_phs_meas {
+       gint32 value;
+       guint32 qual;
+} sv_phs_meas;
+
+typedef struct _sv_frame_data {
+       guint16 smpCnt;
+       guint8 smpSynch;
+       guint8 num_phsMeas;
+       sv_phs_meas phsMeas[IEC61850_SV_MAX_PHSMEAS_ENTRIES];
+} sv_frame_data;
+
+#endif /*__PACKET_SV_H__*/
diff --git a/asn1/sv/sv.asn b/asn1/sv/sv.asn
new file mode 100644 (file)
index 0000000..9aac768
--- /dev/null
@@ -0,0 +1,25 @@
+-- $Id:$
+IEC61850 DEFINITIONS ::= BEGIN
+
+SampledValues ::= CHOICE {
+       savPdu  [APPLICATION 0] IMPLICIT SavPdu,
+       ...
+}
+
+SavPdu ::= SEQUENCE {
+       noASDU  [0] IMPLICIT INTEGER(0..65535),
+       seqASDU [2] IMPLICIT SEQUENCE OF ASDU
+}
+
+ASDU ::= SEQUENCE {
+       svID            [0] IMPLICIT VisibleString,
+       smpCnt          [2] IMPLICIT INTEGER(0..65535),
+       confRef         [3] IMPLICIT INTEGER(0..4294967295),
+       smpSynch        [5] IMPLICIT INTEGER{none(0),local(1),global(2)},
+       seqData         [7] IMPLICIT Data,
+       ...
+}
+
+Data ::= OCTET STRING
+
+END
diff --git a/asn1/sv/sv.cnf b/asn1/sv/sv.cnf
new file mode 100644 (file)
index 0000000..698f37e
--- /dev/null
@@ -0,0 +1,34 @@
+# sv.cnf
+# SampledValue conformation file
+
+# $Id:$
+
+#.MODULE_IMPORT
+
+#.EXPORTS
+
+#.PDU
+
+#.NO_EMIT
+
+#.TYPE_RENAME
+
+#.FIELD_RENAME
+
+#.FN_BODY ASDU/smpCnt
+       guint32 value;
+       offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, &value);
+       sv_data.smpCnt = value;
+#.END
+
+#.FN_BODY ASDU/smpSynch
+       guint32 value;
+       offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, &value);
+       sv_data.smpSynch = value;
+#.END
+
+#.FN_BODY Data
+       offset = dissect_PhsMeas1(implicit_tag, actx->pinfo, tree, tvb, offset, hf_index);
+#.END
+
+#.END_OF_CNF
\ No newline at end of file
index ffd5dd8d3a5c956c567a87681a4f9cf5f09ffb5a..73267b3582c318de70f8e5025fb6d0fdfb41407f 100644 (file)
@@ -1811,6 +1811,7 @@ AC_OUTPUT(
   asn1/smrse/Makefile
   asn1/snmp/Makefile
   asn1/spnego/Makefile
+  asn1/sv/Makefile
   asn1/t125/Makefile
   asn1/t38/Makefile
   asn1/tcap/Makefile
index 4973c3bd13bd6989af4f3fe2208ef111448eb1e9..a372b037ea636bcaa22a450c261c4e3e68e1cf9e 100644 (file)
@@ -148,6 +148,7 @@ ASN1_DISSECTOR_SRC = \
        packet-sabp.c \
        packet-smrse.c \
        packet-spnego.c \
+       packet-sv.c \
        packet-ulp.c \
        packet-wlancertextn.c \
        packet-x224.c \
@@ -1254,6 +1255,7 @@ DISSECTOR_INCLUDES =      \
        packet-ssl-utils.h      \
        packet-stat-notify.h    \
        packet-stat.h   \
+       packet-sv.h     \
        packet-t30.h    \
        packet-t38.h    \
        packet-tacacs.h \
diff --git a/epan/dissectors/packet-sv.c b/epan/dissectors/packet-sv.c
new file mode 100644 (file)
index 0000000..faa6e20
--- /dev/null
@@ -0,0 +1,564 @@
+/* Do not modify this file.                                                   */
+/* It is created automatically by the ASN.1 to Wireshark dissector compiler   */
+/* packet-sv.c                                                                */
+/* ../../tools/asn2wrs.py -b -p sv -c ./sv.cnf -s ./packet-sv-template -D . sv.asn */
+
+/* Input file: packet-sv-template.c */
+
+#line 1 "packet-sv-template.c"
+/* packet-sv.c
+ * Routines for IEC 61850 Sampled Vales packet dissection
+ * Michael Bernhard 2008
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/asn1.h>
+#include <epan/etypes.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-ber.h"
+#include "packet-acse.h"
+
+#include "tap.h"
+
+#include "packet-sv.h"
+
+#define PNAME  "IEC61850 Sampled Values"
+#define PSNAME "SV"
+#define PFNAME "sv"
+
+/* see IEC61850-8-1 8.2 */
+#define Q_VALIDITY_GOOD                        (0x0 << 0)
+#define Q_VALIDITY_INVALID             (0x1 << 0)
+#define Q_VALIDITY_QUESTIONABLE        (0x3 << 0)
+#define Q_VALIDITY_MASK                        (0x3 << 0)
+
+#define Q_OVERFLOW                             (1 << 2)
+#define Q_OUTOFRANGE                   (1 << 3)
+#define Q_BADREFERENCE                 (1 << 4)
+#define Q_OSCILLATORY                  (1 << 5)
+#define Q_FAILURE                              (1 << 6)
+#define Q_OLDDATA                              (1 << 7)
+#define Q_INCONSISTENT                 (1 << 8)
+#define Q_INACCURATE                   (1 << 9)
+
+#define Q_SOURCE_PROCESS               (0 << 10)
+#define Q_SOURCE_SUBSTITUTED   (1 << 10)
+#define Q_SOURCE_MASK                  (1 << 10)
+
+#define Q_TEST                                 (1 << 11)
+#define Q_OPERATORBLOCKED              (1 << 12)
+
+/* see UCA Implementation Guideline for IEC 61850-9-2 */
+#define Q_DERIVED                              (1 << 13)
+
+
+/* Data for SV tap */
+static int sv_tap = -1;
+static sv_frame_data sv_data;
+
+/* Initialize the protocol and registered fields */
+static int proto_sv = -1;
+static int hf_sv_appid = -1;
+static int hf_sv_length = -1;
+static int hf_sv_reserve1 = -1;
+static int hf_sv_reserve2 = -1;
+static int hf_sv_phmeas_instmag_i = -1;
+static int hf_sv_phsmeas_q = -1;
+static int hf_sv_phsmeas_q_validity = -1;
+static int hf_sv_phsmeas_q_overflow = -1;
+static int hf_sv_phsmeas_q_outofrange = -1;
+static int hf_sv_phsmeas_q_badreference = -1;
+static int hf_sv_phsmeas_q_oscillatory = -1;
+static int hf_sv_phsmeas_q_failure = -1;
+static int hf_sv_phsmeas_q_olddata = -1;
+static int hf_sv_phsmeas_q_inconsistent = -1;
+static int hf_sv_phsmeas_q_inaccurate = -1;
+static int hf_sv_phsmeas_q_source = -1;
+static int hf_sv_phsmeas_q_test = -1;
+static int hf_sv_phsmeas_q_operatorblocked = -1;
+static int hf_sv_phsmeas_q_derived = -1;
+
+
+/*--- Included file: packet-sv-hf.c ---*/
+#line 1 "packet-sv-hf.c"
+static int hf_sv_savPdu = -1;                     /* SavPdu */
+static int hf_sv_noASDU = -1;                     /* INTEGER_0_65535 */
+static int hf_sv_seqASDU = -1;                    /* SEQUENCE_OF_ASDU */
+static int hf_sv_seqASDU_item = -1;               /* ASDU */
+static int hf_sv_svID = -1;                       /* VisibleString */
+static int hf_sv_smpCnt = -1;                     /* T_smpCnt */
+static int hf_sv_confRef = -1;                    /* INTEGER_0_4294967295 */
+static int hf_sv_smpSynch = -1;                   /* T_smpSynch */
+static int hf_sv_seqData = -1;                    /* Data */
+
+/*--- End of included file: packet-sv-hf.c ---*/
+#line 102 "packet-sv-template.c"
+
+/* Initialize the subtree pointers */
+static int ett_sv = -1;
+static int ett_phsmeas = -1;
+static int ett_phsmeas_q = -1;
+
+
+/*--- Included file: packet-sv-ett.c ---*/
+#line 1 "packet-sv-ett.c"
+static gint ett_sv_SampledValues = -1;
+static gint ett_sv_SavPdu = -1;
+static gint ett_sv_SEQUENCE_OF_ASDU = -1;
+static gint ett_sv_ASDU = -1;
+
+/*--- End of included file: packet-sv-ett.c ---*/
+#line 109 "packet-sv-template.c"
+
+static const value_string sv_q_validity_vals[] = {
+  {   0, "good" },
+  {   1, "invalid" },
+  {   3, "questionable" },
+  { 0, NULL }
+};
+
+static const value_string sv_q_source_vals[] = {
+  {   0, "process" },
+  {   1, "substituted" },
+  { 0, NULL }
+};
+
+static int
+dissect_PhsMeas1(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int hf_id _U_)
+{
+       gint8 class;
+       gboolean pc;
+       gint32 tag;
+       guint32 len;
+       proto_item *it;
+       proto_tree *subtree = NULL;
+       gint32 value;
+       guint32 qual;
+       guint32 i;
+
+       static const int *q_flags[] = {
+               &hf_sv_phsmeas_q_validity,
+               &hf_sv_phsmeas_q_overflow,
+               &hf_sv_phsmeas_q_outofrange,
+               &hf_sv_phsmeas_q_badreference,
+               &hf_sv_phsmeas_q_oscillatory,
+               &hf_sv_phsmeas_q_failure,
+               &hf_sv_phsmeas_q_olddata,
+               &hf_sv_phsmeas_q_inconsistent,
+               &hf_sv_phsmeas_q_inaccurate,
+               &hf_sv_phsmeas_q_source,
+               &hf_sv_phsmeas_q_test,
+               &hf_sv_phsmeas_q_operatorblocked,
+               &hf_sv_phsmeas_q_derived,
+               NULL
+               };
+
+       if (!implicit_tag) {
+               offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+               offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+       } else {
+               len=tvb_length_remaining(tvb, offset);
+       }
+
+       if (tree) {
+               it = proto_tree_add_text(tree, tvb, offset, len, "PhsMeas1");
+               subtree = proto_item_add_subtree(it, ett_phsmeas);
+       }
+
+       sv_data.num_phsMeas = 0;
+       for (i = 0; i < len/8; i++) {
+               if (tree && subtree) {
+                       value = tvb_get_ntohl(tvb, offset);
+                       qual = tvb_get_ntohl(tvb, offset + 4);
+
+                       proto_tree_add_item(subtree, hf_sv_phmeas_instmag_i, tvb, offset, 4, FALSE);
+                       proto_tree_add_bitmask(subtree, tvb, offset + 4, hf_sv_phsmeas_q, ett_phsmeas_q, q_flags, FALSE);
+
+                       if (i < IEC61850_SV_MAX_PHSMEAS_ENTRIES) {
+                               sv_data.phsMeas[i].value = value;
+                               sv_data.phsMeas[i].qual = qual;
+                               sv_data.num_phsMeas++;
+                       }
+               }
+
+               offset += 8;
+       }
+
+       return offset;
+}
+
+
+/*--- Included file: packet-sv-fn.c ---*/
+#line 1 "packet-sv-fn.c"
+
+
+static int
+dissect_sv_INTEGER_0_65535(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_sv_VisibleString(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_restricted_string(implicit_tag, BER_UNI_TAG_VisibleString,
+                                            actx, tree, tvb, offset, hf_index,
+                                            NULL);
+
+  return offset;
+}
+
+
+
+static int
+dissect_sv_T_smpCnt(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 19 "sv.cnf"
+       guint32 value;
+       offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, &value);
+       sv_data.smpCnt = value;
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_sv_INTEGER_0_4294967295(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
+                                                NULL);
+
+  return offset;
+}
+
+
+static const value_string sv_T_smpSynch_vals[] = {
+  {   0, "none" },
+  {   1, "local" },
+  {   2, "global" },
+  { 0, NULL }
+};
+
+
+static int
+dissect_sv_T_smpSynch(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 25 "sv.cnf"
+       guint32 value;
+       offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index, &value);
+       sv_data.smpSynch = value;
+
+
+  return offset;
+}
+
+
+
+static int
+dissect_sv_Data(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+#line 31 "sv.cnf"
+       offset = dissect_PhsMeas1(implicit_tag, actx->pinfo, tree, tvb, offset, hf_index);
+
+
+  return offset;
+}
+
+
+static const ber_sequence_t ASDU_sequence[] = {
+  { &hf_sv_svID             , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_sv_VisibleString },
+  { &hf_sv_smpCnt           , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_sv_T_smpCnt },
+  { &hf_sv_confRef          , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_sv_INTEGER_0_4294967295 },
+  { &hf_sv_smpSynch         , BER_CLASS_CON, 5, BER_FLAGS_IMPLTAG, dissect_sv_T_smpSynch },
+  { &hf_sv_seqData          , BER_CLASS_CON, 7, BER_FLAGS_IMPLTAG, dissect_sv_Data },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_sv_ASDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   ASDU_sequence, hf_index, ett_sv_ASDU);
+
+  return offset;
+}
+
+
+static const ber_sequence_t SEQUENCE_OF_ASDU_sequence_of[1] = {
+  { &hf_sv_seqASDU_item     , BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_sv_ASDU },
+};
+
+static int
+dissect_sv_SEQUENCE_OF_ASDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
+                                      SEQUENCE_OF_ASDU_sequence_of, hf_index, ett_sv_SEQUENCE_OF_ASDU);
+
+  return offset;
+}
+
+
+static const ber_sequence_t SavPdu_sequence[] = {
+  { &hf_sv_noASDU           , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_sv_INTEGER_0_65535 },
+  { &hf_sv_seqASDU          , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_sv_SEQUENCE_OF_ASDU },
+  { NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_sv_SavPdu(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
+                                   SavPdu_sequence, hf_index, ett_sv_SavPdu);
+
+  return offset;
+}
+
+
+static const value_string sv_SampledValues_vals[] = {
+  {   0, "savPdu" },
+  { 0, NULL }
+};
+
+static const ber_choice_t SampledValues_choice[] = {
+  {   0, &hf_sv_savPdu           , BER_CLASS_APP, 0, BER_FLAGS_IMPLTAG, dissect_sv_SavPdu },
+  { 0, NULL, 0, 0, 0, NULL }
+};
+
+static int
+dissect_sv_SampledValues(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  offset = dissect_ber_choice(actx, tree, tvb, offset,
+                                 SampledValues_choice, hf_index, ett_sv_SampledValues,
+                                 NULL);
+
+  return offset;
+}
+
+
+/*--- End of included file: packet-sv-fn.c ---*/
+#line 188 "packet-sv-template.c"
+
+/*
+* Dissect SV PDUs inside a PPDU.
+*/
+static void
+dissect_sv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+       int offset = 0;
+       int old_offset;
+       proto_item *item = NULL;
+       proto_tree *tree = NULL;
+       asn1_ctx_t asn1_ctx;
+
+       asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+
+       if (parent_tree){
+               item = proto_tree_add_item(parent_tree, proto_sv, tvb, 0, -1, FALSE);
+               tree = proto_item_add_subtree(item, ett_sv);
+       }
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, PNAME);
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
+
+       /* APPID */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 2)
+               proto_tree_add_item(tree, hf_sv_appid, tvb, offset, 2, FALSE);
+
+       /* Length */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 4)
+               proto_tree_add_item(tree, hf_sv_length, tvb, offset + 2, 2, FALSE);
+
+       /* Reserved 1 */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 6)
+               proto_tree_add_item(tree, hf_sv_reserve1, tvb, offset + 4, 2, FALSE);
+
+       /* Reserved 2 */
+       if (tree && tvb_reported_length_remaining(tvb, offset) >= 8)
+               proto_tree_add_item(tree, hf_sv_reserve2, tvb, offset + 6, 2, FALSE);
+
+       offset = 8;
+       while (tree && tvb_reported_length_remaining(tvb, offset) > 0){
+               old_offset = offset;
+               offset = dissect_sv_SampledValues(FALSE, tvb, offset, &asn1_ctx , tree, -1);
+               if (offset == old_offset) {
+                       proto_tree_add_text(tree, tvb, offset, -1, "Internal error, zero-byte SV PDU");
+                       offset = tvb_length(tvb);
+                       break;
+               }
+       }
+
+       if(tree)
+               tap_queue_packet(sv_tap, pinfo, &sv_data);
+}
+
+
+/*--- proto_register_sv -------------------------------------------*/
+void proto_register_sv(void) {
+
+       /* List of fields */
+       static hf_register_info hf[] = {
+               { &hf_sv_appid,
+               { "APPID",      "sv.appid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+               { &hf_sv_length,
+               { "Length",     "sv.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+               { &hf_sv_reserve1,
+               { "Reserved 1", "sv.reserve1", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "", HFILL }},
+
+               { &hf_sv_reserve2,
+               { "Reserved 2", "sv.reserve2", FT_UINT16, BASE_HEX_DEC, NULL, 0x0, "", HFILL }},
+
+               { &hf_sv_phmeas_instmag_i,
+               { "value", "sv.meas_value", FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+
+               { &hf_sv_phsmeas_q,
+               { "quality", "sv.meas_quality", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_validity,
+               { "validity", "sv.meas_quality.validity", FT_UINT32, BASE_HEX, VALS(sv_q_validity_vals), Q_VALIDITY_MASK, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_overflow,
+               { "overflow", "sv.meas_quality.overflow", FT_BOOLEAN, 32, NULL, Q_OVERFLOW, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_outofrange,
+               { "out of range", "sv.meas_quality.outofrange", FT_BOOLEAN, 32, NULL, Q_OUTOFRANGE, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_badreference,
+               { "bad reference", "sv.meas_quality.badreference", FT_BOOLEAN, 32, NULL, Q_BADREFERENCE, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_oscillatory,
+               { "oscillatory", "sv.meas_quality.oscillatory", FT_BOOLEAN, 32, NULL, Q_OSCILLATORY, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_failure,
+               { "failure", "sv.meas_quality.failure", FT_BOOLEAN, 32, NULL, Q_FAILURE, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_olddata,
+               { "old data", "sv.meas_quality.olddata", FT_BOOLEAN, 32, NULL, Q_OLDDATA, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_inconsistent,
+               { "inconsistent", "sv.meas_quality.inconsistent", FT_BOOLEAN, 32, NULL, Q_INCONSISTENT, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_inaccurate,
+               { "inaccurate", "sv.meas_quality.inaccurate", FT_BOOLEAN, 32, NULL, Q_INACCURATE, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_source,
+               { "source", "sv.meas_quality.source", FT_UINT32, BASE_HEX, VALS(sv_q_source_vals), Q_SOURCE_MASK, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_test,
+               { "test", "sv.meas_quality.teset", FT_BOOLEAN, 32, NULL, Q_TEST, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_operatorblocked,
+               { "operator blocked", "sv.meas_quality.operatorblocked", FT_BOOLEAN, 32, NULL, Q_OPERATORBLOCKED, "", HFILL}},
+
+               { &hf_sv_phsmeas_q_derived,
+               { "derived", "sv.meas_quality.derived", FT_BOOLEAN, 32, NULL, Q_DERIVED, "", HFILL}},
+
+
+
+/*--- Included file: packet-sv-hfarr.c ---*/
+#line 1 "packet-sv-hfarr.c"
+    { &hf_sv_savPdu,
+      { "savPdu", "sv.savPdu",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "sv.SavPdu", HFILL }},
+    { &hf_sv_noASDU,
+      { "noASDU", "sv.noASDU",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "sv.INTEGER_0_65535", HFILL }},
+    { &hf_sv_seqASDU,
+      { "seqASDU", "sv.seqASDU",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "sv.SEQUENCE_OF_ASDU", HFILL }},
+    { &hf_sv_seqASDU_item,
+      { "seqASDU", "sv.seqASDU_item",
+        FT_NONE, BASE_NONE, NULL, 0,
+        "sv.ASDU", HFILL }},
+    { &hf_sv_svID,
+      { "svID", "sv.svID",
+        FT_STRING, BASE_NONE, NULL, 0,
+        "sv.VisibleString", HFILL }},
+    { &hf_sv_smpCnt,
+      { "smpCnt", "sv.smpCnt",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "sv.T_smpCnt", HFILL }},
+    { &hf_sv_confRef,
+      { "confRef", "sv.confRef",
+        FT_UINT32, BASE_DEC, NULL, 0,
+        "sv.INTEGER_0_4294967295", HFILL }},
+    { &hf_sv_smpSynch,
+      { "smpSynch", "sv.smpSynch",
+        FT_INT32, BASE_DEC, VALS(sv_T_smpSynch_vals), 0,
+        "sv.T_smpSynch", HFILL }},
+    { &hf_sv_seqData,
+      { "seqData", "sv.seqData",
+        FT_BYTES, BASE_HEX, NULL, 0,
+        "sv.Data", HFILL }},
+
+/*--- End of included file: packet-sv-hfarr.c ---*/
+#line 308 "packet-sv-template.c"
+       };
+
+       /* List of subtrees */
+       static gint *ett[] = {
+               &ett_sv,
+               &ett_phsmeas,
+               &ett_phsmeas_q,
+
+/*--- Included file: packet-sv-ettarr.c ---*/
+#line 1 "packet-sv-ettarr.c"
+    &ett_sv_SampledValues,
+    &ett_sv_SavPdu,
+    &ett_sv_SEQUENCE_OF_ASDU,
+    &ett_sv_ASDU,
+
+/*--- End of included file: packet-sv-ettarr.c ---*/
+#line 316 "packet-sv-template.c"
+       };
+
+       /* Register protocol */
+       proto_sv = proto_register_protocol(PNAME, PSNAME, PFNAME);
+       register_dissector("sv", dissect_sv, proto_sv);
+
+       /* Register fields and subtrees */
+       proto_register_field_array(proto_sv, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+
+       /* Register tap */
+       sv_tap = register_tap("sv");
+}
+
+/*--- proto_reg_handoff_sv --- */
+void proto_reg_handoff_sv(void) {
+
+       dissector_handle_t sv_handle;
+       sv_handle = find_dissector("sv");
+
+       dissector_add("ethertype", ETHERTYPE_IEC61850_SV, sv_handle);
+}
diff --git a/epan/dissectors/packet-sv.h b/epan/dissectors/packet-sv.h
new file mode 100644 (file)
index 0000000..224d4ba
--- /dev/null
@@ -0,0 +1,51 @@
+/* Do not modify this file.                                                   */
+/* It is created automatically by the ASN.1 to Wireshark dissector compiler   */
+/* packet-sv.h                                                                */
+/* ../../tools/asn2wrs.py -b -p sv -c ./sv.cnf -s ./packet-sv-template -D . sv.asn */
+
+/* Input file: packet-sv-template.h */
+
+#line 1 "packet-sv-template.h"
+/* packet-sv.c
+ * Routines for IEC 61850 Sampled Vales packet dissection
+ * Michael Bernhard 2008
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+#ifndef __PACKET_SV_H__
+#define __PACKET_SV_H__
+
+#define IEC61850_SV_MAX_PHSMEAS_ENTRIES 20
+
+typedef struct _sv_phs_meas {
+       gint32 value;
+       guint32 qual;
+} sv_phs_meas;
+
+typedef struct _sv_frame_data {
+       guint16 smpCnt;
+       guint8 smpSynch;
+       guint8 num_phsMeas;
+       sv_phs_meas phsMeas[IEC61850_SV_MAX_PHSMEAS_ENTRIES];
+} sv_frame_data;
+
+#endif /*__PACKET_SV_H__*/
diff --git a/tap-sv.c b/tap-sv.c
new file mode 100644 (file)
index 0000000..a1c074c
--- /dev/null
+++ b/tap-sv.c
@@ -0,0 +1,65 @@
+/* tap-sv.c
+ * Copyright 2008 Michael Bernhard
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include <epan/tap.h>
+#include <epan/nstime.h>
+#include "register.h"
+#include "epan/dissectors/packet-sv.h"
+
+static int
+sv_packet(void *prs _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pri)
+{
+       int i;
+       const sv_frame_data * sv_data = pri;
+
+       printf("%f %u ", nstime_to_sec(&pinfo->fd->rel_ts), sv_data->smpCnt);
+
+       for(i = 0; i < sv_data->num_phsMeas; i++) {
+               printf("%d ", sv_data->phsMeas[i].value);
+       }
+
+       printf("\n");
+
+       return 0;
+}
+
+void
+register_tap_listener_sv(void)
+{
+       register_tap_listener("sv", NULL, NULL, 0, NULL, sv_packet, NULL);
+}