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 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <epan/packet.h>
36 #include <epan/to_str.h>
37 #include <epan/dissectors/packet-tcp.h>
38 #include <epan/dissectors/packet-udp.h>
40 #include <epan/conversation.h>
43 typedef struct _tcp_frag {
48 struct _tcp_frag *next;
52 FILE* data_out_file = NULL;
54 gboolean empty_tcp_stream;
55 gboolean incomplete_tcp_stream;
57 static guint32 stream_to_follow[MAX_STREAM] = {0};
58 static gboolean find_addr[MAX_STREAM] = {FALSE};
59 static gboolean find_index[MAX_STREAM] = {FALSE};
60 static address tcp_addr[2];
61 static stream_addr ip_address[2];
63 static guint bytes_written[2];
64 static gboolean is_ipv6 = FALSE;
67 follow_stats(follow_stats_t* stats)
71 for (i = 0; i < 2 ; i++) {
72 stats->ip_address[i] = ip_address[i];
73 stats->port[i] = port[i];
74 stats->bytes_written[i] = bytes_written[i];
76 stats->is_ipv6 = is_ipv6;
79 /* This will build a display filter text that will only
80 pass the packets related to the stream. There is a
81 chance that two streams could intersect, but not a
84 build_follow_conv_filter( packet_info *pi, const char* append_filter ) {
87 conversation_t *conv=NULL;
88 struct tcp_analysis *tcpd;
89 struct udp_analysis *udpd;
90 wmem_list_frame_t* protos;
92 const char* proto_name;
93 gboolean is_tcp = FALSE, is_udp = FALSE;
95 protos = wmem_list_head(pi->layers);
97 /* walk the list of a available protocols in the packet to
98 figure out if any of them affect context sensitivity */
99 while (protos != NULL)
101 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
102 proto_name = proto_get_protocol_filter_name(proto_id);
104 if (!strcmp(proto_name, "tcp")) {
106 } else if (!strcmp(proto_name, "udp")) {
110 protos = wmem_list_frame_next(protos);
113 if( ((pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4) ||
114 (pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6))
115 && is_tcp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
116 pi->srcport, pi->destport, 0)) != NULL ) {
117 /* TCP over IPv4/6 */
118 tcpd=get_tcp_conversation_data(conv, pi);
120 if (append_filter == NULL) {
121 buf = g_strdup_printf("tcp.stream eq %d", tcpd->stream);
123 buf = g_strdup_printf("((tcp.stream eq %d) && (%s))", tcpd->stream, append_filter);
125 stream_to_follow[TCP_STREAM] = tcpd->stream;
126 if (pi->net_src.type == AT_IPv4) {
137 else if( ((pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4) ||
138 (pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6))
139 && is_udp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
140 pi->srcport, pi->destport, 0)) != NULL ) {
141 /* UDP over IPv4/6 */
142 udpd=get_udp_conversation_data(conv, pi);
144 if (append_filter == NULL) {
145 buf = g_strdup_printf("udp.stream eq %d", udpd->stream);
147 buf = g_strdup_printf("((udp.stream eq %d) && (%s))", udpd->stream, append_filter);
149 stream_to_follow[UDP_STREAM] = udpd->stream;
150 if (pi->net_src.type == AT_IPv4) {
164 memcpy(&ip_address[0], pi->net_src.data, len);
165 memcpy(&ip_address[1], pi->net_dst.data, len);
166 port[0] = pi->srcport;
167 port[1] = pi->destport;
172 udp_follow_packet(void *tapdata _U_, packet_info *pinfo,
173 epan_dissect_t *edt _U_, const void *data _U_)
175 if (find_addr[UDP_STREAM]) {
176 if (pinfo->net_src.type == AT_IPv6) {
181 memcpy(&ip_address[0], pinfo->net_src.data, pinfo->net_src.len);
182 memcpy(&ip_address[1], pinfo->net_dst.data, pinfo->net_dst.len);
183 port[0] = pinfo->srcport;
184 port[1] = pinfo->destport;
185 find_addr[UDP_STREAM] = FALSE;
192 /* here we are going to try and reconstruct the data portion of a TCP
193 session. We will try and handle duplicates, TCP fragments, and out
194 of order packets in a smart way. */
196 static tcp_frag *frags[2] = { 0, 0 };
197 static guint32 seq[2];
198 static stream_addr src_addr[2];
199 static guint src_port[2] = { 0, 0 };
202 reset_stream_follow(stream_type stream) {
203 tcp_frag *current, *next;
206 remove_tap_listener(&stream_to_follow[stream]);
207 find_addr[stream] = FALSE;
208 find_index[stream] = FALSE;
209 if (stream == TCP_STREAM) {
210 empty_tcp_stream = TRUE;
211 incomplete_tcp_stream = FALSE;
213 for( i=0; i<2; i++ ) {
215 memset(&src_addr[i], 0, sizeof(src_addr[i]));
217 memset(&ip_address[i], 0, sizeof(src_addr[i]));
219 bytes_written[i] = 0;
222 next = current->next;
223 g_free( current->data );
233 build_follow_index_filter(stream_type stream) {
236 find_addr[stream] = TRUE;
237 if (stream == TCP_STREAM) {
238 buf = g_strdup_printf("tcp.stream eq %d", stream_to_follow[TCP_STREAM]);
240 GString * error_string;
241 buf = g_strdup_printf("udp.stream eq %d", stream_to_follow[UDP_STREAM]);
242 error_string = register_tap_listener("udp_follow", &stream_to_follow[UDP_STREAM], buf, 0, NULL, udp_follow_packet, NULL);
244 g_string_free(error_string, TRUE);
250 /* select a tcp stream to follow via it's address/port pairs */
252 follow_addr(stream_type stream, const address *addr0, guint port0,
253 const address *addr1, guint port1)
255 if (addr0 == NULL || addr1 == NULL || addr0->type != addr1->type ||
256 port0 > G_MAXUINT16 || port1 > G_MAXUINT16 ) {
260 if (find_index[stream] || find_addr[stream]) {
264 switch (addr0->type) {
269 is_ipv6 = addr0->type == AT_IPv6;
274 memcpy(&ip_address[0], addr0->data, addr0->len);
277 memcpy(&ip_address[1], addr1->data, addr1->len);
280 if (stream == TCP_STREAM) {
281 find_index[TCP_STREAM] = TRUE;
282 set_address(&tcp_addr[0], addr0->type, addr0->len, &ip_address[0]);
283 set_address(&tcp_addr[1], addr1->type, addr1->len, &ip_address[1]);
289 /* select a stream to follow via its index */
291 follow_index(stream_type stream, guint32 indx)
293 if (find_index[stream] || find_addr[stream]) {
297 find_addr[stream] = TRUE;
298 stream_to_follow[stream] = indx;
299 memset(ip_address, 0, sizeof ip_address);
300 port[0] = port[1] = 0;
306 get_follow_index(stream_type stream) {
307 return stream_to_follow[stream];
311 * Editor modelines - http://www.wireshark.org/tools/modelines.html
316 * indent-tabs-mode: nil
319 * ex: set shiftwidth=2 tabstop=8 expandtab:
320 * :indentSize=2:tabSize=8:noTabs=true: