Do changes from Generalize wtap_pkthdr into a structure for packet and
[metze/wireshark/wip.git] / ui / traffic_table_ui.c
1 /* traffic_table_ui.c
2  * Copied from gtk/conversations_table.c   2003 Ronnie Sahlberg
3  * Helper routines common to all conversations taps.
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 #include "config.h"
11
12 #include <glib.h>
13
14 #include "traffic_table_ui.h"
15 #include <wsutil/utf8_entities.h>
16
17 #ifdef HAVE_GEOIP
18 #include <GeoIP.h>
19 #include "epan/address.h"
20 #include "epan/addr_resolv.h"
21 #include "epan/geoip_db.h"
22 #include "epan/strutil.h"
23 #include "wsutil/pint.h"
24 #include "wsutil/str_util.h"
25
26 #include "epan/packet_info.h"
27 #include "epan/conversation_table.h"
28
29 #include <errno.h>
30 #include <stdio.h>
31 #include "wsutil/filesystem.h"
32 #include "wsutil/file_util.h"
33 #include "wsutil/tempfile.h"
34 #endif
35
36 const char *conv_column_titles[CONV_NUM_COLUMNS] = {
37     "Address A",
38     "Port A",
39     "Address B",
40     "Port B",
41     "Packets",
42     "Bytes",
43     "Packets A " UTF8_RIGHTWARDS_ARROW " B",
44     "Bytes A " UTF8_RIGHTWARDS_ARROW " B",
45     "Packets B " UTF8_RIGHTWARDS_ARROW " A",
46     "Bytes B " UTF8_RIGHTWARDS_ARROW " A",
47     "Rel Start",
48     "Duration",
49     "Bits/s A " UTF8_RIGHTWARDS_ARROW " B",
50     "Bits/s B " UTF8_RIGHTWARDS_ARROW " A"
51 };
52
53 const char *conv_conn_a_title = "Connection A";
54 const char *conv_conn_b_title = "Connection B";
55 const char *conv_abs_start_title = "Abs Start";
56
57 const char *endp_column_titles[ENDP_NUM_COLUMNS] = {
58     "Address",
59     "Port",
60     "Packets",
61     "Bytes",
62     "Tx Packets",
63     "Tx Bytes",
64     "Rx Packets",
65     "Rx Bytes"
66 };
67
68 const char *endp_conn_title = "Connection";
69
70 #ifdef HAVE_GEOIP
71 #define MAX_TPL_LINE_LEN 4096
72 gchar *
73 create_endpoint_geoip_map(const GArray *endp_array, gchar **err_str) {
74     char *tpl_filename, *tpl_line;
75     FILE *tpl_file, *out_file;
76     char *map_path;
77     gchar *map_filename = NULL;
78     guint i;
79     GString *tpl_entry;
80     gchar *esc_entry;
81     int db_lon, db_lat, db_country4, db_country6, db_city4, db_city6, db_asn4, db_asn6;
82     guint cur_db;
83     const char *map_endpoint_opener = "{\n";
84
85     db_lon = db_lat = db_country4 = db_country6 = db_city4 = db_city6 = db_asn4 = db_asn6 = -1;
86
87     /* Create a location map HTML file from a template */
88     /* XXX - add error handling */
89     tpl_filename = get_datafile_path("ipmap.html");
90     tpl_file = ws_fopen(tpl_filename, "r");
91     if(tpl_file == NULL) {
92         if (err_str) {
93             GString *err_descr = g_string_new("");
94             g_string_printf(err_descr, file_open_error_message(errno, FALSE), tpl_filename);
95             *err_str = g_string_free(err_descr, FALSE);
96         }
97         g_free(tpl_filename);
98         return NULL;
99     }
100     g_free(tpl_filename);
101
102 #if 1
103     /* We should probably create a file with a temporary name and a .html extension instead */
104     if (! create_tempdir(&map_path, "Wireshark IP Map ")) {
105         if (err_str) {
106             GString *err_descr = g_string_new("");
107             g_string_printf(err_descr, "Could not create temporary directory\n%s",
108                             map_path);
109             *err_str = g_string_free(err_descr, FALSE);
110         }
111         fclose(tpl_file);
112         return NULL;
113     }
114 #else
115     /* Debugging only */
116     map_path = "/tmp";
117 #endif
118
119     map_filename = g_strdup_printf("%s%cipmap.html", map_path, G_DIR_SEPARATOR);
120     out_file = ws_fopen(map_filename, "w");
121     if(out_file == NULL) {
122         if (err_str) {
123             GString *err_descr = g_string_new("");
124             g_string_printf(err_descr, file_open_error_message(errno, FALSE), map_filename);
125             *err_str = g_string_free(err_descr, FALSE);
126         }
127         g_free(map_filename);
128         fclose(tpl_file);
129         return NULL;
130     }
131
132     tpl_line = (char *)g_malloc(MAX_TPL_LINE_LEN);
133
134     while (fgets(tpl_line, MAX_TPL_LINE_LEN, tpl_file) != NULL) {
135         fputs(tpl_line, out_file);
136         /* MUST match ipmap.html */
137         if (strstr(tpl_line, "// Start endpoint list")) {
138             break;
139         }
140     }
141
142     for (cur_db = 0; cur_db < geoip_db_num_dbs(); cur_db++) {
143         switch (geoip_db_type(cur_db)) {
144         case WS_LON_FAKE_EDITION:
145             db_lon = cur_db;
146             break;
147         case WS_LAT_FAKE_EDITION:
148             db_lat = cur_db;
149             break;
150         case GEOIP_COUNTRY_EDITION:
151             db_country4 = cur_db;
152             break;
153         case GEOIP_COUNTRY_EDITION_V6:
154             db_country6 = cur_db;
155             break;
156         case GEOIP_CITY_EDITION_REV0:
157         case GEOIP_CITY_EDITION_REV1:
158             db_city4 = cur_db;
159             break;
160         case GEOIP_CITY_EDITION_REV0_V6:
161         case GEOIP_CITY_EDITION_REV1_V6:
162             db_city6 = cur_db;
163             break;
164         }
165     }
166
167     if(db_lon < 0 || db_lat < 0) {
168         if (err_str) {
169             *err_str = g_strdup("Unable to open GeoIP database");
170         }
171         /* We can't write the map file, so close it and get rid of it */
172         fclose(out_file);
173         ws_unlink(map_filename);
174         g_free(map_filename);
175         fclose(tpl_file);
176         g_free(tpl_line);
177         return NULL;
178     }
179
180     /* Fill in our map data */
181     tpl_entry = g_string_new("");
182
183     for (i = 0; i < endp_array->len; i++) {
184         char *lat = NULL, *lon = NULL, *country = NULL, *city = NULL, *asn = NULL;
185         hostlist_talker_t *endp_item = &g_array_index(endp_array, hostlist_talker_t, i);
186
187         if (endp_item->myaddress.type == AT_IPv4) {
188             lon = geoip_db_lookup_ipv4(db_lon, pntoh32(endp_item->myaddress.data), NULL);
189             lat = geoip_db_lookup_ipv4(db_lat, pntoh32(endp_item->myaddress.data), NULL);
190             country = geoip_db_lookup_ipv4(db_country4, pntoh32(endp_item->myaddress.data), "-");
191             city = geoip_db_lookup_ipv4(db_city4, pntoh32(endp_item->myaddress.data), "-");
192             asn = geoip_db_lookup_ipv4(db_asn4, pntoh32(endp_item->myaddress.data), "-");
193         } else if (endp_item->myaddress.type == AT_IPv6) {
194             const ws_in6_addr *addr = (const ws_in6_addr *) endp_item->myaddress.data;
195             lon = geoip_db_lookup_ipv6(db_lon, *addr, NULL);
196             lat = geoip_db_lookup_ipv6(db_lat, *addr, NULL);
197             country = geoip_db_lookup_ipv6(db_country6, *addr, "-");
198             city = geoip_db_lookup_ipv6(db_city6, *addr, "-");
199             asn = geoip_db_lookup_ipv6(db_asn6, *addr, "-");
200         } else {
201             continue;
202         }
203
204         /*
205         {
206           'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [-122.583889, 37.898889] },
207           'properties': { 'title': 'host.example.com', 'description': 'AS: AS12345 Ewok Holdings, Inc.<br/>Country: US<br/>City: Muir Woods, CA<br/>Packets: 6<br/>Bytes: 980' }
208         },
209          */
210
211         if (lon && lat) {
212             char* addr_str;
213
214             g_string_printf(tpl_entry, "%s", map_endpoint_opener);
215
216             /* Longitude + latitude */
217             g_string_append_printf(tpl_entry, "    'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [%s, %s] },\n", lon, lat);
218
219             /* Address */
220             addr_str = address_to_display(NULL, &endp_item->myaddress);
221             g_string_append_printf(tpl_entry, "    'properties': { 'title': '%s', ", addr_str);
222             wmem_free(NULL, addr_str);
223
224             /* Description */
225
226             /* City */
227             esc_entry = string_replace(city, "'", "&#39;");
228             g_string_append_printf(tpl_entry, "'description': '<div class=\"geoip_property\">City: %s</div>", esc_entry);
229             g_free(esc_entry);
230
231             /* Country */
232             esc_entry = string_replace(country, "'", "&#39;");
233             g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Country: %s</div>", esc_entry);
234             g_free(esc_entry);
235
236             /* Packets */
237             esc_entry = format_size(endp_item->tx_frames + endp_item->rx_frames,
238                                     (format_size_flags_e)(format_size_unit_none|format_size_prefix_si));
239             g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Packets: %s</div>", esc_entry);
240             g_free(esc_entry);
241
242             /* Bytes */
243             esc_entry = format_size(endp_item->tx_bytes + endp_item->rx_bytes,
244                                     (format_size_flags_e)(format_size_unit_none|format_size_prefix_si));
245             g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">Bytes: %s</div>", esc_entry);
246             g_free(esc_entry);
247
248             /* ASN */
249             esc_entry = string_replace(asn, "'", "&#39;");
250             g_string_append_printf(tpl_entry, "<div class=\"geoip_property\">AS Number: %s</div>", esc_entry);
251             g_free(esc_entry);
252
253             /* XXX - We could add specific icons, e.g. depending on the amount of packets or bytes */
254             g_string_append(tpl_entry, "' }\n");
255             g_string_append(tpl_entry, "}");
256
257             fputs(tpl_entry->str, out_file);
258             map_endpoint_opener = ",\n{\n";
259         }
260
261         wmem_free(NULL, lat);
262         wmem_free(NULL, lon);
263         wmem_free(NULL, country);
264         wmem_free(NULL, city);
265         wmem_free(NULL, asn);
266
267         /* XXX Display an error if we we have no entries */
268     }
269
270     while (fgets(tpl_line, MAX_TPL_LINE_LEN, tpl_file) != NULL) {
271         fputs(tpl_line, out_file);
272     }
273     g_free(tpl_line);
274
275     fclose(tpl_file);
276     fclose(out_file);
277
278     return map_filename;
279
280
281 }
282 #endif
283
284 /*
285  * Editor modelines
286  *
287  * Local Variables:
288  * c-basic-offset: 4
289  * tab-width: 8
290  * indent-tabs-mode: nil
291  * End:
292  *
293  * ex: set shiftwidth=4 tabstop=8 expandtab:
294  * :indentSize=4:tabSize=8:noTabs=true:
295  */