Revert "tap: change glib functions to wmem."
[jlayton/wireshark.git] / ui / cli / tap-sctpchunkstat.c
1 /* tap_sctpchunkstat.c
2  * SCTP chunk counter for wireshark
3  * Copyright 2005 Oleg Terletsky <oleg.terletsky@comverse.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 #include "config.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <glib.h>
31
32 #include <epan/packet_info.h>
33 #include <epan/tap.h>
34 #include <epan/stat_tap_ui.h>
35 #include <epan/value_string.h>
36 #include <epan/dissectors/packet-sctp.h>
37 #include <epan/to_str.h>
38
39 void register_tap_listener_sctpstat(void);
40
41 typedef struct sctp_ep {
42         struct sctp_ep *next;
43         address src;
44         address dst;
45         guint16 sport;
46         guint16 dport;
47         guint32 chunk_count[256];
48 } sctp_ep_t;
49
50
51 /* used to keep track of the statistics for an entire program interface */
52 typedef struct _sctpstat_t {
53         char      *filter;
54         guint32    number_of_packets;
55         sctp_ep_t *ep_list;
56 } sctpstat_t;
57
58 #define CHUNK_TYPE_OFFSET 0
59 #define CHUNK_TYPE(x)(tvb_get_guint8((x), CHUNK_TYPE_OFFSET))
60
61 static void
62 sctpstat_reset(void *phs)
63 {
64         sctpstat_t *sctp_stat = (sctpstat_t *)phs;
65         sctp_ep_t  *list      = (sctp_ep_t *)sctp_stat->ep_list;
66         sctp_ep_t  *tmp       = NULL;
67         guint16     chunk_type;
68
69         if (!list)
70                 return;
71
72         for (tmp = list; tmp; tmp = tmp->next)
73                 for (chunk_type = 0; chunk_type < 256; chunk_type++)
74                         tmp->chunk_count[chunk_type] = 0;
75
76         sctp_stat->number_of_packets = 0;
77 }
78
79
80 static sctp_ep_t *
81 alloc_sctp_ep(const struct _sctp_info *si)
82 {
83         sctp_ep_t *ep;
84         guint16 chunk_type;
85
86         if (!si)
87                 return NULL;
88
89         if (!(ep = g_new(sctp_ep_t, 1)))
90                 return NULL;
91
92         copy_address(&ep->src, &si->ip_src);
93         copy_address(&ep->dst, &si->ip_dst);
94         ep->sport = si->sport;
95         ep->dport = si->dport;
96         ep->next  = NULL;
97         for (chunk_type = 0; chunk_type < 256; chunk_type++)
98                 ep->chunk_count[chunk_type] = 0;
99         return ep;
100 }
101
102
103
104
105 static int
106 sctpstat_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
107 {
108
109         sctpstat_t *hs = (sctpstat_t *)phs;
110         sctp_ep_t *tmp = NULL, *te = NULL;
111         const struct _sctp_info *si = (const struct _sctp_info *)phi;
112         guint32 tvb_number;
113         guint8  chunk_type;
114
115         if (!hs)
116                 return (0);
117
118         hs->number_of_packets++;
119
120         if (!hs->ep_list) {
121                 hs->ep_list = alloc_sctp_ep(si);
122                 te = hs->ep_list;
123         } else {
124                 for (tmp = hs->ep_list; tmp; tmp = tmp->next)
125                 {
126                         if ((!cmp_address(&tmp->src, &si->ip_src)) &&
127                            (!cmp_address(&tmp->dst, &si->ip_dst)) &&
128                            (tmp->sport == si->sport) &&
129                            (tmp->dport == si->dport))
130                         {
131                                 te = tmp;
132                                 break;
133                         }
134                 }
135                 if (!te) {
136                         if ((te = alloc_sctp_ep(si))) {
137                                 te->next = hs->ep_list;
138                                 hs->ep_list = te;
139                         }
140                 }
141         }
142
143         if (!te)
144                 return (0);
145
146
147         if (si->number_of_tvbs > 0) {
148                 chunk_type = CHUNK_TYPE(si->tvb[0]);
149                 if ((chunk_type == SCTP_INIT_CHUNK_ID) ||
150                     (chunk_type == SCTP_INIT_ACK_CHUNK_ID)) {
151                         te->chunk_count[chunk_type]++;
152                 } else {
153                         for (tvb_number = 0; tvb_number < si->number_of_tvbs; tvb_number++)
154                                 te->chunk_count[CHUNK_TYPE(si->tvb[tvb_number])]++;
155                 }
156         }
157         return (1);
158 }
159
160
161 static void
162 sctpstat_draw(void *phs)
163 {
164         sctpstat_t *hs = (sctpstat_t *)phs;
165         sctp_ep_t  *list = hs->ep_list, *tmp;
166         char *src_addr, *dst_addr;
167
168         printf("-------------------------------------------- SCTP Statistics --------------------------------------------------------------------------\n");
169         printf("|  Total packets RX/TX %u\n", hs->number_of_packets);
170         printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
171         printf("|   Source IP   |PortA|    Dest. IP   |PortB|  DATA  |  SACK  |  HBEAT |HBEATACK|  INIT  | INITACK| COOKIE |COOKIACK| ABORT  |  ERROR |\n");
172         printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
173
174         for (tmp = list; tmp; tmp = tmp->next) {
175                 src_addr = (char*)address_to_str(NULL, &tmp->src);
176                 dst_addr = (char*)address_to_str(NULL, &tmp->dst);
177                 printf("|%15s|%5u|%15s|%5u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|%8u|\n",
178                                 src_addr, tmp->sport,
179                                 dst_addr, tmp->dport,
180                                 tmp->chunk_count[SCTP_DATA_CHUNK_ID],
181                                 tmp->chunk_count[SCTP_SACK_CHUNK_ID],
182                                 tmp->chunk_count[SCTP_HEARTBEAT_CHUNK_ID],
183                                 tmp->chunk_count[SCTP_HEARTBEAT_ACK_CHUNK_ID],
184                                 tmp->chunk_count[SCTP_INIT_CHUNK_ID],
185                                 tmp->chunk_count[SCTP_INIT_ACK_CHUNK_ID],
186                                 tmp->chunk_count[SCTP_COOKIE_ECHO_CHUNK_ID],
187                                 tmp->chunk_count[SCTP_COOKIE_ACK_CHUNK_ID],
188                                 tmp->chunk_count[SCTP_ABORT_CHUNK_ID],
189                                 tmp->chunk_count[SCTP_ERROR_CHUNK_ID]);
190                 wmem_free(NULL, src_addr);
191                 wmem_free(NULL, dst_addr);
192         }
193         printf("---------------------------------------------------------------------------------------------------------------------------------------\n");
194 }
195
196
197 static void
198 sctpstat_init(const char *opt_arg, void *userdata _U_)
199 {
200         sctpstat_t *hs;
201         GString    *error_string;
202
203         hs = (sctpstat_t *)g_malloc(sizeof(sctpstat_t));
204         if (!strncmp(opt_arg, "sctp,stat,", 11)) {
205                 hs->filter = g_strdup(opt_arg+11);
206         } else {
207                 hs->filter = NULL;
208         }
209         hs->ep_list = NULL;
210         hs->number_of_packets = 0;
211
212         sctpstat_reset(hs);
213
214         error_string = register_tap_listener("sctp", hs, hs->filter, 0, NULL, sctpstat_packet, sctpstat_draw);
215         if (error_string) {
216                 /* error, we failed to attach to the tap. clean up */
217                 g_free(hs->filter);
218                 g_free(hs);
219
220                 fprintf(stderr, "tshark: Couldn't register sctp,stat tap: %s\n",
221                         error_string->str);
222                 g_string_free(error_string, TRUE);
223                 exit(1);
224         }
225 }
226
227 static stat_tap_ui sctpstat_ui = {
228         REGISTER_STAT_GROUP_GENERIC,
229         NULL,
230         "sctp,stat",
231         sctpstat_init,
232         0,
233         NULL
234 };
235
236 void
237 register_tap_listener_sctpstat(void)
238 {
239         register_stat_tap_ui(&sctpstat_ui, NULL);
240 }
241
242 /*
243  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
244  *
245  * Local variables:
246  * c-basic-offset: 8
247  * tab-width: 8
248  * indent-tabs-mode: t
249  * End:
250  *
251  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
252  * :indentSize=8:tabSize=8:noTabs=false:
253  */