Wireshark  4.3.0
The Wireshark network protocol analyzer
packet-coap.h
1 /* packet-coap.h
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #ifndef __PACKET_COAP_H__
11 #define __PACKET_COAP_H__
12 
13 #include "packet-oscore.h"
14 
15 /* bitmasks */
16 #define COAP_VERSION_MASK 0xC0
17 #define COAP_TYPE_MASK 0x30
18 #define COAP_TOKEN_LEN_MASK 0x0F
19 #define COAP_BLOCK_MFLAG_MASK 0x08
20 #define COAP_BLOCK_SIZE_MASK 0x07
21 #define COAP_OBJECT_SECURITY_RESERVED_MASK 0xE0
22 #define COAP_OBJECT_SECURITY_KID_CONTEXT_MASK 0x10
23 #define COAP_OBJECT_SECURITY_KID_MASK 0x08
24 #define COAP_OBJECT_SECURITY_PIVLEN_MASK 0x07
25 
26 /* Parent protocol for CoAP */
27 typedef enum {
28  PARENT_WEBSOCKETS, /* WebSockets */
29  PARENT_TCP_TLS, /* TCP or TLS */
30  PARENT_OTHER /* UDP, WAP, other packet-based protocols */
31 } coap_parent_protocol;
32 
33 /* CoAP Message information */
34 typedef struct {
35  const gchar *ctype_str;
36  guint ctype_value;
37  guint block_option; /* Indicates Block1 or Block2 option */
38  guint block_number;
39  guint block_mflag;
40  wmem_strbuf_t *uri_str_strbuf; /* the maximum is 1024 > 510 = Uri-Host:255 + Uri-Path:255 x 2 */
41  wmem_strbuf_t *uri_query_strbuf; /* the maximum is 1024 > 765 = Uri-Query:255 x 3 */
42  gboolean is_coap_for_tmf; /* CoAP for Thread Management Framework */
43  gboolean object_security;
44  oscore_info_t *oscore_info; /* OSCORE data needed to decrypt */
45 } coap_info;
46 
47 /* CoAP Conversation information */
48 typedef struct {
49  wmem_map_t *messages;
51 
52 /* CoAP Transaction tracking information */
53 typedef struct {
54  wmem_map_t *req_rsp;
55  wmem_strbuf_t *uri_str_strbuf;
56  oscore_info_t *oscore_info; /* OSCORE transaction to decrypt response */
58 
59 typedef struct {
60  guint32 req_frame;
61  guint32 rsp_frame;
62  nstime_t req_time;
64 
65 /* common header fields, subtrees and expert info for SSL and DTLS dissectors */
66 typedef struct coap_common_dissect {
67  struct {
68  /* Header fields */
69  int code;
70  /* Payload fields */
71  int payload;
72  int payload_desc;
73  int payload_length;
74 
75  /* Option fields */
76  int opt_name;
77  int opt_desc;
78  int opt_delta;
79  int opt_delta_ext;
80  int opt_length;
81  int opt_length_ext;
82  int opt_end_marker;
83  int opt_ctype;
84  int opt_max_age;
85  int opt_proxy_uri;
86  int opt_proxy_scheme;
87  int opt_size1;
88  int opt_etag;
89  int opt_uri_host;
90  int opt_location_path;
91  int opt_uri_port;
92  int opt_location_query;
93  int opt_uri_path;
94  int opt_uri_path_recon;
95  int opt_observe_req;
96  int opt_observe_rsp;
97  int opt_hop_limit;
98  int opt_accept;
99  int opt_if_match;
100  int opt_block_number;
101  int opt_block_mflag;
102  int opt_block_size;
103  int opt_uri_query;
104  int opt_echo;
105  int opt_no_response;
106  int opt_request_tag;
107  int opt_ocf_version;
108  int opt_ocf_accept_version;
109  int opt_unknown;
110  int opt_object_security_reserved;
111  int opt_object_security_kid_context_present;
112  int opt_object_security_kid_present;
113  int opt_object_security_piv_len;
114  int opt_object_security_piv;
115  int opt_object_security_kid_context_len;
116  int opt_object_security_kid_context;
117  int opt_object_security_kid;
118 
119  /* do not forget to update COAP_COMMON_HF_LIST! */
120  } hf;
121 
122  struct {
123  gint payload;
124  gint option;
125 
126  /* do not forget to update COAP_COMMON_ETT_LIST! */
127  } ett;
128 
129  struct {
130  /* Generic expert info for malformed packets. */
131  expert_field opt_unknown_number;
132  expert_field opt_invalid_number;
133  expert_field opt_invalid_range;
134  expert_field opt_length_bad;
135  expert_field opt_object_security_bad;
136 
137  /* do not forget to update COAP_COMMON_EI_LIST! */
138  } ei;
140 
141 guint8 dissect_coap_code(tvbuff_t *tvb, proto_tree *coap_tree, gint *offset, coap_common_dissect_t *dissect_hf, guint8 *code_class);
142 int dissect_coap_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *coap_tree, gint offset, gint offset_end, guint8 code_class, coap_info *coinfo, coap_common_dissect_t *dissect_hf);
143 void dissect_coap_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *coap_tree, proto_tree *parent_tree, gint offset, gint offset_end, guint8 code_class, coap_info *coinfo, coap_common_dissect_t *dissect_hf, gboolean oscore);
144 
145 extern const value_string coap_vals_observe_options[];
146 extern value_string_ext coap_vals_code_ext;
147 
148 /* {{{ */
149 #define COAP_COMMON_LIST_T(name) \
150 coap_common_dissect_t name;
151 /* }}} */
152 
153 /* {{{ */
154 #define COAP_COMMON_HF_LIST(name, prefix) \
155  { & name .hf.code, \
156  { "Code", prefix ".code", \
157  FT_UINT8, BASE_DEC | BASE_EXT_STRING, &coap_vals_code_ext, 0x0, \
158  NULL, HFILL } \
159  }, \
160  { & name .hf.payload, \
161  { "Payload", prefix ".payload", \
162  FT_STRING, BASE_NONE, NULL, 0x0, \
163  NULL, HFILL } \
164  }, \
165  { & name .hf.payload_desc, \
166  { "Payload Desc", prefix ".payload_desc", \
167  FT_STRING, BASE_NONE, NULL, 0x0, \
168  NULL, HFILL } \
169  }, \
170  { & name .hf.payload_length, \
171  { "Payload Length", prefix ".payload_length", \
172  FT_UINT32, BASE_DEC, NULL, 0x0, \
173  NULL, HFILL } \
174  }, \
175  { & name .hf.opt_name, \
176  { "Opt Name", prefix ".opt.name", \
177  FT_STRING, BASE_NONE, NULL, 0x0, \
178  NULL, HFILL } \
179  }, \
180  { & name .hf.opt_desc, \
181  { "Opt Desc", prefix ".opt.desc", \
182  FT_STRING, BASE_NONE, NULL, 0x0, \
183  NULL, HFILL } \
184  }, \
185  { & name .hf.opt_delta, \
186  { "Opt Delta", prefix ".opt.delta", \
187  FT_UINT8, BASE_DEC, NULL, 0xf0, \
188  NULL, HFILL } \
189  }, \
190  { & name .hf.opt_delta_ext, \
191  { "Opt Delta extended", prefix ".opt.delta_ext", \
192  FT_UINT16, BASE_DEC, NULL, 0x0, \
193  NULL, HFILL } \
194  }, \
195  { & name .hf.opt_length, \
196  { "Opt Length", prefix ".opt.length", \
197  FT_UINT8, BASE_DEC, NULL, 0x0f, \
198  "Option Length", HFILL } \
199  }, \
200  { & name .hf.opt_length_ext, \
201  { "Opt Length extended", prefix ".opt.length_ext", \
202  FT_UINT16, BASE_DEC, NULL, 0x0, \
203  NULL, HFILL } \
204  }, \
205  { & name .hf.opt_end_marker, \
206  { "End of options marker", prefix ".opt.end_marker", \
207  FT_UINT8, BASE_DEC, NULL, 0x00, \
208  NULL, HFILL } \
209  }, \
210  { & name .hf.opt_ctype, \
211  { "Content-type", prefix ".opt.ctype", \
212  FT_STRING, BASE_NONE, NULL, 0x0, \
213  NULL, HFILL } \
214  }, \
215  { & name .hf.opt_max_age, \
216  { "Max-age", prefix ".opt.max_age", \
217  FT_UINT32, BASE_DEC, NULL, 0x0, \
218  NULL, HFILL } \
219  }, \
220  { & name .hf.opt_proxy_uri, \
221  { "Proxy-Uri", prefix ".opt.proxy_uri", \
222  FT_STRING, BASE_NONE, NULL, 0x0, \
223  NULL, HFILL } \
224  }, \
225  { & name .hf.opt_proxy_scheme, \
226  { "Proxy-Scheme", prefix ".opt.proxy_scheme", \
227  FT_STRING, BASE_NONE, NULL, 0x0, \
228  NULL, HFILL } \
229  }, \
230  { & name .hf.opt_size1, \
231  { "Size1", prefix ".opt.size1", \
232  FT_UINT32, BASE_DEC, NULL, 0x0, \
233  NULL, HFILL } \
234  }, \
235  { & name .hf.opt_etag, \
236  { "Etag", prefix ".opt.etag", \
237  FT_BYTES, BASE_NONE, NULL, 0x0, \
238  "Option Etag", HFILL } \
239  }, \
240  { & name .hf.opt_uri_host, \
241  { "Uri-Host", prefix ".opt.uri_host", \
242  FT_STRING, BASE_NONE, NULL, 0x0, \
243  NULL, HFILL } \
244  }, \
245  { & name .hf.opt_location_path, \
246  { "Location-Path", prefix ".opt.location_path", \
247  FT_STRING, BASE_NONE, NULL, 0x0, \
248  NULL, HFILL } \
249  }, \
250  { & name .hf.opt_uri_port, \
251  { "Uri-Port", prefix ".opt.uri_port", \
252  FT_UINT16, BASE_DEC, NULL, 0x0, \
253  NULL, HFILL } \
254  }, \
255  { & name .hf.opt_location_query, \
256  { "Location-Query", prefix ".opt.location_query", \
257  FT_STRING, BASE_NONE, NULL, 0x0, \
258  NULL, HFILL } \
259  }, \
260  { & name .hf.opt_object_security_reserved, \
261  { "Reserved", prefix ".opt.object_security_reserved", \
262  FT_BOOLEAN, 8, NULL, COAP_OBJECT_SECURITY_RESERVED_MASK, \
263  NULL, HFILL } \
264  }, \
265  { & name .hf.opt_object_security_kid_context_present, \
266  { "Key ID Context Present", prefix ".opt.object_security_kid_context_present",\
267  FT_BOOLEAN, 8, NULL, COAP_OBJECT_SECURITY_KID_CONTEXT_MASK, \
268  NULL, HFILL } \
269  }, \
270  { & name .hf.opt_object_security_kid_present, \
271  { "Key ID Present", prefix ".opt.object_security_kid_present", \
272  FT_BOOLEAN, 8, NULL, COAP_OBJECT_SECURITY_KID_MASK, \
273  NULL, HFILL } \
274  }, \
275  { & name .hf.opt_object_security_piv_len, \
276  { "Partial IV Length", prefix ".opt.object_security_piv_len", \
277  FT_UINT8, BASE_DEC, NULL, COAP_OBJECT_SECURITY_PIVLEN_MASK, \
278  NULL, HFILL } \
279  }, \
280  { & name .hf.opt_object_security_piv, \
281  { "Partial IV", prefix ".opt.object_security_piv", \
282  FT_BYTES, BASE_NONE, NULL, 0x00, \
283  NULL, HFILL } \
284  }, \
285  { & name .hf.opt_object_security_kid_context_len, \
286  { "Key ID Context Length", prefix ".opt.object_security_kid_context_len",\
287  FT_UINT8, BASE_DEC, NULL, 0x00, \
288  NULL, HFILL } \
289  }, \
290  { & name .hf.opt_object_security_kid_context, \
291  { "Key ID Context", prefix ".opt.object_security_kid_context", \
292  FT_BYTES, BASE_NONE, NULL, 0x00, \
293  NULL, HFILL } \
294  }, \
295  { & name .hf.opt_object_security_kid, \
296  { "Key ID", prefix ".opt.object_security_kid", \
297  FT_BYTES, BASE_NONE, NULL, 0x00, \
298  NULL, HFILL } \
299  }, \
300  { & name .hf.opt_uri_path, \
301  { "Uri-Path", prefix ".opt.uri_path", \
302  FT_STRING, BASE_NONE, NULL, 0x0, \
303  NULL, HFILL } \
304  }, \
305  { & name .hf.opt_uri_path_recon, \
306  { "Uri-Path", prefix ".opt.uri_path_recon", \
307  FT_STRING, BASE_NONE, NULL, 0x0, \
308  NULL, HFILL } \
309  }, \
310  { & name .hf.opt_observe_req, \
311  { "Observe", prefix ".opt.observe", \
312  FT_UINT32, BASE_DEC, VALS(coap_vals_observe_options), 0x0, \
313  NULL, HFILL } \
314  }, \
315  { & name .hf.opt_observe_rsp, \
316  { "Observe sequence number", prefix ".opt.observe", \
317  FT_UINT32, BASE_DEC, NULL, 0x0, \
318  NULL, HFILL } \
319  }, \
320  { & name .hf.opt_hop_limit, \
321  { "Hop Limit", prefix ".opt.hop_limit", \
322  FT_UINT8, BASE_DEC, NULL, 0x0, \
323  NULL, HFILL } \
324  }, \
325  { & name .hf.opt_accept, \
326  { "Accept", prefix ".opt.accept", \
327  FT_STRING, BASE_NONE, NULL, 0x0, \
328  NULL, HFILL } \
329  }, \
330  { & name .hf.opt_if_match, \
331  { "If-Match", prefix ".opt.if_match", \
332  FT_BYTES, BASE_NONE, NULL, 0x0, \
333  NULL, HFILL } \
334  }, \
335  { & name .hf.opt_block_number, \
336  { "Block Number", prefix ".opt.block_number", \
337  FT_UINT32, BASE_DEC, NULL, 0x0, \
338  NULL, HFILL } \
339  }, \
340  { & name .hf.opt_block_mflag, \
341  { "More Flag", prefix ".opt.block_mflag", \
342  FT_UINT8, BASE_DEC, NULL, COAP_BLOCK_MFLAG_MASK, \
343  NULL, HFILL } \
344  }, \
345  { & name .hf.opt_block_size, \
346  { "Encoded Block Size", prefix ".opt.block_size", \
347  FT_UINT8, BASE_DEC, NULL, COAP_BLOCK_SIZE_MASK, \
348  NULL, HFILL } \
349  }, \
350  { & name .hf.opt_uri_query, \
351  { "Uri-Query", prefix ".opt.uri_query", \
352  FT_STRING, BASE_NONE, NULL, 0x0, \
353  NULL, HFILL } \
354  }, \
355  { & name .hf.opt_echo, \
356  { "Echo", prefix ".opt.opt_echo", \
357  FT_BYTES, BASE_NONE, NULL, 0x0, \
358  NULL, HFILL } \
359  }, \
360  { & name .hf.opt_no_response, \
361  { "No-Response", prefix ".opt.opt_no_response", \
362  FT_UINT8, BASE_DEC, NULL, 0x0, \
363  NULL, HFILL } \
364  }, \
365  { & name .hf.opt_request_tag, \
366  { "Request-Tag", prefix ".opt.opt_request_tag", \
367  FT_BYTES, BASE_NONE, NULL, 0x0, \
368  NULL, HFILL } \
369  }, \
370  { & name .hf.opt_ocf_version, \
371  { "OCF-Content-Format-Version", \
372  prefix ".opt.opt_ocf_version", \
373  FT_UINT8, BASE_DEC, NULL, 0x0, \
374  NULL, HFILL } \
375  }, \
376  { & name .hf.opt_ocf_accept_version, \
377  { "OCF-Accept-Content-Format-Version", \
378  prefix ".opt.opt_ocf_accept_version", \
379  FT_UINT8, BASE_DEC, NULL, 0x0, \
380  NULL, HFILL } \
381  }, \
382  { & name .hf.opt_unknown, \
383  { "Unknown", prefix ".opt.unknown", \
384  FT_BYTES, BASE_NONE, NULL, 0x0, \
385  NULL, HFILL } \
386  }, \
387 /* }}} */
388 
389 /* {{{ */
390 #define COAP_COMMON_ETT_LIST(name) \
391  & name .ett.payload, \
392  & name .ett.option, \
393 
394 /* }}} */
395 
396 /* {{{ */
397 #define COAP_COMMON_EI_LIST(name, prefix) \
398  { & name .ei.opt_unknown_number, \
399  { prefix ".unknown_option_number", PI_UNDECODED, PI_WARN, \
400  "Unknown Option Number", EXPFILL } \
401  }, \
402  { & name .ei.opt_invalid_number, \
403  { prefix ".invalid_option_number", PI_MALFORMED, PI_WARN, \
404  "Invalid Option Number", EXPFILL } \
405  }, \
406  { & name .ei.opt_invalid_range, \
407  { prefix ".invalid_option_range", PI_MALFORMED, PI_WARN, \
408  "Invalid Option Range", EXPFILL } \
409  }, \
410  { & name .ei.opt_length_bad, \
411  { prefix ".option_length_bad", PI_MALFORMED, PI_WARN, \
412  "Option length bad", EXPFILL } \
413  }, \
414  { & name .ei.opt_object_security_bad, \
415  { prefix ".option_oscore_bad", PI_MALFORMED, PI_WARN, \
416  "Invalid OSCORE Option Format", EXPFILL } \
417  }, \
418 
419 /* }}} */
420 
421 #endif /* __PACKET_COAP_H__ */
422 
423 /*
424  * Editor modelines - https://www.wireshark.org/tools/modelines.html
425  *
426  * Local variables:
427  * c-basic-offset: 8
428  * tab-width: 8
429  * indent-tabs-mode: t
430  * End:
431  *
432  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
433  * :indentSize=8:tabSize=8:noTabs=false:
434  */
Definition: packet_info.h:44
Definition: proto.h:904
Definition: value_string.h:170
Definition: value_string.h:26
Definition: wmem_map.c:44
Definition: wmem_strbuf.h:42
Definition: packet-coap.h:66
Definition: packet-coap.h:48
Definition: packet-coap.h:34
Definition: packet-coap.h:59
Definition: packet-coap.h:53
Definition: expert.h:39
Definition: nstime.h:26
Definition: packet-oscore.h:51
Definition: tvbuff-int.h:35