1 /* follow.c 2 * 3 * Copyright 1998 Mike Hall <mlh@io.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 #include "config.h" 14 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include <glib.h> 19 #include <epan/packet.h> 20 #include "follow.h" 21 #include <epan/tap.h> 22 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 }; 32 33 static wmem_tree_t *registered_followers = NULL; 34 35 void register_follow_stream(const int proto_id, const char* tap_listener, 36 follow_conv_filter_func conv_filter, follow_index_filter_func index_filter, follow_address_filter_func address_filter, 37 follow_port_to_display_func port_to_display, tap_packet_cb tap_handler) 38 { signal_handler(Handler & h)39 register_follow_t *follower; 40 DISSECTOR_ASSERT(tap_listener); 41 DISSECTOR_ASSERT(conv_filter); 42 DISSECTOR_ASSERT(index_filter); 43 DISSECTOR_ASSERT(address_filter); 44 DISSECTOR_ASSERT(port_to_display); 45 DISSECTOR_ASSERT(tap_handler); do_complete(void * owner,operation * base,const boost::system::error_code &,std::size_t)46 47 follower = wmem_new(wmem_epan_scope(), register_follow_t); 48 49 follower->proto_id = proto_id; 50 follower->tap_listen_str = tap_listener; 51 follower->conv_filter = conv_filter; 52 follower->index_filter = index_filter; 53 follower->address_filter = address_filter; 54 follower->port_to_display = port_to_display; 55 follower->tap_handler = tap_handler; 56 57 if (registered_followers == NULL) 58 registered_followers = wmem_tree_new(wmem_epan_scope()); 59 60 wmem_tree_insert_string(registered_followers, proto_get_protocol_short_name(find_protocol_by_id(proto_id)), follower, 0); 61 } 62 63 int get_follow_proto_id(register_follow_t* follower) 64 { 65 if (follower == NULL) 66 return -1; 67 68 return follower->proto_id; 69 } 70 71 const char* get_follow_tap_string(register_follow_t* follower) 72 { 73 if (follower == NULL) 74 return ""; 75 76 return follower->tap_listen_str; 77 } 78 79 follow_conv_filter_func get_follow_conv_func(register_follow_t* follower) 80 { 81 return follower->conv_filter; 82 } 83 84 follow_index_filter_func get_follow_index_func(register_follow_t* follower) 85 { 86 return follower->index_filter; 87 } 88 89 follow_address_filter_func get_follow_address_func(register_follow_t* follower) 90 { 91 return follower->address_filter; 92 } 93 94 follow_port_to_display_func get_follow_port_to_display(register_follow_t* follower) 95 { 96 return follower->port_to_display; 97 } 98 99 tap_packet_cb get_follow_tap_handler(register_follow_t* follower) 100 { 101 return follower->tap_handler; 102 } 103 104 105 register_follow_t* get_follow_by_name(const char* proto_short_name) 106 { 107 return (register_follow_t*)wmem_tree_lookup_string(registered_followers, proto_short_name, 0); 108 } 109 110 void follow_iterate_followers(wmem_foreach_func func, gpointer user_data) 111 { 112 wmem_tree_foreach(registered_followers, func, user_data); 113 } 114 115 gchar* follow_get_stat_tap_string(register_follow_t* follower) 116 { 117 GString *cmd_str = g_string_new("follow,"); 118 g_string_append(cmd_str, proto_get_protocol_filter_name(follower->proto_id)); 119 return g_string_free(cmd_str, FALSE); 120 } 121 122 /* here we are going to try and reconstruct the data portion of a TCP 123 session. We will try and handle duplicates, TCP fragments, and out 124 of order packets in a smart way. */ 125 void 126 follow_reset_stream(follow_info_t* info) 127 { 128 info->bytes_written[0] = info->bytes_written[1] = 0; 129 info->client_port = 0; 130 info->server_port = 0; 131 info->client_ip.type = FT_NONE; 132 info->client_ip.len = 0; 133 info->server_ip.type = FT_NONE; 134 info->server_ip.len = 0; 135 info->fragments[0] = info->fragments[1] = NULL; 136 info->seq[0] = info->seq[1] = 0; 137 info->substream_id = SUBSTREAM_UNUSED; 138 } 139 140 void 141 follow_info_free(follow_info_t* follow_info) 142 { 143 GList *cur; 144 follow_record_t *follow_record; 145 146 for (cur = follow_info->payload; cur; cur = g_list_next(cur)) { 147 if(cur->data) { 148 follow_record = (follow_record_t *)cur->data; 149 if(follow_record->data) 150 g_byte_array_free(follow_record->data, TRUE); 151 152 g_free(follow_record); 153 } 154 } 155 g_list_free(follow_info->payload); 156 157 //Only TCP stream uses fragments 158 for (cur = follow_info->fragments[0]; cur; cur = g_list_next(cur)) { 159 follow_record = (follow_record_t *)cur->data; 160 if(follow_record->data) { 161 g_byte_array_free(follow_record->data, TRUE); 162 } 163 g_free(follow_record); 164 } 165 for (cur = follow_info->fragments[1]; cur; cur = g_list_next(cur)) { 166 follow_record = (follow_record_t *)cur->data; 167 if(follow_record->data) { 168 g_byte_array_free(follow_record->data, TRUE); 169 } 170 g_free(follow_record); 171 } 172 173 free_address(&follow_info->client_ip); 174 free_address(&follow_info->server_ip); 175 g_free(follow_info->filter_out_filter); 176 g_free(follow_info); 177 } 178 179 tap_packet_status 180 follow_tvb_tap_listener(void *tapdata, packet_info *pinfo, 181 epan_dissect_t *edt _U_, const void *data) 182 { 183 follow_record_t *follow_record; 184 follow_info_t *follow_info = (follow_info_t *)tapdata; 185 tvbuff_t *next_tvb = (tvbuff_t *)data; 186 187 follow_record = g_new(follow_record_t,1); 188 189 follow_record->data = g_byte_array_sized_new(tvb_captured_length(next_tvb)); 190 follow_record->data = g_byte_array_append(follow_record->data, 191 tvb_get_ptr(next_tvb, 0, -1), 192 tvb_captured_length(next_tvb)); 193 follow_record->packet_num = pinfo->fd->num; 194 follow_record->abs_ts = pinfo->fd->abs_ts; 195 196 if (follow_info->client_port == 0) { 197 follow_info->client_port = pinfo->srcport; 198 copy_address(&follow_info->client_ip, &pinfo->src); 199 follow_info->server_port = pinfo->destport; 200 copy_address(&follow_info->server_ip, &pinfo->dst); 201 } 202 203 if (addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport) 204 follow_record->is_server = FALSE; 205 else 206 follow_record->is_server = TRUE; 207 208 /* update stream counter */ 209 follow_info->bytes_written[follow_record->is_server] += follow_record->data->len; 210 211 follow_info->payload = g_list_prepend(follow_info->payload, follow_record); 212 return TAP_PACKET_DONT_REDRAW; 213 } 214 215 /* 216 * Editor modelines - https://www.wireshark.org/tools/modelines.html 217 * 218 * Local Variables: 219 * c-basic-offset: 2 220 * tab-width: 8 221 * indent-tabs-mode: nil 222 * End: 223 * 224 * ex: set shiftwidth=2 tabstop=8 expandtab: 225 * :indentSize=2:tabSize=8:noTabs=true: 226 */ 227