/src/wireshark/epan/dissectors/packet-bpsec.c
Line | Count | Source |
1 | | /* packet-bpsec.c |
2 | | * Routines for Bundle Protocol Version 7 Security (BPSec) dissection |
3 | | * References: |
4 | | * RFC 9172: https://www.rfc-editor.org/rfc/rfc9172.html |
5 | | * |
6 | | * Copyright 2019-2024, Brian Sipos <brian.sipos@gmail.com> |
7 | | * |
8 | | * Wireshark - Network traffic analyzer |
9 | | * By Gerald Combs <gerald@wireshark.org> |
10 | | * Copyright 1998 Gerald Combs |
11 | | * |
12 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
13 | | */ |
14 | | #include "config.h" |
15 | | #include <stdint.h> |
16 | | |
17 | | #include "packet-bpsec.h" |
18 | | #include <epan/packet.h> |
19 | | #include <epan/prefs.h> |
20 | | #include <epan/proto.h> |
21 | | #include <epan/expert.h> |
22 | | #include <epan/tfs.h> |
23 | | #include <epan/wscbor.h> |
24 | | |
25 | | void proto_register_bpsec(void); |
26 | | void proto_reg_handoff_bpsec(void); |
27 | | |
28 | | /// Protocol handles |
29 | | static int proto_bpsec; |
30 | | |
31 | | /// Dissect opaque CBOR data |
32 | | static dissector_handle_t handle_cbor; |
33 | | /// Context ID sub-dissectors |
34 | | static dissector_table_t secctx_dissectors; |
35 | | /// Parameter value sub-dissectors |
36 | | static dissector_table_t param_dissectors; |
37 | | /// Result value sub-dissectors |
38 | | static dissector_table_t result_dissectors; |
39 | | |
40 | | // Field definitions |
41 | | static int hf_bib; |
42 | | static int hf_bcb; |
43 | | static int hf_asb_target_list; |
44 | | static int hf_asb_target; |
45 | | static int hf_asb_ctxid; |
46 | | static int hf_asb_flags; |
47 | | static int hf_asb_flags_has_params; |
48 | | static int hf_asb_secsrc_nodeid; |
49 | | static int hf_asb_secsrc_uri; |
50 | | static int hf_asb_param_list; |
51 | | static int hf_asb_param_pair; |
52 | | static int hf_asb_param_id; |
53 | | static int hf_asb_result_all_list; |
54 | | static int hf_asb_result_tgt_list; |
55 | | static int hf_asb_result_tgt_ref; |
56 | | static int hf_asb_result_pair; |
57 | | static int hf_asb_result_id; |
58 | | |
59 | | static int *const asb_flags[] = { |
60 | | &hf_asb_flags_has_params, |
61 | | NULL |
62 | | }; |
63 | | |
64 | | // Tree structures |
65 | | static int ett_asb; |
66 | | static int ett_asb_flags; |
67 | | static int ett_tgt_list; |
68 | | static int ett_param_list; |
69 | | static int ett_param_pair; |
70 | | static int ett_result_all_list; |
71 | | static int ett_result_tgt_list; |
72 | | static int ett_result_pair; |
73 | | |
74 | | static expert_field ei_secsrc_diff; |
75 | | static expert_field ei_ctxid_zero; |
76 | | static expert_field ei_ctxid_priv; |
77 | | static expert_field ei_target_invalid; |
78 | | static expert_field ei_value_partial_decode; |
79 | | |
80 | 144 | bpsec_id_t * bpsec_id_new(wmem_allocator_t *alloc, int64_t context_id, int64_t type_id) { |
81 | 144 | bpsec_id_t *obj; |
82 | 144 | if (alloc) { |
83 | 0 | obj = wmem_new(alloc, bpsec_id_t); |
84 | 0 | } |
85 | 144 | else { |
86 | 144 | obj = g_new(bpsec_id_t, 1); |
87 | 144 | } |
88 | 144 | obj->context_id = context_id; |
89 | 144 | obj->type_id = type_id; |
90 | 144 | return obj; |
91 | 144 | } |
92 | | |
93 | 192 | static gboolean bpsec_id_equal(const void *a, const void *b) { |
94 | 192 | const bpsec_id_t *aobj = a; |
95 | 192 | const bpsec_id_t *bobj = b; |
96 | 192 | return ( |
97 | 192 | aobj && bobj |
98 | 192 | && (aobj->context_id == bobj->context_id) |
99 | 32 | && (aobj->type_id == bobj->type_id) |
100 | 192 | ); |
101 | 192 | } |
102 | | |
103 | 288 | static unsigned bpsec_id_hash(const void *key) { |
104 | 288 | const bpsec_id_t *obj = key; |
105 | 288 | return ( |
106 | 288 | g_int64_hash(&(obj->context_id)) |
107 | 288 | ^ g_int64_hash(&(obj->type_id)) |
108 | 288 | ); |
109 | 288 | } |
110 | | |
111 | | /** Dissect an ID-value pair within a context. |
112 | | * |
113 | | */ |
114 | 0 | static int dissect_value(dissector_handle_t dissector, bpsec_dissector_data_t *const data, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { |
115 | 0 | int sublen = 0; |
116 | 0 | if (dissector) { |
117 | 0 | sublen = call_dissector_with_data(dissector, tvb, pinfo, tree, data); |
118 | 0 | if ((sublen < 0) || ((unsigned)sublen < tvb_captured_length(tvb))) { |
119 | 0 | expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_value_partial_decode); |
120 | 0 | } |
121 | 0 | } |
122 | 0 | if (sublen == 0) { |
123 | 0 | sublen = call_dissector(handle_cbor, tvb, pinfo, tree); |
124 | 0 | } |
125 | 0 | return sublen; |
126 | 0 | } |
127 | | |
128 | | /** Dissector for abstract security block structure. |
129 | | */ |
130 | 3 | static int dissect_block_asb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const bp_dissector_data_t *const data, int root_hfindex) { |
131 | 3 | proto_item *item_asb = proto_tree_add_item(tree, root_hfindex, tvb, 0, -1, ENC_NA); |
132 | 3 | proto_tree *tree_asb = proto_item_add_subtree(item_asb, ett_asb); |
133 | 3 | int offset = 0; |
134 | | |
135 | 3 | wmem_array_t *targets; |
136 | 3 | targets = wmem_array_new(pinfo->pool, sizeof(uint64_t)); |
137 | | |
138 | 3 | wscbor_chunk_t *chunk_tgt_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
139 | 3 | wscbor_require_array(chunk_tgt_list); |
140 | 3 | proto_item *item_tgt_list = proto_tree_add_cbor_container(tree_asb, hf_asb_target_list, pinfo, tvb, chunk_tgt_list); |
141 | 3 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_tgt_list)) { |
142 | 0 | proto_tree *tree_tgt_list = proto_item_add_subtree(item_tgt_list, ett_tgt_list); |
143 | | |
144 | | // iterate all targets |
145 | 0 | for (uint64_t param_ix = 0; param_ix < chunk_tgt_list->head_value; ++param_ix) { |
146 | 0 | wscbor_chunk_t *chunk_tgt = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
147 | 0 | uint64_t *tgt_blknum = wscbor_require_uint64(pinfo->pool, chunk_tgt); |
148 | 0 | proto_item *item_tgt = proto_tree_add_cbor_uint64(tree_tgt_list, hf_asb_target, pinfo, tvb, chunk_tgt, tgt_blknum); |
149 | 0 | if (tgt_blknum) { |
150 | 0 | wmem_array_append(targets, tgt_blknum, 1); |
151 | |
|
152 | 0 | wmem_map_t *map = NULL; |
153 | 0 | if (*tgt_blknum == 0) { |
154 | 0 | map = (root_hfindex == hf_bib) |
155 | 0 | ? data->bundle->primary->sec.data_i |
156 | 0 | : data->bundle->primary->sec.data_c; |
157 | 0 | } |
158 | 0 | else { |
159 | 0 | bp_block_canonical_t *found = wmem_map_lookup(data->bundle->block_nums, tgt_blknum); |
160 | 0 | if (found) { |
161 | 0 | map = (root_hfindex == hf_bib) |
162 | 0 | ? found->sec.data_i |
163 | 0 | : found->sec.data_c; |
164 | 0 | } |
165 | 0 | else { |
166 | 0 | expert_add_info(pinfo, item_tgt, &ei_target_invalid); |
167 | 0 | } |
168 | 0 | } |
169 | 0 | if (map && (data->block->block_number)) { |
170 | 0 | wmem_map_insert( |
171 | 0 | map, |
172 | 0 | data->block->block_number, |
173 | 0 | NULL |
174 | 0 | ); |
175 | 0 | } |
176 | 0 | } |
177 | 0 | } |
178 | |
|
179 | 0 | proto_item_set_len(item_tgt_list, offset - chunk_tgt_list->start); |
180 | 0 | } |
181 | | |
182 | 3 | wscbor_chunk_t *chunk_ctxid = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
183 | 3 | int64_t *ctxid = wscbor_require_int64(pinfo->pool, chunk_ctxid); |
184 | 3 | proto_item *item_ctxid = proto_tree_add_cbor_int64(tree_asb, hf_asb_ctxid, pinfo, tvb, chunk_ctxid, ctxid); |
185 | 3 | if (ctxid && item_ctxid) { |
186 | 3 | if (*ctxid == 0) { |
187 | 2 | expert_add_info(pinfo, item_ctxid, &ei_ctxid_zero); |
188 | 2 | } |
189 | 1 | else if (*ctxid < 0) { |
190 | 0 | expert_add_info(pinfo, item_ctxid, &ei_ctxid_priv); |
191 | 0 | } |
192 | | |
193 | | // apply label if registered |
194 | 3 | dissector_handle_t ctx_dis = dissector_get_custom_table_handle(secctx_dissectors, ctxid); |
195 | 3 | const char *dis_name = dissector_handle_get_description(ctx_dis); |
196 | 3 | if (dis_name) { |
197 | 0 | const header_field_info *hfinfo = PITEM_HFINFO(item_ctxid); |
198 | 0 | proto_item_set_text(item_ctxid, "%s: %s (%" PRId64 ")", hfinfo ? hfinfo->name : NULL, dis_name, *ctxid); |
199 | 0 | } |
200 | 3 | } |
201 | | |
202 | 3 | wscbor_chunk_t *chunk_flags = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
203 | 3 | uint64_t *flags = wscbor_require_uint64(pinfo->pool, chunk_flags); |
204 | 3 | proto_tree_add_cbor_bitmask(tree_asb, hf_asb_flags, ett_asb_flags, asb_flags, pinfo, tvb, chunk_flags, flags); |
205 | | |
206 | 3 | { |
207 | 3 | bp_eid_t *secsrc = bp_eid_new(pinfo->pool); |
208 | 3 | proto_item *item_secsrc = proto_tree_add_cbor_eid(tree_asb, hf_asb_secsrc_nodeid, hf_asb_secsrc_uri, pinfo, tvb, &offset, secsrc); |
209 | 3 | if (!bp_eid_equal(data->bundle->primary->src_nodeid, secsrc)) { |
210 | 0 | expert_add_info(pinfo, item_secsrc, &ei_secsrc_diff); |
211 | 0 | } |
212 | 3 | } |
213 | | |
214 | 3 | if (flags && (*flags & BPSEC_ASB_HAS_PARAMS)) { |
215 | 0 | wscbor_chunk_t *chunk_param_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
216 | 0 | wscbor_require_array(chunk_param_list); |
217 | 0 | proto_item *item_param_list = proto_tree_add_cbor_container(tree_asb, hf_asb_param_list, pinfo, tvb, chunk_param_list); |
218 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_param_list)) { |
219 | 0 | proto_tree *tree_param_list = proto_item_add_subtree(item_param_list, ett_param_list); |
220 | | |
221 | | // iterate all parameters |
222 | 0 | for (uint64_t param_ix = 0; param_ix < chunk_param_list->head_value; ++param_ix) { |
223 | 0 | wscbor_chunk_t *chunk_param_pair = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
224 | 0 | wscbor_require_array_size(chunk_param_pair, 2, 2); |
225 | 0 | proto_item *item_param_pair = proto_tree_add_cbor_container(tree_param_list, hf_asb_param_pair, pinfo, tvb, chunk_param_pair); |
226 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_param_pair)) { |
227 | 0 | proto_tree *tree_param_pair = proto_item_add_subtree(item_param_pair, ett_param_pair); |
228 | |
|
229 | 0 | wscbor_chunk_t *chunk_paramid = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
230 | 0 | int64_t *paramid = wscbor_require_int64(pinfo->pool, chunk_paramid); |
231 | 0 | proto_tree_add_cbor_int64(tree_param_pair, hf_asb_param_id, pinfo, tvb, chunk_paramid, paramid); |
232 | |
|
233 | 0 | const int offset_value = offset; |
234 | 0 | if (!wscbor_skip_next_item(pinfo->pool, tvb, &offset)) { |
235 | 0 | return 0; |
236 | 0 | } |
237 | 0 | tvbuff_t *tvb_value = tvb_new_subset_length(tvb, offset_value, offset - offset_value); |
238 | |
|
239 | 0 | bpsec_dissector_data_t bpsec_data = { .bp = data }; |
240 | 0 | dissector_handle_t value_dissect = NULL; |
241 | 0 | if (ctxid && paramid) { |
242 | 0 | bpsec_data.id.context_id = *ctxid; |
243 | 0 | bpsec_data.id.type_id = *paramid; |
244 | 0 | value_dissect = dissector_get_custom_table_handle(param_dissectors, &(bpsec_data.id)); |
245 | 0 | } |
246 | 0 | const char *dis_name = dissector_handle_get_description(value_dissect); |
247 | 0 | if (paramid) { |
248 | 0 | proto_item_append_text(item_param_pair, ": %s (%" PRId64 ")", dis_name, *paramid); |
249 | 0 | } |
250 | 0 | dissect_value(value_dissect, &bpsec_data, tvb_value, pinfo, tree_param_pair); |
251 | |
|
252 | 0 | proto_item_set_len(item_param_pair, offset - chunk_param_pair->start); |
253 | 0 | } |
254 | 0 | } |
255 | | |
256 | 0 | proto_item_set_len(item_param_list, offset - chunk_param_list->start); |
257 | 0 | } |
258 | 0 | } |
259 | | |
260 | | // array sizes should agree |
261 | 3 | const unsigned tgt_size = wmem_array_get_count(targets); |
262 | | |
263 | 3 | wscbor_chunk_t *chunk_result_all_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
264 | 3 | wscbor_require_array_size(chunk_result_all_list, tgt_size, tgt_size); |
265 | 3 | proto_item *item_result_all_list = proto_tree_add_cbor_container(tree_asb, hf_asb_result_all_list, pinfo, tvb, chunk_result_all_list); |
266 | 3 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_result_all_list)) { |
267 | 0 | proto_tree *tree_result_all_list = proto_item_add_subtree(item_result_all_list, ett_result_all_list); |
268 | | |
269 | | // iterate each target's results |
270 | 0 | for (unsigned tgt_ix = 0; tgt_ix < tgt_size; ++tgt_ix) { |
271 | 0 | wscbor_chunk_t *chunk_result_tgt_list = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
272 | 0 | wscbor_require_array(chunk_result_tgt_list); |
273 | 0 | proto_item *item_result_tgt_list = proto_tree_add_cbor_container(tree_result_all_list, hf_asb_result_tgt_list, pinfo, tvb, chunk_result_tgt_list); |
274 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_result_tgt_list)) { |
275 | 0 | proto_tree *tree_result_tgt_list = proto_item_add_subtree(item_result_tgt_list, ett_result_tgt_list); |
276 | | |
277 | | // Hint at the associated target number |
278 | 0 | if (tgt_ix < tgt_size) { |
279 | 0 | const uint64_t *tgt_blknum = wmem_array_index(targets, tgt_ix); |
280 | 0 | proto_item *item_tgt_blknum = proto_tree_add_uint64(tree_result_tgt_list, hf_asb_result_tgt_ref, tvb, 0, 0, *tgt_blknum); |
281 | 0 | proto_item_set_generated(item_tgt_blknum); |
282 | 0 | } |
283 | | |
284 | | // iterate all results for this target |
285 | 0 | for (uint64_t result_ix = 0; result_ix < chunk_result_tgt_list->head_value; ++result_ix) { |
286 | 0 | wscbor_chunk_t *chunk_result_pair = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
287 | 0 | wscbor_require_array_size(chunk_result_pair, 2, 2); |
288 | 0 | proto_item *item_result_pair = proto_tree_add_cbor_container(tree_result_tgt_list, hf_asb_result_pair, pinfo, tvb, chunk_result_pair); |
289 | 0 | if (!wscbor_skip_if_errors(pinfo->pool, tvb, &offset, chunk_result_pair)) { |
290 | 0 | proto_tree *tree_result_pair = proto_item_add_subtree(item_result_pair, ett_result_pair); |
291 | |
|
292 | 0 | wscbor_chunk_t *chunk_resultid = wscbor_chunk_read(pinfo->pool, tvb, &offset); |
293 | 0 | int64_t *resultid = wscbor_require_int64(pinfo->pool, chunk_resultid); |
294 | 0 | proto_tree_add_cbor_int64(tree_result_pair, hf_asb_result_id, pinfo, tvb, chunk_resultid, resultid); |
295 | |
|
296 | 0 | const int offset_value = offset; |
297 | 0 | if (!wscbor_skip_next_item(pinfo->pool, tvb, &offset)) { |
298 | 0 | return 0; |
299 | 0 | } |
300 | 0 | tvbuff_t *tvb_value = tvb_new_subset_length(tvb, offset_value, offset - offset_value); |
301 | |
|
302 | 0 | bpsec_dissector_data_t bpsec_data = { .bp = data }; |
303 | 0 | dissector_handle_t value_dissect = NULL; |
304 | 0 | if (ctxid && resultid) { |
305 | 0 | bpsec_data.id.context_id = *ctxid; |
306 | 0 | bpsec_data.id.type_id = *resultid; |
307 | 0 | value_dissect = dissector_get_custom_table_handle(result_dissectors, &(bpsec_data.id)); |
308 | 0 | } |
309 | 0 | const char *dis_name = dissector_handle_get_description(value_dissect); |
310 | 0 | if (resultid) { |
311 | 0 | proto_item_append_text(item_result_pair, ": %s (%" PRId64 ")", dis_name, *resultid); |
312 | 0 | } |
313 | 0 | dissect_value(value_dissect, &bpsec_data, tvb_value, pinfo, tree_result_pair); |
314 | |
|
315 | 0 | proto_item_set_len(item_result_pair, offset - chunk_result_pair->start); |
316 | 0 | } |
317 | 0 | } |
318 | | |
319 | 0 | proto_item_set_len(item_result_tgt_list, offset - chunk_result_tgt_list->start); |
320 | 0 | } |
321 | 0 | } |
322 | | |
323 | 0 | proto_item_set_len(item_result_all_list, offset - chunk_result_all_list->start); |
324 | 0 | } |
325 | | |
326 | 3 | proto_item_set_len(item_asb, offset); |
327 | 3 | return offset; |
328 | 3 | } |
329 | | |
330 | | /** Dissector for Bundle Integrity block. |
331 | | */ |
332 | 3 | static int dissect_block_bib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
333 | 3 | return dissect_block_asb(tvb, pinfo, tree, (bp_dissector_data_t *)data, hf_bib); |
334 | 3 | } |
335 | | |
336 | | /** Dissector for Bundle Confidentiality block. |
337 | | */ |
338 | 0 | static int dissect_block_bcb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { |
339 | 0 | return dissect_block_asb(tvb, pinfo, tree, (bp_dissector_data_t *)data, hf_bcb); |
340 | 0 | } |
341 | | |
342 | | /// Re-initialize after a configuration change |
343 | 16 | static void reinit_bpsec(void) { |
344 | 16 | } |
345 | | |
346 | | /// Overall registration of the protocol |
347 | 16 | void proto_register_bpsec(void) { |
348 | 16 | static hf_register_info fields[] = { |
349 | 16 | {&hf_bib, {"BPSec Block Integrity Block", "bpsec.bib", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
350 | 16 | {&hf_bcb, {"BPSec Block Confidentiality Block", "bpsec.bcb", FT_PROTOCOL, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
351 | 16 | {&hf_asb_target_list, {"Security Targets, Count", "bpsec.asb.target_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
352 | 16 | {&hf_asb_target, {"Target Block Number", "bpsec.asb.target", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
353 | 16 | {&hf_asb_ctxid, {"Context ID", "bpsec.asb.ctxid", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
354 | 16 | {&hf_asb_flags, {"Flags", "bpsec.asb.flags", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}}, |
355 | 16 | {&hf_asb_flags_has_params, {"Parameters Present", "bpsec.asb.flags.has_params", FT_BOOLEAN, 8, TFS(&tfs_set_notset), BPSEC_ASB_HAS_PARAMS, NULL, HFILL}}, |
356 | 16 | {&hf_asb_secsrc_nodeid, {"Security Source", "bpsec.asb.secsrc.nodeid", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
357 | 16 | {&hf_asb_secsrc_uri, {"Security Source URI", "bpsec.asb.secsrc.uri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
358 | 16 | {&hf_asb_param_list, {"Security Parameters, Count", "bpsec.asb.param_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
359 | 16 | {&hf_asb_param_pair, {"Parameter", "bpsec.asb.param", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
360 | 16 | {&hf_asb_param_id, {"Type ID", "bpsec.asb.param.id", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
361 | 16 | {&hf_asb_result_all_list, {"Security Result Targets, Count", "bpsec.asb.result_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
362 | 16 | {&hf_asb_result_tgt_ref, {"Associated Target Block Number", "bpsec.asb.result_tgt_ref", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
363 | 16 | {&hf_asb_result_tgt_list, {"Security Results, Count", "bpsec.asb.result_count", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
364 | 16 | {&hf_asb_result_pair, {"Result", "bpsec.asb.result", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}}, |
365 | 16 | {&hf_asb_result_id, {"Type ID", "bpsec.asb.result.id", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}}, |
366 | 16 | }; |
367 | 16 | static int *ett[] = { |
368 | 16 | &ett_asb, |
369 | 16 | &ett_asb_flags, |
370 | 16 | &ett_tgt_list, |
371 | 16 | &ett_param_list, |
372 | 16 | &ett_param_pair, |
373 | 16 | &ett_result_all_list, |
374 | 16 | &ett_result_tgt_list, |
375 | 16 | &ett_result_pair, |
376 | 16 | }; |
377 | 16 | static ei_register_info expertitems[] = { |
378 | 16 | {&ei_secsrc_diff, {"bpsec.secsrc_diff", PI_SECURITY, PI_CHAT, "BPSec Security Source different from bundle Source", EXPFILL}}, |
379 | 16 | {&ei_ctxid_zero, {"bpsec.ctxid_zero", PI_SECURITY, PI_WARN, "BPSec Security Context ID zero is reserved", EXPFILL}}, |
380 | 16 | {&ei_ctxid_priv, {"bpsec.ctxid_priv", PI_SECURITY, PI_NOTE, "BPSec Security Context ID from private/experimental block", EXPFILL}}, |
381 | 16 | {&ei_target_invalid, {"bpsec.target_invalid", PI_PROTOCOL, PI_WARN, "Target block number not present", EXPFILL}}, |
382 | 16 | {&ei_value_partial_decode, {"bpsec.value_partial_decode", PI_UNDECODED, PI_WARN, "Value data not fully dissected", EXPFILL}}, |
383 | 16 | }; |
384 | | |
385 | 16 | proto_bpsec = proto_register_protocol("DTN Bundle Protocol Security", "BPSec", "bpsec"); |
386 | | |
387 | 16 | proto_register_field_array(proto_bpsec, fields, array_length(fields)); |
388 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
389 | 16 | expert_module_t *expert = expert_register_protocol(proto_bpsec); |
390 | 16 | expert_register_field_array(expert, expertitems, array_length(expertitems)); |
391 | | |
392 | 16 | secctx_dissectors = register_custom_dissector_table("bpsec.ctx", "BPSec Context", proto_bpsec, g_int64_hash, g_int64_equal, g_free); |
393 | 16 | param_dissectors = register_custom_dissector_table("bpsec.param", "BPSec Parameter", proto_bpsec, bpsec_id_hash, bpsec_id_equal, g_free); |
394 | 16 | result_dissectors = register_custom_dissector_table("bpsec.result", "BPSec Result", proto_bpsec, bpsec_id_hash, bpsec_id_equal, g_free); |
395 | | |
396 | 16 | prefs_register_protocol(proto_bpsec, reinit_bpsec); |
397 | 16 | } |
398 | | |
399 | 16 | void proto_reg_handoff_bpsec(void) { |
400 | 16 | handle_cbor = find_dissector("cbor"); |
401 | | |
402 | | /* Packaged extensions */ |
403 | 16 | { |
404 | 16 | uint64_t *key = g_new(uint64_t, 1); |
405 | 16 | *key = BP_BLOCKTYPE_BIB; |
406 | 16 | dissector_handle_t hdl = create_dissector_handle_with_name_and_description(dissect_block_bib, proto_bpsec, NULL, "Block Integrity Block"); |
407 | 16 | dissector_add_custom_table_handle("bpv7.block_type", key, hdl); |
408 | 16 | } |
409 | 16 | { |
410 | 16 | uint64_t *key = g_new(uint64_t, 1); |
411 | 16 | *key = BP_BLOCKTYPE_BCB; |
412 | 16 | dissector_handle_t hdl = create_dissector_handle_with_name_and_description(dissect_block_bcb, proto_bpsec, NULL, "Block Confidentiality Block"); |
413 | 16 | dissector_add_custom_table_handle("bpv7.block_type", key, hdl); |
414 | 16 | } |
415 | | |
416 | 16 | reinit_bpsec(); |
417 | 16 | } |