RTPS: Adding position in the batch to the rtps_dissector_data
[metze/wireshark/wip.git] / epan / follow.c
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  * 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.
13  *
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.
18  *
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.
22  *
23  */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include "follow.h"
33 #include <epan/tap.h>
34
35 struct register_follow {
36     int proto_id;              /* protocol id (0-indexed) */
37     const char* tap_listen_str;      /* string used in register_tap_listener */
38     follow_conv_filter_func conv_filter;  /* generate "conversation" filter to follow */
39     follow_index_filter_func index_filter; /* generate stream/index filter to follow */
40     follow_address_filter_func address_filter; /* generate address filter to follow */
41     follow_port_to_display_func port_to_display; /* port to name resolution for follow type */
42     follow_tap_func tap_handler; /* tap listener handler */
43 };
44
45 static GSList *registered_followers = NULL;
46
47 static gint
48 insert_sorted_by_name(gconstpointer aparam, gconstpointer bparam)
49 {
50     const register_follow_t *a = (const register_follow_t *)aparam;
51     const register_follow_t *b = (const register_follow_t *)bparam;
52
53     return g_ascii_strcasecmp(proto_get_protocol_short_name(find_protocol_by_id(a->proto_id)), proto_get_protocol_short_name(find_protocol_by_id(b->proto_id)));
54 }
55
56 void register_follow_stream(const int proto_id, const char* tap_listener,
57                             follow_conv_filter_func conv_filter, follow_index_filter_func index_filter, follow_address_filter_func address_filter,
58                             follow_port_to_display_func port_to_display, follow_tap_func tap_handler)
59 {
60   register_follow_t *follower;
61   DISSECTOR_ASSERT(tap_listener);
62   DISSECTOR_ASSERT(conv_filter);
63   DISSECTOR_ASSERT(index_filter);
64   DISSECTOR_ASSERT(address_filter);
65   DISSECTOR_ASSERT(port_to_display);
66   DISSECTOR_ASSERT(tap_handler);
67
68   follower = g_new(register_follow_t,1);
69
70   follower->proto_id       = proto_id;
71   follower->tap_listen_str = tap_listener;
72   follower->conv_filter    = conv_filter;
73   follower->index_filter   = index_filter;
74   follower->address_filter = address_filter;
75   follower->port_to_display = port_to_display;
76   follower->tap_handler    = tap_handler;
77
78   registered_followers = g_slist_insert_sorted(registered_followers, follower, insert_sorted_by_name);
79 }
80
81 int get_follow_proto_id(register_follow_t* follower)
82 {
83   if (follower == NULL)
84     return -1;
85
86   return follower->proto_id;
87 }
88
89 const char* get_follow_tap_string(register_follow_t* follower)
90 {
91   if (follower == NULL)
92     return "";
93
94   return follower->tap_listen_str;
95 }
96
97 follow_conv_filter_func get_follow_conv_func(register_follow_t* follower)
98 {
99   return follower->conv_filter;
100 }
101
102 follow_index_filter_func get_follow_index_func(register_follow_t* follower)
103 {
104   return follower->index_filter;
105 }
106
107 follow_address_filter_func get_follow_address_func(register_follow_t* follower)
108 {
109   return follower->address_filter;
110 }
111
112 follow_port_to_display_func get_follow_port_to_display(register_follow_t* follower)
113 {
114   return follower->port_to_display;
115 }
116
117 follow_tap_func get_follow_tap_handler(register_follow_t* follower)
118 {
119   return follower->tap_handler;
120 }
121
122
123 register_follow_t* get_follow_by_name(const char* proto_short_name)
124 {
125   guint i, size = g_slist_length(registered_followers);
126   register_follow_t *follower;
127   GSList   *slist;
128
129   for (i = 0; i < size; i++) {
130     slist = g_slist_nth(registered_followers, i);
131     follower = (register_follow_t*)slist->data;
132
133     if (strcmp(proto_short_name, proto_get_protocol_short_name(find_protocol_by_id(follower->proto_id))) == 0)
134       return follower;
135   }
136
137   return NULL;
138 }
139
140 void follow_iterate_followers(GFunc func, gpointer user_data)
141 {
142     g_slist_foreach(registered_followers, func, user_data);
143 }
144
145 gchar* follow_get_stat_tap_string(register_follow_t* follower)
146 {
147     GString *cmd_str = g_string_new("follow,");
148     g_string_append(cmd_str, proto_get_protocol_filter_name(follower->proto_id));
149     return g_string_free(cmd_str, FALSE);
150 }
151
152 /* here we are going to try and reconstruct the data portion of a TCP
153    session. We will try and handle duplicates, TCP fragments, and out
154    of order packets in a smart way. */
155 void
156 follow_reset_stream(follow_info_t* info)
157 {
158     info->bytes_written[0] = info->bytes_written[1] = 0;
159     info->client_port = 0;
160     info->server_port = 0;
161     info->client_ip.type = FT_NONE;
162     info->client_ip.len = 0;
163     info->server_ip.type = FT_NONE;
164     info->server_ip.len = 0;
165 }
166
167 gboolean
168 follow_tvb_tap_listener(void *tapdata, packet_info *pinfo,
169                       epan_dissect_t *edt _U_, const void *data)
170 {
171     follow_record_t *follow_record;
172     follow_info_t *follow_info = (follow_info_t *)tapdata;
173     tvbuff_t *next_tvb = (tvbuff_t *)data;
174
175     follow_record = g_new(follow_record_t,1);
176
177     follow_record->data = g_byte_array_sized_new(tvb_captured_length(next_tvb));
178     follow_record->data = g_byte_array_append(follow_record->data,
179                                               tvb_get_ptr(next_tvb, 0, -1),
180                                               tvb_captured_length(next_tvb));
181     follow_record->packet_num = pinfo->fd->num;
182
183     if (follow_info->client_port == 0) {
184         follow_info->client_port = pinfo->srcport;
185         copy_address(&follow_info->client_ip, &pinfo->src);
186         follow_info->server_port = pinfo->destport;
187         copy_address(&follow_info->server_ip, &pinfo->dst);
188     }
189
190     if (addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport)
191         follow_record->is_server = FALSE;
192     else
193         follow_record->is_server = TRUE;
194
195     /* update stream counter */
196     follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
197
198     follow_info->payload = g_list_append(follow_info->payload, follow_record);
199     return FALSE;
200 }
201
202 /*
203  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
204  *
205  * Local Variables:
206  * c-basic-offset: 2
207  * tab-width: 8
208  * indent-tabs-mode: nil
209  * End:
210  *
211  * ex: set shiftwidth=2 tabstop=8 expandtab:
212  * :indentSize=2:tabSize=8:noTabs=true:
213  */