/src/wireshark/epan/dissectors/packet-udp.c
Line | Count | Source |
1 | | /* packet-udp.c |
2 | | * Routines for UDP/UDP-Lite packet disassembly |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * Richard Sharpe, 13-Feb-1999, added dispatch table support and |
9 | | * support for tftp. |
10 | | * |
11 | | * SPDX-License-Identifier: GPL-2.0-or-later |
12 | | */ |
13 | | #include "config.h" |
14 | | #include "packet-udp.h" |
15 | | |
16 | | #include <epan/packet.h> |
17 | | #include <epan/capture_dissectors.h> |
18 | | #include <epan/addr_resolv.h> |
19 | | #include <epan/in_cksum.h> |
20 | | #include <epan/prefs.h> |
21 | | #include <epan/follow.h> |
22 | | #include <epan/expert.h> |
23 | | #include <epan/exceptions.h> |
24 | | #include <epan/show_exception.h> |
25 | | #include <epan/proto_data.h> |
26 | | |
27 | | #include <wsutil/utf8_entities.h> |
28 | | #include <wsutil/pint.h> |
29 | | #include <wsutil/str_util.h> |
30 | | |
31 | | #include <epan/conversation.h> |
32 | | #include <epan/conversation_table.h> |
33 | | #include <epan/conversation_filter.h> |
34 | | #include <epan/exported_pdu.h> |
35 | | #include <epan/decode_as.h> |
36 | | #include <epan/iana-info.h> |
37 | | |
38 | | void proto_register_udp(void); |
39 | | void proto_reg_handoff_udp(void); |
40 | | |
41 | | static dissector_handle_t udp_handle; |
42 | | static dissector_handle_t udplite_handle; |
43 | | static capture_dissector_handle_t udp_cap_handle; |
44 | | static capture_dissector_handle_t udplite_cap_handle; |
45 | | |
46 | | static int udp_tap; |
47 | | static int udp_follow_tap; |
48 | | static int exported_pdu_tap; |
49 | | |
50 | | static int proto_udp; |
51 | | static int proto_udplite; |
52 | | |
53 | | static int hf_udp_checksum; |
54 | | static int hf_udp_checksum_calculated; |
55 | | static int hf_udp_checksum_status; |
56 | | static int hf_udp_dstport; |
57 | | static int hf_udp_length; |
58 | | static int hf_udp_payload; |
59 | | static int hf_udp_pdu_size; |
60 | | static int hf_udp_port; |
61 | | static int hf_udp_proc_dst_cmd; |
62 | | static int hf_udp_proc_dst_pid; |
63 | | static int hf_udp_proc_dst_uid; |
64 | | static int hf_udp_proc_dst_uname; |
65 | | static int hf_udp_proc_src_cmd; |
66 | | static int hf_udp_proc_src_pid; |
67 | | static int hf_udp_proc_src_uid; |
68 | | static int hf_udp_proc_src_uname; |
69 | | static int hf_udp_srcport; |
70 | | static int hf_udp_stream; |
71 | | static int hf_udp_stream_pnum; |
72 | | static int hf_udp_ts_delta; |
73 | | static int hf_udp_ts_relative; |
74 | | static int hf_udplite_checksum_coverage; |
75 | | |
76 | | static int ett_udp; |
77 | | static int ett_udp_checksum; |
78 | | static int ett_udp_process_info; |
79 | | static int ett_udp_timestamps; |
80 | | |
81 | | static expert_field ei_udp_possible_traceroute; |
82 | | static expert_field ei_udp_length_bad; |
83 | | static expert_field ei_udplite_checksum_coverage_bad; |
84 | | static expert_field ei_udp_checksum_zero; |
85 | | static expert_field ei_udp_checksum_partial; |
86 | | static expert_field ei_udp_checksum_bad; |
87 | | static expert_field ei_udp_length_bad_zero; |
88 | | |
89 | | /* Preferences */ |
90 | | |
91 | | /* Place UDP summary in proto tree */ |
92 | | static bool udp_summary_in_tree = true; |
93 | | |
94 | | /* Check UDP checksums */ |
95 | | static bool udp_check_checksum; |
96 | | |
97 | | /* Ignore zero-value UDP checksums over IPv6 */ |
98 | | static bool udp_ignore_ipv6_zero_checksum; |
99 | | |
100 | | /* Collect IPFIX process flow information */ |
101 | | static bool udp_process_info; |
102 | | |
103 | | /* Ignore an invalid checksum coverage field for UDP-Lite */ |
104 | | static bool udplite_ignore_checksum_coverage = true; |
105 | | |
106 | | /* Check UDP-Lite checksums */ |
107 | | static bool udplite_check_checksum; |
108 | | |
109 | | static dissector_table_t udp_dissector_table; |
110 | | static heur_dissector_list_t heur_subdissector_list; |
111 | | static uint32_t udp_stream_count; |
112 | | |
113 | | /* Determine if there is a sub-dissector and call it. This has been */ |
114 | | /* separated into a stand alone routine so other protocol dissectors */ |
115 | | /* can call to it, ie. socks */ |
116 | | |
117 | | static bool try_heuristic_first; |
118 | | |
119 | | static bool udp_calculate_ts = true; |
120 | | static bool udplite_calculate_ts = true; |
121 | | |
122 | | /* Per-packet-info for UDP */ |
123 | | typedef struct { |
124 | | heur_dtbl_entry_t *heur_dtbl_entry; |
125 | | nstime_t ts_delta; |
126 | | bool ts_delta_valid; |
127 | | uint32_t pnum; |
128 | | } udp_p_info_t; |
129 | | |
130 | | static void |
131 | | udp_src_prompt(packet_info *pinfo, char *result) |
132 | 0 | { |
133 | 0 | uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, |
134 | 0 | hf_udp_srcport, pinfo->curr_layer_num)); |
135 | |
|
136 | 0 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%u%s)", port, UTF8_RIGHTWARDS_ARROW); |
137 | 0 | } |
138 | | |
139 | | static void * |
140 | | udp_src_value(packet_info *pinfo) |
141 | 0 | { |
142 | 0 | return p_get_proto_data(pinfo->pool, pinfo, hf_udp_srcport, pinfo->curr_layer_num); |
143 | 0 | } |
144 | | |
145 | | static void |
146 | | udp_dst_prompt(packet_info *pinfo, char *result) |
147 | 0 | { |
148 | 0 | uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, |
149 | 0 | hf_udp_dstport, pinfo->curr_layer_num)); |
150 | |
|
151 | 0 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port); |
152 | 0 | } |
153 | | |
154 | | static void * |
155 | | udp_dst_value(packet_info *pinfo) |
156 | 0 | { |
157 | 0 | return p_get_proto_data(pinfo->pool, pinfo, hf_udp_dstport, pinfo->curr_layer_num); |
158 | 0 | } |
159 | | |
160 | | static void |
161 | | udp_both_prompt(packet_info *pinfo, char *result) |
162 | 0 | { |
163 | 0 | uint32_t srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, |
164 | 0 | hf_udp_srcport, pinfo->curr_layer_num)); |
165 | 0 | uint32_t dstport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, |
166 | 0 | hf_udp_dstport, pinfo->curr_layer_num)); |
167 | 0 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, dstport); |
168 | 0 | } |
169 | | |
170 | | /* Conversation and process code originally copied from packet-tcp.c */ |
171 | | static struct udp_analysis * |
172 | | init_udp_conversation_data(packet_info *pinfo) |
173 | 11.0k | { |
174 | 11.0k | struct udp_analysis *udpd; |
175 | | |
176 | | /* Initialize the udp protocol data structure to add to the udp conversation */ |
177 | 11.0k | udpd = wmem_new0(wmem_file_scope(), struct udp_analysis); |
178 | | /* |
179 | | udpd->flow1.username = NULL; |
180 | | udpd->flow1.command = NULL; |
181 | | udpd->flow2.username = NULL; |
182 | | udpd->flow2.command = NULL; |
183 | | */ |
184 | | |
185 | 11.0k | udpd->stream = udp_stream_count++; |
186 | 11.0k | udpd->ts_first = pinfo->abs_ts; |
187 | 11.0k | udpd->ts_prev = pinfo->abs_ts; |
188 | | |
189 | 11.0k | return udpd; |
190 | 11.0k | } |
191 | | |
192 | | struct udp_analysis * |
193 | | get_udp_conversation_data(conversation_t *conv, packet_info *pinfo) |
194 | 83.4k | { |
195 | 83.4k | int direction; |
196 | 83.4k | struct udp_analysis *udpd = NULL; |
197 | | |
198 | | /* Did the caller supply the conversation pointer? */ |
199 | 83.4k | if (conv == NULL) |
200 | 0 | conv = find_or_create_conversation_strat(pinfo); |
201 | | |
202 | | /* Get the data for this conversation */ |
203 | 83.4k | udpd = conversation_get_proto_data(conv, proto_udp); |
204 | | |
205 | | /* If the conversation was just created or it matched a |
206 | | * conversation with template options, udpd will not |
207 | | * have been initialized. So, initialize |
208 | | * a new udpd structure for the conversation. |
209 | | */ |
210 | 83.4k | if (!udpd) { |
211 | 11.0k | udpd = init_udp_conversation_data(pinfo); |
212 | 11.0k | conversation_add_proto_data(conv, proto_udp, udpd); |
213 | 11.0k | } |
214 | | |
215 | 83.4k | if (!udpd) { |
216 | 0 | return NULL; |
217 | 0 | } |
218 | | |
219 | | /* check direction and get ua lists */ |
220 | 83.4k | direction = cmp_address(&pinfo->src, &pinfo->dst); |
221 | | /* if the addresses are equal, match the ports instead */ |
222 | 83.4k | if (direction == 0) { |
223 | 82.7k | direction = (pinfo->srcport > pinfo->destport) ? 1 : -1; |
224 | 82.7k | } |
225 | 83.4k | if (direction >= 0) { |
226 | 31.4k | udpd->fwd = &(udpd->flow1); |
227 | 31.4k | udpd->rev = &(udpd->flow2); |
228 | 31.4k | } |
229 | 51.9k | else { |
230 | 51.9k | udpd->fwd = &(udpd->flow2); |
231 | 51.9k | udpd->rev = &(udpd->flow1); |
232 | 51.9k | } |
233 | | |
234 | 83.4k | return udpd; |
235 | 83.4k | } |
236 | | |
237 | | static const char* udp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter) |
238 | 0 | { |
239 | 0 | if (filter == CONV_FT_SRC_PORT) |
240 | 0 | return "udp.srcport"; |
241 | | |
242 | 0 | if (filter == CONV_FT_DST_PORT) |
243 | 0 | return "udp.dstport"; |
244 | | |
245 | 0 | if (filter == CONV_FT_ANY_PORT) |
246 | 0 | return "udp.port"; |
247 | | |
248 | 0 | if(!conv) { |
249 | 0 | return CONV_FILTER_INVALID; |
250 | 0 | } |
251 | | |
252 | 0 | if (filter == CONV_FT_SRC_ADDRESS) { |
253 | 0 | if (conv->src_address.type == AT_IPv4) |
254 | 0 | return "ip.src"; |
255 | 0 | if (conv->src_address.type == AT_IPv6) |
256 | 0 | return "ipv6.src"; |
257 | 0 | } |
258 | | |
259 | 0 | if (filter == CONV_FT_DST_ADDRESS) { |
260 | 0 | if (conv->dst_address.type == AT_IPv4) |
261 | 0 | return "ip.dst"; |
262 | 0 | if (conv->dst_address.type == AT_IPv6) |
263 | 0 | return "ipv6.dst"; |
264 | 0 | } |
265 | | |
266 | 0 | if (filter == CONV_FT_ANY_ADDRESS) { |
267 | 0 | if (conv->src_address.type == AT_IPv4) |
268 | 0 | return "ip.addr"; |
269 | 0 | if (conv->src_address.type == AT_IPv6) |
270 | 0 | return "ipv6.addr"; |
271 | 0 | } |
272 | | |
273 | 0 | return CONV_FILTER_INVALID; |
274 | 0 | } |
275 | | |
276 | | static ct_dissector_info_t udp_ct_dissector_info = {&udp_conv_get_filter_type}; |
277 | | |
278 | | static tap_packet_status |
279 | | udpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) |
280 | 0 | { |
281 | 0 | conv_hash_t *hash = (conv_hash_t*) pct; |
282 | 0 | hash->flags = flags; |
283 | |
|
284 | 0 | const e_udphdr *udphdr=(const e_udphdr *)vip; |
285 | |
|
286 | 0 | add_conversation_table_data_with_conv_id(hash, |
287 | 0 | &udphdr->ip_src, &udphdr->ip_dst, udphdr->uh_sport, udphdr->uh_dport, |
288 | 0 | (conv_id_t) udphdr->uh_stream, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, |
289 | 0 | &udp_ct_dissector_info, CONVERSATION_UDP); |
290 | |
|
291 | 0 | return TAP_PACKET_REDRAW; |
292 | 0 | } |
293 | | |
294 | | static const char* udp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter) |
295 | 0 | { |
296 | |
|
297 | 0 | if (filter == CONV_FT_SRC_PORT) |
298 | 0 | return "udp.srcport"; |
299 | | |
300 | 0 | if (filter == CONV_FT_DST_PORT) |
301 | 0 | return "udp.dstport"; |
302 | | |
303 | 0 | if (filter == CONV_FT_ANY_PORT) |
304 | 0 | return "udp.port"; |
305 | | |
306 | 0 | if(!endpoint) { |
307 | 0 | return CONV_FILTER_INVALID; |
308 | 0 | } |
309 | | |
310 | | |
311 | 0 | if (filter == CONV_FT_SRC_ADDRESS) { |
312 | 0 | if (endpoint->myaddress.type == AT_IPv4) |
313 | 0 | return "ip.src"; |
314 | 0 | if (endpoint->myaddress.type == AT_IPv6) |
315 | 0 | return "ipv6.src"; |
316 | 0 | } |
317 | | |
318 | 0 | if (filter == CONV_FT_DST_ADDRESS) { |
319 | 0 | if (endpoint->myaddress.type == AT_IPv4) |
320 | 0 | return "ip.dst"; |
321 | 0 | if (endpoint->myaddress.type == AT_IPv6) |
322 | 0 | return "ipv6.dst"; |
323 | 0 | } |
324 | | |
325 | 0 | if (filter == CONV_FT_ANY_ADDRESS) { |
326 | 0 | if (endpoint->myaddress.type == AT_IPv4) |
327 | 0 | return "ip.addr"; |
328 | 0 | if (endpoint->myaddress.type == AT_IPv6) |
329 | 0 | return "ipv6.addr"; |
330 | 0 | } |
331 | | |
332 | 0 | return CONV_FILTER_INVALID; |
333 | 0 | } |
334 | | |
335 | | static et_dissector_info_t udp_endpoint_dissector_info = {&udp_endpoint_get_filter_type}; |
336 | | |
337 | | static tap_packet_status |
338 | | udpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags) |
339 | 0 | { |
340 | 0 | conv_hash_t *hash = (conv_hash_t*) pit; |
341 | 0 | hash->flags = flags; |
342 | |
|
343 | 0 | const e_udphdr *udphdr=(const e_udphdr *)vip; |
344 | | |
345 | | /* Take two "add" passes per packet, adding for each direction, ensures that all |
346 | | packets are counted properly (even if address is sending to itself) |
347 | | XXX - this could probably be done more efficiently inside endpoint_table */ |
348 | 0 | add_endpoint_table_data(hash, &udphdr->ip_src, udphdr->uh_sport, true, 1, pinfo->fd->pkt_len, &udp_endpoint_dissector_info, ENDPOINT_UDP); |
349 | 0 | add_endpoint_table_data(hash, &udphdr->ip_dst, udphdr->uh_dport, false, 1, pinfo->fd->pkt_len, &udp_endpoint_dissector_info, ENDPOINT_UDP); |
350 | |
|
351 | 0 | return TAP_PACKET_REDRAW; |
352 | 0 | } |
353 | | |
354 | | static bool |
355 | | udp_filter_valid(packet_info *pinfo, void *user_data _U_) |
356 | 0 | { |
357 | 0 | return proto_is_frame_protocol(pinfo->layers, "udp"); |
358 | 0 | } |
359 | | |
360 | | static char* |
361 | | udp_build_filter_by_id(packet_info *pinfo, void *user_data _U_) |
362 | 0 | { |
363 | 0 | return ws_strdup_printf("udp.stream eq %d", pinfo->stream_id); |
364 | 0 | } |
365 | | |
366 | | |
367 | | static char *udp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_) |
368 | 0 | { |
369 | 0 | uint8_t max_layer_num = proto_get_layer_num(pinfo, proto_udp); |
370 | |
|
371 | 0 | for (uint8_t curr_layer_num = max_layer_num; curr_layer_num; --curr_layer_num) { |
372 | 0 | *stream = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_udp_stream, curr_layer_num)); |
373 | 0 | if (*stream) { |
374 | 0 | return ws_strdup_printf("udp.stream eq %u", --*stream); |
375 | 0 | } |
376 | 0 | } |
377 | | |
378 | 0 | return NULL; |
379 | 0 | } |
380 | | |
381 | | static char *udp_follow_index_filter(unsigned stream, unsigned sub_stream _U_) |
382 | 0 | { |
383 | 0 | return ws_strdup_printf("udp.stream eq %u", stream); |
384 | 0 | } |
385 | | |
386 | | char *udp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port) |
387 | 0 | { |
388 | 0 | const char *ip_version = src_addr->type == AT_IPv6 ? "v6" : ""; |
389 | 0 | char src_addr_str[WS_INET6_ADDRSTRLEN]; |
390 | 0 | char dst_addr_str[WS_INET6_ADDRSTRLEN]; |
391 | |
|
392 | 0 | address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str)); |
393 | 0 | address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str)); |
394 | |
|
395 | 0 | return ws_strdup_printf("((ip%s.src eq %s and udp.srcport eq %d) and " |
396 | 0 | "(ip%s.dst eq %s and udp.dstport eq %d))" |
397 | 0 | " or " |
398 | 0 | "((ip%s.src eq %s and udp.srcport eq %d) and " |
399 | 0 | "(ip%s.dst eq %s and udp.dstport eq %d))", |
400 | 0 | ip_version, src_addr_str, src_port, |
401 | 0 | ip_version, dst_addr_str, dst_port, |
402 | 0 | ip_version, dst_addr_str, dst_port, |
403 | 0 | ip_version, src_addr_str, src_port); |
404 | 0 | } |
405 | | |
406 | | |
407 | | /* Attach process info to a flow */ |
408 | | /* XXX - We depend on the UDP dissector finding the conversation first */ |
409 | | void |
410 | | add_udp_process_info(uint32_t frame_num, address *local_addr, address *remote_addr, |
411 | | uint16_t local_port, uint16_t remote_port, uint32_t uid, uint32_t pid, |
412 | | char *username, char *command) |
413 | 0 | { |
414 | 0 | conversation_t *conv; |
415 | 0 | struct udp_analysis *udpd; |
416 | 0 | udp_flow_t *flow = NULL; |
417 | |
|
418 | 0 | if (!udp_process_info) { |
419 | 0 | return; |
420 | 0 | } |
421 | | |
422 | 0 | conv = find_conversation(frame_num, local_addr, remote_addr, CONVERSATION_UDP, local_port, remote_port, 0); |
423 | 0 | if (!conv) { |
424 | 0 | return; |
425 | 0 | } |
426 | | |
427 | 0 | udpd = (struct udp_analysis *)conversation_get_proto_data(conv, proto_udp); |
428 | 0 | if (!udpd) { |
429 | 0 | return; |
430 | 0 | } |
431 | | |
432 | 0 | if ((cmp_address(local_addr, conversation_key_addr1(conv->key_ptr)) == 0) && (local_port == conversation_key_port1(conv->key_ptr))) { |
433 | 0 | flow = &udpd->flow1; |
434 | 0 | } |
435 | 0 | else if ((cmp_address(remote_addr, conversation_key_addr1(conv->key_ptr)) == 0) && (remote_port == conversation_key_port1(conv->key_ptr))) { |
436 | 0 | flow = &udpd->flow2; |
437 | 0 | } |
438 | 0 | if (!flow || flow->command) { |
439 | 0 | return; |
440 | 0 | } |
441 | | |
442 | 0 | flow->process_uid = uid; |
443 | 0 | flow->process_pid = pid; |
444 | 0 | flow->username = wmem_strdup(wmem_file_scope(), username); |
445 | 0 | flow->command = wmem_strdup(wmem_file_scope(), command); |
446 | 0 | } |
447 | | |
448 | | |
449 | | /* Return the current stream count */ |
450 | | uint32_t get_udp_stream_count(void) |
451 | 0 | { |
452 | 0 | return udp_stream_count; |
453 | 0 | } |
454 | | |
455 | | static void |
456 | | handle_export_pdu_dissection_table(packet_info *pinfo, tvbuff_t *tvb, uint32_t port) |
457 | 29.4k | { |
458 | 29.4k | if (have_tap_listener(exported_pdu_tap)) { |
459 | 0 | exp_pdu_data_item_t exp_pdu_data_table_value = {exp_pdu_data_dissector_table_num_value_size, exp_pdu_data_dissector_table_num_value_populate_data, NULL}; |
460 | |
|
461 | 0 | const exp_pdu_data_item_t *udp_exp_pdu_items[] = { |
462 | 0 | &exp_pdu_data_src_ip, |
463 | 0 | &exp_pdu_data_dst_ip, |
464 | 0 | &exp_pdu_data_port_type, |
465 | 0 | &exp_pdu_data_src_port, |
466 | 0 | &exp_pdu_data_dst_port, |
467 | 0 | &exp_pdu_data_orig_frame_num, |
468 | 0 | &exp_pdu_data_table_value, |
469 | 0 | NULL |
470 | 0 | }; |
471 | |
|
472 | 0 | exp_pdu_data_t *exp_pdu_data; |
473 | |
|
474 | 0 | exp_pdu_data_table_value.data = GUINT_TO_POINTER(port); |
475 | |
|
476 | 0 | exp_pdu_data = export_pdu_create_tags(pinfo, "udp.port", EXP_PDU_TAG_DISSECTOR_TABLE_NAME, udp_exp_pdu_items); |
477 | 0 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
478 | 0 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
479 | 0 | exp_pdu_data->pdu_tvb = tvb; |
480 | |
|
481 | 0 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
482 | 0 | } |
483 | 29.4k | } |
484 | | |
485 | | static void |
486 | | handle_export_pdu_heuristic(packet_info *pinfo, tvbuff_t *tvb, heur_dtbl_entry_t *hdtbl_entry) |
487 | 2.09k | { |
488 | 2.09k | exp_pdu_data_t *exp_pdu_data = NULL; |
489 | | |
490 | 2.09k | if (have_tap_listener(exported_pdu_tap)) { |
491 | 0 | if ((!hdtbl_entry->enabled) || |
492 | 0 | (hdtbl_entry->protocol != NULL && !proto_is_protocol_enabled(hdtbl_entry->protocol))) { |
493 | 0 | exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME); |
494 | 0 | } |
495 | 0 | else if (hdtbl_entry->protocol != NULL) { |
496 | 0 | exp_pdu_data = export_pdu_create_common_tags(pinfo, hdtbl_entry->short_name, EXP_PDU_TAG_HEUR_DISSECTOR_NAME); |
497 | 0 | } |
498 | |
|
499 | 0 | if (exp_pdu_data != NULL) { |
500 | 0 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
501 | 0 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
502 | 0 | exp_pdu_data->pdu_tvb = tvb; |
503 | |
|
504 | 0 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
505 | 0 | } |
506 | 0 | } |
507 | 2.09k | } |
508 | | |
509 | | static void |
510 | | handle_export_pdu_conversation(packet_info *pinfo, tvbuff_t *tvb, int uh_dport, int uh_sport) |
511 | 209 | { |
512 | 209 | if (have_tap_listener(exported_pdu_tap)) { |
513 | 0 | conversation_t *conversation = find_conversation(pinfo->num, &pinfo->dst, &pinfo->src, CONVERSATION_UDP, uh_dport, uh_sport, 0); |
514 | 0 | if (conversation != NULL) { |
515 | 0 | dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num); |
516 | 0 | if (handle != NULL) { |
517 | 0 | exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, dissector_handle_get_dissector_name(handle), EXP_PDU_TAG_DISSECTOR_NAME); |
518 | 0 | exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb); |
519 | 0 | exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb); |
520 | 0 | exp_pdu_data->pdu_tvb = tvb; |
521 | |
|
522 | 0 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
523 | 0 | } |
524 | 0 | } |
525 | 0 | } |
526 | 209 | } |
527 | | |
528 | | void |
529 | | decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, |
530 | | proto_tree *udp_tree, int uh_sport, int uh_dport, int uh_ulen) |
531 | 83.4k | { |
532 | 83.4k | tvbuff_t *next_tvb; |
533 | 83.4k | int low_port, high_port; |
534 | 83.4k | bool try_low_port, try_high_port; |
535 | 83.4k | int len, reported_len; |
536 | 83.4k | udp_p_info_t *udp_p_info; |
537 | | /* Save curr_layer_num as it might be changed by subdissector */ |
538 | 83.4k | uint8_t curr_layer_num = pinfo->curr_layer_num; |
539 | 83.4k | heur_dtbl_entry_t *hdtbl_entry; |
540 | 83.4k | exp_pdu_data_t *exp_pdu_data; |
541 | 83.4k | proto_tree* tree = proto_tree_get_parent_tree(udp_tree); |
542 | | |
543 | | /* populate per packet data variable */ |
544 | 83.4k | udp_p_info = (udp_p_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_udp, pinfo->curr_layer_num); |
545 | | |
546 | 83.4k | len = tvb_captured_length_remaining(tvb, offset); |
547 | 83.4k | reported_len = tvb_reported_length_remaining(tvb, offset); |
548 | 83.4k | if (uh_ulen != -1) { |
549 | | /* This is the length from the UDP header; the payload should be cut |
550 | | off at that length. (If our caller passed a value here, they |
551 | | are assumed to have checked that it's >= 8, and hence >= offset.) |
552 | | |
553 | | XXX - what if it's *greater* than the reported length? */ |
554 | 83.4k | if ((uh_ulen - offset) < reported_len) |
555 | 1.83k | reported_len = uh_ulen - offset; |
556 | 83.4k | if (len > reported_len) |
557 | 1.69k | len = reported_len; |
558 | 83.4k | } |
559 | | |
560 | 83.4k | proto_tree_add_bytes_format(udp_tree, hf_udp_payload, tvb, offset, |
561 | 83.4k | -1, NULL, "UDP payload (%u byte%s)", len, |
562 | 83.4k | plurality(len, "", "s")); |
563 | | |
564 | 83.4k | next_tvb = tvb_new_subset_length_caplen(tvb, offset, len, reported_len); |
565 | | |
566 | 83.4k | if (PINFO_FD_VISITED(pinfo)) { |
567 | 0 | if (udp_p_info && udp_p_info->heur_dtbl_entry != NULL) { |
568 | 0 | call_heur_dissector_direct(udp_p_info->heur_dtbl_entry, next_tvb, pinfo, tree, NULL); |
569 | 0 | handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); |
570 | 0 | return; |
571 | 0 | } |
572 | 0 | } |
573 | | |
574 | | /* Determine if this packet is part of a conversation and call dissector |
575 | | * for the conversation if available. |
576 | | * This search is done on the 'other' direction */ |
577 | 83.4k | if (try_conversation_dissector_strat(pinfo, CONVERSATION_UDP, |
578 | 83.4k | next_tvb, tree, NULL, NO_ADDR_B|NO_PORT_B, true)) { |
579 | 209 | handle_export_pdu_conversation(pinfo, next_tvb, uh_dport, uh_sport); |
580 | 209 | return; |
581 | 209 | } |
582 | | |
583 | | /* XXX - we ignore port numbers of 0, as some dissectors use a port |
584 | | number of 0 to disable the port, and as RFC 768 says that the source |
585 | | port in UDP datagrams is optional and is 0 if not used. */ |
586 | | |
587 | 83.2k | if (uh_sport > uh_dport) { |
588 | 31.0k | low_port = uh_dport; |
589 | 31.0k | high_port = uh_sport; |
590 | 31.0k | } |
591 | 52.1k | else { |
592 | 52.1k | low_port = uh_sport; |
593 | 52.1k | high_port = uh_dport; |
594 | 52.1k | } |
595 | | |
596 | 83.2k | try_low_port = false; |
597 | 83.2k | if (low_port != 0) { |
598 | 82.3k | if (dissector_is_uint_changed(udp_dissector_table, low_port)) { |
599 | 0 | if (dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree)) { |
600 | 0 | handle_export_pdu_dissection_table(pinfo, next_tvb, low_port); |
601 | 0 | return; |
602 | 0 | } |
603 | 0 | } |
604 | 82.3k | else { |
605 | | /* The default; try it later */ |
606 | 82.3k | try_low_port = true; |
607 | 82.3k | } |
608 | 82.3k | } |
609 | | |
610 | 83.2k | try_high_port = false; |
611 | 83.2k | if (high_port != 0) { |
612 | 82.8k | if (dissector_is_uint_changed(udp_dissector_table, high_port)) { |
613 | 0 | if (dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree)) { |
614 | 0 | handle_export_pdu_dissection_table(pinfo, next_tvb, high_port); |
615 | 0 | return; |
616 | 0 | } |
617 | 0 | } |
618 | 82.8k | else { |
619 | | /* The default; try it later */ |
620 | 82.8k | try_high_port = true; |
621 | 82.8k | } |
622 | 82.8k | } |
623 | | |
624 | 83.2k | if (try_heuristic_first) { |
625 | | /* Do lookup with the heuristic subdissector table */ |
626 | 0 | if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { |
627 | 0 | if (!udp_p_info) { |
628 | 0 | udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t); |
629 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_udp, curr_layer_num, udp_p_info); |
630 | 0 | } |
631 | |
|
632 | 0 | udp_p_info->heur_dtbl_entry = hdtbl_entry; |
633 | |
|
634 | 0 | handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); |
635 | 0 | return; |
636 | 0 | } |
637 | 0 | } |
638 | | |
639 | | /* Do lookups with the subdissector table. |
640 | | We try the port number with the lower value first, followed by the |
641 | | port number with the higher value. This means that, for packets |
642 | | where a dissector is registered for *both* port numbers: |
643 | | |
644 | | 1) we pick the same dissector for traffic going in both directions; |
645 | | |
646 | | 2) we prefer the port number that's more likely to be the right |
647 | | one (as that prefers well-known ports to reserved ports); |
648 | | |
649 | | although there is, of course, no guarantee that any such strategy |
650 | | will always pick the right port number. |
651 | | */ |
652 | | |
653 | 83.2k | if ((try_low_port) && dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree)) { |
654 | 21.4k | handle_export_pdu_dissection_table(pinfo, next_tvb, low_port); |
655 | 21.4k | return; |
656 | 21.4k | } |
657 | 61.7k | if ((try_high_port) && dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree)) { |
658 | 7.99k | handle_export_pdu_dissection_table(pinfo, next_tvb, high_port); |
659 | 7.99k | return; |
660 | 7.99k | } |
661 | | |
662 | 53.7k | if (!try_heuristic_first) { |
663 | | /* Do lookup with the heuristic subdissector table */ |
664 | 6.15k | if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { |
665 | 2.09k | if (!udp_p_info) { |
666 | 1 | udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t); |
667 | 1 | p_add_proto_data(wmem_file_scope(), pinfo, proto_udp, curr_layer_num, udp_p_info); |
668 | 1 | } |
669 | | |
670 | 2.09k | udp_p_info->heur_dtbl_entry = hdtbl_entry; |
671 | | |
672 | 2.09k | handle_export_pdu_heuristic(pinfo, next_tvb, udp_p_info->heur_dtbl_entry); |
673 | 2.09k | return; |
674 | 2.09k | } |
675 | 6.15k | } |
676 | | |
677 | 51.6k | call_data_dissector(next_tvb, pinfo, tree); |
678 | | |
679 | 51.6k | if (have_tap_listener(exported_pdu_tap)) { |
680 | 0 | exp_pdu_data = export_pdu_create_common_tags(pinfo, "data", EXP_PDU_TAG_DISSECTOR_NAME); |
681 | 0 | exp_pdu_data->tvb_captured_length = tvb_captured_length(next_tvb); |
682 | 0 | exp_pdu_data->tvb_reported_length = tvb_reported_length(next_tvb); |
683 | 0 | exp_pdu_data->pdu_tvb = next_tvb; |
684 | |
|
685 | 0 | tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data); |
686 | 0 | } |
687 | 51.6k | } |
688 | | |
689 | | int |
690 | | udp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
691 | | unsigned fixed_len, bool (*heuristic_check)(packet_info *, tvbuff_t *, int, void*), |
692 | | unsigned (*get_pdu_len)(packet_info *, tvbuff_t *, int, void*), |
693 | | dissector_t dissect_pdu, void* dissector_data) |
694 | 3.40k | { |
695 | 3.40k | volatile int offset = 0; |
696 | 3.40k | int offset_before; |
697 | 3.40k | unsigned captured_length_remaining; |
698 | 3.40k | volatile unsigned plen; |
699 | 3.40k | unsigned length; |
700 | 3.40k | tvbuff_t *next_tvb; |
701 | 3.40k | proto_item *item=NULL; |
702 | 3.40k | const char *saved_proto; |
703 | 3.40k | uint8_t curr_layer_num; |
704 | 3.40k | wmem_list_frame_t *frame; |
705 | | |
706 | 3.94k | while (tvb_reported_length_remaining(tvb, offset) > 0) { |
707 | | /* |
708 | | * We use "tvb_ensure_captured_length_remaining()" to make |
709 | | * sure there actually *is* data remaining. The protocol |
710 | | * we're handling could conceivably consists of a sequence of |
711 | | * fixed-length PDUs, and therefore the "get_pdu_len" routine |
712 | | * might not actually fetch anything from the tvbuff, and thus |
713 | | * might not cause an exception to be thrown if we've run past |
714 | | * the end of the tvbuff. |
715 | | * |
716 | | * This means we're guaranteed that "captured_length_remaining" is positive. |
717 | | */ |
718 | 3.58k | captured_length_remaining = tvb_ensure_captured_length_remaining(tvb, offset); |
719 | | |
720 | | /* |
721 | | * If there is a heuristic function, check it |
722 | | */ |
723 | 3.58k | if ((heuristic_check != NULL) && |
724 | 3.21k | ((*heuristic_check)(pinfo, tvb, offset, dissector_data) == false)) { |
725 | 3.04k | return offset; |
726 | 3.04k | } |
727 | | |
728 | | /* |
729 | | * Get the length of the PDU. |
730 | | */ |
731 | 540 | plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data); |
732 | 540 | if (plen == 0) { |
733 | | /* |
734 | | * Either protocol has variable length (which isn't supposed by UDP) |
735 | | * or packet doesn't belong to protocol |
736 | | */ |
737 | 1 | return offset; |
738 | 1 | } |
739 | | |
740 | 539 | if (plen < fixed_len) { |
741 | | /* |
742 | | * Either: |
743 | | * |
744 | | * 1) the length value extracted from the fixed-length portion |
745 | | * doesn't include the fixed-length portion's length, and |
746 | | * was so large that, when the fixed-length portion's |
747 | | * length was added to it, the total length overflowed; |
748 | | * |
749 | | * 2) the length value extracted from the fixed-length portion |
750 | | * includes the fixed-length portion's length, and the value |
751 | | * was less than the fixed-length portion's length, i.e. it |
752 | | * was bogus. |
753 | | * |
754 | | * Report this as a bounds error. |
755 | | */ |
756 | 1 | show_reported_bounds_error(tvb, pinfo, tree); |
757 | 1 | return offset; |
758 | 1 | } |
759 | | |
760 | 538 | curr_layer_num = pinfo->curr_layer_num-1; |
761 | 538 | frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers)); |
762 | 538 | while (frame && (proto_udp != (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame)))) { |
763 | 0 | frame = wmem_list_frame_prev(frame); |
764 | 0 | curr_layer_num--; |
765 | 0 | } |
766 | | |
767 | | /* |
768 | | * Display the PDU length as a field |
769 | | */ |
770 | 538 | item = proto_tree_add_uint((proto_tree *)p_get_proto_data(pinfo->pool, pinfo, proto_udp, curr_layer_num), |
771 | 538 | hf_udp_pdu_size, tvb, offset, plen, plen); |
772 | 538 | proto_item_set_generated(item); |
773 | | |
774 | | /* |
775 | | * Construct a tvbuff containing the amount of the payload we have |
776 | | * available. Make its reported length the amount of data in the PDU. |
777 | | */ |
778 | 538 | length = captured_length_remaining; |
779 | 538 | if (length > plen) |
780 | 182 | length = plen; |
781 | 538 | next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, plen); |
782 | | |
783 | | /* |
784 | | * Dissect the PDU. |
785 | | * |
786 | | * If it gets an error that means there's no point in |
787 | | * dissecting any more PDUs, rethrow the exception in |
788 | | * question. |
789 | | * |
790 | | * If it gets any other error, report it and continue, as that |
791 | | * means that PDU got an error, but that doesn't mean we should |
792 | | * stop dissecting PDUs within this frame or chunk of reassembled |
793 | | * data. |
794 | | */ |
795 | 538 | saved_proto = pinfo->current_proto; |
796 | 538 | TRY { |
797 | 533 | (*dissect_pdu)(next_tvb, pinfo, tree, dissector_data); |
798 | 533 | } |
799 | 538 | CATCH_NONFATAL_ERRORS { |
800 | | /* Restore the private_data structure in case one of the |
801 | | * called dissectors modified it (and, due to the exception, |
802 | | * was unable to restore it). |
803 | | */ |
804 | 27 | show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); |
805 | | |
806 | | /* |
807 | | * Restore the saved protocol as well; we do this after |
808 | | * show_exception(), so that the "Malformed packet" indication |
809 | | * shows the protocol for which dissection failed. |
810 | | */ |
811 | 27 | pinfo->current_proto = saved_proto; |
812 | 27 | } |
813 | 538 | ENDTRY; |
814 | | |
815 | | /* |
816 | | * Step to the next PDU. |
817 | | * Make sure we don't overflow. |
818 | | */ |
819 | 538 | offset_before = offset; |
820 | 538 | offset += plen; |
821 | 538 | if (offset <= offset_before) |
822 | 0 | break; |
823 | 538 | } |
824 | | |
825 | 356 | return offset; |
826 | 3.40k | } |
827 | | |
828 | | static bool |
829 | | capture_udp(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_) |
830 | 0 | { |
831 | 0 | uint16_t src_port, dst_port, low_port, high_port; |
832 | |
|
833 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 4)) |
834 | 0 | return false; |
835 | | |
836 | 0 | capture_dissector_increment_count(cpinfo, proto_udp); |
837 | |
|
838 | 0 | src_port = pntohu16(&pd[offset]); |
839 | 0 | dst_port = pntohu16(&pd[offset+2]); |
840 | |
|
841 | 0 | if (src_port > dst_port) { |
842 | 0 | low_port = dst_port; |
843 | 0 | high_port = src_port; |
844 | 0 | } |
845 | 0 | else { |
846 | 0 | low_port = src_port; |
847 | 0 | high_port = dst_port; |
848 | 0 | } |
849 | |
|
850 | 0 | if (low_port != 0 && try_capture_dissector("udp.port", low_port, pd, offset+20, len, cpinfo, pseudo_header)) |
851 | 0 | return true; |
852 | | |
853 | 0 | if (high_port != 0 && try_capture_dissector("udp.port", high_port, pd, offset+20, len, cpinfo, pseudo_header)) |
854 | 0 | return true; |
855 | | |
856 | | /* We've at least identified one type of packet, so this shouldn't be "other" */ |
857 | 0 | return true; |
858 | 0 | } |
859 | | |
860 | | /* Calculate the timestamps relative to this conversation */ |
861 | | static void |
862 | | udp_compute_timestamps(packet_info *pinfo, struct udp_analysis *udp_data, int proto) |
863 | 83.4k | { |
864 | 83.4k | if (!udp_data) |
865 | 0 | return; |
866 | | |
867 | | /* get per packet date for UDP/UDP-Lite based on protocol id */ |
868 | 83.4k | udp_p_info_t *udp_per_packet_data = (udp_p_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto, pinfo->curr_layer_num); |
869 | | |
870 | 83.4k | if(!udp_per_packet_data) { |
871 | 83.4k | udp_per_packet_data = wmem_new0(wmem_file_scope(), udp_p_info_t); |
872 | 83.4k | p_add_proto_data(wmem_file_scope(), pinfo, proto, pinfo->curr_layer_num, udp_per_packet_data); |
873 | 83.4k | } |
874 | | |
875 | | /* pre-increment so packet numbers start at 1 */ |
876 | 83.4k | udp_per_packet_data->pnum = ++udp_data->pnum; |
877 | | |
878 | 83.4k | nstime_delta(&udp_per_packet_data->ts_delta, &pinfo->abs_ts, &udp_data->ts_prev); |
879 | 83.4k | udp_per_packet_data->ts_delta_valid = true; |
880 | | |
881 | 83.4k | udp_data->ts_prev = pinfo->abs_ts; |
882 | 83.4k | } |
883 | | |
884 | | /* Add a subtree with the timestamps relative to this conversation */ |
885 | | static void |
886 | | udp_print_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree, struct udp_analysis *udp_data, int proto) |
887 | 83.4k | { |
888 | 83.4k | proto_item *item; |
889 | 83.4k | proto_tree *tree; |
890 | 83.4k | nstime_t ts; |
891 | | |
892 | 83.4k | if (!udp_data) |
893 | 0 | return; |
894 | | |
895 | | /* get per packet date for UDP/UDP-Lite based on protocol id */ |
896 | 83.4k | udp_p_info_t *udp_per_packet_data = (udp_p_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto, pinfo->curr_layer_num); |
897 | | |
898 | 83.4k | if (udp_per_packet_data) { |
899 | 83.4k | item = proto_tree_add_uint(parent_tree, hf_udp_stream_pnum, tvb, 0, 0, |
900 | 83.4k | udp_per_packet_data->pnum); |
901 | 83.4k | proto_item_set_generated(item); |
902 | 83.4k | } |
903 | | |
904 | 83.4k | tree = proto_tree_add_subtree(parent_tree, tvb, 0, 0, ett_udp_timestamps, &item, "Timestamps"); |
905 | 83.4k | proto_item_set_generated(item); |
906 | | |
907 | 83.4k | nstime_delta(&ts, &pinfo->abs_ts, &udp_data->ts_first); |
908 | 83.4k | item = proto_tree_add_time(tree, hf_udp_ts_relative, tvb, 0, 0, &ts); |
909 | 83.4k | proto_item_set_generated(item); |
910 | | |
911 | 83.4k | if (udp_per_packet_data && udp_per_packet_data->ts_delta_valid) { |
912 | 83.4k | item = proto_tree_add_time(tree, hf_udp_ts_delta, tvb, 0, 0, |
913 | 83.4k | &udp_per_packet_data->ts_delta); |
914 | 83.4k | proto_item_set_generated(item); |
915 | 83.4k | } |
916 | 83.4k | } |
917 | | |
918 | | static void |
919 | | udp_handle_timestamps(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, struct udp_analysis *udp_data, uint32_t ip_proto) |
920 | 83.4k | { |
921 | 83.4k | int proto_id = (ip_proto == IP_PROTO_UDP ? proto_udp : proto_udplite); |
922 | | |
923 | | /* |
924 | | * Calculate the timestamps relative to this conversation (but only on the |
925 | | * first run when frames are accessed sequentially) |
926 | | */ |
927 | 83.4k | if (!PINFO_FD_VISITED(pinfo)) |
928 | 83.4k | udp_compute_timestamps(pinfo, udp_data, proto_id); |
929 | | |
930 | | /* handle conversation timestamps */ |
931 | 83.4k | udp_print_timestamps(pinfo, tvb, tree, udp_data, proto_id); |
932 | 83.4k | } |
933 | | |
934 | | static void |
935 | | dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t ip_proto) |
936 | 83.4k | { |
937 | 83.4k | proto_tree *udp_tree = NULL; |
938 | 83.4k | proto_item *ti, *item, *hidden_item, *calc_item; |
939 | 83.4k | proto_item *src_port_item, *dst_port_item, *len_cov_item; |
940 | 83.4k | unsigned len; |
941 | 83.4k | unsigned reported_len; |
942 | 83.4k | vec_t cksum_vec[4]; |
943 | 83.4k | uint32_t phdr[2]; |
944 | 83.4k | uint16_t computed_cksum; |
945 | 83.4k | int offset = 0; |
946 | 83.4k | e_udphdr *udph; |
947 | 83.4k | proto_tree *checksum_tree; |
948 | 83.4k | conversation_t *conv = NULL; |
949 | 83.4k | struct udp_analysis *udpd = NULL; |
950 | 83.4k | proto_tree *process_tree; |
951 | 83.4k | bool udp_jumbogram = false; |
952 | | |
953 | 83.4k | udph = wmem_new0(pinfo->pool, e_udphdr); |
954 | 83.4k | udph->uh_sport = tvb_get_ntohs(tvb, offset); |
955 | 83.4k | udph->uh_dport = tvb_get_ntohs(tvb, offset + 2); |
956 | 83.4k | copy_address_shallow(&udph->ip_src, &pinfo->src); |
957 | 83.4k | copy_address_shallow(&udph->ip_dst, &pinfo->dst); |
958 | | |
959 | 83.4k | col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDP-Lite"); |
960 | 83.4k | col_clear(pinfo->cinfo, COL_INFO); |
961 | 83.4k | col_append_ports(pinfo->cinfo, COL_INFO, PT_UDP, udph->uh_sport, udph->uh_dport); |
962 | | |
963 | 83.4k | reported_len = tvb_reported_length(tvb); |
964 | 83.4k | len = tvb_captured_length(tvb); |
965 | | |
966 | 83.4k | ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA); |
967 | 83.4k | if (udp_summary_in_tree && tree) { |
968 | 83.4k | proto_item_append_text(ti, ", Src Port: %s, Dst Port: %s", |
969 | 83.4k | port_with_resolution_to_str(pinfo->pool, PT_UDP, udph->uh_sport), |
970 | 83.4k | port_with_resolution_to_str(pinfo->pool, PT_UDP, udph->uh_dport)); |
971 | 83.4k | } |
972 | 83.4k | udp_tree = proto_item_add_subtree(ti, ett_udp); |
973 | 83.4k | p_add_proto_data(pinfo->pool, pinfo, proto_udp, pinfo->curr_layer_num, udp_tree); |
974 | | |
975 | 83.4k | src_port_item = proto_tree_add_item(udp_tree, hf_udp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN); |
976 | 83.4k | dst_port_item = proto_tree_add_item(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, ENC_BIG_ENDIAN); |
977 | | |
978 | 83.4k | p_add_proto_data(pinfo->pool, pinfo, hf_udp_srcport, pinfo->curr_layer_num, GUINT_TO_POINTER(udph->uh_sport)); |
979 | 83.4k | p_add_proto_data(pinfo->pool, pinfo, hf_udp_dstport, pinfo->curr_layer_num, GUINT_TO_POINTER(udph->uh_dport)); |
980 | | |
981 | 83.4k | hidden_item = proto_tree_add_item(udp_tree, hf_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN); |
982 | 83.4k | proto_item_set_hidden(hidden_item); |
983 | 83.4k | hidden_item = proto_tree_add_item(udp_tree, hf_udp_port, tvb, offset + 2, 2, ENC_BIG_ENDIAN); |
984 | 83.4k | proto_item_set_hidden(hidden_item); |
985 | | |
986 | | /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code |
987 | | * further assumes that 3 attempts are made per hop */ |
988 | 83.4k | if ((udph->uh_sport > (32768 + 666)) && (udph->uh_sport <= (32768 + 666 + 30))) { |
989 | 2 | expert_add_info_format(pinfo, src_port_item, &ei_udp_possible_traceroute, "Possible traceroute: hop #%u, attempt #%u", |
990 | 2 | ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1, |
991 | 2 | ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1); |
992 | 2 | } |
993 | 83.4k | if ((udph->uh_dport > (32768 + 666)) && (udph->uh_dport <= (32768 + 666 + 30))) { |
994 | 57 | expert_add_info_format(pinfo, dst_port_item, &ei_udp_possible_traceroute, "Possible traceroute: hop #%u, attempt #%u", |
995 | 57 | ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1, |
996 | 57 | ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1); |
997 | 57 | } |
998 | | |
999 | 83.4k | udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset + 4); |
1000 | 83.4k | if (ip_proto == IP_PROTO_UDP) { |
1001 | 83.4k | len_cov_item = proto_tree_add_item(udp_tree, hf_udp_length, tvb, offset + 4, 2, ENC_BIG_ENDIAN); |
1002 | 83.4k | if (udph->uh_ulen == 0 && pinfo->src.type == AT_IPv6) { |
1003 | | /* RFC 2675 (section 4) - UDP Jumbograms */ |
1004 | 50 | udph->uh_ulen = udph->uh_sum_cov = reported_len; |
1005 | 50 | udp_jumbogram = true; |
1006 | 50 | } |
1007 | 83.4k | if (udph->uh_ulen < 8) { |
1008 | | /* Bogus length - it includes the header, so it must be >= 8. */ |
1009 | 5 | proto_item_append_text(len_cov_item, " (bogus, must be >= 8)"); |
1010 | 5 | expert_add_info_format(pinfo, len_cov_item, &ei_udp_length_bad, "Bad length value %u < 8", udph->uh_ulen); |
1011 | 5 | col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen); |
1012 | 5 | return; |
1013 | 5 | } |
1014 | 83.4k | if ((udph->uh_ulen > reported_len) && (!pinfo->fragmented) && (!pinfo->flags.in_error_pkt)) { |
1015 | | /* Bogus length - it goes past the end of the IP payload */ |
1016 | 80.9k | proto_item_append_text(len_cov_item, " (bogus, payload length %u)", reported_len); |
1017 | 80.9k | expert_add_info_format(pinfo, len_cov_item, &ei_udp_length_bad, "Bad length value %u > IP payload length", udph->uh_ulen); |
1018 | 80.9k | col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen); |
1019 | | /*return;*/ |
1020 | 80.9k | } |
1021 | 83.4k | if (udp_jumbogram && (udph->uh_ulen < 65536)) { |
1022 | 50 | expert_add_info(pinfo, len_cov_item, &ei_udp_length_bad_zero); |
1023 | 50 | } |
1024 | 83.4k | } |
1025 | 33 | else { |
1026 | 33 | len_cov_item = proto_tree_add_item(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, ENC_BIG_ENDIAN); |
1027 | 33 | udph->uh_ulen = reported_len; |
1028 | 33 | if (udph->uh_sum_cov == 0) { |
1029 | 0 | udph->uh_sum_cov = reported_len; |
1030 | 0 | } |
1031 | 33 | item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen); |
1032 | 33 | proto_item_set_generated(item); |
1033 | 33 | if ((udph->uh_sum_cov < 8) || (udph->uh_sum_cov > udph->uh_ulen)) { |
1034 | | /* Bogus coverage - it includes the header, so it must be >= 8, and no larger than the IP payload size. */ |
1035 | 0 | proto_item_append_text(len_cov_item, " (bogus, must be >= 8 and <= %u)", udph->uh_ulen); |
1036 | 0 | expert_add_info_format(pinfo, len_cov_item, &ei_udplite_checksum_coverage_bad, "Bad checksum coverage length value %u < 8 or > %u", |
1037 | 0 | udph->uh_sum_cov, udph->uh_ulen); |
1038 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]", |
1039 | 0 | udph->uh_sum_cov, udph->uh_ulen); |
1040 | 0 | if (!udplite_ignore_checksum_coverage) { |
1041 | 0 | return; |
1042 | 0 | } |
1043 | 0 | } |
1044 | 33 | } |
1045 | | |
1046 | 83.4k | col_append_str_uint(pinfo->cinfo, COL_INFO, "Len", udph->uh_ulen - 8, " "); /* Payload length */ |
1047 | 83.4k | if (udp_jumbogram) |
1048 | 50 | col_append_str(pinfo->cinfo, COL_INFO, " [Jumbogram]"); |
1049 | | |
1050 | 83.4k | udph->uh_sum = tvb_get_ntohs(tvb, offset + 6); |
1051 | 83.4k | if (udph->uh_sum == 0) { |
1052 | | /* No checksum supplied in the packet. */ |
1053 | | |
1054 | 4.15k | bool ignore_zero_checksum = (ip_proto == IP_PROTO_UDP) && |
1055 | 4.15k | ((pinfo->src.type == AT_IPv4) || |
1056 | 4.15k | (pinfo->src.type == AT_NONE) || |
1057 | 225 | ((pinfo->src.type == AT_IPv6) && udp_ignore_ipv6_zero_checksum)); |
1058 | 4.15k | proto_checksum_enum_e checksum_status; |
1059 | | |
1060 | 4.15k | item = proto_tree_add_item(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, ENC_BIG_ENDIAN); |
1061 | 4.15k | if (ignore_zero_checksum || pinfo->flags.in_error_pkt) { |
1062 | 3.93k | proto_item_append_text(item, " [zero-value ignored]"); |
1063 | 3.93k | checksum_status = PROTO_CHECKSUM_E_NOT_PRESENT; |
1064 | 3.93k | } |
1065 | 224 | else { |
1066 | 224 | proto_item_append_text(item, " [zero-value illegal]"); |
1067 | 224 | checksum_status = PROTO_CHECKSUM_E_ILLEGAL; |
1068 | 224 | expert_add_info(pinfo, item, &ei_udp_checksum_zero); |
1069 | 224 | col_append_str(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]"); |
1070 | 224 | } |
1071 | 4.15k | checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); |
1072 | 4.15k | item = proto_tree_add_uint(checksum_tree, hf_udp_checksum_status, tvb, offset + 6, 2, checksum_status); |
1073 | 4.15k | proto_item_set_generated(item); |
1074 | 4.15k | } |
1075 | 79.3k | else if (!pinfo->fragmented && (len >= reported_len) && |
1076 | 78.8k | (len >= udph->uh_sum_cov) && (reported_len >= udph->uh_sum_cov) && |
1077 | 1.77k | (udph->uh_sum_cov >= 8)) { |
1078 | | /* The packet isn't part of a fragmented datagram and isn't |
1079 | | truncated, so we can checksum it. |
1080 | | XXX - make a bigger scatter-gather list once we do fragment |
1081 | | reassembly? */ |
1082 | | |
1083 | 1.77k | if (((ip_proto == IP_PROTO_UDP) && udp_check_checksum) || |
1084 | 1.77k | ((ip_proto == IP_PROTO_UDPLITE) && udplite_check_checksum)) { |
1085 | | /* Set up the fields of the pseudo-header. */ |
1086 | 0 | SET_CKSUM_VEC_PTR(cksum_vec[0], (const uint8_t *)pinfo->src.data, pinfo->src.len); |
1087 | 0 | SET_CKSUM_VEC_PTR(cksum_vec[1], (const uint8_t *)pinfo->dst.data, pinfo->dst.len); |
1088 | 0 | switch (pinfo->src.type) { |
1089 | | |
1090 | 0 | case AT_IPv4: |
1091 | 0 | if (ip_proto == IP_PROTO_UDP) |
1092 | 0 | phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen); |
1093 | 0 | else |
1094 | 0 | phdr[0] = g_htonl((ip_proto<<16) | reported_len); |
1095 | 0 | SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)&phdr, 4); |
1096 | 0 | break; |
1097 | | |
1098 | 0 | case AT_IPv6: |
1099 | 0 | if (ip_proto == IP_PROTO_UDP) |
1100 | 0 | phdr[0] = g_htonl(udph->uh_ulen); |
1101 | 0 | else |
1102 | 0 | phdr[0] = g_htonl(reported_len); |
1103 | 0 | phdr[1] = g_htonl(ip_proto); |
1104 | 0 | SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)&phdr, 8); |
1105 | 0 | break; |
1106 | | |
1107 | 0 | case AT_ILNP_NID: |
1108 | 0 | if (ip_proto == IP_PROTO_UDP) |
1109 | 0 | phdr[0] = g_htonl(udph->uh_ulen); |
1110 | 0 | else |
1111 | 0 | phdr[0] = g_htonl(reported_len); |
1112 | 0 | phdr[1] = g_htonl(ip_proto); |
1113 | 0 | SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *)&phdr, 8); |
1114 | 0 | break; |
1115 | | |
1116 | 0 | default: |
1117 | | /* UDP runs only atop IPv4 and IPv6.... */ |
1118 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1119 | 0 | break; |
1120 | 0 | } |
1121 | | /* |
1122 | | * in_cksum() should never return 0xFFFF here, because, to quote |
1123 | | * RFC 1624 section 3 "Discussion": |
1124 | | * |
1125 | | * In one's complement, there are two representations of |
1126 | | * zero: the all zero and the all one bit values, often |
1127 | | * referred to as +0 and -0. One's complement addition |
1128 | | * of non-zero inputs can produce -0 as a result, but |
1129 | | * never +0. Since there is guaranteed to be at least |
1130 | | * one non-zero field in the IP header, and the checksum |
1131 | | * field in the protocol header is the complement of the |
1132 | | * sum, the checksum field can never contain ~(+0), which |
1133 | | * is -0 (0xFFFF). It can, however, contain ~(-0), which |
1134 | | * is +0 (0x0000). |
1135 | | * |
1136 | | * RFC 1624 is discussing the checksum of the *IPv4* header, |
1137 | | * where the "version" field is 4, ensuring that, in a valid |
1138 | | * IPv4 header, there is at least one non-zero field, but it |
1139 | | * also applies to a UDP datagram, because the length includes |
1140 | | * the length of the UDP header, so at least one field in a UDP |
1141 | | * datagram is non-zero. |
1142 | | * |
1143 | | * in_cksum() returns the negation of the one's-complement |
1144 | | * sum of all the data handed to it, and that data won't be |
1145 | | * all zero, so the sum won't be 0 (+0), and thus the negation |
1146 | | * won't be -0, i.e. won't be 0xFFFF. |
1147 | | */ |
1148 | | /* |
1149 | | * Linux and Windows, at least, when performing Local Checksum |
1150 | | * Offload (during Generic Segmentation Offload or at other |
1151 | | * times), place the one's complement sum of the pseudo header |
1152 | | * in the checksum fields initially, which provides the necessary |
1153 | | * correction when a device (or driver) computes the one's |
1154 | | * complement checksum of each buffer in the skbuff. Since it is |
1155 | | * not inverted, the partial_cksum will never be 0x0000 by the |
1156 | | * same argument as above. |
1157 | | */ |
1158 | 0 | uint16_t partial_cksum; |
1159 | 0 | SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, offset, udph->uh_sum_cov); |
1160 | 0 | computed_cksum = in_cksum_ret_partial(&cksum_vec[0], 4, &partial_cksum); |
1161 | 0 | uint16_t shouldbe_cksum = in_cksum_shouldbe(udph->uh_sum, computed_cksum); |
1162 | 0 | if (computed_cksum != 0 && udph->uh_sum == g_htons(partial_cksum)) { |
1163 | | /* Don't use PROTO_CHECKSUM_IN_CKSUM because we expect the value |
1164 | | * to match what we pass in. */ |
1165 | 0 | item = proto_tree_add_checksum(udp_tree, tvb, offset + 6, hf_udp_checksum, hf_udp_checksum_status, &ei_udp_checksum_bad, |
1166 | 0 | pinfo, g_htons(partial_cksum), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); |
1167 | 0 | proto_item_append_text(item, " (matches partial checksum, not 0x%04x, likely caused by \"UDP checksum offload\")", shouldbe_cksum); |
1168 | 0 | expert_add_info(pinfo, item, &ei_udp_checksum_partial); |
1169 | 0 | computed_cksum = 0; |
1170 | | /* XXX: Find some way hint to QUIC (or other dissectors) that |
1171 | | * GSO is a possibility so that extra effort can be made to |
1172 | | * recover coalesced PDUs? E.g., by searching heuristically |
1173 | | * through the payload for the DCID bytes if they're non-zero? |
1174 | | * Add a new status, e.g. PROTO_CHECKSUM_E_PARTIAL? |
1175 | | */ |
1176 | 0 | } else { |
1177 | 0 | item = proto_tree_add_checksum(udp_tree, tvb, offset + 6, hf_udp_checksum, hf_udp_checksum_status, &ei_udp_checksum_bad, |
1178 | 0 | pinfo, computed_cksum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM); |
1179 | 0 | } |
1180 | 0 | checksum_tree = proto_item_add_subtree(item, ett_udp_checksum); |
1181 | |
|
1182 | 0 | if (computed_cksum != 0) { |
1183 | 0 | proto_item_append_text(item, " (maybe caused by \"UDP checksum offload\"?)"); |
1184 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]"); |
1185 | 0 | calc_item = proto_tree_add_uint(checksum_tree, hf_udp_checksum_calculated, |
1186 | 0 | tvb, offset + 6, 2, in_cksum_shouldbe(udph->uh_sum, computed_cksum)); |
1187 | 0 | } |
1188 | 0 | else { |
1189 | 0 | calc_item = proto_tree_add_uint(checksum_tree, hf_udp_checksum_calculated, |
1190 | 0 | tvb, offset + 6, 2, shouldbe_cksum); |
1191 | 0 | } |
1192 | 0 | proto_item_set_generated(calc_item); |
1193 | |
|
1194 | 0 | } |
1195 | 1.77k | else { |
1196 | 1.77k | proto_tree_add_checksum(udp_tree, tvb, offset + 6, hf_udp_checksum, hf_udp_checksum_status, &ei_udp_checksum_bad, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); |
1197 | 1.77k | } |
1198 | 1.77k | } |
1199 | 77.5k | else { |
1200 | 77.5k | proto_tree_add_checksum(udp_tree, tvb, offset + 6, hf_udp_checksum, hf_udp_checksum_status, &ei_udp_checksum_bad, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); |
1201 | 77.5k | } |
1202 | | |
1203 | | /* Skip over header */ |
1204 | 83.4k | offset += 8; |
1205 | | |
1206 | 83.4k | pinfo->ptype = PT_UDP; |
1207 | 83.4k | pinfo->srcport = udph->uh_sport; |
1208 | 83.4k | pinfo->destport = udph->uh_dport; |
1209 | | |
1210 | | /* Find (and extend) an existing conversation, or create a new one. |
1211 | | * Don't try finding at all costs (NO_GREEDY) |
1212 | | */ |
1213 | 83.4k | conv = find_conversation_strat(pinfo, CONVERSATION_UDP, NO_GREEDY, false); |
1214 | 83.4k | if(!conv) { |
1215 | 11.0k | conv=conversation_new_strat(pinfo, CONVERSATION_UDP, 0); |
1216 | 11.0k | } |
1217 | 72.4k | else { |
1218 | | /* Explicitly and immediately move forward the conversation last_frame */ |
1219 | 72.4k | if (!(pinfo->fd->visited) && (pinfo->num > conv->last_frame)) { |
1220 | 72.3k | conv->last_frame = pinfo->num; |
1221 | 72.3k | } |
1222 | 72.4k | } |
1223 | | |
1224 | 83.4k | udpd = get_udp_conversation_data(conv, pinfo); |
1225 | 83.4k | if (udpd) { |
1226 | 83.4k | item = proto_tree_add_uint(udp_tree, hf_udp_stream, tvb, offset, 0, udpd->stream); |
1227 | 83.4k | proto_item_set_generated(item); |
1228 | 83.4k | p_add_proto_data(pinfo->pool, pinfo, hf_udp_stream, pinfo->curr_proto_layer_num, GUINT_TO_POINTER(udpd->stream + 1)); // Add 1 to distinguish stream 0 from NULL |
1229 | | |
1230 | | /* Copy the stream index into the header as well to make it available |
1231 | | * to tap listeners. |
1232 | | */ |
1233 | 83.4k | udph->uh_stream = udpd->stream; |
1234 | | |
1235 | | /* Copy the stream index into pinfo as well to make it available |
1236 | | * to callback functions (essentially conversation following events in GUI) |
1237 | | */ |
1238 | 83.4k | pinfo->stream_id = udpd->stream; |
1239 | | |
1240 | | /* Follow-up of the conversation over ICMP errors. |
1241 | | * When coming over an error packet (typically ICMP), we want to save the |
1242 | | * conversation type, and have a specific tracking then we can match with |
1243 | | * ordinary, non error packets. |
1244 | | */ |
1245 | 83.4k | if (pinfo->flags.in_error_pkt) { |
1246 | | /* Save the conversation type */ |
1247 | 2 | pinfo->track_ctype = CONVERSATION_UDP; |
1248 | | |
1249 | 2 | conversation_t *err_conv = NULL; |
1250 | 2 | err_conv = find_conversation_err_pkts(pinfo->num, CONVERSATION_UDP, udpd->stream, conv->conv_index); |
1251 | 2 | if(!err_conv) { |
1252 | | /* Create the conversation tracking the ordinary UDP conversation */ |
1253 | 2 | err_conv = conversation_new_err_pkts(pinfo->num, CONVERSATION_UDP, udpd->stream, conv->conv_index); |
1254 | | |
1255 | | /* Align the setup_frame with the UDP conversation's one */ |
1256 | 2 | err_conv->setup_frame = conv->setup_frame; |
1257 | 2 | } |
1258 | 0 | else if (pinfo->num > err_conv->last_frame) { |
1259 | | /* If we have multiple error packets related to this same UDP conversation, |
1260 | | * extend the tracker conversation. |
1261 | | */ |
1262 | 0 | err_conv->last_frame = pinfo->num; |
1263 | 0 | } |
1264 | 2 | } |
1265 | 83.4k | } |
1266 | | |
1267 | 83.4k | tap_queue_packet(udp_tap, pinfo, udph); |
1268 | | |
1269 | 83.4k | if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) { |
1270 | 0 | process_tree = proto_tree_add_subtree(udp_tree, tvb, offset, 0, ett_udp_process_info, &ti, "Process Information"); |
1271 | 0 | proto_item_set_generated(ti); |
1272 | 0 | if (udpd->fwd && udpd->fwd->command) { |
1273 | 0 | proto_tree_add_uint(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0, udpd->fwd->process_uid); |
1274 | 0 | proto_tree_add_uint(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0, udpd->fwd->process_pid); |
1275 | 0 | proto_tree_add_string(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0, udpd->fwd->username); |
1276 | 0 | proto_tree_add_string(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0, udpd->fwd->command); |
1277 | 0 | } |
1278 | 0 | if (udpd->rev->command) { |
1279 | 0 | proto_tree_add_uint(process_tree, hf_udp_proc_src_uid, tvb, 0, 0, udpd->rev->process_uid); |
1280 | 0 | proto_tree_add_uint(process_tree, hf_udp_proc_src_pid, tvb, 0, 0, udpd->rev->process_pid); |
1281 | 0 | proto_tree_add_string(process_tree, hf_udp_proc_src_uname, tvb, 0, 0, udpd->rev->username); |
1282 | 0 | proto_tree_add_string(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0, udpd->rev->command); |
1283 | 0 | } |
1284 | 0 | } |
1285 | | |
1286 | | /* Do we need to calculate timestamps relative to the udp-stream? */ |
1287 | | /* Different boolean preferences have to be checked. */ |
1288 | | /* If the protocol is UDP then the UDP preference */ |
1289 | 83.4k | if (!pinfo->flags.in_error_pkt && |
1290 | 83.4k | ((ip_proto == IP_PROTO_UDP && udp_calculate_ts) |
1291 | | /* Otherwise the UDP-Lite preference */ |
1292 | 83.4k | || (ip_proto == IP_PROTO_UDPLITE && udplite_calculate_ts))) { |
1293 | 83.4k | udp_handle_timestamps(pinfo, tvb, udp_tree, udpd, ip_proto); |
1294 | 83.4k | } |
1295 | | |
1296 | 83.4k | if (udph->uh_ulen == 8) { |
1297 | | /* Empty UDP payload, nothing left to do. */ |
1298 | 3 | return; |
1299 | 3 | } |
1300 | | |
1301 | | /* |
1302 | | * Call sub-dissectors. |
1303 | | * |
1304 | | * XXX - should we do this if this is included in an error packet? |
1305 | | * It might be nice to see the details of the packet that caused the |
1306 | | * ICMP error, but it might not be nice to have the dissector update |
1307 | | * state based on it. |
1308 | | * Also, we probably don't want to run UDP taps on those packets. |
1309 | | * |
1310 | | * We definitely don't want to do it for an error packet if there's |
1311 | | * nothing left in the packet. |
1312 | | */ |
1313 | 83.4k | if (!pinfo->flags.in_error_pkt || (tvb_captured_length_remaining(tvb, offset) > 0)) { |
1314 | | /* If the user has a "Follow UDP Stream" window loading, pass a pointer |
1315 | | * to the payload tvb through the tap system. */ |
1316 | 83.4k | if (have_tap_listener(udp_follow_tap)) { |
1317 | 0 | follow_stream_tap_data_t *follow_data = wmem_new0(pinfo->pool, follow_stream_tap_data_t); |
1318 | 0 | follow_data->tvb = tvb_new_subset_length(tvb, offset, udph->uh_ulen - 8); |
1319 | 0 | follow_data->stream_id = udph->uh_stream; |
1320 | 0 | follow_data->substream_id = SUBSTREAM_UNUSED; |
1321 | 0 | copy_address_shallow(&follow_data->src, &udph->ip_src); |
1322 | 0 | copy_address_shallow(&follow_data->dst, &udph->ip_dst); |
1323 | 0 | follow_data->ptype = PT_UDP; |
1324 | 0 | follow_data->srcport = udph->uh_sport; |
1325 | 0 | follow_data->destport = udph->uh_dport; |
1326 | |
|
1327 | 0 | tap_queue_packet(udp_follow_tap, pinfo, follow_data); |
1328 | 0 | } |
1329 | | |
1330 | 83.4k | decode_udp_ports(tvb, offset, pinfo, udp_tree, udph->uh_sport, udph->uh_dport, udph->uh_ulen); |
1331 | 83.4k | } |
1332 | 83.4k | } |
1333 | | |
1334 | | static int |
1335 | | dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1336 | 83.4k | { |
1337 | 83.4k | dissect(tvb, pinfo, tree, IP_PROTO_UDP); |
1338 | 83.4k | return tvb_captured_length(tvb); |
1339 | 83.4k | } |
1340 | | |
1341 | | static int |
1342 | | dissect_udplite(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1343 | 0 | { |
1344 | 0 | dissect(tvb, pinfo, tree, IP_PROTO_UDPLITE); |
1345 | 0 | return tvb_captured_length(tvb); |
1346 | 0 | } |
1347 | | |
1348 | | static void |
1349 | | udp_init(void) |
1350 | 15 | { |
1351 | 15 | udp_stream_count = 0; |
1352 | 15 | } |
1353 | | |
1354 | | void |
1355 | | proto_register_udp(void) |
1356 | 15 | { |
1357 | 15 | static hf_register_info hf_udp[] = { |
1358 | 15 | { &hf_udp_srcport, |
1359 | 15 | { "Source Port", "udp.srcport", |
1360 | 15 | FT_UINT16, BASE_PT_UDP, NULL, 0x0, |
1361 | 15 | NULL, HFILL } |
1362 | 15 | }, |
1363 | 15 | { &hf_udp_dstport, |
1364 | 15 | { "Destination Port", "udp.dstport", |
1365 | 15 | FT_UINT16, BASE_PT_UDP, NULL, 0x0, |
1366 | 15 | NULL, HFILL } |
1367 | 15 | }, |
1368 | 15 | { &hf_udp_port, |
1369 | 15 | { "Source or Destination Port", "udp.port", |
1370 | 15 | FT_UINT16, BASE_PT_UDP, NULL, 0x0, |
1371 | 15 | NULL, HFILL } |
1372 | 15 | }, |
1373 | 15 | { &hf_udp_stream, |
1374 | 15 | { "Stream index", "udp.stream", |
1375 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1376 | 15 | NULL, HFILL } |
1377 | 15 | }, |
1378 | 15 | { &hf_udp_stream_pnum, |
1379 | 15 | { "Stream Packet Number", "udp.stream.pnum", |
1380 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1381 | 15 | "Relative packet number in this UDP stream", HFILL } |
1382 | 15 | }, |
1383 | 15 | { &hf_udp_length, |
1384 | 15 | { "Length", "udp.length", |
1385 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1386 | 15 | "Length in octets including this header and the data", HFILL } |
1387 | 15 | }, |
1388 | 15 | { &hf_udp_checksum, |
1389 | 15 | { "Checksum", "udp.checksum", |
1390 | 15 | FT_UINT16, BASE_HEX, NULL, 0x0, |
1391 | 15 | "Details at: https://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html", HFILL } |
1392 | 15 | }, |
1393 | 15 | { &hf_udp_checksum_calculated, |
1394 | 15 | { "Calculated Checksum", "udp.checksum_calculated", |
1395 | 15 | FT_UINT16, BASE_HEX, NULL, 0x0, |
1396 | 15 | "The expected UDP checksum field as calculated from the UDP packet", HFILL } |
1397 | 15 | }, |
1398 | 15 | { &hf_udp_checksum_status, |
1399 | 15 | { "Checksum Status", "udp.checksum.status", |
1400 | 15 | FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, |
1401 | 15 | NULL, HFILL } |
1402 | 15 | }, |
1403 | 15 | { &hf_udp_proc_src_uid, |
1404 | 15 | { "Source process user ID", "udp.proc.srcuid", |
1405 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1406 | 15 | NULL, HFILL } |
1407 | 15 | }, |
1408 | 15 | { &hf_udp_proc_src_pid, |
1409 | 15 | { "Source process ID", "udp.proc.srcpid", |
1410 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1411 | 15 | NULL, HFILL } |
1412 | 15 | }, |
1413 | 15 | { &hf_udp_proc_src_uname, |
1414 | 15 | { "Source process user name", "udp.proc.srcuname", |
1415 | 15 | FT_STRING, BASE_NONE, NULL, 0x0, |
1416 | 15 | NULL, HFILL } |
1417 | 15 | }, |
1418 | 15 | { &hf_udp_proc_src_cmd, |
1419 | 15 | { "Source process name", "udp.proc.srccmd", |
1420 | 15 | FT_STRING, BASE_NONE, NULL, 0x0, |
1421 | 15 | "Source process command name", HFILL } |
1422 | 15 | }, |
1423 | 15 | { &hf_udp_proc_dst_uid, |
1424 | 15 | { "Destination process user ID", "udp.proc.dstuid", |
1425 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1426 | 15 | NULL, HFILL } |
1427 | 15 | }, |
1428 | 15 | { &hf_udp_proc_dst_pid, |
1429 | 15 | { "Destination process ID", "udp.proc.dstpid", |
1430 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1431 | 15 | NULL, HFILL } |
1432 | 15 | }, |
1433 | 15 | { &hf_udp_proc_dst_uname, |
1434 | 15 | { "Destination process user name", "udp.proc.dstuname", |
1435 | 15 | FT_STRING, BASE_NONE, NULL, 0x0, |
1436 | 15 | NULL, HFILL } |
1437 | 15 | }, |
1438 | 15 | { &hf_udp_proc_dst_cmd, |
1439 | 15 | { "Destination process name", "udp.proc.dstcmd", |
1440 | 15 | FT_STRING, BASE_NONE, NULL, 0x0, |
1441 | 15 | "Destination process command name", HFILL } |
1442 | 15 | }, |
1443 | 15 | { &hf_udp_pdu_size, |
1444 | 15 | { "PDU Size", "udp.pdu.size", |
1445 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1446 | 15 | "The size of this PDU", HFILL } |
1447 | 15 | }, |
1448 | 15 | { &hf_udp_ts_relative, |
1449 | 15 | { "Time since first frame", "udp.time_relative", |
1450 | 15 | FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, |
1451 | 15 | "Time relative to first frame in this UDP stream", HFILL } |
1452 | 15 | }, |
1453 | 15 | { &hf_udp_ts_delta, |
1454 | 15 | { "Time since previous frame", "udp.time_delta", |
1455 | 15 | FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, |
1456 | 15 | "Time delta from previous frame in this UDP stream", HFILL } |
1457 | 15 | }, |
1458 | 15 | { &hf_udp_payload, |
1459 | 15 | { "Payload", "udp.payload", |
1460 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1461 | 15 | NULL, HFILL } |
1462 | 15 | }, |
1463 | 15 | }; |
1464 | | |
1465 | 15 | static hf_register_info hf_udplite[] = { |
1466 | 15 | { &hf_udplite_checksum_coverage, |
1467 | 15 | { "Checksum coverage", "udp.checksum_coverage", |
1468 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1469 | 15 | NULL, HFILL } |
1470 | 15 | }, |
1471 | 15 | }; |
1472 | | |
1473 | 15 | static int *ett[] = { |
1474 | 15 | &ett_udp, |
1475 | 15 | &ett_udp_checksum, |
1476 | 15 | &ett_udp_process_info, |
1477 | 15 | &ett_udp_timestamps |
1478 | 15 | }; |
1479 | | |
1480 | 15 | static ei_register_info ei[] = { |
1481 | 15 | { &ei_udp_possible_traceroute, { "udp.possible_traceroute", PI_SEQUENCE, PI_CHAT, "Possible traceroute", EXPFILL }}, |
1482 | 15 | { &ei_udp_length_bad, { "udp.length.bad", PI_MALFORMED, PI_ERROR, "Bad length value", EXPFILL }}, |
1483 | 15 | { &ei_udplite_checksum_coverage_bad, { "udplite.checksum_coverage.bad", PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value", EXPFILL }}, |
1484 | 15 | { &ei_udp_checksum_zero, { "udp.checksum.zero", PI_CHECKSUM, PI_ERROR, "Illegal checksum value (0)", EXPFILL }}, |
1485 | 15 | { &ei_udp_checksum_partial, { "udp.checksum.partial", PI_CHECKSUM, PI_NOTE, "Partial (pseudo header) checksum (likely caused by \"UDP checksum offload\")", EXPFILL }}, |
1486 | 15 | { &ei_udp_checksum_bad, { "udp.checksum.bad", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, |
1487 | 15 | { &ei_udp_length_bad_zero, { "udp.length.bad_zero", PI_PROTOCOL, PI_WARN, "Length is zero but payload < 65536", EXPFILL }}, |
1488 | 15 | }; |
1489 | | |
1490 | 15 | static build_valid_func udp_da_src_values[1] = {udp_src_value}; |
1491 | 15 | static build_valid_func udp_da_dst_values[1] = {udp_dst_value}; |
1492 | 15 | static build_valid_func udp_da_both_values[2] = {udp_src_value, udp_dst_value}; |
1493 | 15 | static decode_as_value_t udp_da_values[3] = {{udp_src_prompt, 1, udp_da_src_values}, {udp_dst_prompt, 1, udp_da_dst_values}, {udp_both_prompt, 2, udp_da_both_values}}; |
1494 | 15 | static decode_as_t udp_da = {"udp", "udp.port", 3, 2, udp_da_values, "UDP", "port(s) as", |
1495 | 15 | decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL, NULL, NULL }; |
1496 | | |
1497 | 15 | module_t *udp_module; |
1498 | 15 | module_t *udplite_module; |
1499 | 15 | expert_module_t* expert_udp; |
1500 | | |
1501 | 15 | proto_udp = proto_register_protocol("User Datagram Protocol", "UDP", "udp"); |
1502 | 15 | proto_register_field_array(proto_udp, hf_udp, array_length(hf_udp)); |
1503 | 15 | udp_handle = register_dissector("udp", dissect_udp, proto_udp); |
1504 | 15 | udp_cap_handle = register_capture_dissector("udp", capture_udp, proto_udp); |
1505 | 15 | expert_udp = expert_register_protocol(proto_udp); |
1506 | | |
1507 | 15 | proto_udplite = proto_register_protocol("Lightweight User Datagram Protocol", "UDP-Lite", "udplite"); |
1508 | 15 | proto_register_field_array(proto_udplite, hf_udplite, array_length(hf_udplite)); |
1509 | 15 | udplite_handle = register_dissector("udplite", dissect_udplite, proto_udplite); |
1510 | 15 | udplite_cap_handle = register_capture_dissector("udplite", capture_udp, proto_udplite); |
1511 | | |
1512 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1513 | 15 | expert_register_field_array(expert_udp, ei, array_length(ei)); |
1514 | | |
1515 | | /* subdissector code */ |
1516 | 15 | udp_dissector_table = register_dissector_table("udp.port", "UDP port", proto_udp, FT_UINT16, BASE_DEC); |
1517 | 15 | heur_subdissector_list = register_heur_dissector_list_with_description("udp", "UDP heuristic", proto_udp); |
1518 | | |
1519 | 15 | register_capture_dissector_table("udp.port", "UDP"); |
1520 | | |
1521 | | /* Register configuration preferences */ |
1522 | 15 | udp_module = prefs_register_protocol(proto_udp, NULL); |
1523 | 15 | prefs_register_bool_preference(udp_module, "summary_in_tree", |
1524 | 15 | "Show UDP summary in protocol tree", |
1525 | 15 | "Whether the UDP summary line should be shown in the protocol tree", |
1526 | 15 | &udp_summary_in_tree); |
1527 | 15 | prefs_register_bool_preference(udp_module, "try_heuristic_first", |
1528 | 15 | "Try heuristic sub-dissectors first", |
1529 | 15 | "Try to decode a packet using an heuristic sub-dissector" |
1530 | 15 | " before using a sub-dissector registered to a specific port", |
1531 | 15 | &try_heuristic_first); |
1532 | 15 | prefs_register_bool_preference(udp_module, "check_checksum", |
1533 | 15 | "Validate the UDP checksum if possible", |
1534 | 15 | "Whether to validate the UDP checksum", |
1535 | 15 | &udp_check_checksum); |
1536 | 15 | prefs_register_bool_preference(udp_module, "ignore_ipv6_zero_checksum", |
1537 | 15 | "Ignore zero-value UDP checksums over IPv6", |
1538 | 15 | "Whether to ignore zero-value UDP checksums over IPv6", |
1539 | 15 | &udp_ignore_ipv6_zero_checksum); |
1540 | 15 | prefs_register_bool_preference(udp_module, "process_info", |
1541 | 15 | "Collect process flow information", |
1542 | 15 | "Collect process flow information from IPFIX", |
1543 | 15 | &udp_process_info); |
1544 | 15 | prefs_register_bool_preference(udp_module, "calculate_timestamps", |
1545 | 15 | "Calculate stream packet number and timestamps", |
1546 | 15 | "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the udp conversation", |
1547 | 15 | &udp_calculate_ts); |
1548 | | |
1549 | 15 | udplite_module = prefs_register_protocol(proto_udplite, NULL); |
1550 | 15 | prefs_register_bool_preference(udplite_module, "ignore_checksum_coverage", |
1551 | 15 | "Ignore UDP-Lite checksum coverage", |
1552 | 15 | "Ignore an invalid checksum coverage field and continue dissection", |
1553 | 15 | &udplite_ignore_checksum_coverage); |
1554 | 15 | prefs_register_bool_preference(udplite_module, "check_checksum", |
1555 | 15 | "Validate the UDP-Lite checksum if possible", |
1556 | 15 | "Whether to validate the UDP-Lite checksum", |
1557 | 15 | &udplite_check_checksum); |
1558 | 15 | prefs_register_bool_preference(udplite_module, "calculate_timestamps", |
1559 | 15 | "Calculate stream packet number and timestamps", |
1560 | 15 | "Calculate relative packet number and timestamps relative to the first frame and the previous frame in the udp-lite conversation", |
1561 | 15 | &udplite_calculate_ts); |
1562 | | |
1563 | 15 | register_decode_as(&udp_da); |
1564 | 15 | register_conversation_table(proto_udp, false, udpip_conversation_packet, udpip_endpoint_packet); |
1565 | 15 | register_conversation_filter("udp", "UDP", udp_filter_valid, udp_build_filter_by_id, NULL); |
1566 | 15 | register_follow_stream(proto_udp, "udp_follow", udp_follow_conv_filter, udp_follow_index_filter, udp_follow_address_filter, |
1567 | 15 | udp_port_to_display, follow_stream_tap_listener, get_udp_stream_count, NULL); |
1568 | | |
1569 | 15 | register_init_routine(udp_init); |
1570 | | |
1571 | 15 | udp_tap = register_tap("udp"); |
1572 | 15 | udp_follow_tap = register_tap("udp_follow"); |
1573 | 15 | } |
1574 | | |
1575 | | void |
1576 | | proto_reg_handoff_udp(void) |
1577 | 15 | { |
1578 | | |
1579 | 15 | dissector_add_uint("ip.proto", IP_PROTO_UDP, udp_handle); |
1580 | 15 | dissector_add_uint("ip.proto", IP_PROTO_UDPLITE, udplite_handle); |
1581 | | |
1582 | 15 | capture_dissector_add_uint("ip.proto", IP_PROTO_UDP, udp_cap_handle); |
1583 | 15 | capture_dissector_add_uint("ip.proto", IP_PROTO_UDPLITE, udplite_cap_handle); |
1584 | | |
1585 | 15 | exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_4); |
1586 | 15 | } |
1587 | | |
1588 | | /* |
1589 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1590 | | * |
1591 | | * Local variables: |
1592 | | * c-basic-offset: 4 |
1593 | | * tab-width: 8 |
1594 | | * indent-tabs-mode: nil |
1595 | | * End: |
1596 | | * |
1597 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1598 | | * :indentSize=4:tabSize=8:noTabs=true: |
1599 | | */ |