diff options
author | Jeff Morriss <jeff.morriss@ulticom.com> | 2010-10-20 20:40:53 +0000 |
---|---|---|
committer | Jeff Morriss <jeff.morriss@ulticom.com> | 2010-10-20 20:40:53 +0000 |
commit | f6a88f2be5e2ea1f96562ba7cd2ddb3e04244901 (patch) | |
tree | 56c3cb3a55b1cef70a761450fbea88f16a5976d5 /epan/dissectors/packet-coap.c | |
parent | 06325a1bd6771b58202780292292e391d870b9df (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.c | 171 |
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, }; |