Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-coap.c
Warning:line 1149, column 7
Branch condition evaluates to a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-coap.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-06-18-100450-3549-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-coap.c
1/* packet-coap.c
2 * Routines for CoAP packet disassembly
3 * draft-ietf-core-coap-14.txt
4 * draft-ietf-core-block-10.txt
5 * draft-ietf-core-observe-16.txt
6 * draft-ietf-core-link-format-06.txt
7 * Shoichi Sakane <sakane@tanu.org>
8 *
9 * Changes for draft-ietf-core-coap-17.txt
10 * Hauke Mehrtens <hauke@hauke-m.de>
11 *
12 * Support for CoAP over TCP, TLS and WebSockets
13 * https://tools.ietf.org/html/rfc8323
14 * Peter Wu <peter@lekensteyn.nl>
15 *
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
19 *
20 * SPDX-License-Identifier: GPL-2.0-or-later
21 */
22
23#include "config.h"
24
25
26#include <epan/conversation.h>
27#include <epan/packet.h>
28#include <epan/reassemble.h>
29#include <epan/proto_data.h>
30#include <epan/expert.h>
31#include <epan/wmem_scopes.h>
32#include <epan/to_str.h>
33#include <epan/strutil.h>
34#include <wsutil/array.h>
35#include "packet-dtls.h"
36#include "packet-coap.h"
37#include "packet-media-type.h"
38#include "packet-tcp.h"
39#include "packet-tls.h"
40
41void proto_register_coap(void);
42
43static dissector_table_t coap_tmf_media_type_dissector_table;
44static dissector_table_t coap_uri_path_dissector_table;
45static dissector_table_t media_type_dissector_table;
46
47static int proto_coap;
48/*
49 * Used only to register the "CoAP for Thread Management Framework"
50 * dissector, which uses the same protocol and field IDs as the
51 * regular CoAP dissector, as it's just "CoAP except that we interpret
52 * application/octet-stream as meaning Thread Management Framework
53 * messages", because the Thread protocol, for whatever reasons (trying
54 * to keep the CoAP layer of their messages as short and simple to parse
55 * as possible, to save power and reduce the chances of low-power
56 * transmissions being misreceived?), did not register a media type for
57 * its messages and a 'cf' value for that media type.
58 */
59static int proto_coap_for_tmf;
60
61static int hf_coap_length;
62static int hf_coap_version;
63static int hf_coap_ttype;
64static int hf_coap_token_len;
65static int hf_coap_token;
66static int hf_coap_mid;
67
68static int hf_coap_response_in;
69static int hf_coap_response_to;
70static int hf_coap_response_time;
71static int hf_coap_request_resend_in;
72static int hf_coap_response_resend_in;
73static int hf_coap_oscore_kid;
74static int hf_coap_oscore_kid_context;
75static int hf_coap_oscore_piv;
76
77static int hf_block_payload;
78static int hf_block_length;
79
80static int hf_blocks;
81static int hf_block;
82static int hf_block_overlap;
83static int hf_block_overlap_conflicts;
84static int hf_block_multiple_tails;
85static int hf_block_too_long;
86static int hf_block_error;
87static int hf_block_count;
88static int hf_block_reassembled_in;
89static int hf_block_reassembled_length;
90
91static int ett_coap;
92
93static int ett_block;
94static int ett_blocks;
95
96static expert_field ei_retransmitted;
97
98static COAP_COMMON_LIST_T(dissect_coap_hf)coap_common_dissect_t dissect_coap_hf;
99
100static dissector_handle_t coap_tcp_tls_handle;
101static dissector_handle_t coap_other_handle;
102static dissector_handle_t coap_for_tmf_handle;
103static dissector_handle_t oscore_handle;
104
105/* CoAP's IANA-assigned TCP/UDP port numbers */
106#define DEFAULT_COAP_PORT5683 5683
107#define DEFAULT_COAPS_PORT5684 5684
108
109/* indicators whether those are to be showed or not */
110#define DEFAULT_COAP_CTYPE_VALUE~0U ~0U
111#define DEFAULT_COAP_BLOCK_NUMBER~0U ~0U
112
113/* Macros specific to the OCF version options */
114#define COAP_OCF_VERSION_SUB_MASK0x3F 0x3F
115#define COAP_OCF_VERSION_MINOR_MASK0x7C0 0x7C0
116#define COAP_OCF_VERSION_MAJOR_MASK0xF800 0xF800
117
118#define COAP_OCF_VERSION_MINOR_OFFSET6 6
119#define COAP_OCF_VERSION_MAJOR_OFFSET11 11
120
121/*
122 * Transaction Type
123 */
124#define TT_CON0 0 // Confirmable
125#define TT_NON1 1 // Non-Confirmable
126static const value_string vals_ttype[] = {
127 { 0, "Confirmable" },
128 { 1, "Non-Confirmable" },
129 { 2, "Acknowledgement" },
130 { 3, "Reset" },
131 { 0, NULL((void*)0) },
132};
133static const value_string vals_ttype_short[] = {
134 { 0, "CON" },
135 { 1, "NON" },
136 { 2, "ACK" },
137 { 3, "RST" },
138 { 0, NULL((void*)0) },
139};
140
141/*
142 * Method Code
143 * Response Code
144 * "c.dd" denotes (c << 5) | dd
145 */
146static const value_string vals_code[] = {
147 { 0, "Empty Message" },
148
149 /* Method Codes */
150 { 1, "GET" },
151 { 2, "POST" },
152 { 3, "PUT" },
153 { 4, "DELETE" },
154 { 5, "FETCH" }, /* RFC 8132 */
155 { 6, "PATCH" }, /* RFC 8132 */
156 { 7, "iPATCH" }, /* RFC 8132 */
157
158 /* Response Codes */
159 { 65, "2.01 Created" },
160 { 66, "2.02 Deleted" },
161 { 67, "2.03 Valid" },
162 { 68, "2.04 Changed" },
163 { 69, "2.05 Content" },
164 { 95, "2.31 Continue" },
165 { 128, "4.00 Bad Request" },
166 { 129, "4.01 Unauthorized" },
167 { 130, "4.02 Bad Option" },
168 { 131, "4.03 Forbidden" },
169 { 132, "4.04 Not Found" },
170 { 133, "4.05 Method Not Allowed" },
171 { 134, "4.06 Not Acceptable" },
172 { 136, "4.08 Request Entity Incomplete" }, /* RFC 7959 */
173 { 137, "4.09 Conflict" }, /* RFC 8132 */
174 { 140, "4.12 Precondition Failed" },
175 { 141, "4.13 Request Entity Too Large" },
176 { 143, "4.15 Unsupported Content-Format" },
177 { 150, "4.22 Unprocessable Entity" }, /* RFC 8132 */
178 { 157, "4.29 Too Many Requests" }, /* RFC 8516 */
179 { 160, "5.00 Internal Server Error" },
180 { 161, "5.01 Not Implemented" },
181 { 162, "5.02 Bad Gateway" },
182 { 163, "5.03 Service Unavailable" },
183 { 164, "5.04 Gateway Timeout" },
184 { 165, "5.05 Proxying Not Supported" },
185 { 168, "5.08 Hop Limit Reached" }, /* RFC 8768 */
186
187 /* Signalling Codes */
188 { 225, "7.01 CSM" }, /* RFC 8323 */
189 { 226, "7.02 Ping" }, /* RFC 8323 */
190 { 227, "7.03 Pong" }, /* RFC 8323 */
191 { 228, "7.04 Release" }, /* RFC 8323 */
192 { 229, "7.05 Abort" }, /* RFC 8323 */
193
194 { 0, NULL((void*)0) },
195};
196value_string_ext coap_vals_code_ext = VALUE_STRING_EXT_INIT(vals_code){ _try_val_to_str_ext_init, 0, (sizeof (vals_code) / sizeof (
(vals_code)[0]))-1, vals_code, "vals_code", ((void*)0) }
;
197
198const value_string coap_vals_observe_options[] = {
199 { 0, "Register" },
200 { 1, "Deregister" },
201 { 0, NULL((void*)0) },
202};
203
204/*
205 * Option Headers
206 * No-Option must not be included in this structure, is handled in the function
207 * of the dissector, especially.
208 */
209#define COAP_OPT_IF_MATCH1 1
210#define COAP_OPT_URI_HOST3 3
211#define COAP_OPT_ETAG4 4
212#define COAP_OPT_IF_NONE_MATCH5 5
213#define COAP_OPT_OBSERVE6 6 /* RFC 7641 / RFC 8613 */
214#define COAP_OPT_URI_PORT7 7
215#define COAP_OPT_LOCATION_PATH8 8
216#define COAP_OPT_OBJECT_SECURITY9 9 /* RFC 8613 */
217#define COAP_OPT_URI_PATH11 11
218#define COAP_OPT_CONTENT_TYPE12 12
219#define COAP_OPT_MAX_AGE14 14
220#define COAP_OPT_URI_QUERY15 15
221#define COAP_OPT_HOP_LIMIT16 16 /* RFC 8768 */
222#define COAP_OPT_ACCEPT17 17
223#define COAP_OPT_QBLOCK119 19 /* RFC 9177 */
224#define COAP_OPT_LOCATION_QUERY20 20
225#define COAP_OPT_EDHOC21 21 /* draft-ietf-core-oscore-edhoc*/
226#define COAP_OPT_BLOCK223 23 /* RFC 7959 / RFC 8323 */
227#define COAP_OPT_BLOCK127 27 /* RFC 7959 / RFC 8323 */
228#define COAP_OPT_SIZE228 28 /* RFC 7959 */
229#define COAP_OPT_QBLOCK231 31 /* RFC 9177 */
230#define COAP_OPT_PROXY_URI35 35
231#define COAP_OPT_PROXY_SCHEME39 39
232#define COAP_OPT_SIZE160 60
233#define COAP_OPT_ECHO252 252 /* RFC 9175*/
234#define COAP_OPT_NO_RESPONSE258 258 /* RFC 7967 / RFC 8613 */
235#define COAP_OPT_REQUEST_TAG292 292 /* RFC 9175 */
236#define COAP_OPT_OCF_ACCEPT2049 2049 /* OCF Core specification */
237#define COAP_OPT_OCF_CONTENT2053 2053 /* OCF Core specification */
238
239static const value_string vals_opt_type[] = {
240 { COAP_OPT_IF_MATCH1, "If-Match" },
241 { COAP_OPT_URI_HOST3, "Uri-Host" },
242 { COAP_OPT_ETAG4, "Etag" },
243 { COAP_OPT_IF_NONE_MATCH5, "If-None-Match" },
244 { COAP_OPT_URI_PORT7, "Uri-Port" },
245 { COAP_OPT_LOCATION_PATH8, "Location-Path" },
246 { COAP_OPT_OBJECT_SECURITY9,"OSCORE" },
247 { COAP_OPT_URI_PATH11, "Uri-Path" },
248 { COAP_OPT_CONTENT_TYPE12, "Content-Format" },
249 { COAP_OPT_MAX_AGE14, "Max-age" },
250 { COAP_OPT_URI_QUERY15, "Uri-Query" },
251 { COAP_OPT_HOP_LIMIT16, "Hop-Limit" },
252 { COAP_OPT_ACCEPT17, "Accept" },
253 { COAP_OPT_QBLOCK119, "Q-Block1" },
254 { COAP_OPT_LOCATION_QUERY20, "Location-Query" },
255 { COAP_OPT_EDHOC21, "EDHOC" },
256 { COAP_OPT_PROXY_URI35, "Proxy-Uri" },
257 { COAP_OPT_PROXY_SCHEME39, "Proxy-Scheme" },
258 { COAP_OPT_SIZE160, "Size1" },
259 { COAP_OPT_OBSERVE6, "Observe" },
260 { COAP_OPT_BLOCK223, "Block2" },
261 { COAP_OPT_BLOCK127, "Block1" },
262 { COAP_OPT_SIZE228, "Size2" },
263 { COAP_OPT_QBLOCK231, "Q-Block2" },
264 { COAP_OPT_ECHO252, "Echo" },
265 { COAP_OPT_NO_RESPONSE258, "No-Response" },
266 { COAP_OPT_REQUEST_TAG292, "Request-Tag" },
267 { COAP_OPT_OCF_ACCEPT2049, "OCF-Accept-Content-Format-Version" },
268 { COAP_OPT_OCF_CONTENT2053, "OCF-Content-Format-Version" },
269 { 0, NULL((void*)0) },
270};
271
272static const struct coap_option_range_t {
273 unsigned type;
274 int min;
275 int max;
276} coi[] = {
277 { COAP_OPT_IF_MATCH1, 0, 8 },
278 { COAP_OPT_URI_HOST3, 1, 255 },
279 { COAP_OPT_ETAG4, 1, 8 },
280 { COAP_OPT_IF_NONE_MATCH5, 0, 0 },
281 { COAP_OPT_URI_PORT7, 0, 2 },
282 { COAP_OPT_LOCATION_PATH8, 0, 255 },
283 { COAP_OPT_OBJECT_SECURITY9, 0, 255 },
284 { COAP_OPT_URI_PATH11, 0, 255 },
285 { COAP_OPT_CONTENT_TYPE12, 0, 2 },
286 { COAP_OPT_MAX_AGE14, 0, 4 },
287 { COAP_OPT_URI_QUERY15, 1, 255 },
288 { COAP_OPT_HOP_LIMIT16, 1, 1 },
289 { COAP_OPT_ACCEPT17, 0, 2 },
290 { COAP_OPT_QBLOCK119, 0, 3 },
291 { COAP_OPT_LOCATION_QUERY20, 0, 255 },
292 { COAP_OPT_EDHOC21, 0, 0 },
293 { COAP_OPT_PROXY_URI35, 1,1034 },
294 { COAP_OPT_PROXY_SCHEME39, 1, 255 },
295 { COAP_OPT_SIZE160, 0, 4 },
296 { COAP_OPT_OBSERVE6, 0, 3 },
297 { COAP_OPT_BLOCK223, 0, 3 },
298 { COAP_OPT_BLOCK127, 0, 3 },
299 { COAP_OPT_SIZE228, 0, 4 },
300 { COAP_OPT_QBLOCK231, 0, 3 },
301 { COAP_OPT_ECHO252, 1, 40 },
302 { COAP_OPT_NO_RESPONSE258, 0, 1 },
303 { COAP_OPT_REQUEST_TAG292, 0, 8 },
304 { COAP_OPT_OCF_ACCEPT2049, 2, 2 },
305 { COAP_OPT_OCF_CONTENT2053, 2, 2 },
306};
307
308static const value_string vals_ctype[] = {
309 { 0, "text/plain; charset=utf-8" },
310 { 16, "application/cose; cose-type=\"cose-encrypt0\"" },
311 { 17, "application/cose; cose-type=\"cose-mac0\"" },
312 { 18, "application/cose; cose-type=\"cose-sign1\"" },
313 { 19, "application/ace+cbor" },
314 { 21, "image/gif" },
315 { 22, "image/jpeg" },
316 { 23, "image/png" },
317 { 40, "application/link-format" },
318 { 41, "application/xml" },
319 { 42, "application/octet-stream" },
320 { 47, "application/exi" },
321 { 50, "application/json" },
322 { 51, "application/json-patch+json" },
323 { 52, "application/merge-patch+json" },
324 { 60, "application/cbor" },
325 { 61, "application/cwt" },
326 { 62, "application/multipart-core" },
327 { 63, "application/cbor-seq" },
328 { 64, "application/edhoc+cbor-seq" },
329 { 65, "application/cid-edhoc+cbor-seq" },
330 { 96, "application/cose; cose-type=\"cose-encrypt\"" },
331 { 97, "application/cose; cose-type=\"cose-mac\"" },
332 { 98, "application/cose; cose-type=\"cose-sign\"" },
333 { 101, "application/cose-key" },
334 { 102, "application/cose-key-set" },
335 { 110, "application/senml+json" },
336 { 111, "application/sensml+json" },
337 { 112, "application/senml+cbor" },
338 { 113, "application/sensml+cbor" },
339 { 114, "application/senml-exi" },
340 { 115, "application/sensml-exi" },
341 { 140, "application/yang-data+cbor; id=sid" },
342 { 256, "application/coap-group+json" },
343 { 257, "application/concise-problem-details+cbor" },
344 { 258, "application/swid+cbor" },
345 { 271, "application/dots+cbor" },
346 { 272, "application/missing-blocks+cbor-seq" },
347 { 280, "application/pkcs7-mime; smime-type=server-generated-key" },
348 { 281, "application/pkcs7-mime; smime-type=certs-only" },
349 { 284, "application/pkcs8" },
350 { 285, "application/csrattrs" },
351 { 286, "application/pkcs10" },
352 { 287, "application/pkix-cert" },
353 { 290, "application/aif+cbor" },
354 { 291, "application/aif+json" },
355 { 310, "application/senml+xml" },
356 { 311, "application/sensml+xml" },
357 { 320, "application/senml-etch+json" },
358 { 322, "application/senml-etch+cbor" },
359 { 340, "application/yang-data+cbor" },
360 { 341, "application/yang-data+cbor; id=name" },
361 { 432, "application/td+json" },
362 { 433, "application/tm+json" },
363 { 1542, "application/vnd.oma.lwm2m+tlv" },
364 { 1543, "application/vnd.oma.lwm2m+json" },
365 { 10000, "application/vnd.ocf+cbor" },
366 { 10001, "application/oscore" },
367 { 10002, "application/javascript" },
368 { 11050, "application/json (Content Coding: deflate)" },
369 { 11060, "application/cbor (Content Coding: deflate)" },
370 { 11542, "application/vnd.oma.lwm2m+tlv" },
371 { 11543, "application/vnd.oma.lwm2m+json" },
372 { 20000, "text/css" },
373 { 30000, "image/svg+xml" },
374 { 0, NULL((void*)0) },
375};
376
377static const char *nullstr = "(null)";
378
379static reassembly_table coap_block_reassembly_table;
380
381static const fragment_items coap_block_frag_items = {
382 /* Fragment subtrees */
383 &ett_block,
384 &ett_blocks,
385 /* Fragment fields */
386 &hf_blocks,
387 &hf_block,
388 &hf_block_overlap,
389 &hf_block_overlap_conflicts,
390 &hf_block_multiple_tails,
391 &hf_block_too_long,
392 &hf_block_error,
393 &hf_block_count,
394 /* Reassembled in field */
395 &hf_block_reassembled_in,
396 /* Reassembled length field */
397 &hf_block_reassembled_length,
398 /* Reassembled data field */
399 NULL((void*)0),
400 /* Tag */
401 "Block fragments"
402};
403
404void proto_reg_handoff_coap(void);
405
406static conversation_t *
407find_or_create_conversation_noaddrb(packet_info *pinfo, bool_Bool request)
408{
409 conversation_t *conv=NULL((void*)0);
410 address *addr_a;
411 address *addr_b;
412 uint32_t port_a;
413 uint32_t port_b;
414
415 if (pinfo->ptype != PT_TCP) {
416 if (request) {
417 addr_a = &pinfo->src;
418 addr_b = &pinfo->dst;
419 port_a = pinfo->srcport;
420 port_b = pinfo->destport;
421 } else {
422 addr_a = &pinfo->dst;
423 addr_b = &pinfo->src;
424 port_a = pinfo->destport;
425 port_b = pinfo->srcport;
426 }
427 /* Have we seen this conversation before? */
428 if((conv = find_conversation(pinfo->num, addr_a, addr_b,
429 conversation_pt_to_conversation_type(pinfo->ptype), port_a,
430 port_b, NO_ADDR_B0x00010000|NO_PORT_B0x00020000)) != NULL((void*)0)) {
431 if (pinfo->num > conv->last_frame) {
432 conv->last_frame = pinfo->num;
433 }
434 } else {
435 /* No, this is a new conversation. */
436 conv = conversation_new(pinfo->num, &pinfo->src,
437 &pinfo->dst, conversation_pt_to_conversation_type(pinfo->ptype),
438 pinfo->srcport, pinfo->destport, NO_ADDR20x01|NO_PORT20x02);
439 }
440 } else {
441 /* fetch the conversation created by the TCP dissector */
442 conv = find_conversation_pinfo(pinfo, 0);
443 DISSECTOR_ASSERT(conv)((void) ((conv) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-coap.c", 443, "conv"))))
;
444 }
445 return conv;
446}
447
448static int
449coap_get_opt_uint(tvbuff_t *tvb, int offset, int length)
450{
451 switch (length) {
452 case 0:
453 return 0;
454 case 1:
455 return (unsigned)tvb_get_uint8(tvb, offset);
456 case 2:
457 return (unsigned)tvb_get_ntohs(tvb, offset);
458 case 3:
459 return (unsigned)tvb_get_ntoh24(tvb, offset);
460 case 4:
461 return (unsigned)tvb_get_ntohl(tvb, offset);
462 default:
463 return -1;
464 }
465}
466
467static int
468coap_opt_check(packet_info *pinfo, proto_tree *subtree, unsigned opt_num, int opt_length, coap_common_dissect_t *dissect_hf)
469{
470 int i;
471
472 for (i = 0; i < (int)(array_length(coi)(sizeof (coi) / sizeof (coi)[0])); i++) {
473 if (coi[i].type == opt_num)
474 break;
475 }
476 if (i == (int)(array_length(coi)(sizeof (coi) / sizeof (coi)[0]))) {
477 if (opt_num >= 2048 && opt_num <= 65535) {
478 /* private, vendor-specific or reserved for experiments */
479 expert_add_info_format(pinfo, subtree, &dissect_hf->ei.opt_unknown_number,
480 "Unknown Option Number %u", opt_num);
481 } else {
482 expert_add_info_format(pinfo, subtree, &dissect_hf->ei.opt_invalid_number,
483 "Invalid Option Number %u", opt_num);
484 }
485 return -1;
486 }
487 if (opt_length < coi[i].min || opt_length > coi[i].max) {
488 expert_add_info_format(pinfo, subtree, &dissect_hf->ei.opt_invalid_range,
489 "Invalid Option Range: %d (%d < x < %d)", opt_length, coi[i].min, coi[i].max);
490 }
491
492 return 0;
493}
494
495static void
496dissect_coap_opt_hex_string(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, proto_tree *subtree, int offset, int opt_length, int hf)
497{
498 const char *str;
499
500 if (opt_length == 0)
501 str = nullstr;
502 else
503 str = tvb_bytes_to_str_punct(pinfo->pool, tvb, offset, opt_length, ' ');
504
505 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_NA0x00000000);
506
507 /* add info to the head of the packet detail */
508 proto_item_append_text(item, ": %s", str);
509}
510
511static void
512dissect_coap_opt_uint(tvbuff_t *tvb, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
513{
514 unsigned i = 0;
515
516 if (opt_length != 0) {
517 i = coap_get_opt_uint(tvb, offset, opt_length);
518 }
519
520 proto_tree_add_uint(subtree, hf, tvb, offset, opt_length, i);
521
522 /* add info to the head of the packet detail */
523 proto_item_append_text(head_item, ": %u", i);
524}
525
526static void
527dissect_coap_opt_uri_host(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, coap_info *coinfo, int hf)
528{
529 const char *str;
530
531 proto_tree_add_item_ret_string(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000, pinfo->pool, (const uint8_t**)&str);
532
533 /* add info to the head of the packet detail */
534 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
535
536 /* forming a uri-string
537 * If the 'uri host' looks an IPv6 address, assuming that the address has
538 * to be enclosed by brackets.
539 */
540 if (strchr(str, ':') == NULL((void*)0)) {
541 wmem_strbuf_append_printf(coinfo->uri_host_strbuf, "coap://%s", str);
542 } else {
543 wmem_strbuf_append_printf(coinfo->uri_host_strbuf, "coap://[%s]", str);
544 }
545}
546
547static void
548dissect_coap_opt_uri_path(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, coap_info *coinfo, int hf)
549{
550 const char *str = NULL((void*)0);
551
552 wmem_strbuf_append_c(coinfo->uri_path_strbuf, '/');
553
554 if (opt_length == 0) {
555 str = nullstr;
556 } else {
557 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
558 wmem_strbuf_append(coinfo->uri_path_strbuf, str);
559 }
560
561 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
562
563 /* add info to the head of the packet detail */
564 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
565}
566
567static void
568dissect_coap_opt_uri_query(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, coap_info *coinfo, int hf)
569{
570 const char *str = NULL((void*)0);
571
572 wmem_strbuf_append_c(coinfo->uri_query_strbuf,
573 (wmem_strbuf_get_len(coinfo->uri_query_strbuf) == 0) ? '?' : '&');
574
575 if (opt_length == 0) {
576 str = nullstr;
577 } else {
578 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
579 wmem_strbuf_append(coinfo->uri_query_strbuf, str);
580 }
581
582 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
583
584 /* add info to the head of the packet detail */
585 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
586}
587
588static void
589dissect_coap_opt_location_path(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
590{
591 const char *str = NULL((void*)0);
592
593 if (opt_length == 0) {
594 str = nullstr;
595 } else {
596 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
597 }
598
599 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
600
601 /* add info to the head of the packet detail */
602 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
603}
604
605static void
606dissect_coap_opt_location_query(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
607{
608 const char *str = NULL((void*)0);
609
610 if (opt_length == 0) {
611 str = nullstr;
612 } else {
613 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
614 }
615
616 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
617
618 /* add info to the head of the packet detail */
619 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
620}
621
622/* rfc8613 */
623static void
624dissect_coap_opt_object_security(tvbuff_t *tvb, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, packet_info *pinfo, coap_info *coinfo, coap_common_dissect_t *dissect_hf, uint8_t code_class)
625{
626 uint8_t flag_byte = 0;
627 bool_Bool reserved = false0;
628 bool_Bool kid_context_present = false0;
629 bool_Bool kid_present = false0;
630 uint8_t piv_len = 0;
631 uint8_t kid_context_len = 0;
632 uint8_t kid_len = 0;
633
634 coinfo->object_security = true1;
635
636 coinfo->oscore_info->piv = NULL((void*)0);
637 coinfo->oscore_info->piv_len = 0;
638 coinfo->oscore_info->request_piv = NULL((void*)0);
639 coinfo->oscore_info->request_piv_len = 0;
640 coinfo->oscore_info->kid_context = NULL((void*)0);
641 coinfo->oscore_info->kid_context_len = 0;
642 coinfo->oscore_info->kid = NULL((void*)0);
643 coinfo->oscore_info->kid_len = 0;
644 coinfo->oscore_info->response = false0;
645
646 if (opt_length == 0) { /* option length is zero, means flag byte is 0x00*/
647 /* add info to the head of the packet detail */
648 proto_item_append_text(head_item, ": 00 (no Flag Byte)");
649 } else {
650 flag_byte = tvb_get_uint8(tvb, offset);
651
652 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_reserved, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
653 reserved = flag_byte & COAP_OBJECT_SECURITY_RESERVED_MASK0xE0;
654
655 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_kid_context_present, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
656 kid_context_present = flag_byte & COAP_OBJECT_SECURITY_KID_CONTEXT_MASK0x10;
657
658 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_kid_present, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
659 kid_present = flag_byte & COAP_OBJECT_SECURITY_KID_MASK0x08;
660
661 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_piv_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
662 piv_len = (flag_byte & COAP_OBJECT_SECURITY_PIVLEN_MASK0x07) >> 0;
663
664 /* kid_len is what remains in the option after all other fields are parsed
665 we calculate kid_len by subtracting from option length as we parse individual fields */
666 kid_len = opt_length;
667
668 offset += 1;
669 kid_len -= 1;
670
671 if (reserved) {
672 /* how these bits are handled is not yet specified */
673 expert_add_info_format(pinfo, subtree, &dissect_hf->ei.opt_object_security_bad, "Unsupported format");
674 }
675
676 if (piv_len > 0) {
677 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_piv, tvb, offset, piv_len, ENC_NA0x00000000);
678 coinfo->oscore_info->piv = (uint8_t *) tvb_memdup(pinfo->pool, tvb, offset, piv_len);
679 coinfo->oscore_info->piv_len = piv_len;
680
681 if (code_class == 0) {
682 /* If this is a request, copy PIV to request_piv */
683 coinfo->oscore_info->request_piv = (uint8_t *) tvb_memdup(pinfo->pool, tvb, offset, piv_len);
684 coinfo->oscore_info->request_piv_len = piv_len;
685 }
686
687 offset += piv_len;
688 kid_len -= piv_len;
689 }
690
691 if (kid_context_present) {
692 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_kid_context_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
693 kid_context_len = tvb_get_uint8(tvb, offset);
694
695 offset += 1;
696 kid_len -= 1;
697
698 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_kid_context, tvb, offset, kid_context_len, ENC_NA0x00000000);
699 coinfo->oscore_info->kid_context = (uint8_t *) tvb_memdup(pinfo->pool, tvb, offset, kid_context_len);
700 coinfo->oscore_info->kid_context_len = kid_context_len;
701
702 offset += kid_context_len;
703 kid_len -= kid_context_len;
704 }
705
706 if (kid_present) {
707 proto_tree_add_item(subtree, dissect_hf->hf.opt_object_security_kid, tvb, offset, kid_len, ENC_NA0x00000000);
708 coinfo->oscore_info->kid = (uint8_t *) tvb_memdup(pinfo->pool, tvb, offset, kid_len);
709 coinfo->oscore_info->kid_len = kid_len;
710
711 }
712
713 proto_item_append_text(head_item, ": Key ID:%s, Key ID Context:%s, Partial IV:%s",
714 coinfo->oscore_info->kid == NULL((void*)0) ? nullstr : bytes_to_str(pinfo->pool, coinfo->oscore_info->kid, coinfo->oscore_info->kid_len)bytes_to_str_maxlen(pinfo->pool, coinfo->oscore_info->
kid, coinfo->oscore_info->kid_len, 36)
,
715 coinfo->oscore_info->kid_context == NULL((void*)0) ? nullstr : bytes_to_str(pinfo->pool, coinfo->oscore_info->kid_context, coinfo->oscore_info->kid_context_len)bytes_to_str_maxlen(pinfo->pool, coinfo->oscore_info->
kid_context, coinfo->oscore_info->kid_context_len, 36)
,
716 coinfo->oscore_info->piv == NULL((void*)0) ? nullstr : bytes_to_str(pinfo->pool, coinfo->oscore_info->piv, coinfo->oscore_info->piv_len)bytes_to_str_maxlen(pinfo->pool, coinfo->oscore_info->
piv, coinfo->oscore_info->piv_len, 36)
);
717 }
718}
719
720static void
721dissect_coap_opt_proxy_uri(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
722{
723 const char *str = NULL((void*)0);
724
725 if (opt_length == 0) {
726 str = nullstr;
727 } else {
728 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
729 }
730
731 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
732
733 /* add info to the head of the packet detail */
734 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
735}
736
737static void
738dissect_coap_opt_proxy_scheme(tvbuff_t *tvb, packet_info *pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
739{
740 const char *str = NULL((void*)0);
741
742 if (opt_length == 0) {
743 str = nullstr;
744 } else {
745 str = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, opt_length, ENC_ASCII0x00000000);
746 }
747
748 proto_tree_add_item(subtree, hf, tvb, offset, opt_length, ENC_ASCII0x00000000);
749
750 /* add info to the head of the packet detail */
751 proto_item_append_text(head_item, ": %s", format_text_string(pinfo->pool, str));
752}
753
754static void
755dissect_coap_opt_ctype(tvbuff_t *tvb, packet_info* pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf, coap_info *coinfo)
756{
757 if (opt_length == 0) {
758 coinfo->ctype_value = 0;
759 } else {
760 coinfo->ctype_value = coap_get_opt_uint(tvb, offset, opt_length);
761 }
762
763 coinfo->ctype_str = val_to_str(pinfo->pool, coinfo->ctype_value, vals_ctype, "Unknown Type %u");
764
765 proto_tree_add_string(subtree, hf, tvb, offset, opt_length, coinfo->ctype_str);
766
767 /* add info to the head of the packet detail */
768 proto_item_append_text(head_item, ": %s", coinfo->ctype_str);
769}
770
771static void
772dissect_coap_opt_accept(tvbuff_t *tvb, packet_info* pinfo, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hf)
773{
774 const char *str = NULL((void*)0);
775
776 if (opt_length == 0) {
777 str = nullstr;
778 } else {
779 unsigned value = coap_get_opt_uint(tvb, offset, opt_length);
780 str = val_to_str(pinfo->pool, value, vals_ctype, "Unknown Type %u");
781 }
782
783 proto_tree_add_string(subtree, hf, tvb, offset, opt_length, str);
784
785 /* add info to the head of the packet detail */
786 proto_item_append_text(head_item, ": %s", str);
787}
788
789static void
790dissect_coap_opt_block(tvbuff_t *tvb, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, coap_info *coinfo, coap_common_dissect_t *dissect_hf)
791{
792 uint8_t val = 0;
793 unsigned encoded_block_size;
794 unsigned block_esize;
795
796 if (opt_length == 0) {
797 coinfo->block_number = 0;
798 val = 0;
799 } else {
800 coinfo->block_number = coap_get_opt_uint(tvb, offset, opt_length) >> 4;
801 val = tvb_get_uint8(tvb, offset + opt_length - 1) & 0x0f;
802 }
803
804 proto_tree_add_uint(subtree, dissect_hf->hf.opt_block_number,
805 tvb, offset, opt_length, coinfo->block_number);
806
807 /* More flag in the end of the option */
808 coinfo->block_mflag = (val & COAP_BLOCK_MFLAG_MASK0x08) >> 3;
809 proto_tree_add_uint(subtree, dissect_hf->hf.opt_block_mflag,
810 tvb, offset + opt_length - 1, 1, val);
811
812 /* block size */
813 encoded_block_size = val & COAP_BLOCK_SIZE_MASK0x07;
814 block_esize = 1 << (encoded_block_size + 4);
815 proto_tree_add_uint_format(subtree, dissect_hf->hf.opt_block_size,
816 tvb, offset + opt_length - 1, 1, encoded_block_size, "Block Size: %u (%u encoded)", block_esize, encoded_block_size);
817
818 /* add info to the head of the packet detail */
819 proto_item_append_text(head_item, ": NUM:%u, M:%u, SZ:%u",
820 coinfo->block_number, coinfo->block_mflag, block_esize);
821}
822
823static void
824dissect_coap_opt_ocf_version(tvbuff_t *tvb, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, int hfindex)
825{
826 unsigned option_value = coap_get_opt_uint(tvb, offset, opt_length);
827
828 unsigned sub_version = option_value & COAP_OCF_VERSION_SUB_MASK0x3F;
829 unsigned minor_version = (option_value & COAP_OCF_VERSION_MINOR_MASK0x7C0) >> COAP_OCF_VERSION_MINOR_OFFSET6;
830 unsigned major_version = (option_value & COAP_OCF_VERSION_MAJOR_MASK0xF800) >> COAP_OCF_VERSION_MAJOR_OFFSET11;
831
832 proto_tree_add_uint(subtree, hfindex, tvb, offset, opt_length, option_value);
833
834 /* add info to the head of the packet detail */
835 proto_item_append_text(head_item, ": %u.%u.%u",
836 major_version, minor_version, sub_version);
837}
838
839static void
840dissect_coap_opt_uri_port(tvbuff_t *tvb, proto_item *head_item, proto_tree *subtree, int offset, int opt_length, coap_info *coinfo, int hf)
841{
842 unsigned port = 0;
843
844 if (opt_length != 0) {
845 port = coap_get_opt_uint(tvb, offset, opt_length);
846 }
847
848 proto_tree_add_uint(subtree, hf, tvb, offset, opt_length, port);
849
850 proto_item_append_text(head_item, ": %u", port);
851
852 /* forming a uri-string */
853 wmem_strbuf_append_printf(coinfo->uri_host_strbuf, ":%u", port);
854}
855
856/*
857 * dissector for each option of CoAP.
858 * return the total length of the option including the header (e.g. delta and length).
859 */
860static unsigned
861dissect_coap_options_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *coap_tree, unsigned offset, uint8_t opt_count, unsigned *opt_num, unsigned offset_end, uint8_t code_class, coap_info *coinfo, coap_common_dissect_t *dissect_hf, bool_Bool *ok)
862{
863 uint8_t opt_jump;
864 int opt_length, opt_length_ext, opt_delta, opt_delta_ext;
865 int opt_length_ext_off = 0;
866 int8_t opt_length_ext_len = 0;
867 int opt_delta_ext_off = 0;
868 int8_t opt_delta_ext_len = 0;
869 int orig_offset = offset;
870 proto_tree *subtree;
871 proto_item *item;
872 char *strbuf2;
873
874 opt_jump = tvb_get_uint8(tvb, offset);
875 if (0xff == opt_jump)
19
Assuming 'opt_jump' is equal to 255
20
Taking true branch
876 return offset;
21
Returning without writing to '*ok', which participates in a condition later
22
Returning without writing to '*ok'
877 offset += 1;
878
879 /*
880 * section 3.1 in coap-17:
881 * Option Delta: 4-bit unsigned integer. A value between 0 and 12
882 * indicates the Option Delta. Three values are reserved for special
883 * constructs:
884 *
885 * 13: An 8-bit unsigned integer follows the initial byte and
886 * indicates the Option Delta minus 13.
887 *
888 * 14: A 16-bit unsigned integer in network byte order follows the
889 * initial byte and indicates the Option Delta minus 269.
890 *
891 * 15: Reserved for the Payload Marker. If the field is set to this
892 * value but the entire byte is not the payload marker, this MUST
893 * be processed as a message format error.
894 */
895 switch (opt_jump & 0xf0) {
896 case 0xd0:
897 opt_delta_ext = tvb_get_uint8(tvb, offset);
898 opt_delta_ext_off = offset;
899 opt_delta_ext_len = 1;
900 offset += 1;
901
902 opt_delta = 13;
903 opt_delta += opt_delta_ext;
904 break;
905 case 0xe0:
906 opt_delta_ext = coap_get_opt_uint(tvb, offset, 2);
907 opt_delta_ext_off = offset;
908 opt_delta_ext_len = 2;
909 offset += 2;
910
911 opt_delta = 269;
912 opt_delta += opt_delta_ext;
913 break;
914 case 0xf0:
915 expert_add_info_format(pinfo, coap_tree, &dissect_hf->ei.opt_length_bad,
916 "end-of-options marker found, but option length isn't 15");
917 *ok = false0; return offset;
918 default:
919 opt_delta = ((opt_jump & 0xf0) >> 4);
920 break;
921 }
922 *opt_num += opt_delta;
923
924 /*
925 * section 3.1 in coap-17:
926 * Option Length: 4-bit unsigned integer. A value between 0 and 12
927 * indicates the length of the Option Value, in bytes. Three values
928 * are reserved for special constructs:
929 *
930 * 13: An 8-bit unsigned integer precedes the Option Value and
931 * indicates the Option Length minus 13.
932 *
933 * 14: A 16-bit unsigned integer in network byte order precedes the
934 * Option Value and indicates the Option Length minus 269.
935 *
936 * 15: Reserved for future use. If the field is set to this value,
937 * it MUST be processed as a message format error.
938 */
939 switch (opt_jump & 0x0f) {
940 case 0x0d:
941 opt_length_ext = tvb_get_uint8(tvb, offset);
942 opt_length_ext_off = offset;
943 opt_length_ext_len = 1;
944 offset += 1;
945
946 opt_length = 13;
947 opt_length += opt_length_ext;
948 break;
949 case 0x0e:
950 opt_length_ext = coap_get_opt_uint(tvb, offset, 2);
951 opt_length_ext_off = offset;
952 opt_length_ext_len = 2;
953 offset += 2;
954
955 opt_length = 269;
956 opt_length += opt_length_ext;
957 break;
958 case 0x0f:
959 expert_add_info_format(pinfo, coap_tree, &dissect_hf->ei.opt_length_bad,
960 "end-of-options marker found, but option delta isn't 15");
961 *ok = false0; return offset;
962 default:
963 opt_length = (opt_jump & 0x0f);
964 break;
965 }
966 if ((unsigned)opt_length > offset_end - offset) {
967 expert_add_info_format(pinfo, coap_tree, &dissect_hf->ei.opt_length_bad,
968 "option longer than the package");
969 *ok = false0; return offset;
970 }
971
972 strbuf2 = wmem_strdup_printf(pinfo->pool, "#%u: %s", opt_count, val_to_str(pinfo->pool, *opt_num, vals_opt_type,
973 *opt_num % 14 == 0 ? "No-Op" : "Unknown Option (%d)"));
974 item = proto_tree_add_string(coap_tree, dissect_hf->hf.opt_name,
975 tvb, orig_offset, offset - orig_offset + opt_length, strbuf2);
976 subtree = proto_item_add_subtree(item, dissect_hf->ett.option);
977
978 coap_opt_check(pinfo, subtree, *opt_num, opt_length, dissect_hf);
979
980 strbuf2 = wmem_strdup_printf(pinfo->pool, "Type %u, %s, %s%s", *opt_num,
981 (*opt_num & 1) ? "Critical" : "Elective",
982 (*opt_num & 2) ? "Unsafe" : "Safe",
983 ((*opt_num & 0x1e) == 0x1c) ? ", NoCacheKey" : "");
984 proto_tree_add_string(subtree, dissect_hf->hf.opt_desc,
985 tvb, orig_offset, offset - orig_offset + opt_length, strbuf2);
986
987 proto_tree_add_item(subtree, dissect_hf->hf.opt_delta, tvb, orig_offset, 1, ENC_BIG_ENDIAN0x00000000);
988 proto_tree_add_item(subtree, dissect_hf->hf.opt_length, tvb, orig_offset, 1, ENC_BIG_ENDIAN0x00000000);
989
990 if (opt_delta_ext_off && opt_delta_ext_len)
991 proto_tree_add_item(subtree, dissect_hf->hf.opt_delta_ext, tvb, opt_delta_ext_off, opt_delta_ext_len, ENC_BIG_ENDIAN0x00000000);
992
993 if (opt_length_ext_off && opt_length_ext_len)
994 proto_tree_add_item(subtree, dissect_hf->hf.opt_length_ext, tvb, opt_length_ext_off, opt_length_ext_len, ENC_BIG_ENDIAN0x00000000);
995
996 /* offset points the next to its option header */
997 switch (*opt_num) {
998 case COAP_OPT_CONTENT_TYPE12:
999 dissect_coap_opt_ctype(tvb, pinfo, item, subtree, offset,
1000 opt_length, dissect_hf->hf.opt_ctype, coinfo);
1001 break;
1002 case COAP_OPT_MAX_AGE14:
1003 dissect_coap_opt_uint(tvb, item, subtree, offset,
1004 opt_length, dissect_hf->hf.opt_max_age);
1005 break;
1006 case COAP_OPT_PROXY_URI35:
1007 dissect_coap_opt_proxy_uri(tvb, pinfo, item, subtree, offset,
1008 opt_length, dissect_hf->hf.opt_proxy_uri);
1009 break;
1010 case COAP_OPT_PROXY_SCHEME39:
1011 dissect_coap_opt_proxy_scheme(tvb, pinfo, item, subtree, offset,
1012 opt_length, dissect_hf->hf.opt_proxy_scheme);
1013 break;
1014 case COAP_OPT_SIZE160:
1015 dissect_coap_opt_uint(tvb, item, subtree, offset,
1016 opt_length, dissect_hf->hf.opt_size1);
1017 break;
1018 case COAP_OPT_ETAG4:
1019 dissect_coap_opt_hex_string(tvb, pinfo, item, subtree, offset,
1020 opt_length, dissect_hf->hf.opt_etag);
1021 break;
1022 case COAP_OPT_URI_HOST3:
1023 dissect_coap_opt_uri_host(tvb, pinfo, item, subtree, offset,
1024 opt_length, coinfo, dissect_hf->hf.opt_uri_host);
1025 break;
1026 case COAP_OPT_LOCATION_PATH8:
1027 dissect_coap_opt_location_path(tvb, pinfo, item, subtree, offset,
1028 opt_length, dissect_hf->hf.opt_location_path);
1029 break;
1030 case COAP_OPT_URI_PORT7:
1031 dissect_coap_opt_uri_port(tvb, item, subtree, offset,
1032 opt_length, coinfo, dissect_hf->hf.opt_uri_port);
1033 break;
1034 case COAP_OPT_LOCATION_QUERY20:
1035 dissect_coap_opt_location_query(tvb, pinfo, item, subtree, offset,
1036 opt_length, dissect_hf->hf.opt_location_query);
1037 break;
1038 case COAP_OPT_OBJECT_SECURITY9:
1039 dissect_coap_opt_object_security(tvb, item, subtree, offset,
1040 opt_length, pinfo, coinfo, dissect_hf, code_class);
1041 break;
1042 case COAP_OPT_URI_PATH11:
1043 dissect_coap_opt_uri_path(tvb, pinfo, item, subtree, offset,
1044 opt_length, coinfo, dissect_hf->hf.opt_uri_path);
1045 break;
1046 case COAP_OPT_OBSERVE6:
1047 if (code_class == 0) {
1048 /* Request */
1049 dissect_coap_opt_uint(tvb, item, subtree, offset,
1050 opt_length, dissect_hf->hf.opt_observe_req);
1051 } else {
1052 /* Response */
1053 dissect_coap_opt_uint(tvb, item, subtree, offset,
1054 opt_length, dissect_hf->hf.opt_observe_rsp);
1055 }
1056 break;
1057 case COAP_OPT_HOP_LIMIT16:
1058 dissect_coap_opt_uint(tvb, item, subtree, offset,
1059 opt_length, dissect_hf->hf.opt_hop_limit);
1060 break;
1061 case COAP_OPT_ACCEPT17:
1062 dissect_coap_opt_accept(tvb, pinfo, item, subtree, offset,
1063 opt_length, dissect_hf->hf.opt_accept);
1064 break;
1065 case COAP_OPT_IF_MATCH1:
1066 dissect_coap_opt_hex_string(tvb, pinfo, item, subtree, offset,
1067 opt_length, dissect_hf->hf.opt_if_match);
1068 break;
1069 case COAP_OPT_URI_QUERY15:
1070 dissect_coap_opt_uri_query(tvb, pinfo, item, subtree, offset,
1071 opt_length, coinfo, dissect_hf->hf.opt_uri_query);
1072 break;
1073 case COAP_OPT_ECHO252:
1074 dissect_coap_opt_hex_string(tvb, pinfo, item, subtree, offset,
1075 opt_length, dissect_hf->hf.opt_echo);
1076 break;
1077 case COAP_OPT_REQUEST_TAG292:
1078 dissect_coap_opt_hex_string(tvb, pinfo, item, subtree, offset,
1079 opt_length, dissect_hf->hf.opt_request_tag);
1080 break;
1081 case COAP_OPT_NO_RESPONSE258:
1082 dissect_coap_opt_uint(tvb, item, subtree, offset,
1083 opt_length, dissect_hf->hf.opt_no_response);
1084 break;
1085 case COAP_OPT_BLOCK223:
1086 coinfo->block_option = 2;
1087 dissect_coap_opt_block(tvb, item, subtree, offset,
1088 opt_length, coinfo, dissect_hf);
1089 break;
1090 case COAP_OPT_BLOCK127:
1091 coinfo->block_option = 1;
1092 dissect_coap_opt_block(tvb, item, subtree, offset,
1093 opt_length, coinfo, dissect_hf);
1094 break;
1095 case COAP_OPT_QBLOCK231:
1096 coinfo->block_option = 2;
1097 dissect_coap_opt_block(tvb, item, subtree, offset,
1098 opt_length, coinfo, dissect_hf);
1099 break;
1100 case COAP_OPT_QBLOCK119:
1101 coinfo->block_option = 1;
1102 dissect_coap_opt_block(tvb, item, subtree, offset,
1103 opt_length, coinfo, dissect_hf);
1104 break;
1105 case COAP_OPT_IF_NONE_MATCH5:
1106 break;
1107 case COAP_OPT_EDHOC21:
1108 break;
1109 case COAP_OPT_SIZE228:
1110 dissect_coap_opt_uint(tvb, item, subtree, offset,
1111 opt_length, dissect_hf->hf.opt_block_size);
1112 break;
1113 case COAP_OPT_OCF_CONTENT2053:
1114 dissect_coap_opt_ocf_version(tvb, item, subtree, offset,
1115 opt_length, dissect_hf->hf.opt_ocf_version);
1116 break;
1117 case COAP_OPT_OCF_ACCEPT2049:
1118 dissect_coap_opt_ocf_version(tvb, item, subtree, offset,
1119 opt_length, dissect_hf->hf.opt_ocf_accept_version);
1120 break;
1121 default:
1122 dissect_coap_opt_hex_string(tvb, pinfo, item, subtree, offset,
1123 opt_length, dissect_hf->hf.opt_unknown);
1124 break;
1125 }
1126
1127 return offset + opt_length;
1128}
1129
1130/*
1131 * options dissector.
1132 * return offset pointing the next of options. (i.e. the top of the payload
1133 * or the end of the data.
1134 */
1135unsigned
1136dissect_coap_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *coap_tree, unsigned offset, unsigned offset_end, uint8_t code_class, coap_info *coinfo, coap_common_dissect_t *dissect_hf, bool_Bool *ok)
1137{
1138 unsigned opt_num = 0;
1139 int i;
1140 uint8_t endmarker;
1141 bool_Bool sub_ok;
14
'sub_ok' declared without an initial value
1142
1143 if (ok
14.1
'ok' is non-null
) *ok = true1;
15
Taking true branch
1144
1145 /* loop for dissecting options */
1146 for (i = 1; offset < offset_end; i++) {
16
Assuming 'offset' is < 'offset_end'
17
Loop condition is true. Entering loop body
1147 offset = dissect_coap_options_main(tvb, pinfo, coap_tree,
18
Calling 'dissect_coap_options_main'
23
Returning from 'dissect_coap_options_main'
1148 offset, i, &opt_num, offset_end, code_class, coinfo, dissect_hf, &sub_ok);
1149 if (!sub_ok) {
24
Branch condition evaluates to a garbage value
1150 if (ok) *ok = false0;
1151 return offset;
1152 }
1153 if (offset >= offset_end)
1154 break;
1155 endmarker = tvb_get_uint8(tvb, offset);
1156 if (endmarker == 0xff) {
1157 proto_tree_add_item(coap_tree, dissect_hf->hf.opt_end_marker, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1158 offset += 1;
1159 break;
1160 }
1161 }
1162
1163 return offset;
1164}
1165
1166/*
1167 * CoAP code dissector.
1168 * return code value and updates the offset
1169 * */
1170uint8_t
1171dissect_coap_code(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, coap_common_dissect_t *dissect_hf, uint8_t *code_class)
1172{
1173 uint8_t code;
1174
1175 proto_tree_add_item(tree, dissect_hf->hf.code, tvb, *offset, 1, ENC_BIG_ENDIAN0x00000000);
1176 code = tvb_get_uint8(tvb, *offset);
1177 *code_class = code >> 5;
1178 *offset += 1;
1179
1180 return code;
1181}
1182
1183void
1184dissect_coap_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *coap_tree, proto_tree *parent_tree, int offset, int offset_end, uint8_t code_class, coap_info *coinfo, coap_common_dissect_t *dissect_hf, bool_Bool oscore)
1185{
1186 proto_tree *payload_tree;
1187 proto_item *payload_item, *length_item;
1188 tvbuff_t *payload_tvb;
1189 unsigned payload_length = offset_end - offset;
1190 const char *coap_ctype_str_dis;
1191 media_content_info_t content_info = {0};
1192 char str_payload[80];
1193 int result = 0;
1194
1195 /* coinfo->ctype_value == DEFAULT_COAP_CTYPE_VALUE: No Content-Format option present */
1196 if (coinfo->ctype_value == DEFAULT_COAP_CTYPE_VALUE~0U) {
1197 /*
1198 * 5.5.2. Diagnostic Payload
1199 *
1200 * If no Content-Format option is given, the payload of responses
1201 * indicating a client or server error is a brief human-readable
1202 * diagnostic message, explaining the error situation. This diagnostic
1203 * message MUST be encoded using UTF-8 [RFC3629], more specifically
1204 * using Net-Unicode form [RFC5198].
1205 */
1206 if ((code_class >= 4) && (code_class <= 5)) {
1207 coinfo->ctype_str = "text/plain; charset=utf-8";
1208 coap_ctype_str_dis = "text/plain";
1209 } else {
1210 /* Assume no Content-Format is opaque octet stream */
1211 coinfo->ctype_str = "application/octet-stream";
1212 coap_ctype_str_dis = coinfo->ctype_str;
1213 }
1214 }
1215 /* coinfo->ctype_value == 0: Content-Format option present with length 0 */
1216 else if (coinfo->ctype_value == 0) {
1217 /* coinfo->ctype_str is already set by option parsing routine */
1218 coap_ctype_str_dis = "text/plain";
1219 } else {
1220 coap_ctype_str_dis = coinfo->ctype_str;
1221 }
1222
1223 snprintf(str_payload, sizeof(str_payload),
1224 "Payload Content-Format: %s%s, Length: %u",
1225 coinfo->ctype_str, coinfo->ctype_value == DEFAULT_COAP_CTYPE_VALUE~0U ?
1226 " (no Content-Format)" : "", payload_length);
1227
1228 payload_item = proto_tree_add_string(coap_tree, dissect_hf->hf.payload,
1229 tvb, offset, payload_length,
1230 str_payload);
1231 payload_tree = proto_item_add_subtree(payload_item, dissect_hf->ett.payload);
1232
1233 proto_tree_add_string(payload_tree, dissect_hf->hf.payload_desc, tvb, offset, 0, coinfo->ctype_str);
1234 length_item = proto_tree_add_uint(payload_tree, dissect_hf->hf.payload_length, tvb, offset, 0, payload_length);
1235 proto_item_set_generated(length_item);
1236 payload_tvb = tvb_new_subset_length(tvb, offset, payload_length);
1237
1238 content_info.type = (code_class == 0) ? MEDIA_CONTAINER_HTTP_REQUEST : MEDIA_CONTAINER_HTTP_RESPONSE;
1239 content_info.media_str = wmem_strdup_printf(pinfo->pool, "%s%s", wmem_strbuf_get_str(coinfo->uri_host_strbuf), wmem_strbuf_get_str(coinfo->uri_path_strbuf));
1240
1241 /*
1242 * The Thread protocol uses application/octet-stream for its
1243 * messages, rather than having its own media type for those
1244 * messages, as, for example, the Internet Printing Protocol
1245 * does.
1246 *
1247 * Handle "application/octet-stream" specially if this is
1248 * being dissected by the "CoAP for Thread Management Framework"
1249 * dissector.
1250 */
1251 if (coinfo->is_coap_for_tmf) {
1252 /*
1253 * Try the media type dissector table for CoAP-TMF first.
1254 */
1255 result = dissector_try_string_with_data(coap_tmf_media_type_dissector_table,
1256 coap_ctype_str_dis, payload_tvb, pinfo, parent_tree, true1,
1257 &content_info);
1258 }
1259 if (result == 0) {
1260 /*
1261 * Try the CoAP URI-Path table.
1262 */
1263 result = dissector_try_string_with_data(coap_uri_path_dissector_table,
1264 wmem_strbuf_get_str(coinfo->uri_path_strbuf), payload_tvb, pinfo, parent_tree, true1,
1265 &content_info);
1266 }
1267 if (result == 0) {
1268 /*
1269 * That either failed or we didn't try it.
1270 * Now try the regular media type table.
1271 */
1272 dissector_try_string_with_data(media_type_dissector_table,
1273 coap_ctype_str_dis, payload_tvb, pinfo, parent_tree, true1,
1274 &content_info);
1275 }
1276 if (coinfo->object_security && !oscore) {
1277 proto_item_set_text(payload_item, "Encrypted OSCORE Data");
1278 call_dissector_with_data(oscore_handle, payload_tvb, pinfo, parent_tree, coinfo->oscore_info);
1279 }
1280}
1281
1282static uint32_t
1283coap_frame_length(tvbuff_t *tvb, unsigned offset, int *size)
1284{
1285 /*
1286 * Decode Len and Extended Length according to
1287 * https://tools.ietf.org/html/rfc8323#page-10
1288 */
1289 uint8_t len = tvb_get_uint8(tvb, offset) >> 4;
1290 switch (len) {
1291 default:
1292 *size = 1;
1293 return len;
1294 case 13:
1295 if (tvb_reported_length_remaining(tvb, offset) < 2) {
1296 *size = -1;
1297 return 0;
1298 }
1299 *size = 2;
1300 return tvb_get_uint8(tvb, offset + 1) + 13;
1301 case 14:
1302 if (tvb_reported_length_remaining(tvb, offset) < 3) {
1303 *size = -1;
1304 return 0;
1305 }
1306 *size = 3;
1307 return tvb_get_ntohs(tvb, offset + 1) + 269;
1308 case 15:
1309 if (tvb_reported_length_remaining(tvb, offset) < 5) {
1310 *size = -1;
1311 return 0;
1312 }
1313 *size = 5;
1314 return tvb_get_ntohl(tvb, offset + 1) + 65805;
1315 }
1316}
1317
1318static int
1319dissect_coap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, coap_parent_protocol parent_protocol, bool_Bool is_coap_for_tmf)
1320{
1321 unsigned offset = 0;
1322 proto_item *coap_root;
1323 proto_item *pi;
1324 proto_tree *coap_tree;
1325 int length_size = 0;
1326 uint8_t ttype = UINT8_MAX(255);
1327 uint32_t token_len;
1328 uint8_t code;
1329 uint8_t code_class;
1330 uint32_t mid = 0;
1331 unsigned coap_length;
1332 char *coap_token_str;
1333 coap_info *coinfo;
1334 conversation_t *conversation;
1335 coap_conv_info *ccinfo;
1336 coap_transaction *coap_trans = NULL((void*)0);
1337 char *coap_trans_key;
1338 coap_request_response *coap_req_rsp = NULL((void*)0);
1339
1340 // TODO support TCP/WebSocket/TCP with more than one PDU per packet.
1341 // These probably require a unique coinfo for each.
1342
1343 /* Allocate information for upper layers */
1344 coinfo = (coap_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_coap, 0);
1345
1346 if (coinfo == NULL((void*)0))
1
Assuming 'coinfo' is not equal to NULL
2
Taking false branch
1347 {
1348 coinfo = wmem_new0(wmem_file_scope(), coap_info)((coap_info*)wmem_alloc0((wmem_file_scope()), sizeof(coap_info
)))
;
1349 p_add_proto_data(wmem_file_scope(), pinfo, proto_coap, 0, coinfo);
1350 }
1351
1352// coinfo->parent_protocol = parent_protocol;
1353 coinfo->is_coap_for_tmf = is_coap_for_tmf;
1354 /* check if trel is previously dissected */
1355 if (coinfo->is_coap_for_tmf == 0)
3
Assuming field 'is_coap_for_tmf' is not equal to 0
4
Taking false branch
1356 {
1357 unsigned id2 = proto_get_id_by_short_name("TREL");
1358 wmem_list_frame_t* ptr2 = wmem_list_find(pinfo->layers, GUINT_TO_POINTER(id2)((gpointer) (gulong) (id2)));
1359
1360 if ( ptr2 != NULL((void*)0))
1361 coinfo->is_coap_for_tmf = 1;
1362 }
1363
1364 /* initialize the CoAP length and the content-Format */
1365 /*
1366 * The length of CoAP message is not specified in the CoAP header using
1367 * UDP or WebSockets. The lower layers provide it. For TCP/TLS, an
1368 * explicit length is present.
1369 */
1370 coap_length = tvb_reported_length(tvb);
1371 if (parent_protocol == PARENT_TCP_TLS) {
5
Assuming 'parent_protocol' is not equal to PARENT_TCP_TLS
6
Taking false branch
1372 token_len = tvb_get_uint8(tvb, offset) & 0xf;
1373 coap_length = coap_frame_length(tvb, offset, &length_size);
1374 if (length_size < 0) {
1375 pinfo->desegment_offset = offset;
1376 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
1377 return tvb_reported_length(tvb);
1378 }
1379 /*
1380 * Length of the whole CoAP frame includes the (Extended) Length fields
1381 * (1 to 4 bytes), the Code (1 byte) and token length (normally 0 to 8
1382 * bytes), plus everything afterwards.
1383 */
1384 coap_length += 1 + token_len + length_size;
1385 if (coap_length > tvb_reported_length_remaining(tvb, offset)) {
1386 pinfo->desegment_offset = offset;
1387 pinfo->desegment_len = coap_length - tvb_reported_length_remaining(tvb, offset);
1388 return tvb_reported_length(tvb);
1389 }
1390 }
1391 coinfo->ctype_str = "";
1392 coinfo->ctype_value = DEFAULT_COAP_CTYPE_VALUE~0U;
1393
1394 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CoAP");
1395 col_clear(pinfo->cinfo, COL_INFO);
1396
1397 coap_root = proto_tree_add_item(parent_tree, proto_coap, tvb, offset, -1, ENC_NA0x00000000);
1398 coap_tree = proto_item_add_subtree(coap_root, ett_coap);
1399
1400 if (parent_protocol == PARENT_OTHER) {
7
Assuming 'parent_protocol' is not equal to PARENT_OTHER
8
Taking false branch
1401 proto_tree_add_item(coap_tree, hf_coap_version, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1402
1403 proto_tree_add_item_ret_uint8(coap_tree, hf_coap_ttype, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &ttype);
1404
1405 proto_tree_add_item_ret_uint(coap_tree, hf_coap_token_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &token_len);
1406 offset += 1;
1407
1408 code = dissect_coap_code(tvb, coap_tree, &offset, &dissect_coap_hf, &code_class);
1409
1410 proto_tree_add_item_ret_uint(coap_tree, hf_coap_mid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mid);
1411 offset += 2;
1412
1413 col_add_fstr(pinfo->cinfo, COL_INFO,
1414 "%s, MID:%u, %s",
1415 val_to_str(pinfo->pool, ttype, vals_ttype_short, "Unknown %u"),
1416 mid,
1417 val_to_str_ext(pinfo->pool, code, &coap_vals_code_ext, "Unknown %u"));
1418
1419 /* append the header information */
1420 proto_item_append_text(coap_root,
1421 ", %s, %s, MID:%u",
1422 val_to_str(pinfo->pool, ttype, vals_ttype, "Unknown %u"),
1423 val_to_str_ext(pinfo->pool, code, &coap_vals_code_ext, "Unknown %u"),
1424 mid);
1425 } else {
1426 unsigned len = coap_length;
1427 if (parent_protocol == PARENT_WEBSOCKETS) {
9
Assuming 'parent_protocol' is not equal to PARENT_WEBSOCKETS
10
Taking false branch
1428 len = tvb_get_uint8(tvb, offset) >> 4;
1429 length_size = 1;
1430 }
1431 proto_tree_add_uint(coap_tree, hf_coap_length, tvb, offset, length_size, len);
1432
1433 proto_tree_add_item_ret_uint(coap_tree, hf_coap_token_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &token_len);
1434 offset += length_size;
1435
1436 code = dissect_coap_code(tvb, coap_tree, &offset, &dissect_coap_hf, &code_class);
1437
1438 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0),
1439 val_to_str_ext(pinfo->pool, code, &coap_vals_code_ext, "Unknown %u"));
1440
1441 /* append the header information */
1442 proto_item_append_text(coap_root,
1443 ", %s",
1444 val_to_str_ext(pinfo->pool, code, &coap_vals_code_ext, "Unknown %u"));
1445 }
1446
1447 /* initialize the external value */
1448 coinfo->block_option = 0;
1449 coinfo->block_number = DEFAULT_COAP_BLOCK_NUMBER~0U;
1450 coinfo->block_mflag = 0;
1451 coinfo->uri_host_strbuf = wmem_strbuf_create(pinfo->pool)wmem_strbuf_new(pinfo->pool, "");
1452 coinfo->uri_path_strbuf = wmem_strbuf_create(pinfo->pool)wmem_strbuf_new(pinfo->pool, "");
1453 coinfo->uri_query_strbuf = wmem_strbuf_create(pinfo->pool)wmem_strbuf_new(pinfo->pool, "");
1454 /* Allocate pointers and static elements of oscore_info_t, arrays are allocated only if object security option is found during option parsing */
1455 coinfo->oscore_info = wmem_new0(pinfo->pool, oscore_info_t)((oscore_info_t*)wmem_alloc0((pinfo->pool), sizeof(oscore_info_t
)))
;
1456 coinfo->object_security = false0;
1457 coap_token_str = NULL((void*)0);
1458
1459 if (token_len > 0) {
11
Assuming 'token_len' is <= 0
12
Taking false branch
1460 /* This has to be file scope as the token string is stored in the map
1461 * for conversation lookup */
1462 coap_token_str = tvb_bytes_to_str_punct(wmem_file_scope(), tvb, offset, token_len, ' ');
1463 proto_tree_add_item(coap_tree, hf_coap_token,
1464 tvb, offset, token_len, ENC_NA0x00000000);
1465 offset += token_len;
1466
1467 /* Use the token for transaction key */
1468 coap_trans_key = coap_token_str;
1469 } else {
1470 /* Use the message id for transaction key */
1471 coap_trans_key = wmem_strdup_printf(wmem_file_scope(), "%u", mid);
1472 }
1473
1474 /* process options */
1475 { bool_Bool opts_ok;
1476 offset = dissect_coap_options(tvb, pinfo, coap_tree, offset, coap_length, code_class, coinfo, &dissect_coap_hf, &opts_ok);
13
Calling 'dissect_coap_options'
1477 if (!opts_ok)
1478 return tvb_captured_length(tvb);
1479 }
1480
1481 /* Use conversations to track state for request/response */
1482 conversation = find_or_create_conversation_noaddrb(pinfo, (code_class == 0));
1483
1484 /* Retrieve or create state structure for this conversation */
1485 ccinfo = (coap_conv_info *)conversation_get_proto_data(conversation, proto_coap);
1486 if (!ccinfo) {
1487 /* No state structure - create it */
1488 ccinfo = wmem_new(wmem_file_scope(), coap_conv_info)((coap_conv_info*)wmem_alloc((wmem_file_scope()), sizeof(coap_conv_info
)))
;
1489 ccinfo->messages = wmem_map_new(wmem_file_scope(), g_str_hash, g_str_equal);
1490 conversation_add_proto_data(conversation, proto_coap, ccinfo);
1491 }
1492
1493 /* Process request/response in conversation */
1494 if (code != 0) { /* Ignore empty messages */
1495 /* Try and look up a matching token. If it's the first
1496 * sight of a request, there shouldn't be one */
1497 coap_trans = (coap_transaction *)wmem_map_lookup(ccinfo->messages, coap_trans_key);
1498 if (!coap_trans) {
1499 if ((!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) && (code_class == 0)) {
1500 /* New request - log it */
1501 coap_trans = wmem_new0(wmem_file_scope(), coap_transaction)((coap_transaction*)wmem_alloc0((wmem_file_scope()), sizeof(coap_transaction
)))
;
1502 coap_trans->req_rsp = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1503 if (coinfo->uri_host_strbuf) {
1504 /* Store the URI-Host into CoAP transaction info */
1505 coap_trans->uri_host_strbuf = wmem_strbuf_new(wmem_file_scope(), wmem_strbuf_get_str(coinfo->uri_host_strbuf));
1506 }
1507 if (coinfo->uri_path_strbuf) {
1508 /* Store the URI-Path into CoAP transaction info */
1509 coap_trans->uri_path_strbuf = wmem_strbuf_new(wmem_file_scope(), wmem_strbuf_get_str(coinfo->uri_path_strbuf));
1510 }
1511 if (coinfo->oscore_info) {
1512 coap_trans->oscore_info = (oscore_info_t *) wmem_memdup(wmem_file_scope(), coinfo->oscore_info, sizeof(oscore_info_t));
1513 if (coinfo->oscore_info->kid) {
1514 coap_trans->oscore_info->kid = (uint8_t *) wmem_memdup(wmem_file_scope(), coinfo->oscore_info->kid, coinfo->oscore_info->kid_len);
1515 }
1516 if (coinfo->oscore_info->kid_context) {
1517 coap_trans->oscore_info->kid_context = (uint8_t *) wmem_memdup(wmem_file_scope(), coinfo->oscore_info->kid_context, coinfo->oscore_info->kid_context_len);
1518 }
1519 if (coinfo->oscore_info->piv) {
1520 coap_trans->oscore_info->request_piv = (uint8_t *) wmem_memdup(wmem_file_scope(), coinfo->oscore_info->request_piv, coinfo->oscore_info->request_piv_len);
1521 }
1522 }
1523 wmem_map_insert(ccinfo->messages, coap_trans_key, (void *)coap_trans);
1524 }
1525 } else {
1526 if ((code_class >= 2) && (code_class <= 5)) {
1527 if (coap_trans->uri_host_strbuf) {
1528 /* Copy the URI-Host stored in matching transaction info into CoAP packet info */
1529 coinfo->uri_host_strbuf = wmem_strbuf_new(pinfo->pool, wmem_strbuf_get_str(coap_trans->uri_host_strbuf));
1530 }
1531 if (coap_trans->uri_path_strbuf) {
1532 /* Copy the URI-Path stored in matching transaction info into CoAP packet info */
1533 coinfo->uri_path_strbuf = wmem_strbuf_new(pinfo->pool, wmem_strbuf_get_str(coap_trans->uri_path_strbuf));
1534 }
1535 if (coap_trans->oscore_info) {
1536 /* Copy OSCORE info in matching transaction info into CoAP packet info */
1537 if (coap_trans->oscore_info->kid) {
1538 coinfo->oscore_info->kid = (uint8_t *) wmem_memdup(pinfo->pool, coap_trans->oscore_info->kid, coap_trans->oscore_info->kid_len);
1539 }
1540 coinfo->oscore_info->kid_len = coap_trans->oscore_info->kid_len;
1541 if (coap_trans->oscore_info->kid_context) {
1542 coinfo->oscore_info->kid_context = (uint8_t *) wmem_memdup(pinfo->pool, coap_trans->oscore_info->kid_context, coap_trans->oscore_info->kid_context_len);
1543 }
1544 coinfo->oscore_info->kid_context_len = coap_trans->oscore_info->kid_context_len;
1545 if (coap_trans->oscore_info->request_piv) {
1546 coinfo->oscore_info->request_piv = (uint8_t *) wmem_memdup(pinfo->pool, coap_trans->oscore_info->request_piv, coap_trans->oscore_info->request_piv_len);
1547 }
1548 coinfo->oscore_info->request_piv_len = coap_trans->oscore_info->request_piv_len;
1549 coinfo->oscore_info->response = true1;
1550 }
1551 }
1552 }
1553 if (coap_trans) {
1554 coap_req_rsp = (coap_request_response *)wmem_map_lookup(coap_trans->req_rsp, GINT_TO_POINTER(mid)((gpointer) (glong) (mid)));
1555 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1556 if (!coap_req_rsp) {
1557 coap_req_rsp = wmem_new0(wmem_file_scope(), coap_request_response)((coap_request_response*)wmem_alloc0((wmem_file_scope()), sizeof
(coap_request_response)))
;
1558 wmem_map_insert(coap_trans->req_rsp, GINT_TO_POINTER(mid)((gpointer) (glong) (mid)), (void *)coap_req_rsp);
1559 }
1560 if (code_class == 0) {
1561 /* This is a request */
1562 if (coap_req_rsp->req_frame == 0) {
1563 /* Log the first request frame */
1564 coap_req_rsp->req_frame = pinfo->num;
1565 coap_req_rsp->req_time = pinfo->abs_ts;
1566 }
1567 } else if ((code_class >= 2) && (code_class <= 5)) {
1568 /* This is a reply */
1569 if (coap_req_rsp->rsp_frame == 0) {
1570 /* Log the first matching response frame */
1571 coap_req_rsp->rsp_frame = pinfo->num;
1572 }
1573 }
1574 }
1575 }
1576 }
1577
1578 /* dissect the payload after info column updates below */
1579 tvbuff_t *payload_tvb = NULL((void*)0);
1580 if (coap_length > offset) {
1581 if (coinfo->block_number == DEFAULT_COAP_BLOCK_NUMBER~0U) {
1582 payload_tvb = tvb_new_subset_remaining(tvb, offset);
1583 } else {
1584 proto_tree_add_bytes_format(coap_tree, hf_block_payload, tvb, offset,
1585 coap_length - offset, NULL((void*)0), "Block Payload");
1586 pi = proto_tree_add_uint(coap_tree, hf_block_length, tvb, offset, 0, coap_length - offset);
1587 proto_item_set_generated(pi);
1588
1589 fragment_head *frag_msg = fragment_add_seq_check(&coap_block_reassembly_table, tvb, offset,
1590 pinfo, 0, NULL((void*)0), coinfo->block_number,
1591 coap_length - offset, coinfo->block_mflag);
1592 payload_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CoAP blocks",
1593 frag_msg, &coap_block_frag_items, NULL((void*)0), coap_tree);
1594 }
1595 }
1596
1597 /* add informations to the packet list */
1598 if (coap_token_str != NULL((void*)0))
1599 col_append_fstr(pinfo->cinfo, COL_INFO, ", TKN:%s", coap_token_str);
1600 if (coinfo->block_number != DEFAULT_COAP_BLOCK_NUMBER~0U) {
1601 /* The M bit is used in Block1 Option in a request and in Block2 Option in a response */
1602 bool_Bool mflag_is_used = (((coinfo->block_option == 1) && (code_class == 0)) ||
1603 ((coinfo->block_option == 2) && (code_class >= 2) && (code_class <= 5)));
1604 col_append_fstr(pinfo->cinfo, COL_INFO, ", %sBlock #%u",
1605 (coinfo->block_mflag || !mflag_is_used) ? "" : "End of ", coinfo->block_number);
1606 }
1607 if (wmem_strbuf_get_len(coinfo->uri_host_strbuf) > 0 || wmem_strbuf_get_len(coinfo->uri_path_strbuf) > 0) {
1608 char *uri_host_path = wmem_strdup_printf(pinfo->pool, "%s%s", wmem_strbuf_get_str(coinfo->uri_host_strbuf), wmem_strbuf_get_str(coinfo->uri_path_strbuf));
1609 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", format_text(pinfo->pool, uri_host_path, strlen(uri_host_path)));
1610 /* Add a generated protocol item as well */
1611 pi = proto_tree_add_string(coap_tree, dissect_coap_hf.hf.opt_uri_path_recon, tvb, 0, 0, uri_host_path);
1612 proto_item_set_generated(pi);
1613 }
1614 if (wmem_strbuf_get_len(coinfo->uri_query_strbuf) > 0)
1615 col_append_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, wmem_strbuf_get_str(coinfo->uri_query_strbuf), wmem_strbuf_get_len(coinfo->uri_query_strbuf)));
1616
1617 if (coap_req_rsp != NULL((void*)0)) {
1618 /* Print state tracking in the tree */
1619 if (code_class == 0) {
1620 /* This is a request */
1621 if (coap_req_rsp->rsp_frame) {
1622 pi = proto_tree_add_uint(coap_tree, hf_coap_response_in,
1623 tvb, 0, 0, coap_req_rsp->rsp_frame);
1624 proto_item_set_generated(pi);
1625 }
1626 if ((ttype == TT_CON0 || ttype == TT_NON1) && (coap_req_rsp->req_frame != pinfo->num)) {
1627 col_append_str(pinfo->cinfo, COL_INFO, " [Retransmission]");
1628 pi = proto_tree_add_uint(coap_tree, hf_coap_request_resend_in,
1629 tvb, 0, 0, coap_req_rsp->req_frame);
1630 proto_item_set_generated(pi);
1631 expert_add_info(pinfo, pi, &ei_retransmitted);
1632 }
1633 } else if ((code_class >= 2) && (code_class <= 5)) {
1634 /* This is a reply */
1635 if (coap_req_rsp->req_frame) {
1636 nstime_t ns;
1637
1638 pi = proto_tree_add_uint(coap_tree, hf_coap_response_to,
1639 tvb, 0, 0, coap_req_rsp->req_frame);
1640 proto_item_set_generated(pi);
1641
1642 nstime_delta(&ns, &pinfo->abs_ts, &coap_req_rsp->req_time);
1643 pi = proto_tree_add_time(coap_tree, hf_coap_response_time, tvb, 0, 0, &ns);
1644 proto_item_set_generated(pi);
1645 }
1646 if ((ttype == TT_CON0 || ttype == TT_NON1) && (coap_req_rsp->rsp_frame != pinfo->num)) {
1647 col_append_str(pinfo->cinfo, COL_INFO, " [Retransmission]");
1648 pi = proto_tree_add_uint(coap_tree, hf_coap_response_resend_in,
1649 tvb, 0, 0, coap_req_rsp->rsp_frame);
1650 proto_item_set_generated(pi);
1651 expert_add_info(pinfo, pi, &ei_retransmitted);
1652 }
1653 }
1654 }
1655
1656 if (coap_trans != NULL((void*)0)) {
1657 if ((code_class >= 2) && (code_class <= 5)) {
1658 /* This is a reply */
1659 if (coinfo->object_security && coap_trans->oscore_info) {
1660 pi = proto_tree_add_bytes(coap_tree, hf_coap_oscore_kid, tvb, 0, coap_trans->oscore_info->kid_len, coap_trans->oscore_info->kid);
1661 proto_item_set_generated(pi);
1662
1663 pi = proto_tree_add_bytes(coap_tree, hf_coap_oscore_kid_context, tvb, 0, coap_trans->oscore_info->kid_context_len, coap_trans->oscore_info->kid_context);
1664 proto_item_set_generated(pi);
1665
1666 if (coinfo->oscore_info->piv_len) {
1667 pi = proto_tree_add_bytes(coap_tree, hf_coap_oscore_piv, tvb, 0, coinfo->oscore_info->piv_len, coinfo->oscore_info->piv);
1668 } else {
1669 pi = proto_tree_add_bytes(coap_tree, hf_coap_oscore_piv, tvb, 0, coinfo->oscore_info->request_piv_len, coinfo->oscore_info->request_piv);
1670 }
1671 proto_item_set_generated(pi);
1672 }
1673 }
1674 }
1675
1676 if (payload_tvb) {
1677 dissect_coap_payload(payload_tvb, pinfo, coap_tree, parent_tree, 0, tvb_reported_length(payload_tvb),
1678 code_class, coinfo, &dissect_coap_hf, false0);
1679 }
1680
1681 return coap_length;
1682}
1683
1684static int
1685dissect_coap_tcp_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
1686{
1687 return dissect_coap_message(tvb, pinfo, tree, PARENT_TCP_TLS, false0);
1688}
1689
1690static int
1691dissect_coap_websockets(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
1692{
1693 return dissect_coap_message(tvb, pinfo, tree, PARENT_WEBSOCKETS, false0);
1694}
1695
1696static int
1697dissect_coap_other(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
1698{
1699 return dissect_coap_message(tvb, pinfo, tree, PARENT_OTHER, false0);
1700}
1701
1702static int
1703dissect_coap_for_tmf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
1704{
1705 return dissect_coap_message(tvb, pinfo, tree, PARENT_OTHER, true1);
1706}
1707
1708/*
1709 * Protocol initialization
1710 */
1711void
1712proto_register_coap(void)
1713{
1714 static hf_register_info hf[] = {
1715 { &hf_coap_length,
1716 { "Length", "coap.length",
1717 FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1718 "Length of the CoAP frame, combining Len and Extended Length (if any) fields", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1719 },
1720 { &hf_coap_version,
1721 { "Version", "coap.version",
1722 FT_UINT8, BASE_DEC, NULL((void*)0), COAP_VERSION_MASK0xC0,
1723 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1724 },
1725 { &hf_coap_ttype,
1726 { "Type", "coap.type",
1727 FT_UINT8, BASE_DEC, VALS(vals_ttype)((0 ? (const struct _value_string*)0 : ((vals_ttype)))), COAP_TYPE_MASK0x30,
1728 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1729 },
1730 { &hf_coap_token_len,
1731 { "Token Length", "coap.token_len",
1732 FT_UINT8, BASE_DEC, NULL((void*)0), COAP_TOKEN_LEN_MASK0x0F,
1733 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1734 },
1735 { &hf_coap_token,
1736 { "Token", "coap.token",
1737 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
1738 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1739 },
1740 { &hf_coap_mid,
1741 { "Message ID", "coap.mid",
1742 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,
1743 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1744 },
1745 { &hf_coap_response_in,
1746 { "Response In", "coap.response_in",
1747 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0,
1748 "The response to this CoAP request is in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1749 },
1750 { &hf_coap_response_to,
1751 { "Request In", "coap.response_to",
1752 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0,
1753 "This is a response to the CoAP request in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1754 },
1755 { &hf_coap_response_time,
1756 { "Response Time", "coap.response_time",
1757 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,
1758 "The time between the Call and the Reply", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1759 },
1760 { &hf_coap_request_resend_in,
1761 { "Retransmission of request in", "coap.request_first_in",
1762 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
1763 "This request was first sent in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1764 },
1765 { &hf_coap_response_resend_in,
1766 { "Retransmission of response in", "coap.response_first_in",
1767 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
1768 "This response was first sent in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1769 },
1770 { &hf_coap_oscore_kid,
1771 { "OSCORE Key ID", "coap.oscore_kid", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
1772 "Matched OSCORE Key ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1773 },
1774 { &hf_coap_oscore_kid_context,
1775 { "OSCORE Key ID Context", "coap.oscore_kid_context", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
1776 "Matched OSCORE Key ID Context", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1777 },
1778 { &hf_coap_oscore_piv,
1779 { "OSCORE Partial IV", "coap.oscore_piv", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
1780 "Matched OSCORE Partial IV", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1781 },
1782 { &hf_block_payload,
1783 { "Block Payload", "coap.block_payload",
1784 FT_BYTES, BASE_NONE, NULL((void*)0), 0x00,
1785 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1786 },
1787 { &hf_block_length,
1788 { "Block Length", "coap.block_length",
1789 FT_UINT32, BASE_DEC, NULL((void*)0), 0x00,
1790 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1791 },
1792 { &hf_blocks,
1793 { "Blocks", "coap.blocks",
1794 FT_NONE, BASE_NONE, NULL((void*)0), 0x00,
1795 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1796 },
1797 { &hf_block,
1798 { "Block", "coap.block",
1799 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00,
1800 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1801 },
1802 { &hf_block_overlap,
1803 { "Block overlap", "coap.block.overlap",
1804 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1805 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1806 },
1807 { &hf_block_overlap_conflicts,
1808 { "Block overlapping with conflicting data", "coap.block.overlap.conflicts",
1809 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1810 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1811 },
1812 { &hf_block_multiple_tails,
1813 { "Block has multiple tails", "coap.block.multiple_tails",
1814 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1815 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1816 },
1817 { &hf_block_too_long,
1818 { "Block too long", "coap.block.too_long",
1819 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1820 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1821 },
1822 { &hf_block_error,
1823 { "Block defragmentation error", "coap.block.error",
1824 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00,
1825 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1826 },
1827 { &hf_block_count,
1828 { "Block count", "coap.block.count",
1829 FT_UINT32, BASE_DEC, NULL((void*)0), 0x00,
1830 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1831 },
1832 { &hf_block_reassembled_in,
1833 { "Reassembled in", "coap.block.reassembled.in",
1834 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00,
1835 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1836 },
1837 { &hf_block_reassembled_length,
1838 { "Reassembled block length", "coap.block.reassembled.length",
1839 FT_UINT32, BASE_DEC, NULL((void*)0), 0x00,
1840 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1841 },
1842 COAP_COMMON_HF_LIST(dissect_coap_hf, "coap"){ & dissect_coap_hf .hf.code, { "Code", "coap" ".code", FT_UINT8
, BASE_DEC | 0x00000200, &coap_vals_code_ext, 0x0, ((void
*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { & dissect_coap_hf
.hf.payload, { "Payload", "coap" ".payload", FT_STRING, BASE_NONE
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { & dissect_coap_hf .hf.payload_desc, { "Payload Desc"
, "coap" ".payload_desc", FT_STRING, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.payload_length, { "Payload Length", "coap"
".payload_length", FT_UINT32, BASE_DEC, ((void*)0), 0x0, ((void
*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { & dissect_coap_hf
.hf.opt_name, { "Opt Name", "coap" ".opt.name", FT_STRING, BASE_NONE
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { & dissect_coap_hf .hf.opt_desc, { "Opt Desc"
, "coap" ".opt.desc", FT_STRING, BASE_NONE, ((void*)0), 0x0, (
(void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_delta, { "Opt Delta", "coap" ".opt.delta"
, FT_UINT8, BASE_DEC, ((void*)0), 0xf0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_delta_ext
, { "Opt Delta extended", "coap" ".opt.delta_ext", FT_UINT16,
BASE_DEC, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_length,
{ "Opt Length", "coap" ".opt.length", FT_UINT8, BASE_DEC, ((
void*)0), 0x0f, "Option Length", -1, 0, HF_REF_TYPE_NONE, -1,
((void*)0) } }, { & dissect_coap_hf .hf.opt_length_ext, {
"Opt Length extended", "coap" ".opt.length_ext", FT_UINT16, BASE_DEC
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { & dissect_coap_hf .hf.opt_end_marker, { "End of options marker"
, "coap" ".opt.end_marker", FT_UINT8, BASE_DEC, ((void*)0), 0x00
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_ctype, { "Content-type", "coap" ".opt.ctype"
, FT_STRING, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_max_age
, { "Max-age", "coap" ".opt.max_age", FT_UINT32, BASE_DEC, ((
void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0) } }, { & dissect_coap_hf .hf.opt_proxy_uri, { "Proxy-Uri"
, "coap" ".opt.proxy_uri", FT_STRING, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_proxy_scheme, { "Proxy-Scheme", "coap"
".opt.proxy_scheme", FT_STRING, BASE_NONE, ((void*)0), 0x0, (
(void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_size1, { "Size1", "coap" ".opt.size1"
, FT_UINT32, BASE_DEC, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_etag, {
"Etag", "coap" ".opt.etag", FT_BYTES, BASE_NONE, ((void*)0),
0x0, "Option Etag", -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
}, { & dissect_coap_hf .hf.opt_uri_host, { "Uri-Host", "coap"
".opt.uri_host", FT_STRING, BASE_NONE, ((void*)0), 0x0, ((void
*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { & dissect_coap_hf
.hf.opt_location_path, { "Location-Path", "coap" ".opt.location_path"
, FT_STRING, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_uri_port
, { "Uri-Port", "coap" ".opt.uri_port", FT_UINT16, BASE_DEC, (
(void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0) } }, { & dissect_coap_hf .hf.opt_location_query, { "Location-Query"
, "coap" ".opt.location_query", FT_STRING, BASE_NONE, ((void*
)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
} }, { & dissect_coap_hf .hf.opt_object_security_reserved
, { "Reserved", "coap" ".opt.object_security_reserved", FT_BOOLEAN
, 8, ((void*)0), 0xE0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -
1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_kid_context_present
, { "Key ID Context Present", "coap" ".opt.object_security_kid_context_present"
, FT_BOOLEAN, 8, ((void*)0), 0x10, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_kid_present
, { "Key ID Present", "coap" ".opt.object_security_kid_present"
, FT_BOOLEAN, 8, ((void*)0), 0x08, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_piv_len
, { "Partial IV Length", "coap" ".opt.object_security_piv_len"
, FT_UINT8, BASE_DEC, ((void*)0), 0x07, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_piv
, { "Partial IV", "coap" ".opt.object_security_piv", FT_BYTES
, BASE_NONE, ((void*)0), 0x00, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_kid_context_len
, { "Key ID Context Length", "coap" ".opt.object_security_kid_context_len"
, FT_UINT8, BASE_DEC, ((void*)0), 0x00, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_kid_context
, { "Key ID Context", "coap" ".opt.object_security_kid_context"
, FT_BYTES, BASE_NONE, ((void*)0), 0x00, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_object_security_kid
, { "Key ID", "coap" ".opt.object_security_kid", FT_BYTES, BASE_NONE
, ((void*)0), 0x00, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { & dissect_coap_hf .hf.opt_uri_path, { "Uri-Path"
, "coap" ".opt.uri_path", FT_STRING, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_uri_path_recon, { "Uri-Path", "coap"
".opt.uri_path_recon", FT_STRING, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_observe_req, { "Observe", "coap" ".opt.observe"
, FT_UINT32, BASE_DEC, ((0 ? (const struct _value_string*)0 :
((coap_vals_observe_options)))), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_observe_rsp
, { "Observe sequence number", "coap" ".opt.observe", FT_UINT32
, BASE_DEC, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_hop_limit
, { "Hop Limit", "coap" ".opt.hop_limit", FT_UINT8, BASE_DEC,
((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((
void*)0) } }, { & dissect_coap_hf .hf.opt_accept, { "Accept"
, "coap" ".opt.accept", FT_STRING, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_if_match, { "If-Match", "coap" ".opt.if_match"
, FT_BYTES, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_block_number
, { "Block Number", "coap" ".opt.block_number", FT_UINT32, BASE_DEC
, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, (
(void*)0) } }, { & dissect_coap_hf .hf.opt_block_mflag, {
"More Flag", "coap" ".opt.block_mflag", FT_UINT8, BASE_DEC, (
(void*)0), 0x08, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0) } }, { & dissect_coap_hf .hf.opt_block_size, { "Encoded Block Size"
, "coap" ".opt.block_size", FT_UINT8, BASE_DEC, ((void*)0), 0x07
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } }, { &
dissect_coap_hf .hf.opt_uri_query, { "Uri-Query", "coap" ".opt.uri_query"
, FT_STRING, BASE_NONE, ((void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0) } }, { & dissect_coap_hf .hf.opt_echo, {
"Echo", "coap" ".opt.opt_echo", FT_BYTES, BASE_NONE, ((void*
)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
} }, { & dissect_coap_hf .hf.opt_no_response, { "No-Response"
, "coap" ".opt.opt_no_response", FT_UINT8, BASE_DEC, ((void*)
0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
}, { & dissect_coap_hf .hf.opt_request_tag, { "Request-Tag"
, "coap" ".opt.opt_request_tag", FT_BYTES, BASE_NONE, ((void*
)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
} }, { & dissect_coap_hf .hf.opt_ocf_version, { "OCF-Content-Format-Version"
, "coap" ".opt.opt_ocf_version", FT_UINT8, BASE_DEC, ((void*)
0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
}, { & dissect_coap_hf .hf.opt_ocf_accept_version, { "OCF-Accept-Content-Format-Version"
, "coap" ".opt.opt_ocf_accept_version", FT_UINT8, BASE_DEC, (
(void*)0), 0x0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0) } }, { & dissect_coap_hf .hf.opt_unknown, { "Unknown"
, "coap" ".opt.unknown", FT_BYTES, BASE_NONE, ((void*)0), 0x0
, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1843 };
1844
1845 static int *ett[] = {
1846 &ett_coap,
1847 &ett_block,
1848 &ett_blocks,
1849 COAP_COMMON_ETT_LIST(dissect_coap_hf)& dissect_coap_hf .ett.payload, & dissect_coap_hf .ett
.option,
1850 };
1851
1852 static ei_register_info ei[] = {
1853 { &ei_retransmitted,
1854 { "coap.retransmitted", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
1855 "Retransmitted", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
1856 },
1857 COAP_COMMON_EI_LIST(dissect_coap_hf, "coap"){ & dissect_coap_hf .ei.opt_unknown_number, { "coap" ".unknown_option_number"
, 0x05000000, 0x00600000, "Unknown Option Number", 0, ((void*
)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}} } }, { & dissect_coap_hf .ei.opt_invalid_number, {
"coap" ".invalid_option_number", 0x07000000, 0x00600000, "Invalid Option Number"
, 0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}} } }, { & dissect_coap_hf .ei.opt_invalid_range
, { "coap" ".invalid_option_range", 0x07000000, 0x00600000, "Invalid Option Range"
, 0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}} } }, { & dissect_coap_hf .ei.opt_length_bad
, { "coap" ".option_length_bad", 0x07000000, 0x00600000, "Option length bad"
, 0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}} } }, { & dissect_coap_hf .ei.opt_object_security_bad
, { "coap" ".option_oscore_bad", 0x07000000, 0x00600000, "Invalid OSCORE Option Format"
, 0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}} } },
1858 };
1859
1860 expert_module_t *expert_coap;
1861
1862 proto_coap = proto_register_protocol("Constrained Application Protocol", "CoAP", "coap");
1863 proto_register_field_array(proto_coap, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1864 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1865 expert_coap = expert_register_protocol(proto_coap);
1866 expert_register_field_array(expert_coap, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1867
1868 reassembly_table_register (&coap_block_reassembly_table, &addresses_reassembly_table_functions);
1869
1870 coap_other_handle = register_dissector("coap", dissect_coap_other, proto_coap);
1871 coap_tcp_tls_handle = register_dissector("coap_tcp_tls", dissect_coap_tcp_tls, proto_coap);
1872 coap_for_tmf_handle = register_dissector_with_description("coap_for_tmf", "CoAP-TMF", dissect_coap_for_tmf, proto_coap_for_tmf);
1873
1874 /*
1875 * Set up a subdissector table for media types for CoAP-TMF.
1876 */
1877 coap_tmf_media_type_dissector_table =
1878 register_dissector_table("coap_tmf_media_type",
1879 "Internet media type for CoAP-TMF", proto_coap, FT_STRING, STRING_CASE_INSENSITIVE1);
1880
1881 /*
1882 * Set up a subdissector table for CoAP URI-Path.
1883 */
1884 coap_uri_path_dissector_table =
1885 register_dissector_table("coap_uri_path",
1886 "URI-Path for CoAP", proto_coap, FT_STRING, STRING_CASE_INSENSITIVE1);
1887}
1888
1889void
1890proto_reg_handoff_coap(void)
1891{
1892 dissector_handle_t coap_websockets_handle;
1893
1894 media_type_dissector_table = find_dissector_table("media_type");
1895
1896 /* UDP and DTLS */
1897 dissector_add_uint_with_preference("udp.port", DEFAULT_COAP_PORT5683, coap_other_handle);
1898 dtls_dissector_add(DEFAULT_COAPS_PORT5684, coap_other_handle);
1899
1900 /* TCP, TLS */
1901 dissector_add_uint_with_preference("tcp.port", DEFAULT_COAP_PORT5683, coap_tcp_tls_handle);
1902 ssl_dissector_add(DEFAULT_COAPS_PORT5684, coap_tcp_tls_handle);
1903 dissector_add_string("tls.alpn", "coap", coap_tcp_tls_handle);
1904
1905 /* WebSockets (RFC 8323) */
1906 coap_websockets_handle = create_dissector_handle(dissect_coap_websockets, proto_coap);
1907 dissector_add_string("ws.protocol", "coap", coap_websockets_handle);
1908
1909 /* CoAP for Thread Management Framework */
1910 dissector_add_for_decode_as("udp.port", coap_for_tmf_handle);
1911
1912 oscore_handle = find_dissector("oscore");
1913}
1914
1915/*
1916 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1917 *
1918 * Local variables:
1919 * c-basic-offset: 8
1920 * tab-width: 8
1921 * indent-tabs-mode: t
1922 * End:
1923 *
1924 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1925 * :indentSize=8:tabSize=8:noTabs=false:
1926 */