From 6a842040253689fa2e9542605ee4c0ea6415fe6c Mon Sep 17 00:00:00 2001 From: Fred Klassen Date: Tue, 27 Aug 2019 21:12:42 -0700 Subject: [PATCH] Add support for AppNeta protocols --- CMakeLists.txt | 3 +- CMakeListsCustom.txt | 43 + README.appneta.md | 98 + debian/changelog | 31 + epan/packet.c | 2 +- packaging/debian/rules | 15 +- packaging/nsis/custom_plugins.txt | 6 +- packaging/nsis/wireshark.nsi | 3 + plugins/epan/ani_payload/CMakeLists.txt | 53 + plugins/epan/ani_payload/packet-ani-payload.c | 399 +++ plugins/epan/ani_payload/packet-ani-payload.h | 25 + plugins/epan/ani_rpp/CMakeLists.txt | 53 + plugins/epan/ani_rpp/packet-ani-rpp.c | 2774 +++++++++++++++++ plugins/epan/twamp/CMakeLists.txt | 53 + plugins/epan/twamp/Changelog | 5 + plugins/epan/twamp/packet-twamp.c | 331 ++ 16 files changed, 3885 insertions(+), 9 deletions(-) create mode 100644 CMakeListsCustom.txt create mode 100644 README.appneta.md create mode 100644 debian/changelog create mode 100644 plugins/epan/ani_payload/CMakeLists.txt create mode 100644 plugins/epan/ani_payload/packet-ani-payload.c create mode 100644 plugins/epan/ani_payload/packet-ani-payload.h create mode 100644 plugins/epan/ani_rpp/CMakeLists.txt create mode 100644 plugins/epan/ani_rpp/packet-ani-rpp.c create mode 100644 plugins/epan/twamp/CMakeLists.txt create mode 100644 plugins/epan/twamp/Changelog create mode 100644 plugins/epan/twamp/packet-twamp.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 48368387cfbb..6e1517a61af5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,8 @@ set(PROJECT_MAJOR_VERSION 4) set(PROJECT_MINOR_VERSION 2) set(PROJECT_PATCH_VERSION 0) set(PROJECT_BUILD_VERSION 0) -set(PROJECT_VERSION_EXTENSION "") +set(PROJECT_BUILD_VERSION ${GIT_REVISION}) +set(PROJECT_VERSION_EXTENSION "-appneta.52") if(DEFINED ENV{WIRESHARK_VERSION_EXTRA}) set(PROJECT_VERSION_EXTENSION "$ENV{WIRESHARK_VERSION_EXTRA}") diff --git a/CMakeListsCustom.txt b/CMakeListsCustom.txt new file mode 100644 index 000000000000..47c68b6d9044 --- /dev/null +++ b/CMakeListsCustom.txt @@ -0,0 +1,43 @@ +# CMakeListsCustom.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Add a list of your custom plugins SRC dir here including the path +# + +# Fail CMake stage if any of these plugins are missing from source tree +set(CUSTOM_PLUGIN_SRC_DIR + plugins/epan/ani_payload + plugins/epan/ani_rpp + plugins/epan/twamp +) + +# Do not fail CMake stage if any of the optional plugins are missing from source tree +set(_OPTIONAL_CUSTOM_PLUGIN_SRC_DIR + plugins/epan/bar +) + +foreach( _plugin_dir ${_OPTIONAL_CUSTOM_PLUGIN_SRC_DIR} ) + if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_plugin_dir}/CMakeLists.txt ) + list( APPEND CUSTOM_PLUGIN_SRC_DIR ${_plugin_dir} ) + else() + message( WARNING "Custom plugins: No ${_plugin_dir}/CMakeLists.txt file found - ignoring" ) + endif() +endforeach() + +# +# Editor modelines - https://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 8 +# tab-width: 8 +# indent-tabs-mode: t +# End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# diff --git a/README.appneta.md b/README.appneta.md new file mode 100644 index 000000000000..5665127c4c2c --- /dev/null +++ b/README.appneta.md @@ -0,0 +1,98 @@ +MacOS +===== + +References: +----------- + +* Code Signing: + * https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html + * https://developer.apple.com/library/archive/technotes/tn2206/_index.html + +* Notarizing + * https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution + +Prereq: +------- + + sudo gem install asciidoctor + pip3 install dmgbuild + +Build: +------ + +Run one time only, or if moving to a new Wireshark revision + + MACOSX_SUPPORT_LIBS=/Users//git/pvc-appliance/macos-support-libs tools/macos-setup.sh -t 10.14 + +Here are some exports - CODE_SIGN_IDENTITY as per 'security find-identity -p codesigning -v login.keychain' + + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/Users//Qt5.12.4/5.12.4/clang_64/lib/pkgconfig + export CMAKE_PREFIX_PATH=/Users//Qt5.12.4/5.12.4/clang_64/lib/cmake + export CODE_SIGN_IDENTITY="AppNeta Inc" + PATH=/Users//Qt5.12.4/5.12.4/clang_64/bin:/Library/Frameworks/Python.framework/Versions/3.7/bin/:$PATH + export PATH + + mkdir build; cd build + cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.14 -G Ninja .. + ninja + ninja app_bundle + +Notarize: +--------- + +At this point you may want to notarize the app_bundle - you will require an +application-specific password - https://support.apple.com/en-us/HT204397 + + cd run + ditto -ck --keepParent Wireshark.app Wireshark.zip + xcrun altool --notarize-app --primary-bundle-id "com.appneta.wireshark.app" --username --password --file Wireshark.zip + +Wait up to 5 minutes for success - check using this command + + xcrun altool --notarize-history 0 --username --password + +Staple the notarization result so app can be verified as notarized when offline + + xcrun stapler staple Wireshark.app + cd .. + +macOS Package: +-------------- + + cd run + ../packaging/macosx/osx-dmg.sh + xcrun altool --notarize-app --primary-bundle-id "com.appneta.wireshark.dmg" --username --password --file Wireshark\ \ Intel\ 64.dmg + xcrun altool --notarize-history 0 --username --password + xcrun stapler staple Wireshark\ \ Intel\ 64.dmg + cd .. + +Linux +===== + +To build Linux debug: +--------------------- + + mkdir -p build-debug + cd build-debug + cmake -DCMAKE_BUILD_TYPE=Debug .. + make -j6 + +Make Linux Package: +------------------ + +Update version in CMakeList.txt and debian/changelog + + $ mkdir -p /tmp/wireshark_3.4.2.appneta.50_repo + pdebuild --use-pdebuild-internal --debbuildopts "-b -a amd64 -us -uc" --buildresult /tmp/wireshark_3.4.2.appneta.50_repo + +Once packages are made, do something like: + + $ cd /tmp/wireshark_3.4.2.appneta.50_repo + $ dpkg-scanpackages . | xz -c > Packages.xz + +Optionally you can move directory and install packages locally +... in /etc/apt/sources.list.d/wireshark.list ... + + deb [trusted=yes] file:/home/fklassen/data/wireshark_3.4.2.appneta.50_repo ./ + $ sudo apt update + $ sudo apt install wireshark diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000000..3c9e3994578d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,31 @@ +wireshark (3.4.3.appneta.52) UNRELEASED; urgency=medium + + * fix for windows build + + -- AppNeta Thu, 16 Feb 2021 08:33:48 -0800 + +wireshark (3.4.3.appneta.51) UNRELEASED; urgency=medium + + * fix init.lua build issue + + -- AppNeta Thu, 11 Feb 2021 12:05:12 -0800 + +wireshark (3.4.2.appneta.50) unstable; urgency=medium + + * updates to build on Buster + + -- AppNeta Wed, 20 Jan 2021 19:50:12 -0800 + +wireshark (3.2.5.appneta.49) unstable; urgency=medium + + * macOS installer supports Mojave and Catalina + * macosx-setup non-sudo mode + * update to 3.2.5 + + -- AppNeta Wed, 26 May 2020 11:30:00 -0700 + +wireshark (3.4.5) unstable; urgency=low + + * Self-made package + + -- Wireshark Self-made package Mon, 17 Oct 2016 12:05:44 +0200 diff --git a/epan/packet.c b/epan/packet.c index 70507045af35..870aa6ef38e8 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -226,7 +226,7 @@ packet_cache_proto_handles(void) file_handle = find_dissector("file"); ws_assert(file_handle != NULL); - data_handle = find_dissector("data"); + data_handle = find_dissector("appneta_payload"); ws_assert(data_handle != NULL); proto_malformed = proto_get_id_by_filter_name("_ws.malformed"); diff --git a/packaging/debian/rules b/packaging/debian/rules index 16e39abf49eb..40d8ce257ffc 100755 --- a/packaging/debian/rules +++ b/packaging/debian/rules @@ -7,6 +7,9 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 +# Catch symbol additions. +export DPKG_GENSYMBOLS_CHECK_LEVEL=4 + distrelease := $(shell lsb_release -cs) ifeq ($(distrelease),n/a) distrelease := sid @@ -31,7 +34,7 @@ endif dh $@ --with python3 --buildsystem $(DH_BUILDSYSTEM) --with quilt override_dh_auto_configure: - dh_auto_configure -- -DBUILD_xxx2deb=ON -DBUILD_corbaidl2wrs=ON -DUSE_qt6=OFF + dh_auto_configure -- -DBUILD_xxx2deb=ON -DBUILD_corbaidl2wrs=ON override_dh_auto_build: # Ignore warnings from asn2wrs.py about duplicate field names. @@ -55,13 +58,13 @@ override_dh_strip: override_dh_auto_install: dh_auto_install -ifeq ($(MAKE),ninja) - DESTDIR=$(CURDIR)/debian/tmp $(MAKE) -C $(CURDIR)/obj-* install-headers -else - $(MAKE) DESTDIR=$(CURDIR)/debian/tmp -C $(CURDIR)/obj-* install-headers -endif rm -f debian/*.shlibs rm -rf $(CURDIR)/debian/tmp/usr/share/wireshark/COPYING + mkdir -p $(CURDIR)/debian/tmp/etc/wireshark/ + mv $(CURDIR)/debian/tmp/usr/share/wireshark/init.lua \ + $(CURDIR)/debian/tmp/etc/wireshark/ + ln -s /etc/wireshark/init.lua \ + $(CURDIR)/debian/tmp/usr/share/wireshark/init.lua override_dh_install: dh_install diff --git a/packaging/nsis/custom_plugins.txt b/packaging/nsis/custom_plugins.txt index 12338056e7de..6d0e182d0d07 100644 --- a/packaging/nsis/custom_plugins.txt +++ b/packaging/nsis/custom_plugins.txt @@ -1,3 +1,7 @@ ;Add your custom plugins directives here ; Example: -;File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\foo.dll" +;File "${STAGING_DIR}\plugins\${VERSION_MAJOR}.${VERSION_MINOR}\epan\foo.dll" + +File "${STAGING_DIR}\plugins\${VERSION_MAJOR}.${VERSION_MINOR}\epan\ani_payload.dll" +File "${STAGING_DIR}\plugins\${VERSION_MAJOR}.${VERSION_MINOR}\epan\ani_rpp.dll" +File "${STAGING_DIR}\plugins\${VERSION_MAJOR}.${VERSION_MINOR}\epan\twamp.dll" diff --git a/packaging/nsis/wireshark.nsi b/packaging/nsis/wireshark.nsi index e85656b994e7..7921d75f08b2 100644 --- a/packaging/nsis/wireshark.nsi +++ b/packaging/nsis/wireshark.nsi @@ -1070,6 +1070,9 @@ SetOutPath '$INSTDIR\profiles\No Reassembly' File "${STAGING_DIR}\profiles\No Reassembly\preferences" SetOutPath '$INSTDIR\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan' +File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\ani_payload.dll" +File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\ani_rpp.dll" +File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\twamp.dll" File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\ethercat.dll" File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\gryphon.dll" File "${STAGING_DIR}\plugins\${MAJOR_VERSION}.${MINOR_VERSION}\epan\irda.dll" diff --git a/plugins/epan/ani_payload/CMakeLists.txt b/plugins/epan/ani_payload/CMakeLists.txt new file mode 100644 index 000000000000..e878fecf672f --- /dev/null +++ b/plugins/epan/ani_payload/CMakeLists.txt @@ -0,0 +1,53 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(ani_payload 0 0 1 0) + +set(PLUGIN_FILES + packet-ani-payload.c +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +add_plugin_library(ani_payload epan) + +target_link_libraries(ani_payload epan) + +install_plugin(ani_payload epan) + +file(GLOB PLUGIN_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + ani_payload + SWITCHES + -g abort -g termoutput -build + SOURCES + ${PLUGIN_FILES} + ${PLUGIN_HEADERS} +) + +# +# Editor modelines - http://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 8 +# tab-width: 8 +# indent-tabs-mode: t +# End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# diff --git a/plugins/epan/ani_payload/packet-ani-payload.c b/plugins/epan/ani_payload/packet-ani-payload.c new file mode 100644 index 000000000000..3910f5831617 --- /dev/null +++ b/plugins/epan/ani_payload/packet-ani-payload.c @@ -0,0 +1,399 @@ +/* packet-ani-payload.c + * Routines for packet payload disassembly + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include "config.h" + + /* plugins are DLLs */ +#define WS_BUILD_DLL +#include "ws_symbol_export.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "packet-ani-payload.h" + +WS_DLL_PUBLIC_DEF const gchar plugin_version[] = PLUGIN_VERSION; +WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR; +WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR; + +WS_DLL_PUBLIC void plugin_register(void); + +/* proto_data cannot be static because it's referenced in the + * print routines + */ +static module_t *proto_reg_ani_payload = NULL; +static void proto_handoff_ani_payload(void); +static void proto_register_ani_payload(void); +static dissector_handle_t appneta_responder_handle = NULL; + +static gint proto_ani_payload = -1; +static gint hf_payload_data = -1; +static gint hf_payload_legacy_signature = -1; +static gint hf_payload_legacy_corrupt_signature = -1; +static gint hf_payload_path_signature = -1; +static gint hf_payload_path_reply_signature = -1; +static gint hf_payload_path_flags = -1; +static gint hf_payload_path_flags_first = -1; +static gint hf_payload_path_flags_last = -1; +static gint hf_payload_path_flags_iht = -1; +static gint hf_payload_path_flags_ext = -1; +static gint hf_payload_path_burst_length = -1; +static gint hf_payload_path_iht_value = -1; +static gint hf_payload_pathtest_signature = -1; +static gint hf_payload_pathtest_burst_packets = -1; +static gint hf_payload_pathtest_sequence = -1; +static gint hf_payload_pathtest_stream = -1; +static gint hf_payload_flags = -1; +static gint hf_payload_burst_size = -1; +static gint hf_payload_data_len = -1; + +static gboolean new_pane = FALSE; +static gboolean show_appneta_payload = TRUE; + +static gint ett_payload = -1; +static gint ett_flags = -1; + +const guchar ANI_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFF }; +const guchar ANI_REPLY_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFD }; +const guchar ANI_LEGACY_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0x54, 0xD5 }; +const guchar ANI_LEGACY_PAYLOAD_SIGNATURE_CORRUPT[] = { 0xEC, 0xBD, 0x7F, 0x60, 0x54 }; +const guchar PATHTEST_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFE }; + +static const true_false_string ani_tf_set_not_set = { + "Set", + "Not Set" +}; + +static gint +dissect_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint bytes; + + if (show_appneta_payload) { + bytes = tvb_captured_length_remaining(tvb, 0); + if (bytes > 0) { + tvbuff_t *data_tvb; + proto_item *ti, *tf; + proto_tree *data_tree, *field_tree; + gint offset = 0; + const guint8 *cp = tvb_get_ptr(tvb, offset, bytes); + guint path_payload_min_size = (sizeof(ANI_PAYLOAD_SIGNATURE) + 4); + guint ecb_payload_min_size = path_payload_min_size + 6; + + if (new_pane) { + guint8 *real_data = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, bytes); + data_tvb = tvb_new_child_real_data(tvb,real_data,bytes,bytes); + tvb_set_free_cb(data_tvb, g_free); + add_new_data_source(pinfo, data_tvb, "Not dissected data bytes"); + } else { + data_tvb = tvb; + } + if (bytes >= sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE) && + !memcmp(cp, ANI_LEGACY_PAYLOAD_SIGNATURE, sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE))) { + /* legacy packet */ + offset = sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE); + ti = proto_tree_add_protocol_format(tree, proto_ani_payload, tvb, + 0, + bytes, "Data (%d byte%s) - AppNeta Legacy Payload", bytes, + plurality(bytes, "", "s")); + data_tree = proto_item_add_subtree(ti, ett_payload); + + proto_tree_add_item(data_tree, hf_payload_legacy_signature, data_tvb, 0, offset, ENC_NA); + col_append_fstr(pinfo->cinfo, COL_INFO, " AppNeta Legacy Payload"); + } else if (bytes >= sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE_CORRUPT) && + !memcmp(cp, ANI_LEGACY_PAYLOAD_SIGNATURE_CORRUPT, sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE_CORRUPT))) { + /* legacy packet */ + offset = sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE_CORRUPT); + ti = proto_tree_add_protocol_format(tree, proto_ani_payload, tvb, + 0, + bytes, "Data (%d byte%s) - AppNeta Legacy Payload - CORRUPT", bytes, + plurality(bytes, "", "s")); + data_tree = proto_item_add_subtree(ti, ett_payload); + + proto_tree_add_item(data_tree, hf_payload_legacy_corrupt_signature, data_tvb, 0, offset, ENC_NA); + col_append_fstr(pinfo->cinfo, COL_INFO, " AppNeta Legacy Payload - CORRUPT"); + } else if (bytes >= (sizeof(PATHTEST_PAYLOAD_SIGNATURE) + 7) && + !memcmp(cp, PATHTEST_PAYLOAD_SIGNATURE, sizeof(PATHTEST_PAYLOAD_SIGNATURE))) { + /* pathtest packet */ + guint32 burst_packets; + guint16 seq; + guint16 stream; + + offset = sizeof(PATHTEST_PAYLOAD_SIGNATURE); + burst_packets = tvb_get_ntohl(tvb, offset) >> 8; + seq = tvb_get_ntohs(tvb, offset + 3); + stream = tvb_get_ntohs(tvb, offset + 5); + + ti = proto_tree_add_protocol_format(tree, proto_ani_payload, tvb, + 0, + bytes, "Data (%d byte%s) - PathTest Payload stream=%u", bytes, + plurality(bytes, "", "s"), stream); + data_tree = proto_item_add_subtree(ti, ett_payload); + proto_tree_add_item(data_tree, hf_payload_pathtest_signature, data_tvb, 0, offset, ENC_NA); + + if (bytes == 18) + proto_item_append_text(ti, " (Final)"); + else + proto_item_append_text(ti, " seq=%u", seq); + + proto_tree_add_uint(data_tree, hf_payload_pathtest_burst_packets, tvb, offset, 3, burst_packets); + proto_tree_add_uint(data_tree, hf_payload_pathtest_sequence, tvb, offset + 3, 2, seq); + proto_tree_add_uint(data_tree, hf_payload_pathtest_stream, tvb, offset + 5, 2, stream); + + if (bytes == 18) + col_append_fstr(pinfo->cinfo, COL_INFO, " PathTest payload - stream=%u (Final)", stream); + else + col_append_fstr(pinfo->cinfo, COL_INFO, " PathTest payload - stream=%u seq=%u", stream, seq); + offset += 7; + } else if (bytes >= path_payload_min_size && + (!memcmp(cp, ANI_PAYLOAD_SIGNATURE, sizeof(ANI_PAYLOAD_SIGNATURE)) + || !memcmp(cp, ANI_REPLY_PAYLOAD_SIGNATURE, sizeof(ANI_REPLY_PAYLOAD_SIGNATURE)))) { + /* path packet */ + guint32 status; + gboolean first = FALSE; + gboolean last = FALSE; + gboolean iht = FALSE; + gboolean ext = FALSE; + guint8 flags; + guint32 burst_length; + guint32 iht_value = 0; + int bit_offset; + const gchar *reply_str; + gchar *type_str; + + if (!memcmp(cp, ANI_REPLY_PAYLOAD_SIGNATURE, sizeof(ANI_REPLY_PAYLOAD_SIGNATURE))) { + reply_str = "Reply "; + type_str = "ani-reply-payload"; + } else { + reply_str = ""; + type_str = "ani-payload"; + } + + offset = sizeof(ANI_PAYLOAD_SIGNATURE); + status = tvb_get_ntohl(tvb, offset); + bit_offset = offset * 8; + flags = (guint8)(status >> 28); + + first = !!(flags & 0x01); + last = !!(flags & 0x02); + iht = !!(flags & 0x04); + ext = !!(flags & 0x08); + burst_length = ((status >> 8) & 0x000FFFFF); + + ti = proto_tree_add_protocol_format(tree, proto_ani_payload, tvb, + 0, + bytes, "Data (%d byte%s) - AppNeta Path %sPayload", bytes, + plurality(bytes, "", "s"), reply_str); + data_tree = proto_item_add_subtree(ti, ett_payload); + if (reply_str[0]) + proto_tree_add_item(data_tree, hf_payload_path_reply_signature, data_tvb, 0, offset, ENC_NA); + else + proto_tree_add_item(data_tree, hf_payload_path_signature, data_tvb, 0, offset, ENC_NA); + + tf = proto_tree_add_uint(data_tree, hf_payload_path_flags, tvb, offset, 1, flags); + field_tree = proto_item_add_subtree(tf, ett_flags); + + if (first) { + proto_item_append_text(ti, " (First)"); + proto_item_append_text(tf, " (First)"); + } + + if (last) { + proto_item_append_text(ti, " (Last)"); + proto_item_append_text(tf, " (Last)"); + } + + if (iht) { + iht_value = tvb_get_ntohl(tvb, offset+3); + proto_item_append_text(ti, " (iht)"); + proto_item_append_text(tf, " (iht)"); + } + + if (ext) { + proto_item_append_text(ti, " (Ext)"); + proto_item_append_text(tf, " (Extended Headers)"); + } + + proto_tree_add_bits_item(field_tree, hf_payload_path_flags_ext, tvb, bit_offset + 0, + 1, ENC_BIG_ENDIAN); + + proto_tree_add_bits_item(field_tree, hf_payload_path_flags_iht, tvb, bit_offset + 1, + 1, ENC_BIG_ENDIAN); + + proto_tree_add_bits_item(field_tree, hf_payload_path_flags_last, tvb, bit_offset + 2, + 1, ENC_BIG_ENDIAN); + + proto_tree_add_bits_item(field_tree, hf_payload_path_flags_first, tvb, bit_offset + 3, + 1, ENC_BIG_ENDIAN); + + if (ext) { + /* Extended headers*/ + ++offset; + col_append_fstr(pinfo->cinfo, COL_INFO, " Extended %spayload", reply_str); + if (!appneta_responder_handle) + appneta_responder_handle = find_dissector("appneta_responder"); + + if (appneta_responder_handle && bytes >= ecb_payload_min_size && + tvb_captured_length_remaining(tvb, offset) > 0) + call_dissector_with_data(appneta_responder_handle, + tvb_new_subset_remaining(tvb, offset), + pinfo, data_tree, type_str); + + return tvb_captured_length(tvb); + } else { + /* Path */ + proto_tree_add_uint(data_tree, hf_payload_path_burst_length, tvb, offset, 3, burst_length); + proto_item_append_text(ti, " (%u bytes)", burst_length); + + if (iht) { + proto_tree_add_uint(data_tree, hf_payload_path_iht_value, tvb, offset+3, 4, iht_value); + proto_item_append_text(ti, " (iht=%u nsec)", iht_value); + offset += 4; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, " Path %spayload:", reply_str); + + col_append_fstr(pinfo->cinfo, COL_INFO, " first=%u last=%u", first, last); + + if (iht) + col_append_fstr(pinfo->cinfo, COL_INFO, " iht=%u nsec", iht_value); + + col_append_fstr(pinfo->cinfo, COL_INFO, " burst=%u", burst_length); + + offset += sizeof(guint) - 1; + } + } else { + /* non-ANI packet */ + ti = proto_tree_add_protocol_format(tree, proto_ani_payload, tvb, + 0, + bytes, "Payload (%d byte%s)", bytes - offset, + plurality(bytes, "", "s")); + data_tree = proto_item_add_subtree(ti, ett_payload); + } + + proto_tree_add_item(data_tree, hf_payload_data, data_tvb, offset, + tvb_captured_length_remaining(data_tvb, offset), ENC_NA); + ti = proto_tree_add_int(data_tree, hf_payload_data_len, data_tvb, 0, 0, + tvb_captured_length_remaining(data_tvb, offset)); + PROTO_ITEM_SET_GENERATED (ti); + } + } + + return tvb_captured_length(tvb); +} + +static void +proto_register_ani_payload(void) +{ + static hf_register_info hf[] = { + { &hf_payload_burst_size, + { "Burst size", "appneta_payload.burst_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_flags, + { "Flags", "appneta_payload.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_legacy_signature, + { "AppNeta Legacy signature", "appneta_payload.legacy_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_legacy_corrupt_signature, + { "AppNeta Legacy signature", "appneta_payload.legacy_reply_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_path_signature, + { "AppNeta Path signature", "appneta_payload.path_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_path_reply_signature, + { "AppNeta Path Reply signature", "appneta_payload.path_reply_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_data, + { "Data", "appneta_payload.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_data_len, + { "Length", "appneta_payload.len", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_path_flags, + { "Path flags", "appneta_payload.path_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_path_flags_first, + { "First packet", "appneta_payload.path_flags.first", FT_BOOLEAN, BASE_NONE, TFS(&ani_tf_set_not_set), 0x0, NULL, HFILL } }, + { &hf_payload_path_flags_last, + { "Last packet", "appneta_payload.path_flags.last", FT_BOOLEAN, BASE_NONE, TFS(&ani_tf_set_not_set), 0x0, NULL, HFILL } }, + { &hf_payload_path_flags_iht, + { "Interrupt Hold Time (iht) available", "appneta_payload.path_flags.iht", FT_BOOLEAN, BASE_NONE, TFS(&ani_tf_set_not_set), 0x0, NULL, HFILL } }, + { &hf_payload_path_flags_ext, + { "Extended Headers", "appneta_payload.path_flags.ext", FT_BOOLEAN, BASE_NONE, TFS(&ani_tf_set_not_set), 0x0, NULL, HFILL } }, + { &hf_payload_path_burst_length, + { "Burst length", "appneta_payload.path_burst_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_path_iht_value, + { "iht value", "appneta_payload.path_iht_value", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_pathtest_signature, + { "PathTest signature", "appneta_payload.pathtest_signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_pathtest_burst_packets, + { "Burst packets", "appneta_payload.pathtest_burst_packets", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_pathtest_sequence, + { "Sequence", "appneta_payload.pathtest_sequence", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_payload_pathtest_stream, + { "Stream", "appneta_payload.pathtest_stream", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + }; + + static gint *ett[] = { + &ett_payload, + &ett_flags, + }; + + module_t *module_data; + + proto_ani_payload = proto_register_protocol ( + "AppNeta Payload", /* name */ + "AppNeta_Payload", /* short name */ + "appneta_payload" /* abbrev */ + ); + + register_dissector("appneta_payload", dissect_payload, proto_ani_payload); + + /* Register preferences module */ + proto_reg_ani_payload = prefs_register_protocol(proto_ani_payload, + proto_handoff_ani_payload); + + proto_register_field_array(proto_ani_payload, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + module_data = prefs_register_protocol(proto_ani_payload, NULL); + prefs_register_bool_preference(module_data, "show_appneta_payload", + "Show dissected data on AppNeta payload", + "Show dissected data on AppNeta payload in the Packet Details pane", + &show_appneta_payload); +} + +static void +proto_handoff_ani_payload(void) +{ + appneta_responder_handle = find_dissector("appneta_responder"); +} + +void +plugin_register(void) +{ + static proto_plugin plug; + + plug.register_protoinfo = proto_register_ani_payload; + plug.register_handoff = proto_handoff_ani_payload; + proto_register_plugin(&plug); +} diff --git a/plugins/epan/ani_payload/packet-ani-payload.h b/plugins/epan/ani_payload/packet-ani-payload.h new file mode 100644 index 000000000000..dff05d04ff8a --- /dev/null +++ b/plugins/epan/ani_payload/packet-ani-payload.h @@ -0,0 +1,25 @@ +/* packet-ani-payload.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __PACKET_PAYLOAD_H__ +#define __PACKET_PAYLOAD_H__ + +#endif /* __PACKET_PAYLOAD_H__ */ diff --git a/plugins/epan/ani_rpp/CMakeLists.txt b/plugins/epan/ani_rpp/CMakeLists.txt new file mode 100644 index 000000000000..a40bbab639f1 --- /dev/null +++ b/plugins/epan/ani_rpp/CMakeLists.txt @@ -0,0 +1,53 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(ani_rpp 0 0 1 0) + +set(PLUGIN_FILES + packet-ani-rpp.c +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +add_plugin_library(ani_rpp epan) + +target_link_libraries(ani_rpp epan) + +install_plugin(ani_rpp epan) + +file(GLOB PLUGIN_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + ani_rpp + SWITCHES + -g abort -g termoutput -build + SOURCES + ${PLUGIN_FILES} + ${PLUGIN_HEADERS} +) + +# +# Editor modelines - http://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 8 +# tab-width: 8 +# indent-tabs-mode: t +# End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# diff --git a/plugins/epan/ani_rpp/packet-ani-rpp.c b/plugins/epan/ani_rpp/packet-ani-rpp.c new file mode 100644 index 000000000000..0bc2389170d1 --- /dev/null +++ b/plugins/epan/ani_rpp/packet-ani-rpp.c @@ -0,0 +1,2774 @@ +/* packet-ani-rpp.c + * Routines for Responder Packet Protocol dissection + * Copyright 2007-2014 AppNeta + * + * RTP Parsing copied from packet-rtp.c + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" + + /* plugins are DLLs */ +#define WS_BUILD_DLL +#include "ws_symbol_export.h" + +#include + +#include +#include +#include +#include + +WS_DLL_PUBLIC_DEF const gchar plugin_version[] = PLUGIN_VERSION; +WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR; +WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR; + +WS_DLL_PUBLIC void plugin_register(void); + +#define UDP_PORT_ANI_RPP 3239 +#define RTP_HEADER_LENGTH 12 +#define NO_FLOW 0xffffffff + +const guchar ANI_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFF }; +const guchar ANI_REPLY_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFD }; +const guchar ANI_LEGACY_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0x54 }; +const guchar PATHTEST_PAYLOAD_SIGNATURE[] = { 0xEC, 0xBD, 0x7F, 0x60, 0xFE }; + +enum appneta_pkt_type { + APPNETA_PACKET_TYPE_UNDEFINED, + APPNETA_PACKET_TYPE_PATH, + APPNETA_PACKET_TYPE_PATH_REPLY, + APPNETA_PACKET_TYPE_LEGACY, + APPNETA_PACKET_TYPE_PATHTEST, +}; +typedef enum appneta_pkt_type appneta_pkt_type_t; + +/* + * Fields in the first octet of the RTP header. + */ + +/* Version is the first 2 bits of the first octet*/ +#define RTP_VERSION(octet) ((octet) >> 6) + +/* Padding is the third bit; No need to shift, because true is any value +other than 0! */ +#define RTP_PADDING(octet) ((octet) & 0x20) + +/* Extension bit is the fourth bit */ +#define RTP_EXTENSION(octet) ((octet) & 0x10) + +/* CSRC count is the last four bits */ +#define RTP_CSRC_COUNT(octet) ((octet) & 0xF) + +/* + * Fields in the second octet of the RTP header. + */ + +/* Marker is the first bit of the second octet */ +#define RTP_MARKER(octet) ((octet) & 0x80) + +/* Payload type is the last 7 bits */ +#define RTP_PAYLOAD_TYPE(octet) ((octet) & 0x7F) + +/* IF PROTO exposes code to other dissectors, then it must be exported + in a header file. If not, a header file is not needed at all. */ +/* #include "packet-ani-rpp.h" */ + +/* Forward declaration we need below */ +static void proto_register_ani_rpp(void); +static void proto_reg_handoff_ani_rpp(void); + +/* handle for sub-protocols */ +static dissector_handle_t ani_rpp_handle = NULL; +static dissector_handle_t ip_handle = NULL; +static dissector_handle_t payload_handle = NULL; + +gint proto_appneta_responder = -1; + +/* Initialize the protocol and registered fields */ +static gint proto_ani_rpp = -1; +static guint global_udp_port_artnet = UDP_PORT_ANI_RPP; + +/* Responder packet fields */ +static gint hf_ani_rpp_next_header_type = -1; +static gint hf_ani_rpp_header_length = -1; +static gint hf_ani_rpp_pkt_id = -1; +static gint hf_ani_rpp_flow_num = -1; +static gint hf_ani_rpp_flow_port = -1; +static gint hf_ani_rpp_flow_port_first = -1; +static gint hf_ani_rpp_flow_port_last = -1; +static gint hf_ani_rpp_test_weight = -1; +static gint hf_ani_rpp_error_code = -1; +static gint hf_ani_rpp_error_value = -1; +static gint hf_ani_rpp_response_status = -1; +static gint hf_ani_rpp_responder_version_major = -1; +static gint hf_ani_rpp_responder_version_minor = -1; +static gint hf_ani_rpp_responder_version_revision = -1; +static gint hf_ani_rpp_responder_version_build = -1; +static gint hf_ani_rpp_unknown_header = -1; +static gint hf_ani_rpp_burst_size = -1; +static gint hf_ani_rpp_packet_size = -1; +static gint hf_ani_rpp_command_type = -1; +static gint hf_ani_rpp_first_id = -1; +static gint hf_ani_rpp_outbound_arrival_bits = -1; +static gint hf_ani_burst_hold_time_us = -1; +static gint hf_ani_burst_process_time_us = -1; +static gint hf_ani_rpp_outbound_arrival_times = -1; +static gint hf_ani_rpp_lost_id = -1; +static gint hf_ani_rpp_sipport = -1; +static gint hf_ani_rpp_ta_id = -1; +static gint hf_ani_rpp_protocol = -1; +static gint hf_ani_rpp_cb_inbound_packetcount = -1; +static gint hf_ani_rpp_cb_inbound_interpacketgap = -1; +static gint hf_ani_rpp_cb_outbound_packetcount = -1; +static gint hf_ani_rpp_cb_outbound_interpacketgap = -1; +static gint hf_ani_rpp_cb_inbound_flags_csv_debug = -1; +static gint hf_ani_rpp_cb_resp_ratelimitcbrate = -1; +static gint hf_ani_rpp_cb_resp_minpacketcount = -1; +static gint hf_ani_rpp_cb_flags_resp_csv_debug = -1; +static gint hf_ani_rpp_iface_info_flags = -1; +static gint hf_ani_rpp_iface_info_flags_is_ani_modified = -1; +static gint hf_ani_rpp_iface_info_mtu = -1; +static gint hf_ani_rpp_iface_info_speed = -1; +static gint hf_ani_rpp_inboundpacketcount = -1; +static gint hf_ani_rpp_inboundpacketsize = -1; +static gint hf_ani_rpp_h323port = -1; +static gint hf_ani_rpp_appliance_type = -1; +static gint hf_ani_rpp_custom_appliance_type = -1; +static gint hf_ani_rpp_command_flags = -1; +static gint hf_ani_rpp_command_flags_is_jumbo = -1; +static gint hf_ani_rpp_command_flags_is_super_jumbo = -1; +static gint hf_ani_rpp_command_flags_is_inbound = -1; +static gint hf_ani_rpp_cb_request_reserved1 = -1; +static gint hf_ani_rpp_cb_request_reserved2 = -1; +static gint hf_ani_rpp_cb_ready_reserved1 = -1; +static gint hf_ani_rpp_cb_ready_reserved2 = -1; +static gint hf_ani_rpp_ecb_request_padding = -1; +static gint hf_ani_rpp_ecb_request_flags = -1; +static gint hf_ani_rpp_ecb_request_flags_first_seq = -1; +static gint hf_ani_rpp_ecb_request_flags_last_seq = -1; +static gint hf_ani_rpp_ecb_request_flags_reply = -1; +static gint hf_ani_rpp_ecb_request_flags_rx_report_all = -1; +static gint hf_ani_rpp_ecb_request_flags_inbound_gap_ns = -1; +static gint hf_ani_rpp_ecb_request_flags_outbound_gap_ns = -1; +static gint hf_ani_rpp_ecb_request_ssn = -1; +static gint hf_ani_rpp_ecb_request_outbound_magnify = -1; +static gint hf_ani_rpp_ecb_request_outbound_duration = -1; +static gint hf_ani_rpp_ecb_request_outbound_gap = -1; +static gint hf_ani_rpp_ecb_request_inbound_magnify = -1; +static gint hf_ani_rpp_ecb_request_inbound_duration = -1; +static gint hf_ani_rpp_ecb_request_inbound_gap = -1; +static gint hf_ani_rpp_ecb_request_outbound_max_packets = -1; +static gint hf_ani_rpp_ecb_request_inbound_max_packets = -1; +static gint hf_ani_rpp_ecb_resp_padding = -1; +static gint hf_ani_rpp_ecb_resp_flags = -1; +static gint hf_ani_rpp_ecb_resp_flags_in = -1; +static gint hf_ani_rpp_ecb_resp_flags_out = -1; +static gint hf_ani_rpp_ecb_resp_flags_final = -1; +static gint hf_ani_rpp_ecb_resp_outbound_first_tx_ts = -1; +static gint hf_ani_rpp_ecb_resp_outbound_first_rx_ts = -1; +static gint hf_ani_rpp_ecb_resp_outbound_ll_rx = -1; +static gint hf_ani_rpp_ecb_resp_outbound_ll_rx_bytes = -1; +static gint hf_ani_rpp_ecb_resp_outbound_ll_us = -1; +static gint hf_ani_rpp_ecb_resp_outbound_total_rx = -1; +static gint hf_ani_rpp_ecb_resp_outbound_total_rx_bytes = -1; +static gint hf_ani_rpp_ecb_resp_outbound_total_us = -1; +static gint hf_ani_rpp_ecb_resp_inbound_first_tx_ts = -1; +static gint hf_ani_rpp_ecb_resp_inbound_first_rx_ts = -1; +static gint hf_ani_rpp_ecb_resp_inbound_ll_rx = -1; +static gint hf_ani_rpp_ecb_resp_inbound_ll_rx_bytes = -1; +static gint hf_ani_rpp_ecb_resp_inbound_ll_us = -1; +static gint hf_ani_rpp_ecb_resp_inbound_total_rx = -1; +static gint hf_ani_rpp_ecb_resp_inbound_total_rx_bytes = -1; +static gint hf_ani_rpp_ecb_resp_inbound_total_us = -1; +static gint hf_ani_rpp_pseudo_chksum = -1; +static gint hf_ani_rpp_payload = -1; +static gint hf_ani_rpp_signature_undefined = -1; +static gint hf_ani_rpp_signature_path = -1; +static gint hf_ani_rpp_signature_path_reply = -1; +static gint hf_ani_rpp_signature_legacy = -1; +static gint hf_ani_rpp_signature_pathtest = -1; +static gint hf_ani_rpp_signature_flags = -1; +static gint hf_ani_rpp_signature_flags_first = -1; +static gint hf_ani_rpp_signature_flags_last = -1; +static gint hf_ani_rpp_signature_flags_iht = -1; +static gint hf_ani_rpp_signature_flags_ext = -1; +static gint hf_ani_rpp_signature_iht = -1; +static gint hf_ani_rpp_signature_burst_len = -1; +static gint hf_ani_rpp_public_ip = -1; +static gint hf_ani_rpp_public_ip_addr = -1; +static gint hf_ani_rpp_public_ipv6 = -1; +static gint hf_ani_rpp_public_ipv6_addr = -1; + + +/* RTP header fields */ +/* Assumptions about RTP: no padding, no extensions, */ +/* and no CSRC identifiers (i.e. 12 bytes only) */ +static gint hf_rtp_version = -1; +static gint hf_rtp_padding = -1; +static gint hf_rtp_extension = -1; +static gint hf_rtp_csrc_count = -1; +static gint hf_rtp_marker = -1; +static gint hf_rtp_payload_type = -1; +static gint hf_rtp_seq_nr = -1; +static gint hf_rtp_ext_seq_nr = -1; +static gint hf_rtp_timestamp = -1; +static gint hf_rtp_ssrc = -1; + +/* Initialize the subtree pointers */ +static gint ett_ani_rpp = -1; +static gint ett_ani_rtp = -1; +static gint ett_ani_seq = -1; +static gint ett_ani_custom = -1; +static gint ett_ani_request = -1; +static gint ett_ani_reply = -1; +static gint ett_ani_flow_create = -1; +static gint ett_ani_flow_response = -1; +static gint ett_ani_flow_close = -1; +static gint ett_ani_test_weight = -1; +static gint ett_ani_test_parameters = -1; +static gint ett_ani_flow_not_found = -1; +static gint ett_ani_burst_info = -1; +static gint ett_ani_responder_version = -1; +static gint ett_ani_outbound_arrival = -1; +static gint ett_ani_burst_hold_time = -1; +static gint ett_ani_outbound_arrival_times = -1; +static gint ett_ani_lost_pkts = -1; +static gint ett_ani_sipport = -1; +static gint ett_ani_protocol = -1; +static gint ett_ani_controlled_burst = -1; +static gint ett_ani_controlled_burst_response = -1; +static gint ett_ani_inboundpacketattr = -1; +static gint ett_ani_h323port = -1; +static gint ett_ani_appliance_type = -1; +static gint ett_ani_error = -1; +static gint ett_ani_controlled_burst_request = -1; +static gint ett_ani_controlled_burst_ready = -1; +static gint ett_ani_enhanced_controlled_burst_request = -1; +static gint ett_ani_enhanced_controlled_burst_response = -1; +static gint ett_ani_signature = -1; +static gint ett_ani_pseudo_cksum = -1; +static gint ett_ani_iface_info = -1; +static gint ett_ani_public_ip_addr = -1; +static gint ett_ani_invalid = -1; + +/* Setup protocol subtree array */ +static gint *ett[] = { + &ett_ani_rpp, + &ett_ani_rtp, + &ett_ani_seq, + &ett_ani_custom, + &ett_ani_reply, + &ett_ani_flow_create, + &ett_ani_flow_response, + &ett_ani_flow_close, + &ett_ani_test_weight, + &ett_ani_test_parameters, + &ett_ani_burst_info, + &ett_ani_responder_version, + &ett_ani_outbound_arrival, + &ett_ani_burst_hold_time, + &ett_ani_outbound_arrival_times, + &ett_ani_lost_pkts, + &ett_ani_sipport, + &ett_ani_protocol, + &ett_ani_controlled_burst, + &ett_ani_controlled_burst_response, + &ett_ani_inboundpacketattr, + &ett_ani_h323port, + &ett_ani_appliance_type, + &ett_ani_error, + &ett_ani_controlled_burst_request, + &ett_ani_controlled_burst_ready, + &ett_ani_enhanced_controlled_burst_request, + &ett_ani_enhanced_controlled_burst_response, + &ett_ani_signature, + &ett_ani_pseudo_cksum, + &ett_ani_iface_info, + &ett_ani_public_ip_addr, + &ett_ani_invalid, +}; + +/* + * an array of pointers to the subtree index and pointer values to the + * structure below. NULL means don't print + */ +static gint *hf_subtrees[] = { + NULL, + NULL, /* HDR_LAST */ + &ett_ani_seq, /* HDR_SEQUENCE */ + &ett_ani_custom, /* HDR_CUSTOM_TYPE */ + &ett_ani_request, /* HDR_REQUEST */ + &ett_ani_reply, /* HDR_REPLY */ + &ett_ani_flow_create, /* HDR_FLOW_CREATE */ + &ett_ani_flow_response, /* HDR_FLOW_RESPONSE */ + &ett_ani_flow_close, /* HDR_FLOW_CLOSE */ + &ett_ani_test_weight, /* HDR_TEST_WEIGHT */ + &ett_ani_test_parameters, /* HDR_TEST_PARAMS */ + &ett_ani_flow_not_found, /* HDR_FLOW_PACKET */ + &ett_ani_burst_info, /* HDR_COMMAND_INFO */ + &ett_ani_responder_version, /* HDR_RESPONDERVERSION */ + &ett_ani_outbound_arrival, /* HDR_OUTBOUNDARRIVAL */ + &ett_ani_burst_hold_time, /* HDR_RESPONDERHOLDTIME */ + &ett_ani_outbound_arrival_times, /* HDR_OUTBOUNDARRIVALTIME */ + &ett_ani_lost_pkts, /* HDR_LOST_PACKETS */ + &ett_ani_sipport, /* HDR_SIPPORT */ + &ett_ani_protocol, /* HDR_PROTOCOL */ + &ett_ani_controlled_burst, /* HDR_CONTROLLEDBURST */ + &ett_ani_controlled_burst_response, /* HDR_CONTROLLEDBURSTRESPONSE */ + &ett_ani_inboundpacketattr, /* HDR_INBOUNDPACKETATTR */ + &ett_ani_h323port, /* HDR_H323PORT */ + &ett_ani_appliance_type, /* HDR_APPLIANCE_TYPE */ + &ett_ani_error, /* HDR_ERROR */ + &ett_ani_controlled_burst_request, /* HDR_CONTROLLEDBURSTREQUEST */ + &ett_ani_controlled_burst_ready, /* HDR_CONTROLLEDBURSTREADY */ + &ett_ani_enhanced_controlled_burst_request, /* HDR_ECBREQUEST */ + &ett_ani_enhanced_controlled_burst_response, /* HDR_ECBRESPONSE */ + &ett_ani_signature, /* HDR_SIGNATURE */ + &ett_ani_pseudo_cksum, /* HDR_PSEUDO_CKSUM */ + &ett_ani_iface_info, /* HDR_IFACE_INFO */ + &ett_ani_public_ip_addr, /* HDR_PUBLIC_IP_ADDRESS */ + &ett_ani_invalid, /* HDR_RESERVED3 */ + &ett_ani_invalid, /* HDR_RESERVED4 */ + &ett_ani_invalid, /* HDR_RESERVED5 */ + &ett_ani_invalid, /* HDR_RESERVED6 */ + &ett_ani_invalid, /* HDR_RESERVED7 */ + &ett_ani_invalid, /* HDR_RESERVED8 */ + &ett_ani_invalid, /* HDR_RESERVED9 */ + &ett_ani_invalid, /* HDR_INVALID */ + NULL, + NULL, +}; + +/* + * descriptions corresponding to the above subree + */ +static const value_string ani_rpp_header_type_vals[] = +{ + { 1, "No more headers" }, + { 2, "Sequence" }, + { 3, "Custom Type" }, + { 4, "Request" }, + { 5, "Reply" }, + { 6, "Create Flow" }, + { 7, "Flow Response" }, + { 8, "Close Flow" }, + { 9, "Test Weight" }, + { 10, "Test Parameters" }, + { 11, "Flow not found" }, + { 12, "Command Info" }, + { 13, "Responder Version" }, + { 14, "Outbound Arrival Bits" }, + { 15, "Responder Hold Time" }, + { 16, "Outbound Arrival Times" }, + { 17, "Lost Packets" }, + { 18, "Sip Port" }, + { 19, "Protocol" }, + { 20, "Controlled Burst" }, + { 21, "Controlled Burst Response" }, + { 22, "Inbound Packet Attributes" }, + { 23, "H.323" }, + { 24, "Device Type" }, + { 25, "Error" }, + { 26, "Controlled Burst Request" }, + { 27, "Controlled Burst Ready" }, + { 28, "Enhanced Controlled Burst" }, + { 29, "Enhanced Controlled Burst Response" }, + { 30, "Signature Header" }, + { 31, "Pseudo Checksum" }, + { 32, "Interface Info" }, + { 33, "Public IP Address" }, + { 34, "Reserved 3" }, + { 35, "Reserved 4" }, + { 36, "Reserved 5" }, + { 37, "Reserved 6" }, + { 38, "Reserved 7" }, + { 39, "Reserved 8" }, + { 40, "Reserved 9" }, + { 41, "Invalid Header" }, + { 0, NULL }, +}; + +enum ResponderHeaderType +{ + HDR_LAST = 1, + HDR_SEQUENCE, + HDR_CUSTOM_TYPE, + HDR_REQUEST, + HDR_REPLY, /* 5 */ + HDR_FLOW_CREATE, + HDR_FLOW_RESPONSE, + HDR_FLOW_CLOSE, + HDR_TEST_WEIGHT, + HDR_TEST_PARAMS, /*10 */ + HDR_FLOW_PACKET, /* not actually a header, used to report flow not found */ + HDR_COMMAND_INFO, + HDR_RESPONDERVERSION, + HDR_OUTBOUNDARRIVAL, + HDR_RESPONDERHOLDTIME, /* 15 */ + HDR_OUTBOUNDARRIVALTIME, + HDR_LOST_PACKETS, + HDR_SIPPORT, + HDR_PROTOCOL, + HDR_CONTROLLEDBURST, /* 20 */ + HDR_CONTROLLEDBURSTRESPONSE, + HDR_INBOUNDPACKETATTR, + HDR_H323PORT, + HDR_APPLIANCE_TYPE, + HDR_ERROR, /* 25 */ + HDR_CONTROLLEDBURSTREQUEST, + HDR_CONTROLLEDBURSTREADY, + HDR_ECBREQUEST, + HDR_ECBRESPONSE, + HDR_SIGNATURE, /* 30 */ + HDR_PSEUDO_CKSUM, + HDR_IFACE_INFO, + HDR_PUBLIC_IP_ADDRESS, + HDR_RESERVED3, + HDR_RESERVED4, + HDR_RESERVED5, + HDR_RESERVED6, + HDR_RESERVED7, + HDR_RESERVED8, + HDR_INVALID, + HDR_COUNT, +} ResponderHeaderType; + +/* strings to make protocol parsing more readable */ +static const value_string rtp_version_vals[] = +{ + { 0, "Old VAT Version" }, + { 1, "First Draft Version" }, + { 2, "RFC 1889 Version" }, + { 0, NULL }, +}; + + +static const value_string ani_rpp_error_code_vals[] = +{ + { 0, "Success" }, + { 1, "QoS disabled" }, + { 2, "Unknown header" }, + { 3, "Option not supported" }, + { 4, "Administratively Prohibited" }, + { 5, "Must set DF" }, + { 6, "UDP checksum not supported" }, + { 7, "Internal error" }, + { 8, "Unknown flow" }, + { 9, "Count error" }, + { 10, "QoS lock unavailable" }, + { 11, "SIP port unavailable" }, + { 12, "QoS altered" }, + { 0, NULL } +}; + +static const value_string ani_rpp_cmd_type_vals[] = +{ + { 0, "Invalid" }, + { 1, "Burst" }, + { 2, "Datagram" }, + { 3, "Controlled Burst" }, + { 4, "Tight Datagram" }, + { 5, "Burst Load" }, + { 6, "Enhanced Controlled Burst" }, + { 0, "Invalid" }, + { 0x81, "Burst with Primer" }, + { 0x82, "Datagram with Primer" }, + { 0x83, "Controlled Burst with Primer" }, + { 0x84, "Tight Datagram with Primer" }, + { 0x85, "Burst Load with Primer" }, + { 0x86, "Controlled Burst with Primer" }, + { 0, NULL } +}; + +static const value_string ani_rpp_appliance_type_vals[] = +{ + { 0, "Invalid" }, + { 1, "Windows" }, + { 2, "Linux 32-bit" }, + { 3, "HP UX" }, + { 4, "Mac" }, + { 5, "iOS" }, + { 6, "Solaris Intel" }, + { 7, "Solaris SPARC" }, + { 8, "m20 appliance" }, + { 9, "m22 appliance" }, + { 10, "m30 appliance" }, + { 11, "r40 appliance" }, + { 12, "r400 appliance" }, + { 13, "virtual appliance" }, + { 14, "v30 appliance" }, + { 15, "Polycom HDX" }, + { 16, "Custom" }, + { 17, "Linux" }, + { 18, "m25 appliance" }, + { 19, "m35 appliance" }, + { 20, "r45 appliance" }, + { 21, "r450 appliance" }, + { 22, "vk35 appliance" }, + { 23, "vk25 appliance" }, + { 24, "wv00 appliance" }, + { 25, "Unknown" }, + { 26, "Unknown" }, + { 27, "Unknown" }, + { 28, "Unknown" }, + { 29, "Unknown" }, + { 30, "Unknown" }, + { 31, "Unknown" }, + { 32, "Unknown" }, + { 33, "Unknown" }, + { 0, NULL } +}; + +/*******************************************************************/ +/* Parse the RTP header and return the number of bytes processed. + * If ani_rpp_tree is set to NULL just return the length of + * the header; otherwise add items to the dissector tree. + */ +static gint +dissect_rtp_header(tvbuff_t *tvb, packet_info *pinfo _U_, gint offset, + proto_tree *ani_rpp_tree, gboolean get_len_only) +{ + guint8 octet1, octet2; + guint16 seq_num; + guint32 timestamp; + guint32 sync_src; + proto_tree* rtp_tree = NULL; + gchar *path_type; + + /* Get the fields in the first octet */ + octet1 = tvb_get_guint8(tvb, offset); + octet2 = tvb_get_guint8(tvb, offset + 1); + + if (octet1 != 0x80 || (octet2 & 0x7F) != 0x02) { + /* this is not an RTP header, so return 0 bytes processed */ + return 0; + } + + /* Get the fields in the second octet */ + if (get_len_only) { + /* just return the length without adding items to the dissector tree */ + return RTP_HEADER_LENGTH; + } + + path_type = RTP_MARKER(octet2) ? " Dual-ended" : " Single-ended"; + col_append_str(pinfo->cinfo, COL_INFO, path_type); + + /* Get the subsequent fields */ + seq_num = tvb_get_ntohs( tvb, offset + 2); + timestamp = tvb_get_ntohl( tvb, offset + 4); + sync_src = tvb_get_ntohl( tvb, offset + 8); + + /* Create a subtree for RTP */ + if (sync_src == NO_FLOW) { + rtp_tree = proto_tree_add_subtree_format(ani_rpp_tree, tvb, offset, RTP_HEADER_LENGTH, ett_ani_rtp, NULL, + "Responder RTP Header: No flow, %s", path_type); + } else { + rtp_tree = proto_tree_add_subtree_format(ani_rpp_tree, tvb, offset, RTP_HEADER_LENGTH, ett_ani_rtp, NULL, + "Responder RTP Header: Flow %u, %s", sync_src, path_type); + col_append_fstr(pinfo->cinfo, COL_INFO, " Flow=%u", sync_src); + + } + + /* Add items to the RTP subtree */ + proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb, offset, 1, octet1); + proto_tree_add_boolean(rtp_tree, hf_rtp_padding, tvb, offset, 1, octet1); + proto_tree_add_boolean(rtp_tree, hf_rtp_extension, tvb, offset, 1, octet1); + proto_tree_add_uint( rtp_tree, hf_rtp_csrc_count, tvb, offset, 1, octet1); + offset++; + + proto_tree_add_boolean(rtp_tree, hf_rtp_marker, tvb, offset, + 1, octet2); + offset++; + + /* Sequence number 16 bits (2 octets) */ + proto_tree_add_uint( rtp_tree, hf_rtp_seq_nr, tvb, offset, 2, seq_num); + offset += 2; + + /* Timestamp 32 bits (4 octets) */ + proto_tree_add_uint( rtp_tree, hf_rtp_timestamp, tvb, offset, 4, timestamp); + offset += 4; + + /* Synchronization source identifier 32 bits (4 octets) */ + proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src); + offset += 4; + + return offset; +} + +static proto_tree *add_subtree(tvbuff_t *tvb, gint *offset, proto_tree *current_tree, + gint header, guint8 headerLength, const char *title) +{ + proto_tree *tree = NULL; + + if (current_tree && header < HDR_COUNT && hf_subtrees[header]) { + tree = proto_tree_add_subtree(current_tree, tvb, *offset, headerLength, + *(hf_subtrees[header]), NULL, title); + } + + if (tree) { + proto_tree_add_item(tree, hf_ani_rpp_next_header_type, tvb, *offset, 1, FALSE); + proto_tree_add_item(tree, hf_ani_rpp_header_length, tvb, *offset+1, 1, FALSE); + } + + *offset += 2; + + return tree; +} + +/*******************************************************************/ +/* Parse the responder header starting at the offset in the tvb + * buffer. If ani_rpp_tree is set to NULL just return the length of + * the header; otherwise add items to the dissector tree. + */ +static gint +dissect_responder_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ani_rpp_tree, void *data) +{ + gint currentHeader, nextHeader; + guint8 headerLength = 0, mode = 0; + guint8 flags = 0; + gint offset = 0; + guint32 id, flow, major, minor, revision, build, first_id = 0, + burst_hold_time, i, depth; + guint32 cb_in_count = 0, + cb_in_gap = 0, + cb_out_count = 0, + cb_out_gap = 0, + cb_in_flags = 0; + guint16 port, portend, weight, burstsize = 0; + proto_tree *current_tree = NULL, *field_tree = NULL; + proto_item *tf = NULL; + tvbuff_t *next_tvb; + gboolean save_in_error_pkt; + gint remaining = tvb_captured_length_remaining(tvb, 0); + appneta_pkt_type_t appneta_pkt_type = APPNETA_PACKET_TYPE_UNDEFINED; + guint pass = 0; + + if (data && strcmp((const char*)data, "ani-payload") == 0) { + currentHeader = HDR_SIGNATURE; + appneta_pkt_type = APPNETA_PACKET_TYPE_PATH; + } else if (data && strcmp((const char*)data, "ani-reply-payload") == 0) { + currentHeader = HDR_SIGNATURE; + appneta_pkt_type = APPNETA_PACKET_TYPE_PATH_REPLY; + } else { + currentHeader = HDR_SEQUENCE; + } + + while (currentHeader != HDR_LAST && currentHeader < HDR_INVALID) { + current_tree = ani_rpp_tree; + nextHeader = tvb_get_guint8(tvb, offset); + headerLength = tvb_get_guint8(tvb, offset+1); + + if (offset > remaining || pass++ > 50) { + g_print("dissect_responder_header: opps: offset=%d remaining=%d pass=%d\n", + offset, remaining, pass); + return 0; + } + + switch (currentHeader) { + case HDR_SEQUENCE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Sequence Header"); + id = tvb_get_ntohl( tvb, offset); + proto_tree_add_item(current_tree, hf_ani_rpp_pkt_id, tvb, offset, 4, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " ID=%u", id); + break; + case HDR_ERROR: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Error Header"); + proto_tree_add_item(current_tree, hf_ani_rpp_error_code, tvb, offset, 1, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_error_value, tvb, offset+1, 1, FALSE); + + /* set some text in the info column */ + col_append_str(pinfo->cinfo, COL_INFO, " [Contains Errors]"); + break; + case HDR_REQUEST: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Request Header"); + break; + case HDR_REPLY: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Reply Header"); + /* the next 28 bytes are the ip and udp headers to be used in the response */ + /* Save the current value of the "we're inside an error packet" + flag, and set that flag; subdissectors may treat packets + that are the payload of error packets differently from + "real" packets. */ + save_in_error_pkt = pinfo->flags.in_error_pkt; + pinfo->flags.in_error_pkt = TRUE; + + next_tvb = tvb_new_subset_remaining(tvb, offset); + set_actual_length(next_tvb, 28); + if (ip_handle) { + call_dissector( ip_handle, next_tvb, pinfo, current_tree); + } + + /* Restore the "we're inside an error packet" flag. */ + pinfo->flags.in_error_pkt = save_in_error_pkt; + break; + case HDR_FLOW_CREATE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Create Flow Header"); + port = tvb_get_ntohs( tvb, offset); + if (headerLength >= 6) { + proto_tree_add_item(current_tree, hf_ani_rpp_flow_port_first, tvb, offset, 2, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_flow_port_last, tvb, offset+2, 2, FALSE); + } else { + proto_tree_add_item(current_tree, hf_ani_rpp_flow_port, tvb, offset, 2, FALSE); + } + + /* set some text in the info column */ + if (headerLength >= 6) { + portend = tvb_get_ntohs( tvb, offset+2); + col_append_fstr(pinfo->cinfo, COL_INFO, " Create Flows (ports %d through %d)", port, portend); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, " Create Flow (port %d)", port); + } + break; + case HDR_FLOW_RESPONSE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Reply Header"); + flow = tvb_get_ntohl( tvb, offset); + port = tvb_get_ntohs( tvb, offset+4); + proto_tree_add_item(current_tree, hf_ani_rpp_flow_num, tvb, offset, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_flow_port, tvb, offset+4, 2, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_response_status, tvb, offset+6, 2, FALSE); + + /* tell Wireshark to dissect packets addressed to hf_ani_rpp_flow_port + * using this dissector. + */ + if (port != UDP_PORT_ANI_RPP) + dissector_add_uint("udp.port", port, ani_rpp_handle); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Flow Response: Flow ID=%u", flow); + break; + case HDR_FLOW_CLOSE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Close Flow Header"); + flow = tvb_get_ntohl( tvb, offset); + proto_tree_add_item(current_tree, hf_ani_rpp_flow_num, tvb, offset, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_flow_port, tvb, offset+4, 2, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_response_status, tvb, offset+6, 2, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Close Flow: Flow ID=%u", flow); + break; + case HDR_TEST_WEIGHT: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Test Weight Header"); + weight = tvb_get_ntohs( tvb, offset); + proto_tree_add_item(current_tree, hf_ani_rpp_test_weight, tvb, offset, 2, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Weight=%d", weight); + break; + case HDR_RESPONDERVERSION: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Responder Version Header"); + major = tvb_get_ntohl( tvb, offset); + minor = tvb_get_ntohl( tvb, offset+4); + revision = tvb_get_ntohl( tvb, offset+8); + build = tvb_get_ntohl( tvb, offset+12); + proto_tree_add_item(current_tree, hf_ani_rpp_responder_version_major, tvb, offset, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_responder_version_minor, tvb, offset+4, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_responder_version_revision, tvb, offset+8, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_responder_version_build, tvb, offset+12, 4, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%d.%d.%d.%d", major, minor, revision, build); + break; + case HDR_COMMAND_INFO: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Command Info Header"); + first_id = tvb_get_ntohl( tvb, offset); + burstsize = tvb_get_ntohs( tvb, offset+4); + proto_tree_add_item(current_tree, hf_ani_rpp_first_id, tvb, offset, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_burst_size, tvb, offset+4, 2, FALSE); + if (headerLength > 8) { + proto_tree_add_item(current_tree, hf_ani_rpp_packet_size, tvb, offset+6, 2, FALSE); + } + if (headerLength >= 11) { + proto_tree_add_item(current_tree, hf_ani_rpp_command_type, tvb, offset+8, 1, FALSE); + mode = tvb_get_guint8(tvb, offset+8); + } + if (headerLength >= 12) { + flags = tvb_get_guint8(tvb, offset + 9); + tf = proto_tree_add_uint(current_tree, hf_ani_rpp_command_flags, tvb, offset+9, 1, flags); + field_tree = proto_item_add_subtree( tf, ett_ani_burst_info); + proto_tree_add_boolean(field_tree, hf_ani_rpp_command_flags_is_inbound, tvb, offset+9, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_command_flags_is_super_jumbo, tvb, offset+9, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_command_flags_is_jumbo, tvb, offset+9, 1, flags); + } + + /* set some text in the info column */ + if (mode == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Burst"); + } else if (mode == 2) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Datagram"); + } else if (mode == 3) { + if ((flags & 0x4)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Controlled Burst Response"); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, " Controlled Burst"); + } + } else if (mode == 4) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Tight Dgrm"); + } else if (mode == 5) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Burst Load"); + } else if (mode == 0x81) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Burst (Primer)"); + } else if (mode == 0x82) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Datagram (Primer)"); + } else if (mode == 0x83) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Controlled Burst (Primer)"); + } else if (mode == 0x84) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Tight Dgrm (Primer)"); + } else if (mode == 0x85) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Burst Load (Primer)"); + } + col_append_fstr(pinfo->cinfo, COL_INFO, " First ID=%d Packets=%d", first_id, burstsize); + break; + case HDR_OUTBOUNDARRIVAL: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Outbound Arrival Bits"); + proto_tree_add_item(current_tree, hf_ani_rpp_outbound_arrival_bits, tvb, offset, 8, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Response"); + break; + case HDR_RESPONDERHOLDTIME: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Responder Hold Times"); + burst_hold_time = tvb_get_ntohl( tvb, offset); + proto_tree_add_item(current_tree, hf_ani_burst_hold_time_us, tvb, offset, 4, FALSE); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " RHT=%u usec", burst_hold_time); + break; + case HDR_OUTBOUNDARRIVALTIME: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Outbound Arrival Timestamps"); + i = 0; + depth = headerLength - 2; + for (; icinfo, COL_INFO, " Loss"); + break; + case HDR_SIPPORT: + { + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Sip Port"); + guint32 idLength = headerLength - 4; + proto_tree_add_item(current_tree, hf_ani_rpp_sipport, tvb, offset, 2, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ta_id, tvb, offset + 2, idLength, FALSE); + break; + } + case HDR_PROTOCOL: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Protocol"); + proto_tree_add_item(current_tree, hf_ani_rpp_protocol, tvb, offset, 4, FALSE); + break; + case HDR_CONTROLLEDBURST: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Controlled Burst "); + cb_in_count = tvb_get_ntohl( tvb, offset); + cb_in_gap = tvb_get_ntohl( tvb, offset+4); + cb_in_flags = cb_in_count & 0x80000000; + proto_tree_add_boolean(current_tree, hf_ani_rpp_cb_inbound_flags_csv_debug, tvb, offset, 4, cb_in_flags); + proto_tree_add_uint(current_tree, hf_ani_rpp_cb_inbound_packetcount, tvb, offset, 4, cb_in_count & 0x7fffffff); + proto_tree_add_uint(current_tree, hf_ani_rpp_cb_inbound_interpacketgap, tvb, offset+4, 4, cb_in_gap); + if (cb_in_flags) { + col_append_fstr(pinfo->cinfo, COL_INFO, "Debug "); + } + if (headerLength >= 18) { + cb_out_count = tvb_get_ntohl( tvb, offset+8); + cb_out_gap = tvb_get_ntohl( tvb, offset+12); + proto_tree_add_uint(current_tree, hf_ani_rpp_cb_outbound_packetcount, tvb, offset+8, 4, cb_out_count); + proto_tree_add_uint(current_tree, hf_ani_rpp_cb_outbound_interpacketgap, tvb, offset+12, 4, cb_out_gap); + col_append_fstr(pinfo->cinfo, COL_INFO, "Out=%d/%d In=%d/%d (pkts/gap)", + cb_out_count, cb_out_gap, cb_in_count & 0x7fffffff, cb_in_gap); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, "%d/%d (pkts/gap)", cb_in_count & 0x7fffffff, cb_in_gap); + } + break; + case HDR_CONTROLLEDBURSTRESPONSE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Controlled Burst Response"); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_resp_ratelimitcbrate, tvb, offset, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_resp_minpacketcount, tvb, offset+4, 4, FALSE); + break; + case HDR_INBOUNDPACKETATTR: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Inbound Packet Attributes"); + proto_tree_add_item(current_tree, hf_ani_rpp_inboundpacketcount, tvb, offset, 2, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_inboundpacketsize, tvb, offset+2, 2, FALSE); + burstsize = tvb_get_ntohs( tvb, offset); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%d (out/in)", burstsize); + break; + case HDR_H323PORT: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "H.323"); + proto_tree_add_item(current_tree, hf_ani_rpp_h323port, tvb, offset, 2, FALSE); + break; + case HDR_APPLIANCE_TYPE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Device Type"); + proto_tree_add_item(current_tree, hf_ani_rpp_appliance_type, tvb, offset, 1, FALSE); + break; + case HDR_CUSTOM_TYPE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Custom Type"); + proto_tree_add_item(current_tree, hf_ani_rpp_custom_appliance_type, tvb, offset, headerLength - 2, FALSE); + break; + case HDR_CONTROLLEDBURSTREADY: + col_append_fstr(pinfo->cinfo, COL_INFO, " Controlled Burst Ready"); + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Controlled Burst Ready"); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_ready_reserved1, tvb, offset, 1, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_ready_reserved2, tvb, offset+1, 1, FALSE); + break; + case HDR_CONTROLLEDBURSTREQUEST: + col_append_fstr(pinfo->cinfo, COL_INFO, " Controlled Burst Request"); + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Controlled Burst Request"); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_request_reserved1, tvb, offset, 1, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_cb_request_reserved2, tvb, offset+1, 1, FALSE); + break; + case HDR_ECBREQUEST: + { + gboolean first_seq, last_seq, is_reply, is_rx_report_all, + is_in_gap_ns, is_out_gap_ns; + + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Enhanced Controlled Burst Request"); + flags = tvb_get_guint8(tvb, offset + 1); + first_seq = !!(flags & 0x01); + last_seq = !!(flags & 0x02); + is_reply = !!(flags & 0x04); + is_rx_report_all = !!(flags & 0x08); + is_in_gap_ns = !!(flags & 0x10); + is_out_gap_ns = !!(flags & 0x20); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_padding, tvb, offset, 1, FALSE); + tf = proto_tree_add_uint(current_tree, hf_ani_rpp_ecb_request_flags, tvb, offset+1, 1, flags); + field_tree = proto_item_add_subtree( tf, ett_ani_enhanced_controlled_burst_request); + if (is_reply) { + proto_item_append_text(tf, " (Reply)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " Reply"); + } + if (first_seq) { + proto_item_append_text(tf, " (First sequence)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " First Seq"); + } + if (last_seq) { + proto_item_append_text(tf, " (Last sequence)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " Last Seq"); + } + if (is_rx_report_all) { + proto_item_append_text(tf, " (RX Report All)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " Report All"); + } + if (is_in_gap_ns) { + proto_item_append_text(tf, " (Inbound Gap NS)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " IN NS"); + } + if (is_out_gap_ns) { + proto_item_append_text(tf, " (Outbound Gap NS)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " OUT NS"); + } + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_outbound_gap_ns, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_inbound_gap_ns, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_rx_report_all, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_reply, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_last_seq, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_request_flags_first_seq, tvb, offset+1, 1, flags); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_ssn, tvb, offset+2, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_outbound_magnify, tvb, offset+6, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " ECB out[mag=%u", tvb_get_ntohs(tvb, offset+6)); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_outbound_duration, tvb, offset+8, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " dur=%ums", tvb_get_ntohs(tvb, offset+8)); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_outbound_gap, tvb, offset+10, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " gap=%uus", tvb_get_ntohs(tvb, offset+10)); + if (headerLength > 20) { + col_append_fstr(pinfo->cinfo, COL_INFO, " max=%upkts", tvb_get_ntohl(tvb, offset+18)); + } + col_append_fstr(pinfo->cinfo, COL_INFO, "]"); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_inbound_magnify, tvb, offset+12, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " in[mag=%u", tvb_get_ntohs(tvb, offset+12)); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_inbound_duration, tvb, offset+14, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " dur=%ums", tvb_get_ntohs(tvb, offset+14)); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_inbound_gap, tvb, offset+16, 2, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " gap=%uus", tvb_get_ntohs(tvb, offset+16)); + if (headerLength > 20) { + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_outbound_max_packets, tvb, offset+18, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_request_inbound_max_packets, tvb, offset+22, 4, FALSE); + col_append_fstr(pinfo->cinfo, COL_INFO, " max=%upkts", tvb_get_ntohl(tvb, offset+22)); + } + col_append_fstr(pinfo->cinfo, COL_INFO, "]"); + break; + } + case HDR_ECBRESPONSE: + { + gboolean out_avail, in_avail, final_results; + + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Enhanced Controlled Burst Response"); + flags = tvb_get_guint8(tvb, offset + 1); + in_avail = !!(flags & 0x01); + out_avail = !!(flags & 0x02); + final_results = !!(flags & 0x04); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_padding, tvb, offset, 1, FALSE); + tf = proto_tree_add_uint(current_tree, hf_ani_rpp_ecb_resp_flags, tvb, offset+1, 1, flags); + field_tree = proto_item_add_subtree( tf, ett_ani_enhanced_controlled_burst_response); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_resp_flags_final, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_resp_flags_out, tvb, offset+1, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_ecb_resp_flags_in, tvb, offset+1, 1, flags); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_first_tx_ts, tvb, offset+2, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_first_rx_ts, tvb, offset+6, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_ll_rx, tvb, offset+10, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_ll_rx_bytes, tvb, offset+14, 8, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_ll_us, tvb, offset+22, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_total_rx, tvb, offset+26, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_total_rx_bytes, tvb, offset+30, 8, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_outbound_total_us, tvb, offset+38, 4, FALSE); + if (final_results) { + proto_item_append_text(tf, " (Final results)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " Final"); + } + if (out_avail) { + proto_item_append_text(tf, " (Out-bound results)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " RX-out[ll=%u", tvb_get_ntohl(tvb, offset+10)); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%uus", tvb_get_ntohl(tvb, offset+22) - tvb_get_ntohl(tvb, offset+6)); + col_append_fstr(pinfo->cinfo, COL_INFO, " total=%u", tvb_get_ntohl(tvb, offset+26)); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%uus]", tvb_get_ntohl(tvb, offset+38) - tvb_get_ntohl(tvb, offset+6)); + } + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_first_tx_ts, tvb, offset+42, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_first_rx_ts, tvb, offset+46, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_ll_rx, tvb, offset+50, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_ll_rx_bytes, tvb, offset+54, 8, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_ll_us, tvb, offset+62, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_total_rx, tvb, offset+66, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_total_rx_bytes, tvb, offset+70, 8, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_ecb_resp_inbound_total_us, tvb, offset+78, 4, FALSE); + if (in_avail) { + proto_item_append_text(tf, " (In-bound results)"); + col_append_fstr(pinfo->cinfo, COL_INFO, " RX-in[ll=%u", tvb_get_ntohl(tvb, offset+50)); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%uus", tvb_get_ntohl(tvb, offset+62) - tvb_get_ntohl(tvb, offset+46)); + col_append_fstr(pinfo->cinfo, COL_INFO, " total=%u", tvb_get_ntohl(tvb, offset+66)); + col_append_fstr(pinfo->cinfo, COL_INFO, "/%uus]", tvb_get_ntohl(tvb, offset+78) - tvb_get_ntohl(tvb, offset+46)); + } + break; + } + case HDR_SIGNATURE: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Signature Header"); + if (appneta_pkt_type == APPNETA_PACKET_TYPE_UNDEFINED) { + const guint8 *cp = tvb_get_ptr(tvb, offset, + tvb_captured_length_remaining(tvb, offset)); + + if (cp) { + if (!memcmp(cp, ANI_PAYLOAD_SIGNATURE, sizeof(ANI_PAYLOAD_SIGNATURE))) + appneta_pkt_type = APPNETA_PACKET_TYPE_PATH; + else if (!memcmp(cp, ANI_REPLY_PAYLOAD_SIGNATURE, sizeof(ANI_REPLY_PAYLOAD_SIGNATURE))) + appneta_pkt_type = APPNETA_PACKET_TYPE_PATH_REPLY; + else if (!memcmp(cp, ANI_LEGACY_PAYLOAD_SIGNATURE, sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE))) + appneta_pkt_type = APPNETA_PACKET_TYPE_LEGACY; + else if (!memcmp(cp, PATHTEST_PAYLOAD_SIGNATURE, sizeof(PATHTEST_PAYLOAD_SIGNATURE))) + appneta_pkt_type = APPNETA_PACKET_TYPE_PATHTEST; + } + } + + if (headerLength > 6) { + /* this is a dual-ended signature */ + switch (appneta_pkt_type) { + case APPNETA_PACKET_TYPE_PATH: + proto_tree_add_item(current_tree, hf_ani_rpp_signature_path, tvb, offset, + sizeof(ANI_PAYLOAD_SIGNATURE), ENC_NA); + break; + case APPNETA_PACKET_TYPE_PATH_REPLY: + proto_tree_add_item(current_tree, hf_ani_rpp_signature_path_reply, tvb, offset, + sizeof(ANI_REPLY_PAYLOAD_SIGNATURE), ENC_NA); + break; + case APPNETA_PACKET_TYPE_LEGACY: + proto_tree_add_item(current_tree, hf_ani_rpp_signature_legacy, tvb, offset, + sizeof(ANI_LEGACY_PAYLOAD_SIGNATURE), ENC_NA); + break; + case APPNETA_PACKET_TYPE_PATHTEST: + proto_tree_add_item(current_tree, hf_ani_rpp_signature_pathtest, tvb, offset, + sizeof(PATHTEST_PAYLOAD_SIGNATURE), ENC_NA); + break; + default: + proto_tree_add_item(current_tree, hf_ani_rpp_signature_undefined, + tvb, offset, sizeof(ANI_PAYLOAD_SIGNATURE), ENC_NA); + } + + switch (appneta_pkt_type) { + case APPNETA_PACKET_TYPE_PATH: + case APPNETA_PACKET_TYPE_PATH_REPLY: + flags = tvb_get_guint8(tvb, offset + 5); + tf = proto_tree_add_uint(current_tree, hf_ani_rpp_signature_flags, tvb, offset+5, 1, flags); + field_tree = proto_item_add_subtree( tf, ett_ani_signature); + proto_tree_add_boolean(field_tree, hf_ani_rpp_signature_flags_ext, tvb, offset+5, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_signature_flags_iht, tvb, offset+5, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_signature_flags_last, tvb, offset+5, 1, flags); + proto_tree_add_boolean(field_tree, hf_ani_rpp_signature_flags_first, tvb, offset+5, 1, flags); + break; + default: + ; + } + proto_tree_add_item(current_tree, hf_ani_rpp_signature_burst_len, tvb, offset+6, 4, FALSE); + proto_tree_add_item(current_tree, hf_ani_rpp_signature_iht, tvb, offset+10, 4, FALSE); + } else { + /* this is a single-ended or ICMP extended packet signature found in payload */ + proto_tree_add_item(current_tree, hf_ani_rpp_signature_iht, tvb, offset, 4, FALSE); + } + break; + case HDR_PSEUDO_CKSUM: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Pseudo Checksum"); + tf = proto_tree_add_item(current_tree, hf_ani_rpp_pseudo_chksum, tvb, offset, 2, FALSE); + field_tree = proto_item_add_subtree( tf, ett_ani_pseudo_cksum); + break; + case HDR_IFACE_INFO: + { + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Interface Info"); + guint32 flags32 = tvb_get_ntohl(tvb, offset); + guint32 mtu = tvb_get_ntohl(tvb, offset+4); + guint32 speed = tvb_get_ntohl(tvb, offset+8); + + tf = proto_tree_add_uint(current_tree, hf_ani_rpp_iface_info_flags, tvb, offset, 4, flags32); + field_tree = proto_item_add_subtree(tf, ett_ani_iface_info); + proto_tree_add_boolean(field_tree, hf_ani_rpp_iface_info_flags_is_ani_modified, tvb, offset, 4, flags32); + proto_tree_add_uint(current_tree, hf_ani_rpp_iface_info_mtu, tvb, offset+4, 4, mtu); + proto_tree_add_uint(current_tree, hf_ani_rpp_iface_info_speed, tvb, offset+8, 4, speed); + break; + } + case HDR_PUBLIC_IP_ADDRESS: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Public IP Address"); + if (headerLength == 6) { + /* IPv4 */ + proto_item *item; + guint32 addr = tvb_get_ipv4(tvb, offset); + + tf = proto_tree_add_ipv4(current_tree, hf_ani_rpp_public_ip, tvb, offset, 4, addr); + field_tree = proto_item_add_subtree(tf, ett_ani_public_ip_addr); + item = proto_tree_add_ipv4(field_tree, hf_ani_rpp_public_ip_addr, tvb, + offset, 4, addr); + PROTO_ITEM_SET_GENERATED(item); + PROTO_ITEM_SET_HIDDEN(item); + } else if (headerLength == 18) { + /* IPv6 */ + proto_item *item; + ws_in6_addr addr; + tvb_get_ipv6(tvb, offset, &addr); + + tf = proto_tree_add_ipv6(current_tree, hf_ani_rpp_public_ipv6, tvb, offset, IPv6_ADDR_SIZE, &addr); + field_tree = proto_item_add_subtree(tf, ett_ani_public_ip_addr); + item = proto_tree_add_ipv6(field_tree, hf_ani_rpp_public_ipv6_addr, tvb, + offset, IPv6_ADDR_SIZE, &addr); + PROTO_ITEM_SET_GENERATED(item); + PROTO_ITEM_SET_HIDDEN(item); + } + break; + default: + current_tree = add_subtree(tvb, &offset, current_tree, currentHeader, headerLength, + "Unknown Header"); + tf = proto_tree_add_item(current_tree, hf_ani_rpp_unknown_header, tvb, offset, headerLength-2, FALSE); + field_tree = proto_item_add_subtree( tf, ett_ani_invalid); + + /* set some text in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " [Unknown Header %u]", currentHeader); + } + + offset += (headerLength - 2); + currentHeader = nextHeader; + } + + return offset; +} + +/*******************************************************************/ +/* Code to actually dissect the packets + */ +static gint +dissect_ani_rpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + unsigned int offset = 0; + proto_item *ti = NULL; + proto_tree *ani_rpp_tree = NULL; + + /* determine how many bytes of the packet will be processed */ + offset = dissect_rtp_header(tvb, pinfo, offset, NULL, TRUE); + + /* if not dissected, return 0 to indicate dissector disabled */ + if (!offset) + return 0; + + /* Make entry in Protocol column */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "appneta_rpp"); + + /* Indicate the number of bytes that will be processed */ + ti = proto_tree_add_item(tree, proto_ani_rpp, tvb, 0, offset, FALSE); + + /* Get a pointer to our subtree */ + ani_rpp_tree = proto_item_add_subtree(ti, ett_ani_rpp); + + /* Add items to our subtree */ + offset = 0; + offset = dissect_rtp_header (tvb, pinfo, offset, ani_rpp_tree, FALSE); + tvb = tvb_new_subset_remaining(tvb, offset); + offset = dissect_responder_header(tvb, pinfo, ani_rpp_tree, data); + return call_dissector(payload_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree); +} + +static const true_false_string ani_tf_set_not_set = { + "Set", + "Not Set" +}; + +/*******************************************************************/ +/* Register the protocol with Wireshark + */ +static void +proto_register_ani_rpp(void) +{ + module_t *ani_rpp_module; + + static hf_register_info hf[] = { + + { + &hf_rtp_version, + { + "RTP Version", + "appneta.rtp.version", + FT_UINT8, + BASE_DEC, + VALS(rtp_version_vals), + 0xC0, + "", HFILL + } + }, + { + &hf_rtp_padding, + { + "RTP Padding", + "appneta.rtp.padding", + FT_BOOLEAN, + 8, + NULL, + 0x20, + "", HFILL + } + }, + { + &hf_rtp_extension, + { + "RTP Extension", + "appneta.rtp.ext", + FT_BOOLEAN, + 8, + NULL, + 0x10, + "", HFILL + } + }, + { + &hf_rtp_csrc_count, + { + "RTP Contributing source identifiers count", + "appneta.rtp.cc", + FT_UINT8, + BASE_DEC, + NULL, + 0x0F, + "", HFILL + } + }, + { + &hf_rtp_marker, + { + "RTP Marker (Dual-ended)", + "appneta.rtp.marker", + FT_BOOLEAN, + 8, + NULL, + 0x80, + "", HFILL + } + }, + { + &hf_rtp_payload_type, + { + "RTP Payload type", + "appneta.rtp.p_type", + FT_UINT8, + BASE_DEC, + NULL, + 0x7F, + "", HFILL + } + }, + { + &hf_rtp_seq_nr, + { + "RTP Sequence number", + "appneta.rtp.seq", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_rtp_ext_seq_nr, + { + "RTP Extended sequence number", + "appneta.rtp.extseq", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_rtp_timestamp, + { + "RTP Timestamp", + "appneta.rtp.timestamp", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_rtp_ssrc, + { + "RTP SSRC (Flow ID)", + "appneta.rtp.ssrc", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_next_header_type, + { + "Next Header Type", + "appneta.next_hdr_type", + FT_UINT8, + BASE_DEC, + VALS(ani_rpp_header_type_vals), + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_header_length, + { + "Header Length", + "appneta.hdr_length", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_pkt_id, + { + "Packet ID", + "appneta.pkt_id", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_error_code, + { + "Error Code", + "appneta.err_code", + FT_UINT8, + BASE_DEC, + VALS(ani_rpp_error_code_vals), + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_error_value, + { + "Error Value", + "appneta.err_value", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_response_status, + { + "Status", + "appneta.status", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_flow_num, + { + "Flow Number", + "appneta.flow_num", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_flow_port, + { + "Flow Port", + "appneta.flow_port", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_flow_port_first, + { + "Flow Port First", + "appneta.flow_port_first", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_flow_port_last, + { + "Flow Port Last", + "appneta.flow_port_last", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_test_weight, + { + "Test Weight", + "appneta.test_weight", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_responder_version_major, + { + "Major", + "appneta.responder_version_major", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_responder_version_minor, + { + "Minor", + "appneta.responder_version_minor", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_responder_version_revision, + { + "Revision", + "appneta.responder_version_revision", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_responder_version_build, + { + "Build", + "appneta.responder_version_build", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_burst_size, + { + "Packets", + "appneta.burst_size", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_packet_size, + { + "Packet Size", + "appneta.packet_size", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_command_type, + { + "Command Type", + "appneta.command_type", + FT_UINT8, + BASE_HEX, + VALS(ani_rpp_cmd_type_vals), + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_first_id, + { + "First Packet ID in Command", + "appneta.first_id", + FT_UINT32, + BASE_DEC_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_outbound_arrival_bits, + { + "Outbound Arrival Bits", + "appneta.outbound_bits", + FT_UINT64, + BASE_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_burst_hold_time_us, + { + "Responder hold time usec", + "appneta.burst_hold_time", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_flags_resp_csv_debug, + { + "Responder CSV Debug", + "appneta.resp_csv_debug", + FT_UINT32, + BASE_DEC, + NULL, + 0x80000000, + "", HFILL + } + }, + { + &hf_ani_rpp_command_flags, + { + "Command Flags", + "appneta.command_flags", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_command_flags_is_jumbo, + { + "Is Jumbo Packet", + "appneta.is_jumbo", + FT_BOOLEAN, + 8, + NULL, + 0x01, + "", HFILL + } + }, + { + &hf_ani_rpp_command_flags_is_super_jumbo, + { + "Is Super Jumbo Packet", + "appneta.is_super_jumbo", + FT_BOOLEAN, + 8, + NULL, + 0x02, + "", HFILL + } + }, + { + &hf_ani_rpp_command_flags_is_inbound, + { + "Is Inbound Packet", + "appneta.is_inbound", + FT_BOOLEAN, + 8, + NULL, + 0x04, + "", HFILL + } + }, + { + &hf_ani_burst_process_time_us, + { + "Responder processing time usec", + "appneta.burst_proc_time", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_outbound_arrival_times, + { + "Outbound Arrival Times", + "appneta.outbound_times", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_lost_id, + { + "Lost Packet ID", + "appneta.lost_id", + FT_UINT32, + BASE_DEC_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_sipport, + { + "Sip Port", + "appneta.sip_port", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ta_id, + { + "Traffic Analysys ID", + "appneta.ta_id", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_protocol, + { + "Sequencer Protocol Version", + "appneta.protocol", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_inbound_packetcount, + { + "Inbound Packet Count", + "appneta.cb_inbound_packet_count", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_inbound_interpacketgap, + { + "Inbound Inter-packet Gap (usec)", + "appneta.cb_inbound_interpacket_gap", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_outbound_packetcount, + { + "Outbound Packet Count", + "appneta.cb_outbound_packet_count", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_outbound_interpacketgap, + { + "Outbound Inter-packet Gap (usec)", + "appneta.cb_outbound_interpacket_gap", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_inbound_flags_csv_debug, + { + "CSV Debug", + "appneta.cb_flags_is_csv_debug", + FT_BOOLEAN, + 32, + NULL, + 0x80000000, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_resp_ratelimitcbrate, + { + "Rate Limit CB Rate", + "appneta.cb_resp_ratelimit_cb_rate", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_resp_minpacketcount, + { + "Minimum Packet Count", + "appneta.cb_resp_min_packet_count", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_request_reserved1, + { + "Rate Limit CB Request - reserved1", + "appneta.cb_resp_ratelimit_cb_request_reserved1", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_request_reserved2, + { + "Rate Limit CB Request - reserved2", + "appneta.cb_resp_ratelimit_cb_request_reserved2", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_ready_reserved1, + { + "Rate Limit CB Ready - reserved1", + "appneta.cb_resp_ratelimit_cb_ready_reserved1", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_cb_ready_reserved2, + { + "Rate Limit CB Ready - reserved2", + "appneta.cb_resp_ratelimit_cb_ready_reserved2", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_padding, + { + "ECB Request padding", + "appneta.ecb_request_padding", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags, + { + "ECB Request flags", + "appneta.ecb_request_flags", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_first_seq, + { + "Is First sequence", + "appneta.ecb_request_flags.first", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x01, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_last_seq, + { + "Is Last sequence", + "appneta.ecb_request_flags.last", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x02, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_reply, + { + "Is Reply", + "appneta.ecb_request_flags.reply", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x04, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_rx_report_all, + { + "RX Report All", + "appneta.ecb_request_flags.report_all", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x08, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_inbound_gap_ns, + { + "Inbound Gap Nanoseconds", + "appneta.ecb_request_flags.inbound_gap_nanoseconds", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x10, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_flags_outbound_gap_ns, + { + "Outbound Gap Nanoseconds", + "appneta.ecb_request_flags.outbound_gap_nanoseconds", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x20, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_ssn, + { + "ECB Starting Sequence Number", + "appneta.ecb_request_ssn", + FT_UINT32, + BASE_DEC_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_outbound_magnify, + { + "ECB Out-bound Magnification", + "appneta.ecb_request_outbound_magnify", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_outbound_duration, + { + "ECB Out-bound Duration (msec)", + "appneta.ecb_request_outbound_duration", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_outbound_gap, + { + "ECB Out-bound Inter-packet Gap (usec)", + "appneta.ecb_request_outbound_gap", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_inbound_magnify, + { + "ECB In-bound Magnification", + "appneta.ecb_request_inbound_magnify", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_inbound_duration, + { + "ECB In-bound Duration (msec)", + "appneta.ecb_request_inbound_duration", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_inbound_gap, + { + "ECB In-bound Inter-packet Gap (usec)", + "appneta.ecb_request_inbound_gap", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_outbound_max_packets, + { + "ECB Out-bound Maximum Packets", + "appneta.ecb_request_outbound_max_packets", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_request_inbound_max_packets, + { + "ECB In-bound Maximum Packets", + "appneta.ecb_request_inbound_max_packets", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_padding, + { + "ECB Response padding", + "appneta.ecb_resp_padding", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_flags, + { + "ECB Response flags", + "appneta.ecb_resp_flags", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_flags_in, + { + "In-bound results available", + "appneta.ecb_resp_flags.in", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x01, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_flags_out, + { + "Out-bound results available", + "appneta.ecb_resp_flags.out", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x02, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_flags_final, + { + "Final results", + "appneta.ecb_resp_flags.final", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x04, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_first_tx_ts, + { + "ECB Response Out-bound TX timestamp (usecs)", + "appneta.ecb_resp_outbound_first_tx_ts", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_first_rx_ts, + { + "ECB Response Out-bound First RX timestamp (usecs)", + "appneta.ecb_resp_outbound_first_rx_ts", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_ll_rx, + { + "ECB Response Out-bound loss-less RX (packets)", + "appneta.ecb_resp_outbound_ll_rx", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_ll_rx_bytes, + { + "ECB Response Out-bound loss-less RX (bytes)", + "appneta.ecb_resp_outbound_ll_rx_bytes", + FT_UINT64, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_ll_us, + { + "ECB Response Out-bound loss-less RX timestamp (usec)", + "appneta.ecb_resp_outbound_ll_us", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_total_rx, + { + "ECB Response Out-bound total RX (packets)", + "appneta.ecb_resp_outbound_total_rx", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_total_rx_bytes, + { + "ECB Response Out-bound total RX (bytes)", + "appneta.ecb_resp_outbound_total_rx_bytes", + FT_UINT64, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_outbound_total_us, + { + "ECB Response Out-bound total RX timestamp (usec)", + "appneta.ecb_resp_outbound_total_us", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_first_tx_ts, + { + "ECB Response In-bound TX timestamp (usecs)", + "appneta.ecb_resp_inbound_first_tx_ts", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_first_rx_ts, + { + "ECB Response In-bound First RX timestamp (usecs)", + "appneta.ecb_resp_inbound_first_rx_ts", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_ll_rx, + { + "ECB Response In-bound loss-less RX (packets)", + "appneta.ecb_resp_inbound_ll_rx", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_ll_rx_bytes, + { + "ECB Response In-bound loss-less RX (bytes)", + "appneta.ecb_resp_inbound_ll_rx_bytes", + FT_UINT64, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_ll_us, + { + "ECB Response In-bound loss-less RX timestamp (usec)", + "appneta.ecb_resp_inbound_ll_us", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_total_rx, + { + "ECB Response In-bound total RX (packets)", + "appneta.ecb_resp_inbound_total_rx", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_total_rx_bytes, + { + "ECB Response In-bound total RX (bytes)", + "appneta.ecb_resp_inbound_total_rx_bytes", + FT_UINT64, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_ecb_resp_inbound_total_us, + { + "ECB Response In-bound total RX timestamp (usec)", + "appneta.ecb_resp_inbound_total_us", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_pseudo_chksum, + { + "Pseudo Checksum", + "appneta.pseudo_cksum", + FT_UINT16, + BASE_HEX_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_iface_info_flags, + { + "Interface Flags", + "appneta.iface_flags", + FT_UINT32, + BASE_HEX, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_iface_info_flags_is_ani_modified, + { + "Is ANI Modified", + "appneta.iface_is_ani_modified", + FT_BOOLEAN, + 32, + NULL, + 0x01, + "", HFILL + } + }, + { + &hf_ani_rpp_iface_info_mtu, + { + "Interface MTU", + "appneta.iface_mtu", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_iface_info_speed, + { + "Interface Speed", + "appneta.iface_speed", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_inboundpacketcount, + { + "Inbound Packet Count", + "appneta.inbound_packet_count", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_inboundpacketsize, + { + "Inbound Packet Size", + "appneta.inbound_packet_size", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_h323port, + { + "H.323 Port", + "appneta.h323_port", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_appliance_type, + { + "Device Type", + "appneta.appliance_type", + FT_UINT8, + BASE_DEC, + VALS(ani_rpp_appliance_type_vals), + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_custom_appliance_type, + { + "Custom Type", + "appneta.custom_appliance_type", + FT_STRING, + BASE_NONE, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_payload, + { + "ANI Payload", + "appneta.payload", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_unknown_header, + { + "Unknown Header", + "appneta.unknown_header", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_signature_undefined, + { + "Undefined signature", + "appneta.signature.undefined_signature", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_legacy, + { + "AppNeta Legacy signature", + "appneta.signature.legacy_signature", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_path, + { + "AppNeta Path signature", + "appneta.signature.path_signature", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_path_reply, + { + "AppNeta Path Reply signature", + "appneta.signature.path_reply_signature", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_pathtest, + { + "AppNeta PathTest signature", + "appneta.signature.pathtest_signature", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_flags, + { + "Path flags", + "appneta.signature.path_flags", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_flags_first, + { + "First packet", + "appneta.signature.path_flags.first", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x10, + "", HFILL + } + }, + { + &hf_ani_rpp_signature_flags_last, + { + "Last packet", + "appneta.signature.path_flags.last", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x20, + "", HFILL + } + }, + { + &hf_ani_rpp_signature_flags_iht, + { + "Interrupt Hold Time (iht) available", + "appneta.signature.path_flags.iht", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x40, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_flags_ext, + { + "Extended Headers", + "appneta.signature.path_flags.ext_hdr", + FT_BOOLEAN, + 8, + TFS(&ani_tf_set_not_set), + 0x80, + NULL, HFILL + } + }, + { + &hf_ani_rpp_signature_iht, + { + "Interrupt Hold Time (iht)", + "appneta.signature.iht", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_signature_burst_len, + { + "Burst Length", + "appneta.signature.burst_len", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + "", HFILL + } + }, + { + &hf_ani_rpp_public_ip, + { + "Public Address", + "appneta.public_ip", + FT_IPv4, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_ani_rpp_public_ip_addr, + { + "Public IPv4 Address", + "appneta.public_ip.addr", + FT_IPv4, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_ani_rpp_public_ipv6, + { + "Public Address", + "appneta.public_ip", + FT_IPv6, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_ani_rpp_public_ipv6_addr, + { + "Public IPv6 Address", + "appneta.public_ip.addr", + FT_IPv6, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + }; + + proto_appneta_responder = proto_register_protocol( + "AppNeta Responder Headers", /* name */ + "AppNeta_Responder", /* short name */ + "appneta_responder" /* abbrev */ + ); + + register_dissector("appneta_responder", dissect_responder_header, + proto_appneta_responder); + + /* Register the protocol name and description */ + proto_ani_rpp = proto_register_protocol("Responder Packet Protocol", + "APPNETA_RPP", "appneta_rpp"); + + proto_register_field_array(proto_ani_rpp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register preferences module */ + ani_rpp_module = prefs_register_protocol(proto_ani_rpp, + proto_reg_handoff_ani_rpp); + + prefs_register_uint_preference(ani_rpp_module, "udp_port", + "UDP Port", + "The UDP port on which " + "AppNeta Responder " + "packets will be sent", + 10,&global_udp_port_artnet); + +} + + +/*******************************************************************************/ +/* If this dissector uses sub-dissector registration add a registration routine. + This exact format is required because a script is used to find these + routines and create the code that calls these routines. + + This function is also called by preferences whenever "Apply" is pressed + (see prefs_register_protocol above) so it should accommodate being called + more than once. + */ +static void +proto_reg_handoff_ani_rpp(void) +{ + static gboolean inited = FALSE; + static guint udp_port_ani_rpp = UDP_PORT_ANI_RPP; + + if (!inited) { + ani_rpp_handle = create_dissector_handle(dissect_ani_rpp, proto_ani_rpp); + inited = TRUE; + } + else { + /* delete the dissector with the old port value */ + dissector_delete_uint("udp.port", udp_port_ani_rpp, ani_rpp_handle); + } + + /* save the new port value */ + udp_port_ani_rpp = global_udp_port_artnet; + + dissector_add_uint("udp.port", global_udp_port_artnet, ani_rpp_handle); + + ip_handle = find_dissector("ip"); + payload_handle = find_dissector("appneta_payload"); +} + +void +plugin_register(void) +{ + static proto_plugin plug; + + plug.register_protoinfo = proto_register_ani_rpp; + plug.register_handoff = proto_reg_handoff_ani_rpp; + proto_register_plugin(&plug); +} diff --git a/plugins/epan/twamp/CMakeLists.txt b/plugins/epan/twamp/CMakeLists.txt new file mode 100644 index 000000000000..9289ac6001b5 --- /dev/null +++ b/plugins/epan/twamp/CMakeLists.txt @@ -0,0 +1,53 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(twamp 0 0 1 0) + +set(PLUGIN_FILES + packet-twamp.c +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +add_plugin_library(twamp epan) + +target_link_libraries(twamp epan) + +install_plugin(twamp epan) + +file(GLOB PLUGIN_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + twamp + SWITCHES + -g abort -g termoutput -build + SOURCES + ${PLUGIN_FILES} + ${PLUGIN_HEADERS} +) + +# +# Editor modelines - http://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 8 +# tab-width: 8 +# indent-tabs-mode: t +# End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# diff --git a/plugins/epan/twamp/Changelog b/plugins/epan/twamp/Changelog new file mode 100644 index 000000000000..f382599a2da2 --- /dev/null +++ b/plugins/epan/twamp/Changelog @@ -0,0 +1,5 @@ +Overview of changes in Art-Net Ethereal plugin: + +Version 0.0.0: + +* initial implementation diff --git a/plugins/epan/twamp/packet-twamp.c b/plugins/epan/twamp/packet-twamp.c new file mode 100644 index 000000000000..a08ee9931473 --- /dev/null +++ b/plugins/epan/twamp/packet-twamp.c @@ -0,0 +1,331 @@ +/* packet-twamp.c + * Routines for Two-Way Active Measurement Protocl (TWAMP) dissection + * + * Currently only implements dissection for unauthenticated packets (TWAMP Light) + * Copyright (c) 2015 AppNeta + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + + /* plugins are DLLs */ +#define WS_BUILD_DLL +#include "ws_symbol_export.h" + + +#include +#include + +#include +#include + +WS_DLL_PUBLIC_DEF const gchar plugin_version[] = PLUGIN_VERSION; +WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR; +WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR; + +WS_DLL_PUBLIC void plugin_register(void); + +static void proto_reg_handoff_twamp(void); +static void proto_register_twamp(void); + +static dissector_handle_t data_handle; + +static int proto_twamp = -1; + +static int hf_twamp_seq = -1; +static int hf_twamp_timestamp = -1; +static int hf_twamp_timestamp_synced = -1; +static int hf_twamp_error_scale = -1; +static int hf_twamp_error_multi = -1; +static int hf_twamp_receive_timestamp = -1; +static int hf_twamp_sender_seq = -1; +static int hf_twamp_sender_timestamp = -1; +static int hf_twamp_sender_timestamp_synced = -1; +static int hf_twamp_sender_error_scale = -1; +static int hf_twamp_sender_error_multi = -1; +static int hf_twamp_sender_ttl = -1; + +static gint ett_twamp = -1; +static gint ett_twamp_error_estim = -1; +static gint ett_twamp_receive_estim = -1; + +/* Global port preference */ +static guint gTWAMP_PORT = 6000; + +/* dissect unauthenticated twamp packets (TWAMP Light) */ +static int +dissect_twamp_unauth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data _U_) +{ + /* SUBTREE VARIABLES AND MISC LOCALS */ + proto_item *ti; + proto_tree *twamp_tree, *error_estim_tree; + + guint error_bytes; + guint64 seq_num_bytes; + gboolean is_request_packet; + guint offset = 0; + + /* CHECK FOR REQUEST PACKET */ + /* if the receive timestamp field is zeroed, + * this packet has not been reflected yet */ + is_request_packet = (tvb_get_ntoh40(tvb, 24) == 0); + + /* SET INFO COLUMN */ + if (is_request_packet) { + col_set_str(pinfo->cinfo, COL_INFO, "TWAMP Request: "); + } else { + col_set_str(pinfo->cinfo, COL_INFO, "TWAMP Reply: "); + } + + /*** PROTOCOL TREE ***/ + /* create display subtree for the TWAMP light protocol */ + ti = proto_tree_add_item(tree, proto_twamp, tvb, 0, -1, ENC_NA); + twamp_tree = proto_item_add_subtree(ti, ett_twamp); + + /* add packet fields to the subtree */ + proto_tree_add_item(twamp_tree, hf_twamp_seq, + tvb, offset, 4, ENC_BIG_ENDIAN); + if (is_request_packet) { + seq_num_bytes = tvb_get_ntoh40(tvb, offset); + if (seq_num_bytes) { + col_append_fstr(pinfo->cinfo, COL_INFO, "Sequence Number = %lu", seq_num_bytes); + } + } + offset+=4; + + proto_tree_add_item(twamp_tree, hf_twamp_timestamp, + tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + offset+=8; + + /* parse the error estimate field in a subtree */ + error_estim_tree = proto_tree_add_subtree(twamp_tree, tvb, offset, 2, + ett_twamp_error_estim, NULL, "Error Estimate"); + + error_bytes = (gboolean) tvb_get_guint8(tvb, offset); + proto_tree_add_boolean(error_estim_tree, hf_twamp_timestamp_synced, + tvb, offset, 1, (gboolean) error_bytes >> 7); + proto_tree_add_uint(error_estim_tree, hf_twamp_error_scale, + tvb, offset, 1, (guint8) error_bytes & 0x3f); + proto_tree_add_item(error_estim_tree, hf_twamp_error_multi, + tvb, offset+1, 1, ENC_BIG_ENDIAN); + offset+=4; /*error bytes followed by two-byte MBZ*/ + + /* add the receiver timestamp to the twamp tree */ + proto_tree_add_item(twamp_tree, hf_twamp_receive_timestamp, + tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + offset+=8; + + proto_tree_add_item(twamp_tree, hf_twamp_sender_seq, + tvb, offset, 4, ENC_BIG_ENDIAN); + if (! is_request_packet) { + seq_num_bytes = tvb_get_ntoh40(tvb, offset); + if (seq_num_bytes) { + col_append_fstr(pinfo->cinfo, COL_INFO, "Sequence Number = %lu", seq_num_bytes); + } + } + offset+=4; + + proto_tree_add_item(twamp_tree, hf_twamp_sender_timestamp, + tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + offset+=8; + + /* parse the sender error estimate field in a subtree */ + error_estim_tree = proto_tree_add_subtree(twamp_tree, tvb, offset, 2, + ett_twamp_receive_estim, NULL, "Sender Error Estimate"); + + error_bytes = tvb_get_guint8(tvb, offset); + proto_tree_add_boolean(error_estim_tree, hf_twamp_sender_timestamp_synced, + tvb, offset, 1, (gboolean) error_bytes >> 7); + proto_tree_add_uint(error_estim_tree, hf_twamp_sender_error_scale, + tvb, offset, 1, (guint8) error_bytes & 0x3f); + proto_tree_add_item(error_estim_tree, hf_twamp_sender_error_multi, + tvb, offset+1, 1, ENC_BIG_ENDIAN); + offset+=4; /*error bytes followed by two-byte MBZ*/ + + /* sender ttl in main tree */ + proto_tree_add_item(twamp_tree, hf_twamp_sender_ttl, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset+=1; + + /* pass remaining data to data handler */ + if (tvb_captured_length_remaining(tvb, offset) > 0) + call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), + pinfo, twamp_tree); + + return tvb_captured_length(tvb); +} /* end dissect_twamp_unauth */ + +static int +dissect_twamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data _U_) +{ + /*** COLUMN DATA ***/ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "TWAMP"); + col_clear(pinfo->cinfo, COL_INFO); + col_set_str(pinfo->cinfo, COL_INFO, "TWAMP Test Packet"); + + /*** HEURISTICS ***/ + /* Check MBZ fields for unauthenticated TWAMP packets */ + if (tvb_get_ntohs(tvb, 14) == 0 && tvb_get_ntohs(tvb, 38) == 0) { + return dissect_twamp_unauth(tvb, pinfo, tree, data); + } else { + /* dissection not supported or invalid packet */ + return 0; + } +} + +static void +proto_register_twamp(void) +{ + module_t *twamp_module; + + /* Setup list of header fields See Section 1.5 of README.dissector for + * details. */ + static hf_register_info hf[] = { + { &hf_twamp_seq, + { "Sequence Number", "twamp.seq", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_timestamp, + { "Timestamp", "twamp.timestamp", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_timestamp_synced, + { "Timestamp Synced", "twamp.timestamp_synced", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_error_scale, + { "Error Scale", "twamp.error_scale", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_error_multi, + { "Error Multiplier", "twamp.error_multi", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_receive_timestamp, + { "Receive Timestamp", "twamp.receiver.timestamp", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_seq, + { "Sender Sequence Number", "twamp.sender.seq", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_timestamp, + { "Sender Timestamp", "twamp.sender.timestamp", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_timestamp_synced, + { "Sender Timestamp Synced", "twamp.sender.timestamp_synced", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_error_scale, + { "Sender Error Scale", "twamp.sender.error_scale", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_error_multi, + { "Sender Error Multiplier", "twamp.sender.error_multi", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_twamp_sender_ttl, + { "Sender TTL", "twamp.sender.ttl", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_twamp, + &ett_twamp_error_estim, + &ett_twamp_receive_estim, + }; + + /* Register the protocol name and description */ + proto_twamp = proto_register_protocol("Two-Way Active Measurement Protocl", + "TWAMP", "twamp"); + + /* Required function calls to register the header fields and subtrees */ + proto_register_field_array(proto_twamp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register preferences */ + twamp_module = prefs_register_protocol(proto_twamp, proto_reg_handoff_twamp); + + /* Register a port preference */ + prefs_register_uint_preference(twamp_module, "udp.port", "TWAMP UDP Port", + " TWAMP UDP port if other than the default", + 10, &gTWAMP_PORT); +} /* end proto_register_twamp */ + +static void proto_reg_handoff_twamp(void) +{ + static gboolean initialized = FALSE; + static dissector_handle_t twamp_handle; + static int currentPort; + + if (!initialized) { + twamp_handle = create_dissector_handle(dissect_twamp, proto_twamp); + currentPort = gTWAMP_PORT; + initialized = TRUE; + + /* get the handle for the data handler */ + data_handle = find_dissector("data"); + } else { + /* needed to change the configured port */ + dissector_delete_uint("udp.port", currentPort, twamp_handle); + currentPort = gTWAMP_PORT; + } + + dissector_add_uint("udp.port", gTWAMP_PORT, twamp_handle); +} + +void +plugin_register(void) +{ + static proto_plugin plug; + + plug.register_protoinfo = proto_register_twamp; + plug.register_handoff = proto_reg_handoff_twamp; + proto_register_plugin(&plug); +} + +/* + * Editor modelines - http://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: + */