aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-coap.c
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss@ulticom.com>2010-10-20 20:40:53 +0000
committerJeff Morriss <jeff.morriss@ulticom.com>2010-10-20 20:40:53 +0000
commitf6a88f2be5e2ea1f96562ba7cd2ddb3e04244901 (patch)
tree56c3cb3a55b1cef70a761450fbea88f16a5976d5 /epan/dissectors/packet-coap.c
parent06325a1bd6771b58202780292292e391d870b9df (diff)
From Shoichi Sakane via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5270 :
I made a patch to support more COAP options. some options includes variable length field. svn path=/trunk/; revision=34592
Diffstat (limited to 'epan/dissectors/packet-coap.c')
-rw-r--r--epan/dissectors/packet-coap.c171
1 files changed, 123 insertions, 48 deletions
diff --git a/epan/dissectors/packet-coap.c b/epan/dissectors/packet-coap.c
index f58b8dafc6..daf5449f62 100644
--- a/epan/dissectors/packet-coap.c
+++ b/epan/dissectors/packet-coap.c
@@ -3,7 +3,11 @@
* Shoichi Sakane <sakane@tanu.org>
*
* $Id$
+ *
* draft-core-coap-02.txt
+ * draft-ietf-core-coap-02.txt
+ * draft-ietf-core-block-00.txt
+ * draft-ietf-core-observe-00.txt
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
@@ -44,11 +48,11 @@ static int hf_coap_code = -1;
static int hf_coap_tid = -1;
static int hf_coap_opt_type = -1;
static int hf_coap_opt_ctype = -1;
-static int hf_coap_opt_max_age = -1;
static int hf_coap_opt_etag = -1;
static int hf_coap_opt_uri_authority = -1;
static int hf_coap_opt_location = -1;
static int hf_coap_opt_uri_path = -1;
+static int hf_coap_opt_opaque_bytes = -1;
static gint ett_coap = -1;
static gint ett_coap_noop = -1;
@@ -59,6 +63,9 @@ static gint ett_coap_etag = -1;
static gint ett_coap_uri_authority = -1;
static gint ett_coap_location = -1;
static gint ett_coap_uri_path = -1;
+static gint ett_coap_subscr_lifetime = -1;
+static gint ett_coap_opaque_bytes = -1;
+static gint ett_coap_block = -1;
static gint ett_coap_payload = -1;
/* TODO: COAP port number will be assigned by IANA after the draft become a RFC */
@@ -116,22 +123,28 @@ static const value_string vals_code[] = {
#define COAP_OPT_URI_AUTHORITY 5
#define COAP_OPT_LOCATION 6
#define COAP_OPT_URI_PATH 9
+#define COAP_OPT_SUBSCR_LIFETIME 10
+#define COAP_OPT_OPAQUE_BYTES 11
+#define COAP_OPT_BLOCK 13
static const value_string vals_opt_type[] = {
{ COAP_OPT_CONTENT_TYPE, "Content-Type" },
- { COAP_OPT_MAX_AGE, "Max-age"},
- { COAP_OPT_ETAG, "Etag"},
- { COAP_OPT_URI_AUTHORITY, "Uri-Authority"},
- { COAP_OPT_LOCATION, "Location"},
- { COAP_OPT_URI_PATH, "Uri-Path"},
+ { COAP_OPT_MAX_AGE, "Max-age" },
+ { COAP_OPT_ETAG, "Etag" },
+ { COAP_OPT_URI_AUTHORITY, "Uri-Authority" },
+ { COAP_OPT_LOCATION, "Location" },
+ { COAP_OPT_URI_PATH, "Uri-Path" },
+ { COAP_OPT_SUBSCR_LIFETIME, "Subscription Lifetime" },
+ { COAP_OPT_OPAQUE_BYTES, "Opaque Bytes" },
+ { COAP_OPT_BLOCK, "Block" },
{ 0, NULL },
};
static const value_string vals_ctype[] = {
- { 0, "text/plain (UTF-8)" },
- { 1, "text/xml (UTF-8)" },
- { 2, "text/csv (UTF-8)" },
- { 3, "text/html (UTF-8)" },
+ { 0, "text/plain" },
+ { 1, "text/xml" },
+ { 2, "text/csv" },
+ { 3, "text/html" },
{ 21, "image/gif" },
{ 22, "image/jpeg" },
{ 23, "image/png" },
@@ -155,16 +168,77 @@ static const value_string vals_ctype[] = {
void proto_reg_handoff_coap(void);
+/* the value of opt_length should be checked out of this function */
+static void
+dissect_coap_opt_time(tvbuff_t *tvb, proto_tree *subtree, int offset, gint opt_length, char *str)
+{
+ guint time = 0;
+
+ switch (opt_length) {
+ case 0:
+ time = 0;
+ break;
+ case 1:
+ time = (guint)tvb_get_guint8(tvb, offset);
+ break;
+ case 2:
+ time = (guint)tvb_get_ntohs(tvb, offset);
+ break;
+ case 3:
+ time = (guint)tvb_get_ntoh24(tvb, offset);
+ break;
+ case 4:
+ time = (guint)tvb_get_ntohl(tvb, offset);
+ break;
+ default:
+ proto_tree_add_text(subtree, tvb, 0, 0, "Invalid length: %d", opt_length);
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, offset, opt_length, "%s: %d (s)", str, time);
+
+ return;
+}
+
+static void
+dissect_coap_opt_block(tvbuff_t *tvb, proto_tree *subtree, int offset, gint opt_length)
+{
+ guint block_number = 0;
+ guint more_flag = 0;
+ guint block_size = 0;
+ guint8 val = 0;
+
+ switch (opt_length) {
+ case 1:
+ block_number = (guint)(tvb_get_guint8(tvb, offset) >> 4);
+ break;
+ case 2:
+ block_number = (guint)(tvb_get_ntohs(tvb, offset) >> 4);
+ break;
+ case 3:
+ block_number = (guint)(tvb_get_ntoh24(tvb, offset) >> 4);
+ break;
+ default:
+ proto_tree_add_text(subtree, tvb, 0, 0, "Invalid length: %d", opt_length);
+ return;
+ }
+
+ val = tvb_get_guint8(tvb, offset + opt_length - 1) & 0x0f;
+ more_flag = (val & 0x08) >> 3;
+ block_size = val & 0x07;
+ block_size = 2^(block_size + 4);
+
+ proto_tree_add_text(subtree, tvb, offset, opt_length, "Block Number:%d, More Flag:%d, Block Size:%d", block_number, more_flag, block_size);
+}
+
/*
* dissector for each option of COAP.
* return the total length of the option including the header (e.g. delta and length).
*/
static int
-dissect_coap_options(tvbuff_t *tvb, proto_tree *coap_tree, proto_tree *parent_tree _U_, int offset, guint8 *opt_code)
+dissect_coap_options(tvbuff_t *tvb, proto_tree *coap_tree, proto_tree *parent_tree _U_, int offset, guint8 opt_count, guint8 *opt_code)
{
guint8 opt_delta;
guint32 opt_ctype = 0;
- guint opt_max_age = 0;
gint opt_length;
proto_tree *subtree = NULL;
proto_item *item = NULL;
@@ -178,9 +252,10 @@ dissect_coap_options(tvbuff_t *tvb, proto_tree *coap_tree, proto_tree *parent_tr
opt_length += tvb_get_guint8(tvb, offset + 1);
opt_hlen = 2;
}
- item = proto_tree_add_uint_format(coap_tree, hf_coap_opt_type, tvb, offset, 1, *opt_code,
- "Option (Length: %u) %s",
- opt_length, val_to_str(*opt_code, vals_opt_type, "Unknown Option Type"));
+
+ item = proto_tree_add_text(coap_tree, tvb, offset, opt_hlen + opt_length,
+ "Option #%u (Length: %u) %s", opt_count, opt_length,
+ val_to_str(*opt_code, vals_opt_type, "Unknown Option Type %u"));
offset += opt_hlen;
/* if opt_code is a multiple of 14, that means the option is a noop option */
@@ -192,31 +267,16 @@ dissect_coap_options(tvbuff_t *tvb, proto_tree *coap_tree, proto_tree *parent_tr
case COAP_OPT_CONTENT_TYPE:
subtree = proto_item_add_subtree(item, ett_coap_ctype);
opt_ctype = tvb_get_guint8(tvb, offset);
- coap_content_type = val_to_str(opt_ctype, vals_code, "Unknown %d");
+ coap_content_type = val_to_str(opt_ctype, vals_ctype, "Unknown %d");
proto_tree_add_item(subtree, hf_coap_opt_ctype, tvb, offset, 1, FALSE);
break;
case COAP_OPT_MAX_AGE:
subtree = proto_item_add_subtree(item, ett_coap_max_age);
- switch (opt_length) {
- case 1:
- opt_max_age = (guint)tvb_get_guint8(tvb, offset);
- break;
- case 2:
- opt_max_age = (guint)tvb_get_ntohs(tvb, offset);
- break;
- case 3:
- opt_max_age = (guint)tvb_get_ntoh24(tvb, offset);
- break;
- case 4:
- opt_max_age = (guint)tvb_get_ntohl(tvb, offset);
- break;
- default:
- proto_tree_add_text(subtree, tvb, 0, 0, "Invalid length: %d", opt_length);
- break;
- }
- if (opt_length >= 1 && opt_length <= 4) {
- proto_tree_add_item(subtree, hf_coap_opt_max_age, tvb, offset, opt_length, FALSE);
- }
+ dissect_coap_opt_time(tvb, subtree, offset, opt_length, "Max-age");
+ break;
+ case COAP_OPT_SUBSCR_LIFETIME:
+ subtree = proto_item_add_subtree(item, ett_coap_subscr_lifetime);
+ dissect_coap_opt_time(tvb, subtree, offset, opt_length, "Subscription Lifetime");
break;
case COAP_OPT_ETAG:
subtree = proto_item_add_subtree(item, ett_coap_etag);
@@ -234,6 +294,13 @@ dissect_coap_options(tvbuff_t *tvb, proto_tree *coap_tree, proto_tree *parent_tr
subtree = proto_item_add_subtree(item, ett_coap_uri_path);
proto_tree_add_item(subtree, hf_coap_opt_uri_path, tvb, offset, opt_length, FALSE);
break;
+ case COAP_OPT_OPAQUE_BYTES:
+ /* TODO: implement it after a draft will be published */
+ break;
+ case COAP_OPT_BLOCK:
+ subtree = proto_item_add_subtree(item, ett_coap_block);
+ dissect_coap_opt_block(tvb, subtree, offset, opt_length);
+ break;
default:
proto_tree_add_text(subtree, tvb, 0, 0, "Unkown Option Type");
}
@@ -251,8 +318,9 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
guint8 opt_count = 0;
guint8 code = 0;
guint16 tid = 0;
- guint coap_length = pinfo->iplen - pinfo->iphdrlen - 8;
+ guint coap_length = 0;
guint8 opt_code = 0;
+ int i;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "COAP");
col_clear(pinfo->cinfo, COL_INFO);
@@ -260,6 +328,15 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
if (!parent_tree)
return;
+ /* initialize the COAP length and the content-type */
+ /*
+ * the length of COAP message is not specified in the COAP header.
+ * It has to be from the lower layer. the iplen of packet_info is not accurate.
+ * Currently, the length is just copied from the reported length of the tvbuffer.
+ */
+ coap_length = tvb_reported_length(tvb);
+ coap_content_type = NULL;
+
coap_root = proto_tree_add_item(parent_tree, proto_coap, tvb, offset, -1, FALSE);
coap_tree = proto_item_add_subtree(coap_root, ett_coap);
@@ -286,8 +363,8 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
proto_item_append_text(coap_tree, ", TID: %u, Length: %u", tid, coap_length);
/* dissect the options */
- while (opt_count--) {
- offset = dissect_coap_options(tvb, coap_tree, parent_tree, offset, &opt_code);
+ for (i = 1; i <= opt_count; i++) {
+ offset = dissect_coap_options(tvb, coap_tree, parent_tree, offset, i, &opt_code);
if (coap_length < offset) {
/* error */
proto_tree_add_text(coap_tree, tvb, 0, 0, "Invalid length: coap_length(%d) < offset(%d)", coap_length, offset);
@@ -302,7 +379,6 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
tvbuff_t *payload_tvb;
guint payload_length = coap_length - offset;
char *ctype_str_default = "";
- gboolean result = TRUE;
/*
* TODO:
@@ -314,7 +390,7 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
/* default: coap-02 section 3.2.1 */
/* when it's NULL, "text/plain" is set anyway */
coap_content_type = "text/plain";
- ctype_str_default = "(as default)";
+ ctype_str_default = " (default)";
}
/*
* TODO: should the content type be canonicalized,
@@ -322,15 +398,11 @@ dissect_coap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
*/
payload_item = proto_tree_add_text(coap_tree, tvb, offset, -1, "Payload Content-Type: %s%s, Length: %u, offset: %u",
- coap_content_type, ctype_str_default, payload_length, offset);
+ coap_content_type, ctype_str_default, payload_length, offset);
payload_tree = proto_item_add_subtree(payload_item, ett_coap_payload);
payload_tvb = tvb_new_subset(tvb, offset, payload_length, payload_length);
- result = dissector_try_string(media_type_dissector_table, coap_content_type, payload_tvb, pinfo, payload_tree);
- if (!result) {
- /* TODO: call heuristic dissector */
- ;
- }
+ dissector_try_string(media_type_dissector_table, coap_content_type, payload_tvb, pinfo, payload_tree);
}
}
@@ -348,11 +420,11 @@ proto_register_coap(void)
{ &hf_coap_tid, { "Transaction ID", "coap.tid", FT_UINT16, BASE_DEC, NULL, 0x0, "COAP Transaction ID", HFILL }},
{ &hf_coap_opt_type, { "Option Type", "coap.opt.opt_type", FT_UINT8, BASE_DEC, VALS(&vals_opt_type), 0x0, "COAP Option Type", HFILL }},
{ &hf_coap_opt_ctype, { "Content-type", "coap.opt.ctype", FT_UINT8, BASE_DEC, VALS(&vals_ctype), 0x0, "COAP Media Type", HFILL }},
- { &hf_coap_opt_max_age, { "Max-age", "coap.opt.maxage", FT_UINT32, BASE_DEC, NULL, 0x0, "COAP Max-age", HFILL }},
{ &hf_coap_opt_etag, { "Etag", "coap.opt.etag", FT_BYTES, BASE_NONE, NULL, 0x0, "COAP Etag", HFILL }},
{ &hf_coap_opt_uri_authority, { "Uri-Authority", "coap.opt.uri_auth", FT_STRING, BASE_NONE, NULL, 0x0, "COAP Uri-Authority", HFILL }},
{ &hf_coap_opt_location, { "Location", "coap.opt.location", FT_STRING, BASE_NONE, NULL, 0x0, "COAP Location", HFILL }},
{ &hf_coap_opt_uri_path, { "Uri-Path", "coap.opt.uri_path", FT_STRING, BASE_NONE, NULL, 0x0, "COAP Uri-Path", HFILL }},
+ { &hf_coap_opt_opaque_bytes, { "Opaque Bytes", "coap.opt.opaquebytes", FT_BYTES, BASE_NONE, NULL, 0x0, "COAP Opaque Bytes", HFILL }},
};
static gint *ett[] = {
@@ -365,6 +437,9 @@ proto_register_coap(void)
&ett_coap_uri_authority,
&ett_coap_location,
&ett_coap_uri_path,
+ &ett_coap_subscr_lifetime,
+ &ett_coap_opaque_bytes,
+ &ett_coap_block,
&ett_coap_payload,
};