b5483191551369a8bd847de3393f603926d9ce28
[metze/wireshark/wip.git] / epan / epan.c
1 /* epan.c
2  *
3  * Wireshark Protocol Analyzer Library
4  *
5  * Copyright (c) 2001 by Gerald Combs <gerald@wireshark.org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "config.h"
23
24 #include <stdarg.h>
25
26 #ifdef HAVE_LIBGCRYPT
27 #include <wsutil/wsgcrypt.h>
28 #endif /* HAVE_LIBGCRYPT */
29
30 #ifdef HAVE_LIBGNUTLS
31 #include <gnutls/gnutls.h>
32 #endif /* HAVE_LIBGNUTLS */
33
34 #include <glib.h>
35
36 #include <wsutil/report_err.h>
37
38 #include <epan/exceptions.h>
39
40 #include "epan-int.h"
41 #include "epan.h"
42 #include "dfilter/dfilter.h"
43 #include "epan_dissect.h"
44
45 #include "conversation.h"
46 #include "circuit.h"
47 #include "except.h"
48 #include "packet.h"
49 #include "prefs.h"
50 #include "column-utils.h"
51 #include "tap.h"
52 #include "addr_resolv.h"
53 #include "oids.h"
54 #include "wmem/wmem.h"
55 #include "expert.h"
56 #include "print.h"
57
58 #ifdef HAVE_LUA
59 #include <lua.h>
60 #include <wslua/wslua.h>
61 #endif
62
63 #ifdef HAVE_LIBSMI
64 #include <smi.h>
65 #endif
66
67 #ifdef HAVE_C_ARES
68 #include <ares_version.h>
69 #endif
70
71 static wmem_allocator_t *pinfo_pool_cache = NULL;
72
73 const gchar*
74 epan_get_version(void) {
75         return VERSION;
76 }
77
78 /*
79  * Register all the plugin types that are part of libwireshark, namely
80  * dissector and tap plugins.
81  *
82  * Must be called before init_plugins(), which must be called before
83  * any registration routines are called.
84  */
85 void
86 epan_register_plugin_types(void)
87 {
88 #ifdef HAVE_PLUGINS
89         register_dissector_plugin_type();
90         register_tap_plugin_type();
91 #endif
92 }
93
94 gboolean
95 epan_init(void (*register_all_protocols_func)(register_cb cb, gpointer client_data),
96           void (*register_all_handoffs_func)(register_cb cb, gpointer client_data),
97           register_cb cb,
98           gpointer client_data)
99 {
100         volatile gboolean status = TRUE;
101
102         /* initialize memory allocation subsystem */
103         wmem_init();
104
105         /* initialize the GUID to name mapping table */
106         guids_init();
107
108         /* initialize name resolution (addr_resolv.c) */
109         addr_resolv_init();
110
111         except_init();
112 #ifdef HAVE_LIBGCRYPT
113         /* initialize libgcrypt (beware, it won't be thread-safe) */
114         gcry_check_version(NULL);
115         gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
116         gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
117 #endif
118 #ifdef HAVE_LIBGNUTLS
119         gnutls_global_init();
120 #endif
121         TRY {
122                 tap_init();
123                 prefs_init();
124                 expert_init();
125                 packet_init();
126                 proto_init(register_all_protocols_func, register_all_handoffs_func,
127                     cb, client_data);
128                 packet_cache_proto_handles();
129                 dfilter_init();
130                 final_registration_all_protocols();
131                 print_cache_field_handles();
132                 expert_packet_init();
133 #ifdef HAVE_LUA
134                 wslua_init(cb, client_data);
135 #endif
136         }
137         CATCH(DissectorError) {
138                 /*
139                  * This is probably a dissector, or something it calls,
140                  * calling REPORT_DISSECTOR_ERROR() in a registration
141                  * routine or something else outside the normal dissection
142                  * code path.
143                  */
144                 const char *exception_message = GET_MESSAGE;
145                 static const char dissector_error_nomsg[] =
146                     "Dissector writer didn't bother saying what the error was";
147
148                 report_failure("Dissector bug: %s",
149                                exception_message == NULL ?
150                                  dissector_error_nomsg : exception_message);
151                 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
152                         abort();
153                 status = FALSE;
154         }
155         ENDTRY;
156         return status;
157 }
158
159 void
160 epan_cleanup(void)
161 {
162         dfilter_cleanup();
163         proto_cleanup();
164         prefs_cleanup();
165         packet_cleanup();
166         expert_cleanup();
167 #ifdef HAVE_LUA
168         wslua_cleanup();
169 #endif
170 #ifdef HAVE_LIBGNUTLS
171         gnutls_global_deinit();
172 #endif
173         except_deinit();
174         addr_resolv_cleanup();
175
176         if (pinfo_pool_cache != NULL) {
177                 wmem_destroy_allocator(pinfo_pool_cache);
178                 pinfo_pool_cache = NULL;
179         }
180
181         wmem_cleanup();
182 }
183
184 epan_t *
185 epan_new(void)
186 {
187         epan_t *session = g_slice_new(epan_t);
188
189         /* XXX, it should take session as param */
190         init_dissection();
191
192         return session;
193 }
194
195 const char *
196 epan_get_user_comment(const epan_t *session, const frame_data *fd)
197 {
198         if (session->get_user_comment)
199                 return session->get_user_comment(session->data, fd);
200
201         return NULL;
202 }
203
204 const char *
205 epan_get_interface_name(const epan_t *session, guint32 interface_id)
206 {
207         if (session->get_interface_name)
208                 return session->get_interface_name(session->data, interface_id);
209
210         return NULL;
211 }
212
213 const nstime_t *
214 epan_get_frame_ts(const epan_t *session, guint32 frame_num)
215 {
216         const nstime_t *abs_ts = NULL;
217
218         if (session->get_frame_ts)
219                 abs_ts = session->get_frame_ts(session->data, frame_num);
220
221         if (!abs_ts)
222                 g_warning("!!! couldn't get frame ts for %u !!!\n", frame_num);
223
224         return abs_ts;
225 }
226
227 void
228 epan_free(epan_t *session)
229 {
230         if (session) {
231                 /* XXX, it should take session as param */
232                 cleanup_dissection();
233
234                 g_slice_free(epan_t, session);
235         }
236 }
237
238 void
239 epan_conversation_init(void)
240 {
241         conversation_init();
242 }
243
244 void
245 epan_conversation_cleanup(void)
246 {
247         conversation_cleanup();
248 }
249
250 void
251 epan_circuit_init(void)
252 {
253         circuit_init();
254 }
255
256 void
257 epan_circuit_cleanup(void)
258 {
259         circuit_cleanup();
260 }
261
262 /* Overrides proto_tree_visible i epan_dissect_init to make all fields visible.
263  * This is > 0 if a Lua script wanted to see all fields all the time.
264  * This is ref-counted, so clearing it won't override other taps/scripts wanting it.
265  */
266 static gint always_visible_refcount = 0;
267
268 void
269 epan_set_always_visible(gboolean force)
270 {
271         if (force)
272                 always_visible_refcount++;
273         else if (always_visible_refcount > 0)
274                 always_visible_refcount--;
275 }
276
277 epan_dissect_t*
278 epan_dissect_init(epan_dissect_t *edt, epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
279 {
280         g_assert(edt);
281
282         edt->session = session;
283
284         memset(&edt->pi, 0, sizeof(edt->pi));
285         if (pinfo_pool_cache != NULL) {
286                 edt->pi.pool = pinfo_pool_cache;
287                 pinfo_pool_cache = NULL;
288         }
289         else {
290                 edt->pi.pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK_FAST);
291         }
292
293         if (create_proto_tree) {
294                 edt->tree = proto_tree_create_root(&edt->pi);
295                 proto_tree_set_visible(edt->tree, (always_visible_refcount > 0) ? TRUE : proto_tree_visible);
296         }
297         else {
298                 edt->tree = NULL;
299         }
300
301         edt->tvb = NULL;
302
303         return edt;
304 }
305
306 void
307 epan_dissect_reset(epan_dissect_t *edt)
308 {
309         /* We have to preserve the pool pointer across the memzeroing */
310         wmem_allocator_t *tmp;
311
312         g_assert(edt);
313
314         g_slist_free(edt->pi.proto_data);
315         g_slist_free(edt->pi.dependent_frames);
316
317         /* Free the data sources list. */
318         free_data_sources(&edt->pi);
319
320         if (edt->tvb) {
321                 /* Free all tvb's chained from this tvb */
322                 tvb_free_chain(edt->tvb);
323                 edt->tvb = NULL;
324         }
325
326         if (edt->tree)
327                 proto_tree_reset(edt->tree);
328
329         tmp = edt->pi.pool;
330         wmem_free_all(tmp);
331
332         memset(&edt->pi, 0, sizeof(edt->pi));
333         edt->pi.pool = tmp;
334 }
335
336 epan_dissect_t*
337 epan_dissect_new(epan_t *session, const gboolean create_proto_tree, const gboolean proto_tree_visible)
338 {
339         epan_dissect_t *edt;
340
341         edt = g_new0(epan_dissect_t, 1);
342
343         return epan_dissect_init(edt, session, create_proto_tree, proto_tree_visible);
344 }
345
346 void
347 epan_dissect_fake_protocols(epan_dissect_t *edt, const gboolean fake_protocols)
348 {
349         if (edt)
350                 proto_tree_set_fake_protocols(edt->tree, fake_protocols);
351 }
352
353 void
354 epan_dissect_run(epan_dissect_t *edt, int file_type_subtype,
355         struct wtap_pkthdr *phdr, tvbuff_t *tvb, frame_data *fd,
356         column_info *cinfo)
357 {
358 #ifdef HAVE_LUA
359         wslua_prime_dfilter(edt); /* done before entering wmem scope */
360 #endif
361         wmem_enter_packet_scope();
362         dissect_record(edt, file_type_subtype, phdr, tvb, fd, cinfo);
363
364         /* free all memory allocated */
365         wmem_leave_packet_scope();
366 }
367
368 void
369 epan_dissect_run_with_taps(epan_dissect_t *edt, int file_type_subtype,
370         struct wtap_pkthdr *phdr, tvbuff_t *tvb, frame_data *fd,
371         column_info *cinfo)
372 {
373         wmem_enter_packet_scope();
374         tap_queue_init(edt);
375         dissect_record(edt, file_type_subtype, phdr, tvb, fd, cinfo);
376         tap_push_tapped_queue(edt);
377
378         /* free all memory allocated */
379         wmem_leave_packet_scope();
380 }
381
382 void
383 epan_dissect_file_run(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
384         tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
385 {
386 #ifdef HAVE_LUA
387         wslua_prime_dfilter(edt); /* done before entering wmem scope */
388 #endif
389         wmem_enter_packet_scope();
390         dissect_file(edt, phdr, tvb, fd, cinfo);
391
392         /* free all memory allocated */
393         wmem_leave_packet_scope();
394 }
395
396 void
397 epan_dissect_file_run_with_taps(epan_dissect_t *edt, struct wtap_pkthdr *phdr,
398         tvbuff_t *tvb, frame_data *fd, column_info *cinfo)
399 {
400         wmem_enter_packet_scope();
401         tap_queue_init(edt);
402         dissect_file(edt, phdr, tvb, fd, cinfo);
403         tap_push_tapped_queue(edt);
404
405         /* free all memory allocated */
406         wmem_leave_packet_scope();
407 }
408
409 void
410 epan_dissect_cleanup(epan_dissect_t* edt)
411 {
412         g_assert(edt);
413
414         g_slist_free(edt->pi.proto_data);
415         g_slist_free(edt->pi.dependent_frames);
416
417         /* Free the data sources list. */
418         free_data_sources(&edt->pi);
419
420         if (edt->tvb) {
421                 /* Free all tvb's chained from this tvb */
422                 tvb_free_chain(edt->tvb);
423         }
424
425         if (edt->tree) {
426                 proto_tree_free(edt->tree);
427         }
428
429         if (pinfo_pool_cache == NULL) {
430                 wmem_free_all(edt->pi.pool);
431                 pinfo_pool_cache = edt->pi.pool;
432         }
433         else {
434                 wmem_destroy_allocator(edt->pi.pool);
435         }
436 }
437
438 void
439 epan_dissect_free(epan_dissect_t* edt)
440 {
441         epan_dissect_cleanup(edt);
442         g_free(edt);
443 }
444
445 void
446 epan_dissect_prime_dfilter(epan_dissect_t *edt, const dfilter_t* dfcode)
447 {
448     dfilter_prime_proto_tree(dfcode, edt->tree);
449 }
450
451 /* ----------------------- */
452 const gchar *
453 epan_custom_set(epan_dissect_t *edt, GSList *field_ids,
454                              gint occurrence,
455                              gchar *result,
456                              gchar *expr, const int size )
457 {
458         return proto_custom_set(edt->tree, field_ids, occurrence, result, expr, size);
459 }
460
461 void
462 epan_dissect_fill_in_columns(epan_dissect_t *edt, const gboolean fill_col_exprs, const gboolean fill_fd_colums)
463 {
464         col_custom_set_edt(edt, edt->pi.cinfo);
465         col_fill_in(&edt->pi, fill_col_exprs, fill_fd_colums);
466 }
467
468 gboolean
469 epan_dissect_packet_contains_field(epan_dissect_t* edt,
470                                    const char *field_name)
471 {
472         GPtrArray* array;
473         int field_id;
474         gboolean contains_field;
475
476         if (!edt || !edt->tree)
477                 return FALSE;
478         field_id = proto_get_id_by_filter_name(field_name);
479         if (field_id < 0)
480                 return FALSE;
481         array = proto_find_finfo(edt->tree, field_id);
482         contains_field = (array->len > 0) ? TRUE : FALSE;
483         g_ptr_array_free(array, TRUE);
484         return contains_field;
485 }
486
487 /*
488  * Get compile-time information for libraries used by libwireshark.
489  */
490 void
491 epan_get_compiled_version_info(GString *str)
492 {
493         /* SNMP */
494         g_string_append(str, ", ");
495 #ifdef HAVE_LIBSMI
496         g_string_append(str, "with SMI " SMI_VERSION_STRING);
497 #else /* no SNMP library */
498         g_string_append(str, "without SMI");
499 #endif /* _SMI_H */
500
501         /* c-ares */
502         g_string_append(str, ", ");
503 #ifdef HAVE_C_ARES
504         g_string_append(str, "with c-ares " ARES_VERSION_STR);
505 #else
506         g_string_append(str, "without c-ares");
507
508         /* ADNS - only add if no c-ares */
509         g_string_append(str, ", ");
510 #ifdef HAVE_GNU_ADNS
511         g_string_append(str, "with ADNS");
512 #else
513         g_string_append(str, "without ADNS");
514 #endif /* HAVE_GNU_ADNS */
515 #endif /* HAVE_C_ARES */
516
517         /* LUA */
518         g_string_append(str, ", ");
519 #ifdef HAVE_LUA
520         g_string_append(str, "with ");
521         g_string_append(str, LUA_VERSION);
522 #else
523         g_string_append(str, "without Lua");
524 #endif /* HAVE_LUA */
525
526         /* GnuTLS */
527         g_string_append(str, ", ");
528 #ifdef HAVE_LIBGNUTLS
529         g_string_append(str, "with GnuTLS " LIBGNUTLS_VERSION);
530 #else
531         g_string_append(str, "without GnuTLS");
532 #endif /* HAVE_LIBGNUTLS */
533
534         /* Gcrypt */
535         g_string_append(str, ", ");
536 #ifdef HAVE_LIBGCRYPT
537         g_string_append(str, "with Gcrypt " GCRYPT_VERSION);
538 #else
539         g_string_append(str, "without Gcrypt");
540 #endif /* HAVE_LIBGCRYPT */
541
542         /* Kerberos */
543         /* XXX - I don't see how to get the version number, at least for KfW */
544         g_string_append(str, ", ");
545 #ifdef HAVE_KERBEROS
546 #ifdef HAVE_MIT_KERBEROS
547         g_string_append(str, "with MIT Kerberos");
548 #else
549         /* HAVE_HEIMDAL_KERBEROS */
550         g_string_append(str, "with Heimdal Kerberos");
551 #endif
552 #else
553         g_string_append(str, "without Kerberos");
554 #endif /* HAVE_KERBEROS */
555
556         /* GeoIP */
557         g_string_append(str, ", ");
558 #ifdef HAVE_GEOIP
559         g_string_append(str, "with GeoIP");
560 #else
561         g_string_append(str, "without GeoIP");
562 #endif /* HAVE_GEOIP */
563
564 }
565
566 /*
567  * Get runtime information for libraries used by libwireshark.
568  */
569 void
570 epan_get_runtime_version_info(GString *str
571 #if !defined(HAVE_LIBGNUTLS) && !defined(HAVE_LIBGCRYPT)
572 _U_
573 #endif
574 )
575 {
576         /* GnuTLS */
577 #ifdef HAVE_LIBGNUTLS
578         g_string_append_printf(str, ", with GnuTLS %s", gnutls_check_version(NULL));
579 #endif /* HAVE_LIBGNUTLS */
580
581         /* Gcrypt */
582 #ifdef HAVE_LIBGCRYPT
583         g_string_append_printf(str, ", with Gcrypt %s", gcry_check_version(NULL));
584 #endif /* HAVE_LIBGCRYPT */
585 }
586
587 /*
588  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
589  *
590  * Local variables:
591  * c-basic-offset: 8
592  * tab-width: 8
593  * indent-tabs-mode: t
594  * End:
595  *
596  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
597  * :indentSize=8:tabSize=8:noTabs=false:
598  */