TWAMP dissector for RFC 5357
From https://github.com/demirten/twamp-dissector cleaned up a bit. Change-Id: I3736e2ef09bd84ba30a63fee8bf07771f07bfe6c Reviewed-on: https://code.wireshark.org/review/24283 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
4367855163
commit
f2727b571a
|
@ -84,6 +84,7 @@ FP Mux
|
|||
Network Functional Application Platform Interface (NFAPI) Protocol
|
||||
IEEE 1905.1a
|
||||
Bluetooth Mesh
|
||||
TWAMP and OWAMP
|
||||
--sort-and-group--
|
||||
|
||||
=== Updated Protocol Support
|
||||
|
|
|
@ -1674,6 +1674,7 @@ set(DISSECTOR_SRC
|
|||
packet-turbocell.c
|
||||
packet-turnchannel.c
|
||||
packet-tuxedo.c
|
||||
packet-twamp.c
|
||||
packet-tzsp.c
|
||||
packet-u3v.c
|
||||
packet-ua.c
|
||||
|
|
|
@ -1328,6 +1328,7 @@ DISSECTOR_SRC = \
|
|||
packet-turbocell.c \
|
||||
packet-turnchannel.c \
|
||||
packet-tuxedo.c \
|
||||
packet-twamp.c \
|
||||
packet-tzsp.c \
|
||||
packet-u3v.c \
|
||||
packet-ua.c \
|
||||
|
|
|
@ -0,0 +1,807 @@
|
|||
/* packet-twamp.c
|
||||
* Routines for TWAMP packet dissection
|
||||
*
|
||||
* Murat Demirten <murat@debian.org>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* Documentation:
|
||||
* RFC 4656: A One-way Active Measurement Protocol (OWAMP)
|
||||
* RFC 5357: A Two-Way Active Measurement Protocol (TWAMP)
|
||||
* RFC 5618: Mixed Security Mode for the TWAMP
|
||||
* (not yet implemented)
|
||||
* RFC 5938: Individual Session Control Feature for the TWAMP
|
||||
* (not yet implemented)
|
||||
* RFC 6038: TWAMP Reflect Octets and Symmetrical Size Features
|
||||
* (not yet implemented)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <epan/packet.h>
|
||||
#include <epan/conversation.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/proto_data.h>
|
||||
|
||||
|
||||
void proto_reg_handoff_twamp(void);
|
||||
void proto_register_twamp(void);
|
||||
|
||||
#define TWAMP_CONTROL_PORT 862
|
||||
#define TWAMP_CONTROL_SERVER_GREETING_LEN 64
|
||||
#define TWAMP_SESSION_ACCEPT_OK 0
|
||||
/* Twamp times start from year 1900 */
|
||||
#define TWAMP_FLOAT_DENOM 4294.967296
|
||||
|
||||
#define TWAMP_MODE_UNAUTHENTICATED 0x1
|
||||
#define TWAMP_MODE_AUTHENTICATED 0x2
|
||||
#define TWAMP_MODE_ENCRYPTED 0x4
|
||||
|
||||
enum twamp_control_state {
|
||||
CONTROL_STATE_UNKNOWN = 0,
|
||||
CONTROL_STATE_GREETING,
|
||||
CONTROL_STATE_SETUP_RESPONSE,
|
||||
CONTROL_STATE_SERVER_START,
|
||||
CONTROL_STATE_REQUEST_SESSION,
|
||||
CONTROL_STATE_ACCEPT_SESSION,
|
||||
CONTROL_STATE_START_SESSIONS,
|
||||
CONTROL_STATE_START_SESSIONS_ACK,
|
||||
CONTROL_STATE_TEST_RUNNING,
|
||||
CONTROL_STATE_STOP_SESSIONS,
|
||||
CONTROL_STATE_REQUEST_TW_SESSION
|
||||
};
|
||||
|
||||
typedef struct _twamp_session {
|
||||
guint8 accepted;
|
||||
int padding;
|
||||
guint16 sender_port;
|
||||
guint16 receiver_port;
|
||||
guint32 sender_address[4];
|
||||
guint32 receiver_address[4];
|
||||
guint8 ipvn;
|
||||
} twamp_session_t;
|
||||
|
||||
typedef struct twamp_control_packet {
|
||||
guint32 fd;
|
||||
enum twamp_control_state state;
|
||||
conversation_t *conversation;
|
||||
} twamp_control_packet_t;
|
||||
|
||||
typedef struct twamp_control_transaction {
|
||||
enum twamp_control_state last_state;
|
||||
guint32 first_data_frame;
|
||||
GSList *sessions;
|
||||
proto_tree *tree;
|
||||
} twamp_control_transaction_t;
|
||||
|
||||
static dissector_handle_t owamp_test_handle;
|
||||
static dissector_handle_t twamp_test_handle;
|
||||
static dissector_handle_t twamp_control_handle;
|
||||
|
||||
/* Protocol enabled flags */
|
||||
static int proto_owamp_test = -1;
|
||||
static int proto_twamp_test = -1;
|
||||
static int proto_twamp_control = -1;
|
||||
static gint ett_owamp_test = -1;
|
||||
static gint ett_twamp_test = -1;
|
||||
static gint ett_twamp_control = -1;
|
||||
static gint ett_twamp_error_estimate = -1;
|
||||
|
||||
/* Twamp test fields */
|
||||
static int hf_twamp_seq_number = -1;
|
||||
static int hf_twamp_sender_timestamp = -1;
|
||||
static int hf_twamp_error_estimate = -1;
|
||||
static int hf_twamp_mbz1 = -1;
|
||||
static int hf_twamp_receive_timestamp = -1;
|
||||
static int hf_twamp_sender_seq_number = -1;
|
||||
static int hf_twamp_timestamp = -1;
|
||||
static int hf_twamp_sender_error_estimate = -1;
|
||||
static int hf_twamp_mbz2 = -1;
|
||||
static int hf_twamp_sender_ttl = -1;
|
||||
static int hf_twamp_padding = -1;
|
||||
static int hf_twamp_error_estimate_multiplier = -1;
|
||||
static int hf_twamp_error_estimate_scale = -1;
|
||||
static int hf_twamp_error_estimate_b14 = -1;
|
||||
static int hf_twamp_error_estimate_b15 = -1;
|
||||
|
||||
/* Twamp control fields */
|
||||
static int hf_twamp_control_unused = -1;
|
||||
static int hf_twamp_control_command = -1;
|
||||
static int hf_twamp_control_modes = -1;
|
||||
static int hf_twamp_control_mode = -1;
|
||||
static int hf_twamp_control_challenge = -1;
|
||||
static int hf_twamp_control_salt = -1;
|
||||
static int hf_twamp_control_count = -1;
|
||||
static int hf_twamp_control_keyid = -1;
|
||||
static int hf_twamp_control_sessionid = -1;
|
||||
static int hf_twamp_control_iv = -1;
|
||||
static int hf_twamp_control_ipvn = -1;
|
||||
static int hf_twamp_control_start_time = -1;
|
||||
static int hf_twamp_control_accept = -1;
|
||||
static int hf_twamp_control_timeout = -1;
|
||||
static int hf_twamp_control_type_p = -1;
|
||||
static int hf_twamp_control_mbz1 = -1;
|
||||
static int hf_twamp_control_mbz2 = -1;
|
||||
static int hf_twamp_control_hmac = -1;
|
||||
static int hf_twamp_control_num_sessions = -1;
|
||||
static int hf_twamp_control_sender_port = -1;
|
||||
static int hf_twamp_control_server_uptime = -1;
|
||||
static int hf_twamp_control_receiver_port = -1;
|
||||
static int hf_twamp_control_padding_length = -1;
|
||||
static int hf_twamp_control_sender_ipv4 = -1;
|
||||
static int hf_twamp_control_sender_ipv6 = -1;
|
||||
static int hf_twamp_control_receiver_ipv4 = -1;
|
||||
static int hf_twamp_control_receiver_ipv6 = -1;
|
||||
|
||||
static const value_string twamp_control_accept_vals[] = {
|
||||
{ 0, "OK" },
|
||||
{ 1, "Failure, reason unspecified (catch-all)" },
|
||||
{ 2, "Internal error" },
|
||||
{ 3, "Some aspect of request is not supported" },
|
||||
{ 4, "Cannot perform request due to permanent resource limitations" },
|
||||
{ 5, "Cannot perform request due to temporary resource limitations" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const value_string twamp_control_command_vals[] = {
|
||||
{ 0, "Reserved" },
|
||||
{ 1, "Forbidden" },
|
||||
{ 2, "Start-Sessions" },
|
||||
{ 3, "Stop-Sessions" },
|
||||
{ 4, "Reserved" },
|
||||
{ 5, "Request-TW-Session" },
|
||||
{ 6, "Experimentation" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static
|
||||
gint find_twamp_session_by_sender_port (gconstpointer element, gconstpointer compared)
|
||||
{
|
||||
guint16 *sender_port = (guint16*) compared;
|
||||
twamp_session_t *session = (twamp_session_t*) element;
|
||||
return !(session->sender_port == *sender_port);
|
||||
}
|
||||
|
||||
static
|
||||
gint find_twamp_session_by_first_accept_waiting (gconstpointer element)
|
||||
{
|
||||
twamp_session_t *session = (twamp_session_t*) element;
|
||||
if (session->accepted == 0) return 0; else return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_twamp_control (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
gint offset = 0;
|
||||
gboolean is_request;
|
||||
proto_item *twamp_tree = NULL;
|
||||
conversation_t *conversation = NULL;
|
||||
twamp_control_transaction_t *ct = NULL;
|
||||
twamp_control_packet_t *cp = NULL;
|
||||
twamp_session_t *session = NULL;
|
||||
guint8 accept;
|
||||
guint16 sender_port;
|
||||
guint16 receiver_port;
|
||||
GSList *list;
|
||||
int captured_length;
|
||||
nstime_t ts;
|
||||
proto_tree *item;
|
||||
guint32 modes;
|
||||
guint32 type_p;
|
||||
guint8 ipvn;
|
||||
|
||||
offset = 0;
|
||||
captured_length = tvb_captured_length(tvb);
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "TWAMP-Control");
|
||||
|
||||
if (pinfo->destport == TWAMP_CONTROL_PORT) {
|
||||
is_request = TRUE;
|
||||
} else {
|
||||
is_request = FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!pinfo->fd->flags.visited) {
|
||||
conversation = find_or_create_conversation(pinfo);
|
||||
ct = (twamp_control_transaction_t *) conversation_get_proto_data(conversation, proto_twamp_control);
|
||||
if (ct == NULL && is_request == FALSE && captured_length == TWAMP_CONTROL_SERVER_GREETING_LEN) {
|
||||
/* We got server greeting */
|
||||
if ((ct = wmem_new0(wmem_file_scope(), twamp_control_transaction_t)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
conversation_add_proto_data(conversation, proto_twamp_control, ct);
|
||||
ct->last_state = CONTROL_STATE_UNKNOWN;
|
||||
ct->first_data_frame = pinfo->fd->num;
|
||||
}
|
||||
if ((cp = (twamp_control_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_twamp_control, 0)) == NULL) {
|
||||
cp = wmem_new0(wmem_file_scope(), twamp_control_packet_t);
|
||||
p_add_proto_data(wmem_file_scope(), pinfo, proto_twamp_control, 0, cp);
|
||||
}
|
||||
/* detect state */
|
||||
if (pinfo->fd->num == ct->first_data_frame) {
|
||||
ct->last_state = CONTROL_STATE_GREETING;
|
||||
} else if (ct->last_state == CONTROL_STATE_GREETING) {
|
||||
ct->last_state = CONTROL_STATE_SETUP_RESPONSE;
|
||||
} else if (ct->last_state == CONTROL_STATE_SETUP_RESPONSE) {
|
||||
ct->last_state = CONTROL_STATE_SERVER_START;
|
||||
} else if (ct->last_state == CONTROL_STATE_SERVER_START) {
|
||||
ct->last_state = CONTROL_STATE_REQUEST_SESSION;
|
||||
sender_port = tvb_get_ntohs(tvb, 12);
|
||||
receiver_port = tvb_get_ntohs(tvb, 14);
|
||||
/* try to find session from past visits */
|
||||
if ((list = g_slist_find_custom(ct->sessions, &sender_port,
|
||||
(GCompareFunc) find_twamp_session_by_sender_port)) == NULL) {
|
||||
session = (twamp_session_t *) g_malloc0(sizeof(twamp_session_t));
|
||||
session->sender_port = sender_port;
|
||||
session->receiver_port = receiver_port;
|
||||
session->accepted = 0;
|
||||
ipvn = tvb_get_guint8(tvb, 1) & 0x0F;
|
||||
|
||||
if (ipvn == 6) {
|
||||
tvb_get_ipv6(tvb, 16, (struct e_in6_addr*) &session->sender_address);
|
||||
tvb_get_ipv6(tvb, 32, (struct e_in6_addr*) &session->receiver_address);
|
||||
|
||||
} else {
|
||||
session->sender_address[0] = tvb_get_ipv4(tvb, 16);
|
||||
session->receiver_address[0] = tvb_get_ipv4(tvb, 32);
|
||||
}
|
||||
/*
|
||||
* If ip addresses not specified in control protocol, we have to choose from IP header.
|
||||
* It is a design decision by TWAMP and we need that ports for identifying future UDP conversations
|
||||
*/
|
||||
if (session->sender_address[0] == 0) {
|
||||
memcpy(&session->sender_address[0], pinfo->src.data, pinfo->src.len);
|
||||
}
|
||||
if (session->receiver_address[0] == 0) {
|
||||
memcpy(&session->receiver_address[0], pinfo->dst.data, pinfo->dst.len);
|
||||
}
|
||||
session->padding = tvb_get_ntohl(tvb, 64);
|
||||
ct->sessions = g_slist_append(ct->sessions, session);
|
||||
}
|
||||
} else if (ct->last_state == CONTROL_STATE_REQUEST_SESSION) {
|
||||
ct->last_state = CONTROL_STATE_ACCEPT_SESSION;
|
||||
accept = tvb_get_guint8(tvb, 0);
|
||||
if (accept == TWAMP_SESSION_ACCEPT_OK) {
|
||||
receiver_port = tvb_get_ntohs(tvb, 2);
|
||||
|
||||
if ((list = g_slist_find_custom(ct->sessions, NULL,
|
||||
(GCompareFunc) find_twamp_session_by_first_accept_waiting)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
session = (twamp_session_t*) list->data;
|
||||
session->receiver_port = receiver_port;
|
||||
|
||||
cp->conversation = find_conversation(pinfo->fd->num, &pinfo->dst, &pinfo->src, ENDPOINT_UDP,
|
||||
session->sender_port, session->receiver_port, 0);
|
||||
if (cp->conversation == NULL /*|| cp->conversation->dissector_handle != twamp_test_handle*/) {
|
||||
cp->conversation = conversation_new(pinfo->fd->num, &pinfo->dst, &pinfo->src, ENDPOINT_UDP,
|
||||
session->sender_port, session->receiver_port, 0);
|
||||
if (cp->conversation) {
|
||||
/* create conversation specific data for test sessions */
|
||||
conversation_add_proto_data(cp->conversation, proto_twamp_test, session);
|
||||
conversation_set_dissector(cp->conversation, twamp_test_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ct->last_state == CONTROL_STATE_ACCEPT_SESSION) {
|
||||
ct->last_state = CONTROL_STATE_START_SESSIONS;
|
||||
} else if (ct->last_state == CONTROL_STATE_START_SESSIONS) {
|
||||
ct->last_state = CONTROL_STATE_START_SESSIONS_ACK;
|
||||
} else if (ct->last_state == CONTROL_STATE_START_SESSIONS_ACK) {
|
||||
ct->last_state = CONTROL_STATE_STOP_SESSIONS;
|
||||
} else {
|
||||
/* response */
|
||||
}
|
||||
cp->state = ct->last_state;
|
||||
return captured_length;
|
||||
}
|
||||
|
||||
proto_tree *it = proto_tree_add_item(tree, proto_twamp_control, tvb, 0, -1, ENC_NA);
|
||||
|
||||
if ((cp = (twamp_control_packet_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_twamp_control, 0)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (cp->state) {
|
||||
case CONTROL_STATE_GREETING:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Server Greeting");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_unused, tvb, offset, 12, ENC_NA);
|
||||
offset += 12;
|
||||
modes = tvb_get_ntohl(tvb, offset) & 0x00000007;
|
||||
item = proto_tree_add_item(twamp_tree, hf_twamp_control_modes, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
proto_item_append_text(item, " (%s%s%s)",
|
||||
(modes & TWAMP_MODE_UNAUTHENTICATED) ? " Unauthenticated " : "",
|
||||
(modes & TWAMP_MODE_AUTHENTICATED) ? "Authenticated " : "",
|
||||
(modes & TWAMP_MODE_ENCRYPTED) ? "Encrypted " : "");
|
||||
offset += 4;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_challenge, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_salt, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_count, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 12, ENC_NA);
|
||||
offset += 12;
|
||||
break;
|
||||
|
||||
case CONTROL_STATE_SETUP_RESPONSE:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Setup Response");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mode, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_keyid, tvb, offset, 40, ENC_NA);
|
||||
offset += 40;
|
||||
break;
|
||||
case CONTROL_STATE_SERVER_START:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Server Start");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 15, ENC_NA);
|
||||
offset += 15;
|
||||
accept = tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_uint(twamp_tree, hf_twamp_control_accept, tvb, offset, 1, accept);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", (%s%s)",
|
||||
(accept == 0) ? "" : "Error: ", val_to_str(accept, twamp_control_accept_vals, "%u"));
|
||||
offset += 1;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_iv, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_server_uptime, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz2, tvb, offset, 8, ENC_NA);
|
||||
|
||||
break;
|
||||
case CONTROL_STATE_REQUEST_SESSION:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Request Session");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_command, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset += 1;
|
||||
|
||||
ipvn = tvb_get_guint8(tvb, offset) & 0x0F;
|
||||
proto_tree_add_uint(twamp_tree, hf_twamp_control_ipvn, tvb, offset, 1, ipvn);
|
||||
|
||||
offset = 12;
|
||||
sender_port = tvb_get_ntohs(tvb, offset);
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_sender_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
receiver_port = tvb_get_ntohs(tvb, offset);
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_receiver_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
|
||||
if (ipvn == 6) {
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_sender_ipv6, tvb, offset, 16, ENC_NA);
|
||||
} else {
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_sender_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
}
|
||||
offset += 16;
|
||||
if (ipvn == 6) {
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_receiver_ipv6, tvb, offset, 16, ENC_NA);
|
||||
} else {
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_receiver_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
}
|
||||
offset += 16;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_sessionid, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_padding_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_start_time, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
|
||||
ts.secs = tvb_get_ntohl(tvb, offset);
|
||||
ts.nsecs = (int)(tvb_get_ntohl(tvb, offset + 4) / TWAMP_FLOAT_DENOM);
|
||||
proto_tree_add_none_format(twamp_tree, hf_twamp_control_timeout, tvb, offset, 8,
|
||||
"Timeout: %i.%06i Seconds", (int)ts.secs, (int)ts.nsecs);
|
||||
offset += 8;
|
||||
|
||||
type_p = tvb_get_ntohl(tvb, offset);
|
||||
item = proto_tree_add_item(twamp_tree, hf_twamp_control_type_p, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
proto_item_append_text(item, " (DSCP: %d)", type_p);
|
||||
offset += 4;
|
||||
break;
|
||||
case CONTROL_STATE_ACCEPT_SESSION:
|
||||
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Accept Session");
|
||||
accept = tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_uint(twamp_tree, hf_twamp_control_accept, tvb, offset, 1, accept);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", (%s%s)",
|
||||
(accept == 0) ? "" : "Error: ", val_to_str(accept, twamp_control_accept_vals, "%u"));
|
||||
offset = 2;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_receiver_port, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_sessionid, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 12, ENC_NA);
|
||||
offset += 12;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_hmac, tvb, offset, 16, ENC_NA);
|
||||
break;
|
||||
case CONTROL_STATE_START_SESSIONS:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Start Sessions");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_command, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset += 1;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 15, ENC_NA);
|
||||
offset += 15;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_hmac, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
break;
|
||||
case CONTROL_STATE_START_SESSIONS_ACK:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Start Sessions ACK");
|
||||
accept = tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_uint(twamp_tree, hf_twamp_control_accept, tvb, offset, 1, accept);
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", (%s%s)",
|
||||
(accept == 0) ? "" : "Error: ", val_to_str(accept, twamp_control_accept_vals, "%u"));
|
||||
offset += 1;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 15, ENC_NA);
|
||||
offset += 15;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_hmac, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
break;
|
||||
case CONTROL_STATE_STOP_SESSIONS:
|
||||
twamp_tree = proto_item_add_subtree(it, ett_twamp_control);
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Stop Session");
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_command, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_accept, tvb, offset, 1, ENC_NA);
|
||||
offset += 1;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz1, tvb, offset, 2, ENC_NA);
|
||||
offset += 2;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_num_sessions, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_mbz2, tvb, offset, 8, ENC_NA);
|
||||
offset += 8;
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_control_hmac, tvb, offset, 16, ENC_NA);
|
||||
offset += 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return captured_length;
|
||||
}
|
||||
|
||||
static const int * twamp_error_estimate_flags[] = {
|
||||
&hf_twamp_error_estimate_b15,
|
||||
&hf_twamp_error_estimate_b14,
|
||||
&hf_twamp_error_estimate_scale,
|
||||
&hf_twamp_error_estimate_multiplier,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const true_false_string tfs_twamp_sbit_tfs = {
|
||||
"Synchronized to UTC using an external source",
|
||||
"No notion of external synchronization"
|
||||
};
|
||||
|
||||
static int
|
||||
dissect_owamp_test(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
proto_item *ti = NULL;
|
||||
proto_item *owamp_tree = NULL;
|
||||
int offset = 0, padding = 0;
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "OWAMP-Test");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
ti = proto_tree_add_item(tree, proto_owamp_test, tvb, 0, -1, ENC_NA);
|
||||
owamp_tree = proto_item_add_subtree(ti, ett_owamp_test);
|
||||
|
||||
col_append_str(pinfo->cinfo, COL_INFO, "Measurement packet");
|
||||
|
||||
/* Sequence number ar in both packet types.*/
|
||||
proto_tree_add_item(owamp_tree, hf_twamp_seq_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(owamp_tree, hf_twamp_timestamp, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
|
||||
/*
|
||||
* 0 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |S|Z| Scale | Multiplier |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
proto_tree_add_bitmask(owamp_tree, tvb, offset, hf_twamp_error_estimate, ett_twamp_error_estimate, twamp_error_estimate_flags, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
|
||||
padding = tvb_reported_length(tvb) - offset;
|
||||
if (padding > 0) {
|
||||
proto_tree_add_item(owamp_tree, hf_twamp_padding, tvb, offset, padding, ENC_NA);
|
||||
offset += padding;
|
||||
}
|
||||
|
||||
return tvb_reported_length(tvb);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_twamp_test(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
gint offset = 0;
|
||||
proto_item *ti = NULL;
|
||||
proto_item *twamp_tree = NULL;
|
||||
int padding = 0;
|
||||
|
||||
col_set_str(pinfo-> cinfo, COL_PROTOCOL, "TWAMP-Test");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
ti = proto_tree_add_item (tree, proto_twamp_test, tvb, 0, -1, ENC_NA);
|
||||
twamp_tree = proto_item_add_subtree (ti, ett_twamp_test);
|
||||
|
||||
col_append_str(pinfo->cinfo, COL_INFO, "Measurement packet");
|
||||
|
||||
/* Sequence number are in both packet types.*/
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_seq_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_timestamp, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
|
||||
/*
|
||||
* 0 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |S|Z| Scale | Multiplier |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
proto_tree_add_bitmask(twamp_tree, tvb, offset, hf_twamp_error_estimate, ett_twamp_error_estimate, twamp_error_estimate_flags, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
|
||||
proto_tree_add_item (twamp_tree, hf_twamp_mbz1, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
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_number, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset += 4;
|
||||
|
||||
proto_tree_add_item(twamp_tree, hf_twamp_sender_timestamp, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN);
|
||||
offset += 8;
|
||||
|
||||
proto_tree_add_item (twamp_tree, hf_twamp_sender_error_estimate, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item (twamp_tree, hf_twamp_mbz2, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset += 2;
|
||||
proto_tree_add_item (twamp_tree, hf_twamp_sender_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset += 1;
|
||||
|
||||
padding = tvb_reported_length(tvb) - offset;
|
||||
if (padding > 0) {
|
||||
proto_tree_add_item (twamp_tree, hf_twamp_padding, tvb, offset, padding, ENC_NA);
|
||||
offset += padding;
|
||||
}
|
||||
|
||||
/* Return the total length */
|
||||
return tvb_reported_length(tvb);
|
||||
}
|
||||
|
||||
void proto_register_twamp(void)
|
||||
{
|
||||
static hf_register_info hf_twamp_test[] = {
|
||||
{&hf_twamp_seq_number,
|
||||
{"Sequence Number", "twamp.test.seq_number", FT_UINT32,
|
||||
BASE_DEC, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_timestamp,
|
||||
{"Timestamp", "twamp.test.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
|
||||
NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_error_estimate,
|
||||
{"Error Estimate", "twamp.test.error_estimate", FT_UINT16,
|
||||
BASE_DEC_HEX, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_mbz1,
|
||||
{"MBZ", "twamp.test.mbz1", FT_UINT8, BASE_DEC_HEX,
|
||||
NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_receive_timestamp,
|
||||
{"Receive Timestamp", "twamp.test.receive_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_sender_seq_number,
|
||||
{"Sender Sequence Number", "twamp.test.sender_seq_number",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_sender_timestamp,
|
||||
{"Sender Timestamp", "twamp.test.sender_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_sender_error_estimate,
|
||||
{"Sender Error Estimate", "twamp.test.sender_error_estimate",
|
||||
FT_UINT16, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_mbz2,
|
||||
{"MBZ", "twamp.test.mbz2", FT_UINT8, BASE_DEC_HEX,
|
||||
NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_sender_ttl,
|
||||
{"Sender TTL", "twamp.test.sender_ttl", FT_UINT8, BASE_DEC,
|
||||
NULL, 0x0, NULL, HFILL}},
|
||||
{&hf_twamp_padding,
|
||||
{"Packet Padding", "twamp.test.padding", FT_BYTES, BASE_NONE,
|
||||
NULL, 0x0, NULL, HFILL}},
|
||||
{ &hf_twamp_error_estimate_multiplier,
|
||||
{ "Multiplier", "twamp.test.error_estimate.multiplier", FT_UINT16, BASE_DEC,
|
||||
NULL, 0x00ff, NULL, HFILL } },
|
||||
{ &hf_twamp_error_estimate_scale,
|
||||
{ "Scale", "twamp.test.error_estimate.scale", FT_UINT16, BASE_DEC,
|
||||
NULL, 0x3f00, NULL, HFILL } },
|
||||
{ &hf_twamp_error_estimate_b14,
|
||||
{ "Z", "twamp.test.error_estimate.z", FT_BOOLEAN, 16,
|
||||
NULL, 0x4000, NULL, HFILL } },
|
||||
{ &hf_twamp_error_estimate_b15,
|
||||
{ "S", "twamp.test.error_estimate.s", FT_BOOLEAN, 16,
|
||||
TFS(&tfs_twamp_sbit_tfs), 0x8000, NULL, HFILL } },
|
||||
};
|
||||
|
||||
static gint *ett_twamp_test_arr[] = {
|
||||
&ett_owamp_test,
|
||||
&ett_twamp_test
|
||||
};
|
||||
|
||||
static hf_register_info hf_twamp_control[] = {
|
||||
{&hf_twamp_control_unused,
|
||||
{"Unused", "twamp.control.unused", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_command,
|
||||
{"Control Command", "twamp.control.command", FT_UINT8, BASE_DEC,
|
||||
VALS(twamp_control_command_vals), 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_modes,
|
||||
{"Supported Modes", "twamp.control.modes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_mode,
|
||||
{"Mode", "twamp.control.mode", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_keyid,
|
||||
{"Key ID", "twamp.control.keyid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_challenge,
|
||||
{"Challenge", "twamp.control.challenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_salt,
|
||||
{"Salt", "twamp.control.salt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_count,
|
||||
{"Count", "twamp.control.count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_iv,
|
||||
{"Control IV", "twamp.control.iv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_sessionid,
|
||||
{"Session Id", "twamp.control.session_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_mbz1,
|
||||
{"MBZ", "twamp.control.mbz1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_mbz2,
|
||||
{"MBZ", "twamp.control.mbz2", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_hmac,
|
||||
{"HMAC", "twamp.control.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_padding_length,
|
||||
{"Padding Length", "twamp.control.padding_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_start_time,
|
||||
{"Start Time", "twamp.control.start_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_timeout,
|
||||
{"Timeout", "twamp.control.timeout", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_type_p,
|
||||
{"Type-P Descriptor", "twamp.control.type-p", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_num_sessions,
|
||||
{"Number of Sessions", "twamp.control.numsessions", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_server_uptime,
|
||||
{"Server Start Time", "twamp.control.server_uptime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_accept,
|
||||
{"Accept", "twamp.control.accept", FT_UINT8, BASE_DEC, VALS(twamp_control_accept_vals), 0x0,
|
||||
"Message acceptence by the other side", HFILL}
|
||||
},
|
||||
{&hf_twamp_control_sender_port,
|
||||
{"Sender Port", "twamp.control.sender_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_receiver_port,
|
||||
{"Receiver Port", "twamp.control.receiver_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_ipvn,
|
||||
{"IP Version", "twamp.control.ipvn", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
|
||||
},
|
||||
{&hf_twamp_control_sender_ipv4,
|
||||
{"Sender Address", "twamp.control.sender_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
|
||||
"IPv4 sender address want to use in test packets", HFILL}
|
||||
},
|
||||
{&hf_twamp_control_sender_ipv6,
|
||||
{"Sender Address", "twamp.control.sender_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
|
||||
"IPv6 sender address want to use in test packets", HFILL}
|
||||
},
|
||||
{&hf_twamp_control_receiver_ipv4,
|
||||
{"Receiver Address", "twamp.control.receiver_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
|
||||
"IPv4 sender address want to use in test packets", HFILL}
|
||||
},
|
||||
{&hf_twamp_control_receiver_ipv6,
|
||||
{"Receiver Address", "twamp.control.receiver_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
|
||||
"IPv6 receiver address want to use in test packets", HFILL}
|
||||
}
|
||||
};
|
||||
|
||||
static gint *ett_twamp_control_arr[] = {
|
||||
&ett_twamp_control,
|
||||
&ett_twamp_error_estimate
|
||||
};
|
||||
|
||||
|
||||
/* Register the protocol */
|
||||
proto_twamp_test = proto_register_protocol(
|
||||
"TwoWay Active Measurement Test Protocol",
|
||||
"TWAMP-Test",
|
||||
"twamp.test");
|
||||
|
||||
/* Register the field array */
|
||||
proto_register_field_array (proto_twamp_test, hf_twamp_test,
|
||||
array_length(hf_twamp_test));
|
||||
|
||||
/* Register the subtree array */
|
||||
proto_register_subtree_array (ett_twamp_test_arr,
|
||||
array_length(ett_twamp_test_arr));
|
||||
|
||||
/* Register the protocol */
|
||||
proto_twamp_control = proto_register_protocol(
|
||||
"TwoWay Active Measurement Control Protocol",
|
||||
"TWAMP-Control",
|
||||
"twamp.control");
|
||||
|
||||
/* Register the field array */
|
||||
proto_register_field_array (proto_twamp_control, hf_twamp_control,
|
||||
array_length(hf_twamp_control));
|
||||
|
||||
/* Register the subtree array */
|
||||
proto_register_subtree_array (ett_twamp_control_arr,
|
||||
array_length(ett_twamp_control_arr));
|
||||
|
||||
proto_owamp_test = proto_register_protocol(
|
||||
"One-way Active Measurement Protocol",
|
||||
"OWAMP-Test",
|
||||
"owamp.test");
|
||||
|
||||
}
|
||||
|
||||
void proto_reg_handoff_twamp(void)
|
||||
{
|
||||
twamp_test_handle = create_dissector_handle(dissect_twamp_test, proto_twamp_test);
|
||||
|
||||
owamp_test_handle = create_dissector_handle(dissect_owamp_test, proto_owamp_test);
|
||||
|
||||
twamp_control_handle = create_dissector_handle(dissect_twamp_control, proto_twamp_control);
|
||||
dissector_add_uint("tcp.port", TWAMP_CONTROL_PORT, twamp_control_handle);
|
||||
|
||||
dissector_add_for_decode_as("udp.port", twamp_test_handle);
|
||||
dissector_add_for_decode_as("udp.port", owamp_test_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
Loading…
Reference in New Issue