/src/wireshark/epan/dissectors/packet-ilnp.c
Line | Count | Source |
1 | | /* packet-ilnp.c |
2 | | * Routines for ILNP dissection |
3 | | * Copyright 2025, Shubh Sinhal <shubh.sinhal@gmail.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | /* |
13 | | * ILNP is an extension on IPv6 which changes the addressing semantics to |
14 | | * treat the Identifier (Node Identifier - 64 bits) and the Locator (Network |
15 | | * address - 64 bits) to improve mobility and multi-homing support |
16 | | * |
17 | | * RFC 6740 - ILNP Architectural Description |
18 | | * RFC 6741 - ILNP Engineering Considerations |
19 | | * |
20 | | * More information about ILNP can be found at "https://ilnp.cs.st-andrews.ac.uk/" |
21 | | * |
22 | | * This dissector was developed using the IPv6 dissector as a reference base |
23 | | */ |
24 | | |
25 | | #include "config.h" |
26 | | #include <epan/packet.h> |
27 | | #include <epan/address_types.h> |
28 | | #include <epan/to_str.h> |
29 | | #include <epan/proto.h> |
30 | | #include <epan/tap.h> |
31 | | #include <epan/conversation_table.h> |
32 | | #include <epan/conversation_filter.h> |
33 | | #include <epan/stats_tree.h> |
34 | | |
35 | | void proto_register_ilnp(void); |
36 | | |
37 | | /* Conversation data */ |
38 | | struct ilnp_analysis { |
39 | | uint32_t initial_frame; // Initial frame starting this conversation |
40 | | uint32_t stream; // Stream ID |
41 | | }; |
42 | | |
43 | | typedef struct _ilnp_tap_info_t { |
44 | | address ilnp_src_l64; /* source l64*/ |
45 | | address ilnp_src_nid; /* source nid */ |
46 | | address ilnp_dst_l64; /* destination l64*/ |
47 | | address ilnp_dst_nid; /* destination nid */ |
48 | | address ilnp_src_ilv; /* source ilv */ |
49 | | address ilnp_dst_ilv; /* destination ilv */ |
50 | | uint32_t ilnp_stream; /* track conversations */ |
51 | | } ilnp_tap_info_t; |
52 | | |
53 | | static int proto_ilnp; |
54 | | |
55 | | /* Header fields */ |
56 | | static int hf_ilnp_nonce; |
57 | | static int hf_ilnp_src_l64; |
58 | | static int hf_ilnp_dst_l64; |
59 | | static int hf_ilnp_src_nid; |
60 | | static int hf_ilnp_dst_nid; |
61 | | static int hf_ilnp_src_ilv; |
62 | | static int hf_ilnp_dst_ilv; |
63 | | static int hf_ilnp_l64; |
64 | | static int hf_ilnp_nid; |
65 | | static int hf_ilnp_ilv; |
66 | | static int hf_ilnp_stream; |
67 | | |
68 | | static int ett_ilnp; |
69 | | |
70 | | static dissector_handle_t ilnp_handle; |
71 | | |
72 | | // Global ILNP Stream counter |
73 | | static uint32_t ilnp_stream_count; |
74 | | |
75 | | /* ILNP tap handle */ |
76 | | static int ilnp_tap; |
77 | | |
78 | | |
79 | | /*********************************************************************************************************************************** |
80 | | * |
81 | | * CONVERSATIONS |
82 | | * |
83 | | ***********************************************************************************************************************************/ |
84 | | |
85 | | static const char* ilnp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) |
86 | 0 | { |
87 | 0 | if ((filter == CONV_FT_SRC_ADDRESS) && (conv->src_address.type == AT_ILNP_NID)) |
88 | 0 | return "ilnp.src_nid"; |
89 | | |
90 | 0 | if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == AT_ILNP_NID)) |
91 | 0 | return "ilnp.dst_nid"; |
92 | | |
93 | 0 | if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == AT_ILNP_NID)) |
94 | 0 | return "ilnp.nid"; |
95 | | |
96 | 0 | return CONV_FILTER_INVALID; |
97 | 0 | } |
98 | | |
99 | | static ct_dissector_info_t ilnp_ct_dissector_info = {&ilnp_conv_get_filter_type}; |
100 | | |
101 | | // Callback to add an ilnp conversation to the Statistics->Conversations->ILNP table |
102 | | static tap_packet_status |
103 | | ilnp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) |
104 | 0 | { |
105 | 0 | conv_hash_t *hash = (conv_hash_t*) pct; |
106 | 0 | hash->flags = flags; |
107 | |
|
108 | 0 | const ilnp_tap_info_t *ilnp_tap_info = (const ilnp_tap_info_t *)vip; |
109 | |
|
110 | 0 | add_conversation_table_data_with_conv_id(hash, &ilnp_tap_info->ilnp_src_nid, &ilnp_tap_info->ilnp_dst_nid, 0, 0, |
111 | 0 | (conv_id_t)ilnp_tap_info->ilnp_stream, 1, pinfo->fd->pkt_len, |
112 | 0 | &pinfo->rel_ts, &pinfo->abs_ts, &ilnp_ct_dissector_info, CONVERSATION_ILNP); |
113 | |
|
114 | 0 | return TAP_PACKET_REDRAW; |
115 | 0 | } |
116 | | |
117 | | static const char* ilnp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) |
118 | 0 | { |
119 | 0 | if ((filter == CONV_FT_ANY_ADDRESS) && (endpoint->myaddress.type == AT_ILNP_NID)) |
120 | 0 | return "ilnp.nid"; |
121 | | |
122 | 0 | return CONV_FILTER_INVALID; |
123 | 0 | } |
124 | | |
125 | | static et_dissector_info_t ilnp_endpoint_dissector_info = {&ilnp_endpoint_get_filter_type}; |
126 | | |
127 | | // Callback to add an ilnp nids to the Statistics->Endpoints->ILNP table |
128 | | static tap_packet_status |
129 | | ilnp_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) |
130 | 0 | { |
131 | 0 | conv_hash_t *hash = (conv_hash_t*) pit; |
132 | 0 | hash->flags = flags; |
133 | |
|
134 | 0 | const ilnp_tap_info_t *ilnp_tap_info = (const ilnp_tap_info_t *)vip; |
135 | |
|
136 | 0 | add_endpoint_table_data(hash, &ilnp_tap_info->ilnp_src_nid, 0, true, 1, |
137 | 0 | pinfo->fd->pkt_len, &ilnp_endpoint_dissector_info, ENDPOINT_ILNP); |
138 | 0 | add_endpoint_table_data(hash, &ilnp_tap_info->ilnp_dst_nid, 0, false, 1, |
139 | 0 | pinfo->fd->pkt_len, &ilnp_endpoint_dissector_info, ENDPOINT_ILNP); |
140 | |
|
141 | 0 | return TAP_PACKET_REDRAW; |
142 | 0 | } |
143 | | |
144 | | static bool |
145 | | ilnp_filter_valid(packet_info *pinfo, void *user_data _U_) |
146 | 0 | { |
147 | 0 | return proto_is_frame_protocol(pinfo->layers, "ilnp"); |
148 | 0 | } |
149 | | |
150 | | static char* |
151 | | ilnp_build_filter(packet_info *pinfo, void *user_data _U_) |
152 | 0 | { |
153 | 0 | address src_nid, dst_nid; |
154 | |
|
155 | 0 | alloc_address_wmem(pinfo->pool, &src_nid, AT_ILNP_NID, 8, pinfo->net_src.data); |
156 | 0 | alloc_address_wmem(pinfo->pool, &dst_nid, AT_ILNP_NID, 8, pinfo->net_dst.data); |
157 | |
|
158 | 0 | return ws_strdup_printf("ilnp.nid eq %s and ilnp.nid eq %s", |
159 | 0 | address_to_str(pinfo->pool, &src_nid), |
160 | 0 | address_to_str(pinfo->pool, &dst_nid)); |
161 | 0 | } |
162 | | |
163 | | |
164 | | static struct ilnp_analysis* |
165 | 12 | init_ilnp_conversation_data(packet_info *pinfo) { |
166 | 12 | struct ilnp_analysis *ilnpd; |
167 | | |
168 | | /* Initialize the ip protocol data structure to add to the ilnp conversation */ |
169 | 12 | ilnpd=wmem_new0(wmem_file_scope(), struct ilnp_analysis); |
170 | | |
171 | 12 | ilnpd->initial_frame = pinfo->num; |
172 | 12 | ilnpd->stream = ilnp_stream_count++; |
173 | | |
174 | 12 | return ilnpd; |
175 | 12 | } |
176 | | |
177 | | static struct ilnp_analysis* |
178 | 31 | get_ilnp_conversation_data(conversation_t *conv, packet_info *pinfo) { |
179 | 31 | struct ilnp_analysis *ilnpd; |
180 | | |
181 | | /* Get the data for this conversation */ |
182 | 31 | ilnpd = (struct ilnp_analysis *) conversation_get_proto_data(conv, proto_ilnp); |
183 | 31 | if (!ilnpd) { // if it doesn't exist, initialise new one |
184 | 12 | ilnpd = init_ilnp_conversation_data(pinfo); |
185 | 12 | conversation_add_proto_data(conv, proto_ilnp, ilnpd); |
186 | 12 | } |
187 | | |
188 | 31 | return ilnpd; |
189 | 31 | } |
190 | | |
191 | | |
192 | | |
193 | | /*********************************************************************************************************************************** |
194 | | * |
195 | | * STATISTICS |
196 | | * |
197 | | ***********************************************************************************************************************************/ |
198 | | |
199 | | static int st_node_ilnp_nids = -1; |
200 | | static int st_node_ilnp_src_nid = -1; |
201 | | static int st_node_ilnp_dst_nid = -1; |
202 | | static const char* st_str_ilnp_nid = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "All Node Identifiers"; |
203 | | static const char* st_str_ilnp_srcdst_nid = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "Source and Destination Node Identifier Addresses"; |
204 | | static const char* st_str_ilnp_src_nid = "Source ILNP Node Identifiers"; |
205 | | static const char* st_str_ilnp_dst_nid = "Destination ILNP Node Identifiers"; |
206 | | |
207 | | static int st_node_ilnp_l64s = -1; |
208 | | static int st_node_ilnp_src_l64 = -1; |
209 | | static int st_node_ilnp_dst_l64 = -1; |
210 | | static const char* st_str_ilnp_l64 = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "All Locators"; |
211 | | static const char* st_str_ilnp_srcdst_l64 = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "Source and Destination Locator Addresses"; |
212 | | static const char* st_str_ilnp_src_l64 = "Source ILNP Locators"; |
213 | | static const char* st_str_ilnp_dst_l64 = "Destination ILNP Locators"; |
214 | | |
215 | | static int st_node_ilnp_ilvs = -1; |
216 | | static int st_node_ilnp_src_ilv = -1; |
217 | | static int st_node_ilnp_dst_ilv = -1; |
218 | | static const char* st_str_ilnp_ilv = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "All Identifier-Locator Vectors"; |
219 | | static const char* st_str_ilnp_srcdst_ilv = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "Source and Destination Identifier-Locator Vector Addresses"; |
220 | | static const char* st_str_ilnp_src_ilv = "Source ILNP Identifier-Locator Vectors"; |
221 | | static const char* st_str_ilnp_dst_ilv = "Destination ILNP Identifier-Locator Vectors"; |
222 | | |
223 | | static int st_node_ilnp_ptype = -1; |
224 | | static const char* st_str_ilnp_ptype = "ILNP Statistics" STATS_TREE_MENU_SEPARATOR "IP Protocol Types"; |
225 | | |
226 | | |
227 | 0 | static void ilnp_nids_stats_tree_init(stats_tree* st) { |
228 | 0 | st_node_ilnp_nids = stats_tree_create_node(st, st_str_ilnp_nid, 0, STAT_DT_INT, true); |
229 | 0 | } |
230 | | |
231 | 0 | static void ilnp_l64s_stats_tree_init(stats_tree* st) { |
232 | 0 | st_node_ilnp_l64s = stats_tree_create_node(st, st_str_ilnp_l64, 0, STAT_DT_INT, true); |
233 | 0 | } |
234 | | |
235 | 0 | static void ilnp_ilvs_stats_tree_init(stats_tree* st) { |
236 | 0 | st_node_ilnp_ilvs = stats_tree_create_node(st, st_str_ilnp_ilv, 0, STAT_DT_INT, true); |
237 | 0 | } |
238 | | |
239 | | static tap_packet_status ilnp_nids_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
240 | 0 | { |
241 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
242 | 0 | tick_stat_node(st, st_str_ilnp_nid, 0, false); |
243 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_src_nid), st_node_ilnp_nids, false); |
244 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_dst_nid), st_node_ilnp_nids, false); |
245 | 0 | return TAP_PACKET_REDRAW; |
246 | 0 | } |
247 | | |
248 | | static tap_packet_status ilnp_l64s_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
249 | 0 | { |
250 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
251 | 0 | tick_stat_node(st, st_str_ilnp_l64, 0, false); |
252 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_src_l64), st_node_ilnp_l64s, false); |
253 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_dst_l64), st_node_ilnp_l64s, false); |
254 | 0 | return TAP_PACKET_REDRAW; |
255 | 0 | } |
256 | | |
257 | | static tap_packet_status ilnp_ilvs_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
258 | 0 | { |
259 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
260 | 0 | tick_stat_node(st, st_str_ilnp_ilv, 0, false); |
261 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_src_ilv), st_node_ilnp_ilvs, false); |
262 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, &ilnpt->ilnp_dst_ilv), st_node_ilnp_ilvs, false); |
263 | 0 | return TAP_PACKET_REDRAW; |
264 | 0 | } |
265 | | |
266 | | //Same as ip_srcdst_stats_tree_init |
267 | | static void ilnp_srcdst_stats_tree_init(stats_tree* st, |
268 | | const char* st_str_src, int* st_node_src_ptr, |
269 | | const char* st_str_dst, int* st_node_dst_ptr) |
270 | 0 | { |
271 | | /* create one tree branch for source */ |
272 | 0 | *st_node_src_ptr = stats_tree_create_node(st, st_str_src, 0, STAT_DT_INT, true); |
273 | | /* set flag so this branch will always be sorted to top of tree */ |
274 | 0 | stat_node_set_flags(st, st_str_src, 0, false, ST_FLG_SORT_TOP); |
275 | | /* create another top level node for destination branch */ |
276 | 0 | *st_node_dst_ptr = stats_tree_create_node(st, st_str_dst, 0, STAT_DT_INT, true); |
277 | | /* set flag so this branch will not be expanded by default */ |
278 | 0 | stat_node_set_flags(st, st_str_dst, 0, false, ST_FLG_DEF_NOEXPAND); |
279 | 0 | } |
280 | | |
281 | | static void |
282 | | ilnp_srcdst_nid_stats_tree_init(stats_tree* st) |
283 | 0 | { |
284 | 0 | ilnp_srcdst_stats_tree_init(st, st_str_ilnp_src_nid, &st_node_ilnp_src_nid, st_str_ilnp_dst_nid, &st_node_ilnp_dst_nid); |
285 | 0 | } |
286 | | static void ilnp_srcdst_l64_stats_tree_init(stats_tree* st) |
287 | 0 | { |
288 | 0 | ilnp_srcdst_stats_tree_init(st, st_str_ilnp_src_l64, &st_node_ilnp_src_l64, st_str_ilnp_dst_l64, &st_node_ilnp_dst_l64); |
289 | 0 | } |
290 | | |
291 | | static void ilnp_srcdst_ilv_stats_tree_init(stats_tree* st) |
292 | 0 | { |
293 | 0 | ilnp_srcdst_stats_tree_init(st, st_str_ilnp_src_ilv, &st_node_ilnp_src_ilv, st_str_ilnp_dst_ilv, &st_node_ilnp_dst_ilv); |
294 | 0 | } |
295 | | |
296 | | static tap_packet_status ilnp_srcdst_stats_tree_packet(stats_tree* st, |
297 | | packet_info* pinfo, |
298 | | const address* src_addr, |
299 | | const address* dst_addr, |
300 | | int st_node_src, |
301 | | const char* st_str_src, |
302 | | int st_node_dst, |
303 | | const char* st_str_dst) |
304 | 0 | { |
305 | | /* update source branch */ |
306 | 0 | tick_stat_node(st, st_str_src, 0, false); |
307 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, src_addr), st_node_src, false); |
308 | | /* update destination branch */ |
309 | 0 | tick_stat_node(st, st_str_dst, 0, false); |
310 | 0 | tick_stat_node(st, address_to_str(pinfo->pool, dst_addr), st_node_dst, false); |
311 | 0 | return TAP_PACKET_REDRAW; |
312 | 0 | } |
313 | | |
314 | | static tap_packet_status ilnp_srcdst_nid_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
315 | 0 | { |
316 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
317 | 0 | return ilnp_srcdst_stats_tree_packet(st, pinfo, &ilnpt->ilnp_src_nid, &ilnpt->ilnp_dst_nid, st_node_ilnp_src_nid, st_str_ilnp_src_nid, st_node_ilnp_dst_nid, st_str_ilnp_dst_nid); |
318 | 0 | } |
319 | | |
320 | | static tap_packet_status ilnp_srcdst_l64_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
321 | 0 | { |
322 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
323 | 0 | return ilnp_srcdst_stats_tree_packet(st, pinfo, &ilnpt->ilnp_src_l64, &ilnpt->ilnp_dst_l64, st_node_ilnp_src_l64, st_str_ilnp_src_l64, st_node_ilnp_dst_l64, st_str_ilnp_dst_l64); |
324 | 0 | } |
325 | | |
326 | | static tap_packet_status ilnp_srcdst_ilv_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
327 | 0 | { |
328 | 0 | const ilnp_tap_info_t* ilnpt = (const ilnp_tap_info_t*)p; |
329 | 0 | return ilnp_srcdst_stats_tree_packet(st, pinfo, &ilnpt->ilnp_src_ilv, &ilnpt->ilnp_dst_ilv, st_node_ilnp_src_ilv, st_str_ilnp_src_ilv, st_node_ilnp_dst_ilv, st_str_ilnp_dst_ilv); |
330 | 0 | } |
331 | | |
332 | | static void ilnp_ptype_stats_tree_init(stats_tree* st) |
333 | 0 | { |
334 | 0 | st_node_ilnp_ptype = stats_tree_create_pivot(st, st_str_ilnp_ptype, 0); |
335 | 0 | } |
336 | | |
337 | | static tap_packet_status ilnp_ptype_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p _U_, tap_flags_t flags _U_) |
338 | 0 | { |
339 | 0 | stats_tree_tick_pivot(st, st_node_ilnp_ptype, port_type_to_str(pinfo->ptype)); |
340 | 0 | return TAP_PACKET_REDRAW; |
341 | 0 | } |
342 | | |
343 | | /*********************************************************************************************************************************** |
344 | | * |
345 | | * DISSECTION |
346 | | * |
347 | | ***********************************************************************************************************************************/ |
348 | | |
349 | | static int |
350 | | dissect_ilnp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) |
351 | 44 | { |
352 | 44 | proto_tree *ilnp_tree; |
353 | 44 | proto_item *ilnp_item, *ti; |
354 | 44 | const char *str_ilnp_src_nid, *str_ilnp_src_l64, |
355 | 44 | *str_ilnp_dst_nid, *str_ilnp_dst_l64, |
356 | 44 | *str_ilnp_src_ilv, *str_ilnp_dst_ilv; |
357 | 44 | conversation_t* conv; |
358 | 44 | struct ilnp_analysis* ilnpd; |
359 | 44 | ilnp_tap_info_t* ilnph; |
360 | | |
361 | | //ILNP works on top of IPv6 only (as it "repurposes" the address data) |
362 | 44 | if ((pinfo->net_src.type != AT_IPv6) || (pinfo->net_dst.type != AT_IPv6)) |
363 | 13 | return 0; |
364 | | |
365 | 31 | ilnph = wmem_new0(pinfo->pool, ilnp_tap_info_t); |
366 | | |
367 | | // Define ilnp tree and add it as a subtree to the main proto tree |
368 | 31 | ilnp_item = proto_tree_add_item(tree, proto_ilnp, tvb, 0, -1, ENC_NA); |
369 | 31 | ilnp_tree = proto_item_add_subtree(ilnp_item, ett_ilnp); |
370 | | |
371 | | // Add ILNP Nonce to subtree |
372 | 31 | proto_tree_add_item(ilnp_tree, hf_ilnp_nonce, tvb, 0, -1, ENC_NA); |
373 | | |
374 | | //Set the NID as source and destination addresses of the packet |
375 | 31 | alloc_address_wmem(pinfo->pool, &pinfo->src, AT_ILNP_NID, 8, ((uint8_t*)pinfo->net_src.data)+8); |
376 | 31 | alloc_address_wmem(pinfo->pool, &pinfo->dst, AT_ILNP_NID, 8, ((uint8_t*)pinfo->net_dst.data)+8); |
377 | | |
378 | | //Get address data from the current network layer and put into tap data |
379 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_src_l64, AT_ILNP_L64, 8, pinfo->net_src.data); |
380 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_src_nid, AT_ILNP_NID, 8, ((uint8_t*)pinfo->net_src.data)+8); |
381 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_dst_l64, AT_ILNP_L64, 8, pinfo->net_dst.data); |
382 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_dst_nid, AT_ILNP_NID, 8, ((uint8_t*)pinfo->net_dst.data)+8); |
383 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_src_ilv, AT_ILNP_ILV, 16, pinfo->net_src.data); |
384 | 31 | alloc_address_wmem(pinfo->pool, &ilnph->ilnp_dst_ilv, AT_ILNP_ILV, 16, pinfo->net_dst.data); |
385 | | |
386 | | //Add tap data to the dissection tree |
387 | | |
388 | | // convert all addresses to strings for display |
389 | 31 | str_ilnp_src_nid = address_to_str(pinfo->pool, &ilnph->ilnp_src_nid); |
390 | 31 | str_ilnp_src_l64 = address_to_str(pinfo->pool, &ilnph->ilnp_src_l64); |
391 | 31 | str_ilnp_dst_nid = address_to_str(pinfo->pool, &ilnph->ilnp_dst_nid); |
392 | 31 | str_ilnp_dst_l64 = address_to_str(pinfo->pool, &ilnph->ilnp_dst_l64); |
393 | 31 | str_ilnp_src_ilv = address_to_str(pinfo->pool, &ilnph->ilnp_src_ilv); |
394 | 31 | str_ilnp_dst_ilv = address_to_str(pinfo->pool, &ilnph->ilnp_dst_ilv); |
395 | | |
396 | | // Add address fields to ILNP subtree. Some fields without specifying src or dst for added filter options |
397 | 31 | proto_tree_add_string(ilnp_tree, hf_ilnp_src_l64, tvb, 0, 0, str_ilnp_src_l64); |
398 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_l64, tvb, 0, 0, str_ilnp_src_l64); |
399 | 31 | proto_item_set_hidden(ti); |
400 | 31 | proto_tree_add_string(ilnp_tree, hf_ilnp_src_nid, tvb, 0, 0, str_ilnp_src_nid); |
401 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_nid, tvb, 0, 0, str_ilnp_src_nid); |
402 | 31 | proto_item_set_hidden(ti); |
403 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_src_ilv, tvb, 0, 0, str_ilnp_src_ilv); |
404 | 31 | proto_item_set_hidden(ti); |
405 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_ilv, tvb, 0, 0, str_ilnp_src_ilv); |
406 | 31 | proto_item_set_hidden(ti); |
407 | 31 | proto_tree_add_string(ilnp_tree, hf_ilnp_dst_l64, tvb, 0, 0, str_ilnp_dst_l64); |
408 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_l64, tvb, 0, 0, str_ilnp_dst_l64); |
409 | 31 | proto_item_set_hidden(ti); |
410 | 31 | proto_tree_add_string(ilnp_tree, hf_ilnp_dst_nid, tvb, 0, 0, str_ilnp_dst_nid); |
411 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_nid, tvb, 0, 0, str_ilnp_dst_nid); |
412 | 31 | proto_item_set_hidden(ti); |
413 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_dst_ilv, tvb, 0, 0, str_ilnp_dst_ilv); |
414 | 31 | proto_item_set_hidden(ti); |
415 | 31 | ti = proto_tree_add_string(ilnp_tree, hf_ilnp_ilv, tvb, 0, 0, str_ilnp_dst_ilv); |
416 | 31 | proto_item_set_hidden(ti); |
417 | | |
418 | | // Add test to the main ILNP dropdown in the packet details pane. |
419 | 31 | proto_item_append_text(ilnp_item, ", Src: %s, Dst: %s", str_ilnp_src_ilv, str_ilnp_dst_ilv); |
420 | | |
421 | | // does not use nonce or l64 |
422 | 31 | conv = find_conversation_strat(pinfo, CONVERSATION_ILNP, NO_PORT_X, false); |
423 | 31 | if (!conv) { // if no conversation exists |
424 | 12 | conv = conversation_new_strat(pinfo, CONVERSATION_ILNP, NO_PORTS); |
425 | 12 | } |
426 | 19 | else { // otherwise add to existing conversation |
427 | 19 | if (!(pinfo->fd->visited)) { |
428 | 19 | if (pinfo->num > conv->last_frame) { |
429 | 3 | conv->last_frame = pinfo->num; |
430 | 3 | } |
431 | 19 | } |
432 | 19 | } |
433 | | |
434 | | // Get stream id for display |
435 | 31 | ilnpd = get_ilnp_conversation_data(conv, pinfo); |
436 | 31 | if (ilnpd) { |
437 | | // set stream id in tap info struct |
438 | 31 | ilnph->ilnp_stream = ilnpd->stream; |
439 | | // add to protocol tree |
440 | 31 | ti = proto_tree_add_uint(ilnp_tree, hf_ilnp_stream, tvb, 0, 0, ilnpd->stream); |
441 | 31 | proto_item_set_generated(ti); |
442 | 31 | } |
443 | | |
444 | | // queue packet to trigger linked tap listeners |
445 | 31 | tap_queue_packet(ilnp_tap, pinfo, ilnph); |
446 | | |
447 | 31 | return tvb_captured_length(tvb); |
448 | 44 | } |
449 | | |
450 | | // Initialise the ILNP dissector with a stream count starting at 0 |
451 | 14 | static void ilnp_init(void) { |
452 | 14 | ilnp_stream_count = 0; |
453 | 14 | } |
454 | | |
455 | 14 | void proto_register_ilnp(void) { |
456 | | |
457 | 14 | static hf_register_info hf[] = { |
458 | 14 | { &hf_ilnp_nonce, |
459 | 14 | { "ILNP Nonce Value", "ilnp.nonce", FT_BYTES, BASE_NONE, NULL, 0x0, |
460 | 14 | NULL, HFILL } |
461 | 14 | }, |
462 | 14 | { &hf_ilnp_src_l64, |
463 | 14 | { "Source L64", "ilnp.src_l64", FT_STRING, BASE_NONE, NULL, 0x0, |
464 | 14 | "ILNP Source Locator", HFILL} |
465 | 14 | }, |
466 | 14 | { &hf_ilnp_src_nid, |
467 | 14 | { "Source NID", "ilnp.src_nid", FT_STRING, BASE_NONE, NULL, 0x0, |
468 | 14 | "ILNP Source Node Identifier", HFILL} |
469 | 14 | }, |
470 | 14 | { &hf_ilnp_dst_l64, |
471 | 14 | { "Destination L64", "ilnp.dst_l64", FT_STRING, BASE_NONE, NULL, 0x0, |
472 | 14 | "ILNP Destination Locator", HFILL} |
473 | 14 | }, |
474 | 14 | { &hf_ilnp_dst_nid, |
475 | 14 | { "Destination NID", "ilnp.dst_nid", FT_STRING, BASE_NONE, NULL, 0x0, |
476 | 14 | "ILNP Destination Node Identifier", HFILL} |
477 | 14 | }, |
478 | 14 | { &hf_ilnp_src_ilv, |
479 | 14 | { "Source ILV", "ilnp.src_ilv", FT_STRING, BASE_NONE, NULL, 0x0, |
480 | 14 | "ILNP Source Identifier-Locator Vector", HFILL} |
481 | 14 | }, |
482 | 14 | { &hf_ilnp_dst_ilv, |
483 | 14 | { "Destination ILV", "ilnp.dst_ilv", FT_STRING, BASE_NONE, NULL, 0x0, |
484 | 14 | "ILNP Destination Identifier-Locator Vector", HFILL} |
485 | 14 | }, |
486 | 14 | { &hf_ilnp_ilv, |
487 | 14 | { "Source or Destination ILV", "ilnp.ilv", FT_STRING, BASE_NONE, NULL, 0x0, |
488 | 14 | "ILNP Source or Destination Identifier-Locator Vector", HFILL} |
489 | 14 | }, |
490 | 14 | { &hf_ilnp_nid, |
491 | 14 | { "Source or Destination NID", "ilnp.nid", FT_STRING, BASE_NONE, NULL, 0x0, |
492 | 14 | "ILNP Source or Destination Node Identifier", HFILL} |
493 | 14 | }, |
494 | 14 | { &hf_ilnp_l64, |
495 | 14 | { "Source or Destination L64", "ilnp.l64", FT_STRING, BASE_NONE, NULL, 0x0, |
496 | 14 | "ILNP Source or Destination Locator", HFILL} |
497 | 14 | }, |
498 | 14 | { &hf_ilnp_stream, |
499 | 14 | { "Stream index", "ilnp.stream", |
500 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
501 | 14 | NULL, HFILL } |
502 | 14 | }, |
503 | 14 | }; |
504 | | |
505 | 14 | static int* ett[] = { |
506 | 14 | &ett_ilnp, |
507 | 14 | }; |
508 | | |
509 | 14 | proto_ilnp = proto_register_protocol("Identifier-Locator Network Protocol", "ILNP", "ilnp"); |
510 | 14 | proto_register_field_array(proto_ilnp, hf, array_length(hf)); |
511 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
512 | | |
513 | 14 | register_init_routine(ilnp_init); |
514 | | |
515 | 14 | ilnp_handle = register_dissector("ilnp", dissect_ilnp, proto_ilnp); |
516 | | |
517 | 14 | ilnp_tap = register_tap("ilnp"); |
518 | | |
519 | 14 | register_conversation_table(proto_ilnp, true, ilnp_conversation_packet, ilnp_endpoint_packet); |
520 | 14 | register_conversation_filter("ilnp", "ILNP", ilnp_filter_valid, ilnp_build_filter, NULL); |
521 | | |
522 | | /* XXX - This isn't really a plugin, but the non-plugin version requires GUI changes */ |
523 | 14 | stats_tree_register_plugin("ilnp", "ilnp_nids", st_str_ilnp_nid, 0, ilnp_nids_stats_tree_packet, ilnp_nids_stats_tree_init, NULL); |
524 | 14 | stats_tree_register_plugin("ilnp", "ilnp_l64s", st_str_ilnp_l64, 0, ilnp_l64s_stats_tree_packet, ilnp_l64s_stats_tree_init, NULL); |
525 | 14 | stats_tree_register_plugin("ilnp", "ilnp_ilvs", st_str_ilnp_ilv, 0, ilnp_ilvs_stats_tree_packet, ilnp_ilvs_stats_tree_init, NULL); |
526 | 14 | stats_tree_register_plugin("ilnp", "ilnp_ptype", st_str_ilnp_ptype, 0, ilnp_ptype_stats_tree_packet, ilnp_ptype_stats_tree_init, NULL); |
527 | 14 | stats_tree_register_plugin("ilnp", "ilnp_srcdst_nid", st_str_ilnp_srcdst_nid, 0, ilnp_srcdst_nid_stats_tree_packet, ilnp_srcdst_nid_stats_tree_init, NULL); |
528 | 14 | stats_tree_register_plugin("ilnp", "ilnp_srcdst_l64", st_str_ilnp_srcdst_l64, 0, ilnp_srcdst_l64_stats_tree_packet, ilnp_srcdst_l64_stats_tree_init, NULL); |
529 | | stats_tree_register_plugin("ilnp", "ilnp_srcdst_ilv", st_str_ilnp_srcdst_ilv, 0, ilnp_srcdst_ilv_stats_tree_packet, ilnp_srcdst_ilv_stats_tree_init, NULL); |
530 | 14 | } |