more decompress
[wireshark-sm.git] / epan / follow.c
blob5d9a75d8c783071ca1dbdd7cc0c53427b8a9d40b
1 /* follow.c
3 * Copyright 1998 Mike Hall <mlh@io.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <stdlib.h>
16 #include <string.h>
18 #include <glib.h>
19 #include <epan/packet.h>
20 #include "follow.h"
21 #include <epan/tap.h>
23 struct register_follow {
24 int proto_id; /* protocol id (0-indexed) */
25 const char* tap_listen_str; /* string used in register_tap_listener */
26 follow_conv_filter_func conv_filter; /* generate "conversation" filter to follow */
27 follow_index_filter_func index_filter; /* generate stream/index filter to follow */
28 follow_address_filter_func address_filter; /* generate address filter to follow */
29 follow_port_to_display_func port_to_display; /* port to name resolution for follow type */
30 tap_packet_cb tap_handler; /* tap listener handler */
31 follow_stream_count_func stream_count; /* maximum stream count, used for UI */
32 follow_sub_stream_id_func sub_stream_id; /* sub-stream id, used for UI */
35 static wmem_tree_t *registered_followers;
37 void register_follow_stream(const int proto_id, const char* tap_listener,
38 follow_conv_filter_func conv_filter, follow_index_filter_func index_filter, follow_address_filter_func address_filter,
39 follow_port_to_display_func port_to_display, tap_packet_cb tap_handler,
40 follow_stream_count_func stream_count, follow_sub_stream_id_func sub_stream_id)
42 register_follow_t *follower;
43 DISSECTOR_ASSERT(tap_listener);
44 DISSECTOR_ASSERT(conv_filter);
45 DISSECTOR_ASSERT(index_filter);
46 DISSECTOR_ASSERT(address_filter);
47 DISSECTOR_ASSERT(port_to_display);
48 DISSECTOR_ASSERT(tap_handler);
50 follower = wmem_new(wmem_epan_scope(), register_follow_t);
52 follower->proto_id = proto_id;
53 follower->tap_listen_str = tap_listener;
54 follower->conv_filter = conv_filter;
55 follower->index_filter = index_filter;
56 follower->address_filter = address_filter;
57 follower->port_to_display = port_to_display;
58 follower->tap_handler = tap_handler;
59 follower->stream_count = stream_count;
60 follower->sub_stream_id = sub_stream_id;
62 if (registered_followers == NULL)
63 registered_followers = wmem_tree_new(wmem_epan_scope());
65 wmem_tree_insert_string(registered_followers, proto_get_protocol_short_name(find_protocol_by_id(proto_id)), follower, 0);
68 int get_follow_proto_id(register_follow_t* follower)
70 if (follower == NULL)
71 return -1;
73 return follower->proto_id;
76 const char* get_follow_tap_string(register_follow_t* follower)
78 if (follower == NULL)
79 return "";
81 return follower->tap_listen_str;
84 follow_conv_filter_func get_follow_conv_func(register_follow_t* follower)
86 return follower->conv_filter;
89 follow_index_filter_func get_follow_index_func(register_follow_t* follower)
91 return follower->index_filter;
94 follow_address_filter_func get_follow_address_func(register_follow_t* follower)
96 return follower->address_filter;
99 follow_port_to_display_func get_follow_port_to_display(register_follow_t* follower)
101 return follower->port_to_display;
104 tap_packet_cb get_follow_tap_handler(register_follow_t* follower)
106 return follower->tap_handler;
109 follow_stream_count_func get_follow_stream_count_func(register_follow_t* follower)
111 return follower->stream_count;
114 follow_sub_stream_id_func get_follow_sub_stream_id_func(register_follow_t* follower)
116 return follower->sub_stream_id;
119 register_follow_t* get_follow_by_name(const char* proto_short_name)
121 return (register_follow_t*)wmem_tree_lookup_string(registered_followers, proto_short_name, 0);
124 register_follow_t* get_follow_by_proto_id(const int proto_id)
126 protocol_t *protocol = find_protocol_by_id(proto_id);
127 if (protocol == NULL) {
128 return NULL;
131 return (register_follow_t*)wmem_tree_lookup_string(registered_followers, proto_get_protocol_short_name(protocol), 0);
134 void follow_iterate_followers(wmem_foreach_func func, void *user_data)
136 wmem_tree_foreach(registered_followers, func, user_data);
139 char* follow_get_stat_tap_string(register_follow_t* follower)
141 GString *cmd_str = g_string_new("follow,");
142 g_string_append(cmd_str, proto_get_protocol_filter_name(follower->proto_id));
143 return g_string_free(cmd_str, FALSE);
146 /* here we are going to try and reconstruct the data portion of a TCP
147 session. We will try and handle duplicates, TCP fragments, and out
148 of order packets in a smart way. */
149 void
150 follow_reset_stream(follow_info_t* info)
152 GList *cur;
153 follow_record_t *follow_record;
155 info->bytes_written[0] = info->bytes_written[1] = 0;
156 info->client_port = 0;
157 info->server_port = 0;
159 free_address(&info->client_ip);
160 free_address(&info->server_ip);
162 for (cur = info->payload; cur; cur = g_list_next(cur)) {
163 follow_record = (follow_record_t *)cur->data;
164 if(follow_record->data)
165 g_byte_array_free(follow_record->data, true);
167 g_free(follow_record);
169 g_list_free(info->payload);
170 info->payload = NULL;
172 //Only TCP stream uses fragments
173 for (cur = info->fragments[0]; cur; cur = g_list_next(cur)) {
174 follow_record = (follow_record_t *)cur->data;
175 if(follow_record->data) {
176 g_byte_array_free(follow_record->data, true);
178 g_free(follow_record);
180 for (cur = info->fragments[1]; cur; cur = g_list_next(cur)) {
181 follow_record = (follow_record_t *)cur->data;
182 if(follow_record->data) {
183 g_byte_array_free(follow_record->data, true);
185 g_free(follow_record);
187 info->fragments[0] = info->fragments[1] = NULL;
188 info->seq[0] = info->seq[1] = 0;
190 g_free(info->filter_out_filter);
191 info->filter_out_filter = NULL;
193 /* Don't reset the substream_id - that's used by followers for
194 * for determining which tvbs match, and we don't want to clear
195 * it when the taps are reset due to a retap.
197 #if 0
198 info->substream_id = SUBSTREAM_UNUSED;
199 #endif
202 void
203 follow_info_free(follow_info_t* follow_info)
205 follow_reset_stream(follow_info);
206 g_free(follow_info);
209 tap_packet_status
210 follow_tvb_tap_listener(void *tapdata, packet_info *pinfo,
211 epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
213 follow_record_t *follow_record;
214 follow_info_t *follow_info = (follow_info_t *)tapdata;
215 tvbuff_t *next_tvb = (tvbuff_t *)data;
217 follow_record = g_new(follow_record_t,1);
219 follow_record->data = g_byte_array_sized_new(tvb_captured_length(next_tvb));
220 follow_record->data = g_byte_array_append(follow_record->data,
221 tvb_get_ptr(next_tvb, 0, -1),
222 tvb_captured_length(next_tvb));
223 follow_record->packet_num = pinfo->fd->num;
224 follow_record->abs_ts = pinfo->fd->abs_ts;
226 if (follow_info->client_port == 0) {
227 follow_info->client_port = pinfo->srcport;
228 copy_address(&follow_info->client_ip, &pinfo->src);
229 follow_info->server_port = pinfo->destport;
230 copy_address(&follow_info->server_ip, &pinfo->dst);
233 if (addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport)
234 follow_record->is_server = false;
235 else
236 follow_record->is_server = true;
238 /* update stream counter */
239 follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
241 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
242 return TAP_PACKET_DONT_REDRAW;
246 * Editor modelines - https://www.wireshark.org/tools/modelines.html
248 * Local Variables:
249 * c-basic-offset: 2
250 * tab-width: 8
251 * indent-tabs-mode: nil
252 * End:
254 * ex: set shiftwidth=2 tabstop=8 expandtab:
255 * :indentSize=2:tabSize=8:noTabs=true: