New protocol support for Lawo EmberPlus which is Glow embedded in S101
Bug: 14718 Change-Id: I7ad6503634eb6bc98cee20ef069db3156a6a1e1e Reviewed-on: https://code.wireshark.org/review/27247 Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
This commit is contained in:
parent
e020ccab49
commit
1c7b101b35
|
@ -69,9 +69,9 @@ TPM 2.0 protocol
|
|||
PROXY (v2) protocol
|
||||
Ruby Marshal format
|
||||
Ruby Distributed protocol
|
||||
--
|
||||
GSM-R protocol (User-to-User Information Element usage)
|
||||
--
|
||||
S101 Lawo Emberplus transport frame
|
||||
GLOW Lawo Emberplus Data format
|
||||
STCSIG (Spirent Test Center Signature decoding for Ethernet and FibreChannel, disabled by default)
|
||||
--
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ set(CLEAN_ASN1_DISSECTOR_SRC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/packet-ess.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-f1ap.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-ftam.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-glow.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-goose.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-gsm_map.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-HI2Operations.c
|
||||
|
@ -1598,6 +1599,7 @@ set(DISSECTOR_SRC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/packet-rudp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-rwall.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-rx.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-s101.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-s5066sis.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-s5066dts.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-s7comm.c
|
||||
|
|
|
@ -34,6 +34,7 @@ set(ASN1_SRC_DIRS
|
|||
ess
|
||||
f1ap
|
||||
ftam
|
||||
glow
|
||||
goose
|
||||
gprscdr
|
||||
gsm_map
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# CMakeLists.txt
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
|
||||
set( PROTOCOL_NAME glow )
|
||||
|
||||
set( PROTO_OPT )
|
||||
|
||||
set( EXT_ASN_FILE_LIST
|
||||
)
|
||||
|
||||
set( ASN_FILE_LIST
|
||||
${PROTOCOL_NAME}.asn
|
||||
)
|
||||
|
||||
set( EXTRA_DIST
|
||||
${ASN_FILE_LIST}
|
||||
packet-${PROTOCOL_NAME}-template.c
|
||||
${PROTOCOL_NAME}.cnf
|
||||
)
|
||||
|
||||
set( SRC_FILES
|
||||
${EXTRA_DIST}
|
||||
${EXT_ASN_FILE_LIST}
|
||||
)
|
||||
|
||||
set( A2W_FLAGS -b )
|
||||
|
||||
ASN2WRS()
|
|
@ -0,0 +1,621 @@
|
|||
--
|
||||
-- GlowDtd.asn1
|
||||
-- Lawo GmbH
|
||||
--
|
||||
-- This file defines the Glow DTD used with the Ember+ protocol.
|
||||
--
|
||||
-- Change Log:
|
||||
--
|
||||
-- 2.50:
|
||||
-- - Added nullable parameter values.
|
||||
-- 2.40:
|
||||
-- - NOTE: This version describes the data schema of Ember+ 1.4.
|
||||
-- - Added Template Extensions
|
||||
-- 2.30:
|
||||
-- - NOTE: This version describes the data schema of Ember+ 1.3.
|
||||
-- - Added Schema Extensions
|
||||
-- 2.20:
|
||||
-- - NOTE: This version describes the data schema of Ember+ 1.2.
|
||||
-- - Added Function Extensions (see type Function)
|
||||
-- 2.10:
|
||||
-- - NOTE: This version describes the data schema of Ember+ 1.1.
|
||||
-- - Added Matrix Extensions (see type Matrix)
|
||||
-- - Added "isOnline" field to NodeContents
|
||||
-- 2.5:
|
||||
-- - NOTE: This version describes the data schema of Ember+ 1.0.
|
||||
-- - NOTE: This version introduces breaking changes!
|
||||
-- - Changed Parameter.isCommand (BOOLEAN) to an enumeration named "type".
|
||||
-- To determine the effective type of a parameter, follow this rule:
|
||||
-- - If the parameter has the "type" field that equals "trigger", its
|
||||
-- type is "trigger".
|
||||
-- - If the parameter has either the "enumeration" or the "enumMap" field,
|
||||
-- its type is "enum".
|
||||
-- - If the parameter has the "value" field, its type corresponds to the
|
||||
-- BER type of the value.
|
||||
-- - If the parameter has the "type" field, its type is the value of this
|
||||
-- field.
|
||||
-- This is useful for parameters that do not specify a current value -
|
||||
-- e.g. "trigger" parameters or parameters that have write-only access.
|
||||
-- - Changed Parameter.isWriteable (BOOLEAN) to an enumeration named
|
||||
-- "access".
|
||||
-- - More options for Value - now also supports OCTET STRING and BOOLEAN
|
||||
-- - Introduces QualifiedParameter and QualifiedNode types
|
||||
-- - Introduces RootElement and RootElementCollection types:
|
||||
-- At the root level, a different set of supported types is available.
|
||||
-- - StreamCollection can also be used as root container.
|
||||
-- - Introduces the StreamDescription type and the field "streamDescriptor"
|
||||
-- in type ParameterContents.
|
||||
-- 2.4:
|
||||
-- - NOTE: This version introduces breaking changes!
|
||||
-- - moved "children" in Parameter and Node out of
|
||||
-- "contents" SET.
|
||||
-- 2.3:
|
||||
-- - Added size constraints for INTEGER values.
|
||||
-- - Renamed EnumEntry to StringIntegerPair
|
||||
-- - Renamed EnumCollection to StringIntegerCollection
|
||||
-- 2.2:
|
||||
-- - Added new field "enumMap" to Parameter and types to describe
|
||||
-- enum entries: EnumEntry and EnumCollection
|
||||
-- 2.1:
|
||||
-- - NOTE: This version introduces breaking changes!
|
||||
-- - Replaced all APPLICATION tags for fields with CONTEXT-SPECIFIC tags
|
||||
-- APPLICATION tags are only used for custom types now.
|
||||
-- 2.0:
|
||||
-- Initial Release
|
||||
--
|
||||
|
||||
|
||||
EmberPlus-Glow DEFINITIONS EXPLICIT TAGS ::= BEGIN
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Primitive Types
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
EmberString ::= UTF8String
|
||||
Integer32 ::= INTEGER (-2147483648 .. 2147483647)
|
||||
Integer64 ::= INTEGER (-9223372036854775808 .. 9223372036854775807)
|
||||
|
||||
|
||||
-- this is the base oid for all RELATIVE-OID values defined in this document.
|
||||
-- when using the RELATIVE-OID type, defining a base oid is required by ASN.1.
|
||||
-- does not have any impact upon the DTD.
|
||||
baseOid OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) lsb(37411) lsb-mgmt(2) emberPlus(1) glow(1) glowVolatile(100) }
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Template
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Template ::=
|
||||
[APPLICATION 24] IMPLICIT SET {
|
||||
number [0] Integer32,
|
||||
element [1] TemplateElement OPTIONAL,
|
||||
description [2] EmberString OPTIONAL
|
||||
}
|
||||
|
||||
QualifiedTemplate ::=
|
||||
[APPLICATION 25] IMPLICIT SET {
|
||||
path [0] RELATIVE-OID,
|
||||
element [1] TemplateElement OPTIONAL,
|
||||
description [2] EmberString OPTIONAL
|
||||
}
|
||||
|
||||
TemplateElement ::=
|
||||
CHOICE {
|
||||
parameter Parameter,
|
||||
node Node,
|
||||
matrix Matrix,
|
||||
function Function
|
||||
}
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Parameter
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Parameter ::=
|
||||
[APPLICATION 1] IMPLICIT
|
||||
SEQUENCE {
|
||||
number [0] Integer32,
|
||||
contents [1] ParameterContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
QualifiedParameter ::=
|
||||
[APPLICATION 9] IMPLICIT
|
||||
SEQUENCE {
|
||||
path [0] RELATIVE-OID,
|
||||
contents [1] ParameterContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
ParameterContents ::=
|
||||
SET {
|
||||
identifier [ 0] EmberString OPTIONAL,
|
||||
description [ 1] EmberString OPTIONAL,
|
||||
value [ 2] Value OPTIONAL,
|
||||
minimum [ 3] MinMax OPTIONAL,
|
||||
maximum [ 4] MinMax OPTIONAL,
|
||||
access [ 5] ParameterAccess OPTIONAL,
|
||||
format [ 6] EmberString OPTIONAL,
|
||||
enumeration [ 7] EmberString OPTIONAL,
|
||||
factor [ 8] Integer32 OPTIONAL,
|
||||
isOnline [ 9] BOOLEAN OPTIONAL,
|
||||
formula [10] EmberString OPTIONAL,
|
||||
step [11] Integer32 OPTIONAL,
|
||||
default [12] Value OPTIONAL,
|
||||
type [13] ParameterType OPTIONAL,
|
||||
streamIdentifier [14] Integer32 OPTIONAL,
|
||||
enumMap [15] StringIntegerCollection OPTIONAL,
|
||||
streamDescriptor [16] StreamDescription OPTIONAL,
|
||||
schemaIdentifiers[17] EmberString OPTIONAL,
|
||||
templateReference[18] RELATIVE-OID OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
Value ::=
|
||||
CHOICE {
|
||||
integer Integer64,
|
||||
real REAL,
|
||||
string EmberString,
|
||||
boolean BOOLEAN,
|
||||
octets OCTET STRING,
|
||||
null NULL
|
||||
}
|
||||
|
||||
|
||||
MinMax ::=
|
||||
CHOICE {
|
||||
integer Integer64,
|
||||
real REAL,
|
||||
null NULL
|
||||
}
|
||||
|
||||
|
||||
ParameterType ::=
|
||||
INTEGER {
|
||||
null (0),
|
||||
integer (1),
|
||||
real (2),
|
||||
string (3),
|
||||
boolean (4),
|
||||
trigger (5),
|
||||
enum (6),
|
||||
octets (7)
|
||||
}
|
||||
|
||||
|
||||
ParameterAccess ::=
|
||||
INTEGER {
|
||||
none (0),
|
||||
read (1), -- default
|
||||
write (2),
|
||||
readWrite (3)
|
||||
}
|
||||
|
||||
|
||||
StringIntegerPair ::=
|
||||
[APPLICATION 7] IMPLICIT
|
||||
SEQUENCE {
|
||||
entryString [0] EmberString,
|
||||
entryInteger [1] Integer32
|
||||
}
|
||||
|
||||
|
||||
StringIntegerCollection ::=
|
||||
[APPLICATION 8] IMPLICIT
|
||||
SEQUENCE OF [0] StringIntegerPair
|
||||
|
||||
|
||||
StreamDescription ::=
|
||||
[APPLICATION 12] IMPLICIT
|
||||
SEQUENCE {
|
||||
streamFormat [0] StreamFormat,
|
||||
offset [1] Integer32 -- byte offset of the value in the streamed blob.
|
||||
}
|
||||
|
||||
|
||||
-- type: 0=uint, 1=int, 2=float
|
||||
-- size: 0=1byte, 1=2byte, 2=4byte, 3=8byte
|
||||
-- endianness: 0=big, 1=little
|
||||
StreamFormat ::=
|
||||
INTEGER {
|
||||
unsignedInt8 ( 0), -- 00000 00 0
|
||||
unsignedInt16BigEndian ( 2), -- 00000 01 0
|
||||
unsignedInt16LittleEndian ( 3), -- 00000 01 1
|
||||
unsignedInt32BigEndian ( 4), -- 00000 10 0
|
||||
unsignedInt32LittleEndian ( 5), -- 00000 10 1
|
||||
unsignedInt64BigEndian ( 6), -- 00000 11 0
|
||||
unsignedInt64LittleEndian ( 7), -- 00000 11 1
|
||||
signedInt8 ( 8), -- 00001 00 0
|
||||
signedInt16BigEndian (10), -- 00001 01 0
|
||||
signedInt16LittleEndian (11), -- 00001 01 1
|
||||
signedInt32BigEndian (12), -- 00001 10 0
|
||||
signedInt32LittleEndian (13), -- 00001 10 1
|
||||
signedInt64BigEndian (14), -- 00001 11 0
|
||||
signedInt64LittleEndian (15), -- 00001 11 1
|
||||
ieeeFloat32BigEndian (20), -- 00010 10 0
|
||||
ieeeFloat32LittleEndian (21), -- 00010 10 1
|
||||
ieeeFloat64BigEndian (22), -- 00010 11 0
|
||||
ieeeFloat64LittleEndian (23) -- 00010 11 1
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Command
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Command ::=
|
||||
[APPLICATION 2] IMPLICIT
|
||||
SEQUENCE {
|
||||
number [0] CommandType,
|
||||
options CHOICE {
|
||||
dirFieldMask [1] FieldFlags, -- only valid if number is getDirectory(32)
|
||||
invocation [2] Invocation -- only valid if number is invoke(33)
|
||||
} OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
CommandType ::=
|
||||
INTEGER {
|
||||
subscribe (30),
|
||||
unsubscribe (31),
|
||||
getDirectory (32),
|
||||
invoke (33)
|
||||
}
|
||||
|
||||
|
||||
FieldFlags ::=
|
||||
INTEGER {
|
||||
sparse (-2),
|
||||
all (-1),
|
||||
default ( 0), -- same as "all"
|
||||
identifier ( 1),
|
||||
description ( 2),
|
||||
tree ( 3),
|
||||
value ( 4),
|
||||
connections ( 5)
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Node
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Node ::=
|
||||
[APPLICATION 3] IMPLICIT
|
||||
SEQUENCE {
|
||||
number [0] Integer32,
|
||||
contents [1] NodeContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
QualifiedNode ::=
|
||||
[APPLICATION 10] IMPLICIT
|
||||
SEQUENCE {
|
||||
path [0] RELATIVE-OID,
|
||||
contents [1] NodeContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
NodeContents ::=
|
||||
SET {
|
||||
identifier [0] EmberString OPTIONAL,
|
||||
description [1] EmberString OPTIONAL,
|
||||
isRoot [2] BOOLEAN OPTIONAL,
|
||||
isOnline [3] BOOLEAN OPTIONAL, -- default is true
|
||||
schemaIdentifiers[4] EmberString OPTIONAL,
|
||||
templateReference[5] RELATIVE-OID OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Matrix
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Matrix ::=
|
||||
[APPLICATION 13] IMPLICIT
|
||||
SEQUENCE {
|
||||
number [0] Integer32,
|
||||
contents [1] MatrixContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL,
|
||||
targetList [3] TargetCollection OPTIONAL,
|
||||
sourceList [4] SourceCollection OPTIONAL,
|
||||
connections [5] ConnectionCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
MatrixContents ::=
|
||||
SET {
|
||||
identifier [ 0] EmberString,
|
||||
description [ 1] EmberString OPTIONAL,
|
||||
type [ 2] MatrixType OPTIONAL,
|
||||
addressingMode [ 3] MatrixAddressingMode OPTIONAL,
|
||||
targetCount [ 4] Integer32, -- linear: matrix X size; nonLinear: number of targets
|
||||
sourceCount [ 5] Integer32, -- linear: matrix Y size; nonLinear: number of sources
|
||||
maximumTotalConnects [ 6] Integer32 OPTIONAL, -- nToN: max number of set connections
|
||||
maximumConnectsPerTarget [ 7] Integer32 OPTIONAL, -- nToN: max number of sources connected to one target
|
||||
parametersLocation [ 8] ParametersLocation OPTIONAL,
|
||||
gainParameterNumber [ 9] Integer32 OPTIONAL, -- nToN: number of connection gain parameter
|
||||
labels [10] LabelCollection OPTIONAL,
|
||||
schemaIdentifiers [11] EmberString OPTIONAL,
|
||||
templateReference [12] RELATIVE-OID OPTIONAL
|
||||
}
|
||||
|
||||
-- Addressing scheme for node at MatrixContents.parametersLocation:
|
||||
-- N 0001 targets.<targetNumber>: subtree containing parameters attached to target with <targetNumber>
|
||||
-- N 0002 sources.<sourceNumber>: subtree containing parameters attached to source with <targetNumber>
|
||||
-- N 0003 connections.<targetNumber>.<sourceNumber>: : subtree containing parameters attached to connection <targetNumber>/<sourceNumber>
|
||||
|
||||
|
||||
MatrixType ::=
|
||||
INTEGER {
|
||||
oneToN (0), -- default
|
||||
oneToOne (1),
|
||||
nToN (2)
|
||||
}
|
||||
|
||||
|
||||
MatrixAddressingMode ::=
|
||||
INTEGER {
|
||||
linear (0), -- default
|
||||
nonLinear (1)
|
||||
}
|
||||
|
||||
|
||||
ParametersLocation ::=
|
||||
CHOICE {
|
||||
basePath RELATIVE-OID, -- absolute path to node containing parameters for targets, sources and connections
|
||||
inline Integer32 -- subidentifier to node containing parameters for targets, sources and connections
|
||||
}
|
||||
|
||||
|
||||
LabelCollection ::=
|
||||
SEQUENCE OF [0] Label
|
||||
|
||||
|
||||
Label ::=
|
||||
[APPLICATION 18] IMPLICIT
|
||||
SEQUENCE {
|
||||
basePath [0] RELATIVE-OID,
|
||||
description [1] EmberString
|
||||
}
|
||||
|
||||
|
||||
TargetCollection ::=
|
||||
SEQUENCE OF [0] Target
|
||||
|
||||
|
||||
Target ::=
|
||||
[APPLICATION 14] IMPLICIT
|
||||
Signal
|
||||
|
||||
|
||||
Signal ::=
|
||||
SEQUENCE {
|
||||
number [0] Integer32
|
||||
}
|
||||
|
||||
|
||||
SourceCollection ::=
|
||||
SEQUENCE OF [0] Source
|
||||
|
||||
|
||||
Source ::=
|
||||
[APPLICATION 15] IMPLICIT
|
||||
Signal
|
||||
|
||||
|
||||
ConnectionCollection ::=
|
||||
SEQUENCE OF [0] Connection
|
||||
|
||||
|
||||
Connection ::=
|
||||
[APPLICATION 16] IMPLICIT
|
||||
SEQUENCE {
|
||||
target [0] Integer32,
|
||||
sources [1] PackedNumbers OPTIONAL, -- not present or empty array means "none"
|
||||
operation [2] ConnectionOperation OPTIONAL,
|
||||
disposition [3] ConnectionDisposition OPTIONAL
|
||||
}
|
||||
|
||||
-- Use case 1: Tally (Provider to consumer)
|
||||
-- Connection: { target:1, sources:[5,2], operation:absolute, disposition:tally }
|
||||
|
||||
-- Use case 2: Take (Consumer to provider)
|
||||
-- Connection: { target:1, sources:[4], operation:absolute|connect|disconnect }
|
||||
|
||||
-- Use case 3: TakeResponse (Provider to consumer)
|
||||
-- Connection: { target:1, sources:[4], operation:absolute, disposition:modified|pending|locked|... }
|
||||
|
||||
|
||||
PackedNumbers ::=
|
||||
RELATIVE-OID
|
||||
|
||||
|
||||
ConnectionOperation ::=
|
||||
INTEGER {
|
||||
absolute (0), -- default. sources contains absolute information
|
||||
connect (1), -- nToN only. sources contains sources to add to connection
|
||||
disconnect (2) -- nToN only. sources contains sources to remove from connection
|
||||
}
|
||||
|
||||
|
||||
ConnectionDisposition ::=
|
||||
INTEGER {
|
||||
tally (0), -- default
|
||||
modified (1), -- sources contains new current state
|
||||
pending (2), -- sources contains future state
|
||||
locked (3) -- error: target locked. sources contains current state
|
||||
-- more tbd.
|
||||
}
|
||||
|
||||
|
||||
QualifiedMatrix ::=
|
||||
[APPLICATION 17] IMPLICIT
|
||||
SEQUENCE {
|
||||
path [0] RELATIVE-OID,
|
||||
contents [1] MatrixContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL,
|
||||
targetList [3] TargetCollection OPTIONAL,
|
||||
sourceList [4] SourceCollection OPTIONAL,
|
||||
connections [5] ConnectionCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Function
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Function ::=
|
||||
[APPLICATION 19] IMPLICIT
|
||||
SEQUENCE {
|
||||
number [0] Integer32,
|
||||
contents [1] FunctionContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
QualifiedFunction ::=
|
||||
[APPLICATION 20] IMPLICIT
|
||||
SEQUENCE {
|
||||
path [0] RELATIVE-OID,
|
||||
contents [1] FunctionContents OPTIONAL,
|
||||
children [2] ElementCollection OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
FunctionContents ::=
|
||||
SET {
|
||||
identifier [0] EmberString OPTIONAL,
|
||||
description [1] EmberString OPTIONAL,
|
||||
arguments [2] TupleDescription OPTIONAL,
|
||||
result [3] TupleDescription OPTIONAL,
|
||||
templateReference[4] RELATIVE-OID OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
TupleDescription ::=
|
||||
SEQUENCE OF [0] TupleItemDescription
|
||||
|
||||
|
||||
TupleItemDescription ::=
|
||||
[APPLICATION 21] IMPLICIT
|
||||
SEQUENCE {
|
||||
type [0] ParameterType,
|
||||
name [1] EmberString OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
Invocation ::=
|
||||
[APPLICATION 22] IMPLICIT
|
||||
SEQUENCE {
|
||||
invocationId [0] Integer32 OPTIONAL,
|
||||
arguments [1] Tuple OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
Tuple ::=
|
||||
SEQUENCE OF [0] Value
|
||||
|
||||
|
||||
InvocationResult ::=
|
||||
[APPLICATION 23] IMPLICIT
|
||||
SEQUENCE {
|
||||
invocationId [0] Integer32,
|
||||
success [1] BOOLEAN OPTIONAL,
|
||||
result [2] Tuple OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- ElementCollection
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
ElementCollection ::=
|
||||
[APPLICATION 4] IMPLICIT
|
||||
SEQUENCE OF [0] Element
|
||||
|
||||
|
||||
Element ::=
|
||||
CHOICE {
|
||||
parameter Parameter,
|
||||
node Node,
|
||||
command Command,
|
||||
matrix Matrix,
|
||||
function Function,
|
||||
template Template
|
||||
}
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Streams
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
StreamEntry ::=
|
||||
[APPLICATION 5] IMPLICIT
|
||||
SEQUENCE {
|
||||
streamIdentifier [0] Integer32,
|
||||
streamValue [1] Value
|
||||
}
|
||||
|
||||
|
||||
StreamCollection ::=
|
||||
[APPLICATION 6] IMPLICIT
|
||||
SEQUENCE OF [0] StreamEntry
|
||||
|
||||
|
||||
-- ======================================================
|
||||
--
|
||||
-- Root
|
||||
--
|
||||
-- ======================================================
|
||||
|
||||
Root ::=
|
||||
[APPLICATION 0]
|
||||
CHOICE {
|
||||
elements RootElementCollection,
|
||||
streams StreamCollection,
|
||||
invocationResult InvocationResult
|
||||
}
|
||||
|
||||
|
||||
RootElementCollection ::=
|
||||
[APPLICATION 11] IMPLICIT
|
||||
SEQUENCE OF [0] RootElement
|
||||
|
||||
|
||||
RootElement ::=
|
||||
CHOICE {
|
||||
element Element,
|
||||
qualifiedParameter QualifiedParameter,
|
||||
qualifiedNode QualifiedNode,
|
||||
qualifiedMatrix QualifiedMatrix,
|
||||
qualifiedFunction QualifiedFunction,
|
||||
qualifiedTemplate QualifiedTemplate
|
||||
}
|
||||
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# Glow conformation file
|
||||
|
||||
#.MODULE_IMPORT
|
||||
|
||||
#.EXPORTS
|
||||
|
||||
#.PDU
|
||||
Root
|
||||
|
||||
#.NO_EMIT
|
||||
|
||||
#.TYPE_RENAME
|
||||
|
||||
#.FIELD_RENAME
|
||||
|
||||
#.END
|
|
@ -0,0 +1,90 @@
|
|||
/* packet-glow.c
|
||||
* Routines for GLOW packet dissection
|
||||
*
|
||||
* Copyright 2018, Gilles Dufour <dufour.gilles@gmail.com>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include "packet-ber.h"
|
||||
|
||||
#define PNAME "Glow"
|
||||
#define PSNAME "GLOW"
|
||||
#define PFNAME "glow"
|
||||
|
||||
void proto_register_glow(void);
|
||||
|
||||
static dissector_handle_t glow_handle=NULL;
|
||||
static int proto_glow = -1;
|
||||
|
||||
#include "packet-glow-hf.c"
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static int ett_glow = -1;
|
||||
|
||||
#include "packet-glow-ett.c"
|
||||
|
||||
#include "packet-glow-fn.c"
|
||||
|
||||
static int
|
||||
dissect_glow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
proto_item *glow_item = NULL;
|
||||
proto_tree *glow_tree = NULL;
|
||||
|
||||
/* make entry in the Protocol column on summary display */
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, PNAME);
|
||||
|
||||
/* create the glow protocol tree */
|
||||
glow_item = proto_tree_add_item(tree, proto_glow, tvb, 0, -1, ENC_NA);
|
||||
glow_tree = proto_item_add_subtree(glow_item, ett_glow);
|
||||
|
||||
dissect_Root_PDU(tvb, pinfo, glow_tree, data);
|
||||
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
void proto_register_glow(void) {
|
||||
|
||||
/* List of fields */
|
||||
static hf_register_info hf[] = {
|
||||
|
||||
#include "packet-glow-hfarr.c"
|
||||
};
|
||||
|
||||
/* List of subtrees */
|
||||
static gint *ett[] = {
|
||||
&ett_glow,
|
||||
#include "packet-glow-ettarr.c"
|
||||
};
|
||||
|
||||
|
||||
/* Register protocol */
|
||||
proto_glow = proto_register_protocol(PNAME, PSNAME, PFNAME);
|
||||
glow_handle = register_dissector("glow", dissect_glow, proto_glow);
|
||||
|
||||
/* Register fields and subtrees */
|
||||
proto_register_field_array(proto_glow, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,689 @@
|
|||
/* packet-S101.c
|
||||
* Routines for S101 dissection
|
||||
* Copyright 2018, Gilles Dufour <dufour.gilles@gmail.com>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/*
|
||||
* This Dissector will dissect S101 frames used by Lawo Ember Plus protocol.
|
||||
* https://github.com/Lawo/ember-plus/
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <epan/packet.h> /* Should be first Wireshark include (other than config.h) */
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/reassemble.h>
|
||||
#include <wsutil/crc16.h>
|
||||
#include <epan/expert.h>
|
||||
|
||||
|
||||
#define S101_HEADER_DATA_LENGTH 9
|
||||
#define S101_BOF 0xFE
|
||||
#define S101_EOF 0xFF
|
||||
#define S101_CE 0xFD
|
||||
#define S101_XOR 0x20
|
||||
#define S101_INV 0xF8
|
||||
#define S101_SLOT 0x00
|
||||
#define S101_MSG_EMBER 0x0E
|
||||
#define S101_CMD_EMBER 0x00
|
||||
#define S101_CMD_KEEPALIVE_REQ 0x01
|
||||
#define S101_CMD_KEEPALIVE_RESP 0x02
|
||||
#define S101_VERSION 0x01
|
||||
#define FLAG_SINGLE_PACKET 0xC0
|
||||
#define FLAG_FIRST_MULTI_PACKET 0x80
|
||||
#define FLAG_LAST_MULTI_PACKET 0x40
|
||||
#define FLAG_EMPTY_PACKET 0x20
|
||||
#define FLAG_MULTI_PACKET 0x00
|
||||
#define S101_DTD_GLOW 0x01
|
||||
#define S101_DTD_VERSION_MAJOR 0x02
|
||||
#define S101_DTD_VERSION_MINOR 0x1F
|
||||
#define S101_VALID_CRC 0xF0B8
|
||||
#define APP_BYTES_LEN 2
|
||||
|
||||
static int hf_S101_frame_format = -1;
|
||||
static int hf_S101_length_size = -1;
|
||||
static int hf_S101_message_length = -1;
|
||||
static int hf_S101_slot = -1;
|
||||
static int hf_S101_message_type = -1;
|
||||
static int hf_S101_cmd_type = -1;
|
||||
static int hf_S101_version = -1;
|
||||
static int hf_S101_flags = -1;
|
||||
static int hf_S101_dtd_type = -1;
|
||||
static int hf_S101_app_bytes_len = -1;
|
||||
static int hf_S101_dtd_minor_ver = -1;
|
||||
static int hf_S101_dtd_major_ver = -1;
|
||||
static int hf_S101_crc = -1;
|
||||
static int hf_S101_crc_status = -1;
|
||||
static int hf_S101_eof = -1;
|
||||
static int hf_S101_error = -1;
|
||||
|
||||
static dissector_handle_t glow_handle = NULL;
|
||||
static reassembly_table s101_data_reassembly_table;
|
||||
|
||||
typedef struct _s101_fragment_t {
|
||||
guint32 id;
|
||||
int offset;
|
||||
} s101_fragment_t;
|
||||
|
||||
/* Prototypes */
|
||||
/* (Required to prevent [-Wmissing-prototypes] warnings */
|
||||
void proto_reg_handoff_S101(void);
|
||||
void proto_register_S101(void);
|
||||
tvbuff_t *decode_s101_escaped_buffer(tvbuff_t *tvb, packet_info *pinfo, int *offset, guint16 *crc);
|
||||
guint32 get_fragment_pdu_id(packet_info *pinfo);
|
||||
s101_fragment_t* new_fragment_info(packet_info *pinfo);
|
||||
void display_expert_info(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int len);
|
||||
|
||||
/* Initialize the protocol and registered fields */
|
||||
static int proto_S101 = -1;
|
||||
|
||||
/* Global sample port preference - real port preferences should generally
|
||||
* default to 0 unless there is an IANA-registered (or equivalent) port for your
|
||||
* protocol. */
|
||||
#define S101_TCP_PORT 9000
|
||||
static guint tcp_port_pref = S101_TCP_PORT;
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static gint ett_S101 = -1;
|
||||
static gint ett_decoding_error = -1;
|
||||
|
||||
#define S101_MIN_LENGTH 5
|
||||
|
||||
static int hf_msg_fragments = -1;
|
||||
static int hf_msg_fragment = -1;
|
||||
static int hf_msg_fragment_overlap = -1;
|
||||
static int hf_msg_fragment_overlap_conflicts = -1;
|
||||
static int hf_msg_fragment_multiple_tails = -1;
|
||||
static int hf_msg_fragment_too_long_fragment = -1;
|
||||
static int hf_msg_fragment_error = -1;
|
||||
static int hf_msg_fragment_count = -1;
|
||||
static int hf_msg_reassembled_in = -1;
|
||||
static int hf_msg_reassembled_length = -1;
|
||||
static int hf_msg_reassembled_data = -1;
|
||||
|
||||
|
||||
static expert_field ei_s101_failed_reassembly = EI_INIT;
|
||||
|
||||
static gint ett_msg_fragment = -1;
|
||||
static gint ett_msg_fragments = -1;
|
||||
|
||||
static const fragment_items msg_frag_items = {
|
||||
/* Fragment subtrees */
|
||||
&ett_msg_fragment,
|
||||
&ett_msg_fragments,
|
||||
/* Fragment fields */
|
||||
&hf_msg_fragments,
|
||||
&hf_msg_fragment,
|
||||
&hf_msg_fragment_overlap,
|
||||
&hf_msg_fragment_overlap_conflicts,
|
||||
&hf_msg_fragment_multiple_tails,
|
||||
&hf_msg_fragment_too_long_fragment,
|
||||
&hf_msg_fragment_error,
|
||||
&hf_msg_fragment_count,
|
||||
/* Reassembled in field */
|
||||
&hf_msg_reassembled_in,
|
||||
/* Reassembled length field */
|
||||
&hf_msg_reassembled_length,
|
||||
&hf_msg_reassembled_data,
|
||||
/* Tag */
|
||||
"Message fragments"
|
||||
};
|
||||
|
||||
/*
|
||||
Create a unique id to link fragments together.
|
||||
This is a 4 bytes value:
|
||||
| SRCPORT (16) | SRC_ADDRESS (16) |
|
||||
SRC_ADDRESS is last 2 bytes of the src address.
|
||||
*/
|
||||
guint32 get_fragment_pdu_id(packet_info *pinfo) {
|
||||
guint32 id = pinfo->srcport << 16;
|
||||
const guint8 *data = (const guint8*)pinfo->src.data;
|
||||
if (pinfo->src.len >= 2) {
|
||||
id = id + (((guint32)data[pinfo->src.len - 2]) << 8) + (guint32)data[pinfo->src.len - 1];
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static wmem_map_t* s101_fragment_info_hash = NULL;
|
||||
|
||||
s101_fragment_t* new_fragment_info(packet_info *pinfo) {
|
||||
s101_fragment_t* fi = (s101_fragment_t*)wmem_alloc(wmem_file_scope(), sizeof(s101_fragment_t));
|
||||
if (NULL == fi) { return fi; }
|
||||
fi->id = pinfo->num;
|
||||
fi->offset = 0;
|
||||
return fi;
|
||||
}
|
||||
|
||||
/* Get 1 byte
|
||||
If byte escaped, get the unescaped value
|
||||
*/
|
||||
static guint8 get_byte(tvbuff_t *tvb, int *offset, guint16 *crc) {
|
||||
guint8 b = tvb_get_guint8(tvb, *offset);
|
||||
*crc = crc16_ccitt_seed(&b, 1, *crc) ^ 0xFFFF;
|
||||
*offset = *offset + 1;
|
||||
if (b == S101_CE) {
|
||||
b = tvb_get_guint8(tvb, *offset);
|
||||
*crc = crc16_ccitt_seed(&b, 1, *crc) ^ 0xFFFF;
|
||||
*offset = *offset + 1;
|
||||
return (b ^ S101_XOR);
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const value_string frame_format_vs[] = {
|
||||
{ S101_BOF , "Escaped Frame" },
|
||||
{ S101_INV , "UnEscaped Frame"},
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
static const value_string message_type_vs[] = {
|
||||
{ S101_MSG_EMBER , "Ember" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
static const value_string command_type_vs[] = {
|
||||
{ S101_CMD_EMBER , "Ember Command" },
|
||||
{ S101_CMD_KEEPALIVE_REQ , "Keepalive Request" },
|
||||
{ S101_CMD_KEEPALIVE_RESP , "Keepalive Response" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
static const value_string flags_vs[] = {
|
||||
{ FLAG_SINGLE_PACKET , "Single Packet" },
|
||||
{ FLAG_EMPTY_PACKET , "Empty Packet" },
|
||||
{ FLAG_MULTI_PACKET , "Multi Packet" },
|
||||
{ FLAG_LAST_MULTI_PACKET , "Last Packet" },
|
||||
{ FLAG_FIRST_MULTI_PACKET , "First Packet" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
static const value_string dtd_type_vs[] = {
|
||||
{ S101_DTD_GLOW , "DTD Glow" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
display_expert_info(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int len) {
|
||||
proto_item* pi;
|
||||
proto_tree *error_tree;
|
||||
|
||||
error_tree = proto_tree_add_subtree(tree, tvb, offset, len,
|
||||
ett_decoding_error, &pi, "S101 Error");
|
||||
|
||||
pi = proto_tree_add_string_format_value(
|
||||
error_tree, hf_S101_error, tvb, offset, len, "s101_error",
|
||||
"reassembly error");
|
||||
|
||||
expert_add_info(pinfo, pi, &ei_s101_failed_reassembly);
|
||||
}
|
||||
|
||||
/*
|
||||
Check s101 packet header format.
|
||||
If not valid, return 0.
|
||||
If valid, extract all header parameters and return 1.
|
||||
If variant1, set msgLength to zero. We will have to search the end of frame.
|
||||
If variant2, the msgLength contains the msgLength in bytes 0-6 and byte 7 is the number of bytes.
|
||||
*/
|
||||
static int
|
||||
find_s101_packet_header(tvbuff_t *tvb, int* offset, guint8 *start, guint8 *slot, guint8 *message, guint8 *version, guint8 *dtd, guint8 *command,
|
||||
guint8 *flags, guint8* app_bytes, guint64 *msgLength, guint16 *crc)
|
||||
{
|
||||
guint8 app_bytes_len;
|
||||
int i;
|
||||
|
||||
*start = tvb_get_guint8(tvb, *offset); // no CRC and no escaping on first bytes.
|
||||
*offset = *offset + 1;
|
||||
if (*start == S101_INV) { // Variant 2 of header - unescaped data
|
||||
//Read the frame length
|
||||
app_bytes_len = tvb_get_guint8(tvb, *offset) & 0x7;
|
||||
*offset = *offset + 1;
|
||||
|
||||
if (app_bytes_len > 1) {
|
||||
*msgLength = tvb_get_bits64 (tvb, *offset, app_bytes_len * 8, ENC_BIG_ENDIAN);
|
||||
*msgLength = *msgLength + (((guint64)app_bytes_len) << 56);
|
||||
*offset = app_bytes_len;
|
||||
}
|
||||
}
|
||||
else if (*start != S101_BOF) {
|
||||
// IF NOT Begining of Frame - variant 1 - escaped data
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
*msgLength = 0;
|
||||
}
|
||||
|
||||
*slot = get_byte(tvb, offset, crc);
|
||||
*message = get_byte(tvb, offset, crc);
|
||||
*command = get_byte(tvb, offset, crc);
|
||||
*version = get_byte(tvb, offset, crc);
|
||||
|
||||
if (*command == S101_CMD_EMBER) {
|
||||
*flags = get_byte(tvb, offset, crc);
|
||||
*dtd = get_byte(tvb, offset, crc);
|
||||
app_bytes_len = get_byte(tvb, offset, crc);
|
||||
}
|
||||
if ((S101_SLOT != *slot) ||
|
||||
(S101_MSG_EMBER != *message) || (*command > S101_CMD_KEEPALIVE_RESP) ||
|
||||
(S101_VERSION != *version ) ||
|
||||
((*command == S101_CMD_EMBER) &&
|
||||
((*flags & 0xF) || (S101_DTD_GLOW != *dtd) || (APP_BYTES_LEN != app_bytes_len)))) {
|
||||
return 0;
|
||||
}
|
||||
if (*command == S101_CMD_EMBER) {
|
||||
for(i = 0; i < APP_BYTES_LEN; i++) {
|
||||
app_bytes[i] = get_byte(tvb, offset, crc);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
decode_s101_escaped_buffer(tvbuff_t *tvb, packet_info *pinfo, int *offset, guint16 *crc) {
|
||||
tvbuff_t *next_tvb;
|
||||
int len;
|
||||
int i;
|
||||
guchar *decoded_buffer;
|
||||
guint8 b;
|
||||
|
||||
len = tvb_captured_length(tvb);
|
||||
if (len <= 0) {
|
||||
return tvb;
|
||||
}
|
||||
decoded_buffer = (guchar*)wmem_alloc(pinfo->pool, len);
|
||||
if (decoded_buffer == NULL) {
|
||||
return tvb;
|
||||
}
|
||||
|
||||
for(i = 0; *offset < len; ) {
|
||||
b = tvb_get_guint8(tvb, *offset);
|
||||
*offset = *offset + 1;
|
||||
if (b == S101_CE) {
|
||||
// Escaped Byte
|
||||
b = tvb_get_guint8(tvb, *offset);
|
||||
*offset = *offset + 1;
|
||||
b = (b ^ S101_XOR);
|
||||
decoded_buffer[i++] = b;
|
||||
}
|
||||
else {
|
||||
decoded_buffer[i] = b;
|
||||
if (b == S101_EOF) { // End of Frame
|
||||
// let's remove the CRC and the EOF
|
||||
if (i > 2) {
|
||||
i -= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*crc = crc16_ccitt_seed(&b, 1, *crc) ^ 0xFFFF;
|
||||
}
|
||||
|
||||
next_tvb = tvb_new_child_real_data(tvb, decoded_buffer, i, i);
|
||||
add_new_data_source(pinfo, next_tvb, "Decoded Data");
|
||||
return next_tvb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Code to actually dissect the packets */
|
||||
static int
|
||||
dissect_S101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
||||
void *data _U_)
|
||||
{
|
||||
/* Set up structures needed to add the protocol subtree and manage it */
|
||||
proto_item *ti;
|
||||
proto_tree *S101_tree;
|
||||
tvbuff_t *tvb_payload;
|
||||
/* Other misc. local variables. */
|
||||
int offset = 0;
|
||||
int parsedLen = 0;
|
||||
int len = 0;
|
||||
int current_offset;
|
||||
int datalen = 0;
|
||||
guint16 crc_data;
|
||||
guint64 msgLength = 0;
|
||||
guint16 crc;
|
||||
guint8 start, slot, message, version, dtd, command, flags = 0xFF, app_bytes[APP_BYTES_LEN];
|
||||
|
||||
/* Check that the packet is long enough for it to belong to us. */
|
||||
len = tvb_reported_length(tvb);
|
||||
if (len < S101_MIN_LENGTH)
|
||||
return 0;
|
||||
|
||||
/* Set the Protocol column to the constant string of S101 */
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "S101");
|
||||
|
||||
current_offset = 0;
|
||||
do {
|
||||
offset = current_offset;
|
||||
crc = 0xFFFF;
|
||||
if (0 == find_s101_packet_header(tvb, &offset, &start, &slot, &message, &version, &dtd, &command, &flags, &app_bytes[0], &msgLength, &crc)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* create display subtree for the protocol */
|
||||
ti = proto_tree_add_item(tree, proto_S101, tvb, current_offset, -1, ENC_NA);
|
||||
|
||||
S101_tree = proto_item_add_subtree(ti, ett_S101);
|
||||
proto_tree_add_item(S101_tree, hf_S101_frame_format, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
|
||||
if (msgLength != 0) {
|
||||
// Variant 2, the header contains a frame length
|
||||
int lengthSize = (int)(msgLength >> 56) & 0xF;
|
||||
proto_tree_add_item(S101_tree, hf_S101_length_size, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_message_length, tvb, current_offset,lengthSize, ENC_NA);
|
||||
current_offset += lengthSize;
|
||||
}
|
||||
proto_tree_add_item(S101_tree, hf_S101_slot, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_message_type, tvb, current_offset++,1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_cmd_type, tvb,current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_version, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
|
||||
if (command == S101_CMD_EMBER) {
|
||||
proto_tree_add_item(S101_tree, hf_S101_flags, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_dtd_type, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_app_bytes_len, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_dtd_minor_ver, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(S101_tree, hf_S101_dtd_major_ver, tvb, current_offset++, 1, ENC_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
if (msgLength == 0) {
|
||||
//Variant 1 - data is encoded with escaped bytes.
|
||||
tvb_payload = decode_s101_escaped_buffer(tvb, pinfo, ¤t_offset, &crc);
|
||||
datalen = tvb_captured_length(tvb_payload);
|
||||
crc_data = tvb_get_ntohs(tvb, current_offset - 3);
|
||||
proto_tree_add_checksum(S101_tree, tvb, current_offset - 3, hf_S101_crc, hf_S101_crc_status, NULL,
|
||||
pinfo, crc == S101_VALID_CRC ? crc_data : crc ^ crc_data, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
|
||||
proto_tree_add_item(S101_tree, hf_S101_eof, tvb, current_offset - 1, 1, ENC_BIG_ENDIAN);
|
||||
}
|
||||
else {
|
||||
//variant 2. Packet size is provided and no encoding
|
||||
datalen = (int)(msgLength & 0x0FFFFFFF) - S101_HEADER_DATA_LENGTH;
|
||||
tvb_payload = tvb_new_subset_length(tvb, current_offset, datalen);
|
||||
current_offset += datalen;
|
||||
}
|
||||
|
||||
proto_item_set_len(ti, current_offset - offset);
|
||||
|
||||
if (command == S101_CMD_EMBER) {
|
||||
if (flags != FLAG_SINGLE_PACKET) {
|
||||
fragment_head *frag_msg = NULL;
|
||||
guint32 id = get_fragment_pdu_id(pinfo);
|
||||
s101_fragment_t* fi = (s101_fragment_t*)wmem_map_lookup(s101_fragment_info_hash, &id);
|
||||
pinfo->fragmented = TRUE;
|
||||
|
||||
if (flags == FLAG_FIRST_MULTI_PACKET) {
|
||||
if (NULL == fi) {
|
||||
fi = new_fragment_info(pinfo);
|
||||
wmem_map_insert(s101_fragment_info_hash, &id, fi);
|
||||
}
|
||||
else {
|
||||
fi->id = pinfo->num;
|
||||
}
|
||||
fragment_add(&s101_data_reassembly_table, tvb_payload, 0,
|
||||
pinfo, fi->id, NULL,
|
||||
0, datalen,
|
||||
TRUE);
|
||||
fi->offset = datalen;
|
||||
}
|
||||
else if (flags == FLAG_LAST_MULTI_PACKET) {
|
||||
if (NULL != fi) {
|
||||
// last fragment
|
||||
frag_msg = fragment_add(&s101_data_reassembly_table, tvb_payload, 0,
|
||||
pinfo, fi->id, NULL,
|
||||
fi->offset, datalen,
|
||||
FALSE);
|
||||
tvb_payload = process_reassembled_data(tvb, offset, pinfo,
|
||||
"Reassembled Message", frag_msg, &msg_frag_items,
|
||||
NULL, S101_tree);
|
||||
}
|
||||
if (frag_msg) { /* Reassembled */
|
||||
col_append_str(pinfo->cinfo, COL_INFO,
|
||||
" (Message Reassembled)");
|
||||
}
|
||||
else {
|
||||
display_expert_info(S101_tree, tvb, pinfo, offset, current_offset - offset);
|
||||
}
|
||||
}
|
||||
else if (NULL == fi) {
|
||||
display_expert_info(S101_tree, tvb, pinfo, offset, current_offset - offset);
|
||||
}
|
||||
else if (flags == FLAG_MULTI_PACKET) {
|
||||
fragment_add(&s101_data_reassembly_table, tvb_payload, 0,
|
||||
pinfo, fi->id, NULL,
|
||||
fi->offset, datalen,
|
||||
TRUE);
|
||||
fi->offset += datalen;
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO,
|
||||
" (Message fragment)");
|
||||
}
|
||||
}
|
||||
|
||||
// Call ASN1 Glow dissector - see epan/dissectors/asn1/glow/ if packet is complete.
|
||||
if ((flags == FLAG_LAST_MULTI_PACKET) && (tvb_payload == NULL)) {
|
||||
proto_item* pi;
|
||||
proto_tree_add_subtree(S101_tree, tvb, offset, current_offset - offset,
|
||||
ett_decoding_error, &pi, "S101 Error");
|
||||
expert_add_info(pinfo, pi, &ei_s101_failed_reassembly);
|
||||
}
|
||||
else if ((glow_handle != NULL) && ((flags == FLAG_LAST_MULTI_PACKET) || (flags == FLAG_SINGLE_PACKET))) {
|
||||
parsedLen = call_dissector_only(glow_handle, tvb_payload, pinfo, S101_tree, data);
|
||||
if (parsedLen <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}while(current_offset < len);
|
||||
return current_offset;
|
||||
}
|
||||
|
||||
/* Register the protocol with Wireshark.
|
||||
*
|
||||
* This format is require because a script is used to build the C function that
|
||||
* calls all the protocol registration.
|
||||
*/
|
||||
void
|
||||
proto_register_S101(void)
|
||||
{
|
||||
module_t *S101_module;
|
||||
expert_module_t* expert_s101;
|
||||
|
||||
/* Setup list of header fields See Section 1.5 of README.dissector for
|
||||
* details. */
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_S101_frame_format,
|
||||
{ "Frame Format", "s101.format",
|
||||
FT_UINT8, BASE_HEX, VALS(frame_format_vs), 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_length_size,
|
||||
{ "Bytes for Length", "s101.lensize",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_message_length,
|
||||
{ "Message Length", "s101.msglen",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_slot,
|
||||
{ "Slot", "s101.slot",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_message_type,
|
||||
{ "Message Type", "s101.msgtype",
|
||||
FT_UINT8, BASE_HEX, VALS(message_type_vs), 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_cmd_type,
|
||||
{ "Command Type", "s101.cmdtype",
|
||||
FT_UINT8, BASE_HEX, VALS(command_type_vs), 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_version,
|
||||
{ "Version", "s101.version",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_flags,
|
||||
{ "Flags", "s101.flags",
|
||||
FT_UINT8, BASE_HEX, VALS(flags_vs), 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_dtd_type,
|
||||
{ "DTD Type", "s101.dtdtype",
|
||||
FT_UINT8, BASE_DEC, VALS(dtd_type_vs), 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_app_bytes_len,
|
||||
{ "App Bytes Length", "s101.applen",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_dtd_minor_ver,
|
||||
{ "App Minor Version", "s101.appminver",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_dtd_major_ver,
|
||||
{ "App Major Version", "s101.appmajver",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_crc,
|
||||
{ "CRC", "s101.crc",
|
||||
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_crc_status,
|
||||
{ "Checksum Status", "s101.crc.status",
|
||||
FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
|
||||
NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_eof,
|
||||
{ "End of Frane", "s101.eof",
|
||||
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_S101_error, {
|
||||
"S101 Error", "s101.error", FT_STRING, BASE_NONE,
|
||||
NULL, 0, NULL, HFILL }},
|
||||
|
||||
// fragments info
|
||||
{&hf_msg_fragments,
|
||||
{ "Message fragments", "s101.msg.fragments",
|
||||
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment,
|
||||
{ "Message fragment", "s101.msg.fragment",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_overlap,
|
||||
{ "Message fragment overlap", "s101.msg.fragment.overlap",
|
||||
FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_overlap_conflicts,
|
||||
{ "Message fragment overlapping with conflicting data", "s101.msg.fragment.overlap.conflicts",
|
||||
FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_multiple_tails,
|
||||
{ "Message has multiple tail fragments", "s101.msg.fragment.multiple_tails",
|
||||
FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_too_long_fragment,
|
||||
{ "Message fragment too long", "s101.msg.fragment.too_long_fragment",
|
||||
FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_error,
|
||||
{ "Message defragmentation error", "s101.msg.fragment.error",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_fragment_count,
|
||||
{ "Message fragment count", "s101.msg.fragment.count",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_reassembled_in,
|
||||
{ "Reassembled in", "s101.msg.reassembled.in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_reassembled_length,
|
||||
{ "Reassembled length", "s101.msg.reassembled.length",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
|
||||
|
||||
{&hf_msg_reassembled_data,
|
||||
{ "Reassembled Data", "s101.msg.reassembled.data",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }},
|
||||
};
|
||||
|
||||
/* Setup protocol subtree array */
|
||||
static gint *ett[] = {
|
||||
&ett_S101,
|
||||
&ett_msg_fragment,
|
||||
&ett_msg_fragments,
|
||||
&ett_decoding_error
|
||||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_s101_failed_reassembly, { "s101.reassembly_error", PI_MALFORMED, PI_WARN, "Reassembly Error", EXPFILL }},
|
||||
};
|
||||
|
||||
/* Register the protocol name and description */
|
||||
proto_S101 = proto_register_protocol("S101",
|
||||
"S101", "s101");
|
||||
|
||||
/* Required function calls to register the header fields and subtrees */
|
||||
proto_register_field_array(proto_S101, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
reassembly_table_register(&s101_data_reassembly_table,
|
||||
&addresses_ports_reassembly_table_functions);
|
||||
|
||||
s101_fragment_info_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
|
||||
g_direct_hash, g_direct_equal);
|
||||
|
||||
S101_module = prefs_register_protocol(proto_S101,
|
||||
proto_reg_handoff_S101);
|
||||
|
||||
expert_s101 = expert_register_protocol(proto_S101);
|
||||
expert_register_field_array(expert_s101, ei, array_length(ei));
|
||||
|
||||
/* Register an example port preference */
|
||||
prefs_register_uint_preference(S101_module, "tcp.port", "S101 TCP Port",
|
||||
"S101 TCP port if other than the default",
|
||||
10, &tcp_port_pref);
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_S101(void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
static dissector_handle_t S101_handle;
|
||||
static int current_port;
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
S101_handle = create_dissector_handle(dissect_S101,
|
||||
proto_S101);
|
||||
|
||||
glow_handle = find_dissector_add_dependency("glow", proto_S101);
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
} else {
|
||||
dissector_delete_uint("tcp.port", current_port, S101_handle);
|
||||
}
|
||||
|
||||
current_port = tcp_port_pref;
|
||||
|
||||
dissector_add_uint("tcp.port", current_port, S101_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
Loading…
Reference in New Issue