aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-coap.c
diff options
context:
space:
mode:
authorChristoph Burger-Scheidlin <mail@christoph.burger-scheidlin.name>2016-02-09 23:14:25 +0100
committerMichael Mann <mmann78@netscape.net>2016-02-11 20:35:44 +0000
commite6b59962e895972940b535e23168a9673648d089 (patch)
tree76d73bcfac593803caaf373ab3e406d406215aba /epan/dissectors/packet-coap.c
parent875d95ea605758308fc2369d83a41a34a6adbe53 (diff)
CoAP: Add support for tracking requests and responses
Use CoAP's token to match responses to requests in CoAP. Change-Id: I13141e3490d54aa27aea7c94d8199dcc0166d493 Reviewed-on: https://code.wireshark.org/review/13859 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-coap.c')
-rw-r--r--epan/dissectors/packet-coap.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/epan/dissectors/packet-coap.c b/epan/dissectors/packet-coap.c
index 113743518d..fc7d3b1846 100644
--- a/epan/dissectors/packet-coap.c
+++ b/epan/dissectors/packet-coap.c
@@ -31,9 +31,11 @@
#include "config.h"
+#include <epan/conversation.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/expert.h>
+#include <epan/wmem/wmem.h>
void proto_register_coap(void);
@@ -76,6 +78,10 @@ static int hf_coap_opt_block_size = -1;
static int hf_coap_opt_uri_query = -1;
static int hf_coap_opt_unknown = -1;
+static int hf_coap_response_in = -1;
+static int hf_coap_response_to = -1;
+static int hf_coap_response_time = -1;
+
static gint ett_coap = -1;
static gint ett_coap_option = -1;
static gint ett_coap_payload = -1;
@@ -251,6 +257,16 @@ static const value_string vals_ctype[] = {
{ 0, NULL },
};
+typedef struct _coap_transaction_t {
+ guint32 req_frame;
+ guint32 rep_frame;
+ nstime_t req_time;
+} coap_transaction_t;
+
+typedef struct _coap_conv_info_t {
+ wmem_tree_t *pdus;
+} coap_conv_info_t;
+
static const char *nullstr = "(null)";
void proto_reg_handoff_coap(void);
@@ -797,6 +813,12 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* d
guint16 mid;
gint coap_length;
gchar *coap_token_str;
+ conversation_t *conversation;
+ coap_conv_info_t *coap_info;
+ coap_transaction_t *coap_trans;
+ wmem_tree_key_t coap_key[3];
+ guint32 key_token_length;
+ guint32 key_token[2];
/* initialize the CoAP length and the content-Format */
/*
@@ -857,6 +879,16 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* d
coap_token_str = tvb_bytes_to_str_punct(wmem_packet_scope(), tvb, offset, token_len, ' ');
proto_tree_add_item(coap_tree, hf_coap_token,
tvb, offset, token_len, ENC_NA);
+
+ memset(&key_token[0], 0, sizeof(key_token));
+ if ( token_len > 8 ) {
+ /* The token is limited to a maximum length of 8 but the bits in the
+ * protocol specifies 4 bits. Use 8 bytes at most. */
+ tvb_memcpy(tvb, key_token, offset, 8);
+ } else {
+ tvb_memcpy(tvb, key_token, offset, token_len);
+ }
+
offset += token_len;
}
@@ -877,6 +909,86 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* d
if (wmem_strbuf_get_len(coap_uri_query_strbuf)> 0)
col_append_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(coap_uri_query_strbuf));
+ /*
+ * We need to track some state for this protocol on a per conversation
+ * basis so we can do neat things like request/response tracking
+ */
+ conversation = find_or_create_conversation(pinfo);
+
+ key_token_length = token_len;
+
+ coap_key[0].length = 1;
+ coap_key[0].key = &key_token_length;
+ coap_key[1].length = 2;
+ coap_key[1].key = key_token;
+ coap_key[2].length = 0;
+ coap_key[2].key = NULL;
+
+ /*
+ * Do we already have a state structure for this conv
+ */
+ coap_info = (coap_conv_info_t *)conversation_get_proto_data(conversation, proto_coap);
+ if (!coap_info) {
+ /*
+ * No. Attach that information to the conversation, and add
+ * it to the list of information structures.
+ */
+ coap_info = wmem_new(wmem_file_scope(), coap_conv_info_t);
+ coap_info->pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+
+ conversation_add_proto_data(conversation, proto_coap, coap_info);
+ }
+ if (!PINFO_FD_VISITED(pinfo)) {
+ if (code < 65) {
+ /* This is a request */
+ coap_trans=wmem_new(wmem_file_scope(), coap_transaction_t);
+ coap_trans->req_frame = pinfo->num;
+ coap_trans->rep_frame = 0;
+ coap_trans->req_time = pinfo->fd->abs_ts;
+ wmem_tree_insert32_array(coap_info->pdus, coap_key, (void *)coap_trans);
+ } else {
+ coap_trans=(coap_transaction_t *)wmem_tree_lookup32_array(coap_info->pdus, coap_key);
+ if (coap_trans) {
+ coap_trans->rep_frame = pinfo->num;
+ }
+ }
+ } else {
+ coap_trans=(coap_transaction_t *)wmem_tree_lookup32_array(coap_info->pdus, coap_key);
+ }
+ if (!coap_trans) {
+ /* create a "fake" coap_trans structure */
+ coap_trans=wmem_new(wmem_packet_scope(), coap_transaction_t);
+ coap_trans->req_frame = 0;
+ coap_trans->rep_frame = 0;
+ coap_trans->req_time = pinfo->fd->abs_ts;
+ }
+
+ /* print state tracking in the tree */
+ if (code < 65) {
+ /* This is a request */
+ if (coap_trans->rep_frame) {
+ proto_item *it;
+
+ it = proto_tree_add_uint(coap_tree, hf_coap_response_in,
+ tvb, 0, 0, coap_trans->rep_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+ }
+ } else {
+ /* This is a reply */
+ if (coap_trans->req_frame) {
+ proto_item *it;
+ nstime_t ns;
+
+ it = proto_tree_add_uint(coap_tree, hf_coap_response_to,
+ tvb, 0, 0, coap_trans->req_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+
+ nstime_delta(&ns, &pinfo->fd->abs_ts, &coap_trans->req_time);
+ it = proto_tree_add_time(coap_tree, hf_coap_response_time, tvb, 0, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(it);
+ }
+ }
+
/* dissect the payload */
if (coap_length > offset) {
proto_tree *payload_tree;
@@ -1101,6 +1213,21 @@ proto_register_coap(void)
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
+ { &hf_coap_response_in,
+ { "Response In", "coap.response_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "The response to this PANA request is in this frame", HFILL }
+ },
+ { &hf_coap_response_to,
+ { "Request In", "coap.response_to",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This is a response to the PANA request in this frame", HFILL }
+ },
+ { &hf_coap_response_time,
+ { "Response Time", "coap.response_time",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "The time between the Call and the Reply", HFILL }
+ },
};
static gint *ett[] = {