diff options
author | AndersBroman <anders.broman@ericsson.com> | 2014-09-05 15:40:18 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2014-09-06 09:52:01 +0000 |
commit | 07b003a98f611679994a99cb64c711c6c2b4a613 (patch) | |
tree | 6d648e127f977904dcb2cba00f57b68dd51d8b37 /plugins/asn1/packet-asn1.c | |
parent | ceef7eba755cbecf670653360f72d864949dac49 (diff) |
Remove obsolete dissectors.
Change-Id: Icd480491670de9d8495a95861b18a8a5cb9724b4
Reviewed-on: https://code.wireshark.org/review/4006
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'plugins/asn1/packet-asn1.c')
-rw-r--r-- | plugins/asn1/packet-asn1.c | 5542 |
1 files changed, 0 insertions, 5542 deletions
diff --git a/plugins/asn1/packet-asn1.c b/plugins/asn1/packet-asn1.c deleted file mode 100644 index 07bce98395..0000000000 --- a/plugins/asn1/packet-asn1.c +++ /dev/null @@ -1,5542 +0,0 @@ -/******************************************************************************************************/ -/* packet-asn1.c - * - * Copyright (c) 2003 by Matthijs Melchior <matthijs.melchior@xs4all.nl> - * - * A plugin for: - * - * Wireshark - Network traffic analyzer - * By Gerald Combs <gerald@wireshark.org> - * Copyright 1999 Gerald Combs - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - - -/************************************************************************** - * This plugin will dissect BER encoded ASN.1 messages in UDP packets or in - * a TCP stream. It relies on wireshark to do defragmentation and re-assembly - * to construct complete messages. - * - * To produce packet display with good annotations it needs to know about - * the ASN.1 definition of the messages it reads. To this end, it can read - * the 'type-table' output file of the ASN.1 to C compiler 'snacc'. The - * version I have used came from: http://packages.debian.org/testing/devel/snacc.html - * - * The type-table files produced by snacc are themselves ASN.1 BER encoded - * data structures. Knowledge of the structure of that table, as specified - * in the tbl.asn1 file in the snacc distribution, is hand coded in some - * functions in this plugin. - * - * This also means that this dissector can show its own specification. - * On a unix machine, do the following to see this in action: - * - cd /tmp - * - snacc -u /usr/include/snacc/asn1/asn-useful.asn1 -T tbl.tt /usr/include/snacc/asn1/tbl.asn1 - * - od -Ax -tx1 tbl.tt | text2pcap -T 801,801 - tbl.tt.pcap - * - wireshark tbl.tt.pcap - * GUI: Edit->Preferences->Protocols->ASN1 - * type table file: /tmp/tbl.tt - * PDU name: TBL - * [OK] - * you can now browse the tbl.tt definition. - * - */ - - -/* Include files */ - -#include "config.h" - -#include <errno.h> - -#include <ctype.h> -#include <string.h> - -#include <glib.h> -#include <glib/gprintf.h> - -#include <wsutil/report_err.h> -#include <wsutil/file_util.h> -#include <wsutil/filesystem.h> -#include <wsutil/tempfile.h> - -#include <epan/packet.h> -#include <epan/exceptions.h> -#include <epan/addr_resolv.h> -#include <epan/prefs.h> -#include <epan/dissectors/packet-tcp.h> -#include <epan/oids.h> -#include <epan/emem.h> -#include <plugins/asn1/asn1.h> - -#ifdef DISSECTOR_WITH_GUI -#include <gtk/gtk.h> -#endif - -/* buffer lengths */ -#define BUFLS 32 -#define BUFLM 64 -#define BUFLL 128 - -/* Define default ports */ - -#define TCP_PORT_ASN1 0 -#define UDP_PORT_ASN1 0 -#define SCTP_PORT_ASN1 0 - -void proto_reg_handoff_asn1(void); - -/* Define the asn1 proto */ - -static int proto_asn1 = -1; - -/* Define the tree for asn1*/ - -static int ett_asn1 = -1; - -#define MAXPDU 64 /* max # PDU's in one packet */ -static int ett_pdu[MAXPDU]; - -#define MAX_NEST 32 /* max nesting level for ASN.1 elements */ -static int ett_seq[MAX_NEST]; - -/* - * Global variables associated with the preferences for asn1 - */ - -#ifdef JUST_ONE_PORT -static guint global_tcp_port_asn1 = TCP_PORT_ASN1; -static guint global_udp_port_asn1 = UDP_PORT_ASN1; -static guint global_sctp_port_asn1 = SCTP_PORT_ASN1; -#else -static range_t *global_tcp_ports_asn1; -static range_t *global_udp_ports_asn1; -static range_t *global_sctp_ports_asn1; -#endif /* JUST_ONE_PORT */ - -static gboolean asn1_desegment = TRUE; -static const char *asn1_filename = NULL; -static char *old_default_asn1_filename = NULL; -#define OLD_DEFAULT_ASN1FILE "asn1" G_DIR_SEPARATOR_S "default.tt" -#ifdef _WIN32 -#define BAD_SEPARATOR_OLD_DEFAULT_ASN1FILE "asn1/default.tt" -static char *bad_separator_old_default_asn1_filename = NULL; -#endif -static char *current_asn1 = NULL; -static const char *asn1_pduname = NULL; -static char *current_pduname = NULL; -static gboolean asn1_debug = FALSE; -static guint first_pdu_offset = 0; -static gboolean asn1_message_win = FALSE; -static gboolean asn1_verbose = FALSE; /* change to TRUE for logging the startup phase */ -static gboolean asn1_full = FALSE; /* show full names */ -static guint type_recursion_level = 1; /* eliminate 1 level of references */ -static char *asn1_logfile = NULL; - -#define ASN1LOGFILE "wireshark.log" - -/* PDU counter, for correlation between GUI display and log file in debug mode */ -static int pcount = 0; - -static tvbuff_t *asn1_desc; /* the PDU description */ -static GNode *asn1_nodes = NULL; /* GNode tree pointing to every asn1 data element */ -static GNode *data_nodes = NULL; /* GNode tree describing the syntax data */ -static GNode *PDUtree = NULL; /* GNode tree describing the expected PDU format */ - -static guint PDUerrcount = 0; /* count of parse errors in one ASN.1 message */ - -#define NEL(x) (sizeof(x)/sizeof(*x)) /* # elements in static array */ - - -static char pabbrev[] = "asn1"; /* field prefix */ - -static char fieldname[512]; /* for constructing full names */ -static guint pabbrev_pdu_len; /* length initial part of fieldname with 'abbrev.asn1pdu.' */ - -/* - * Text strings describing the standard, universal, ASN.1 names. - */ - -#define ASN1_EOI 4 /* this is in the class number space... */ -#define ASN1_BEG 2 /* to be merged with constructed flag, first entry in sequence */ - -static const char tag_class[] = "UACPX"; - -static const char *asn1_cls[] = { "Universal", "Application", "Context", "Private" }; - -static const char *asn1_con[] = { "Primitive", "Constructed" }; - -static const char *asn1_tag[] = { - /* 0 */ "EOC", "Boolean", "Integer", "BitString", - /* 4 */ "OctetString", "Null", "ObjectIdentifier", "ObjectDescriptor", - /* 8 */ "External", "Real", "Enumerated", "tag11", - /* 12 */ "UTF8String", "tag13", "tag14", "tag15", - /* 16 */ "Sequence", "Set", "NumericString", "PrintableString", - /* 20 */ "TeletexString", "VideotexString", "IA5String", "UTCTime", - /* 24 */ "GeneralTime", "GraphicString", "ISO646String", "GeneralString", - /* 28 */ "UniversalString", "tag29", "BMPString", "Long tag prefix" -/* TT61 == TELETEX */ -/* ISO646 == VISIBLE*/ -}; - -/* type names used in the output of the snacc ASN.1 compiler, the TBLTypeId enum */ -static gboolean tbl_types_verified = FALSE; - -typedef enum { /* copied from .../snacc/c-lib/boot/tbl.h */ - TBL_BOOLEAN = 0, - TBL_INTEGER = 1, - TBL_BITSTRING = 2, - TBL_OCTETSTRING = 3, - TBL_NULL = 4, - TBL_OID = 5, - TBL_REAL = 6, - TBL_ENUMERATED = 7, - TBL__SIMPLE = 8, /* values smaller than this can have a value */ - TBL_SEQUENCE = 8, - TBL_SET = 9, - TBL_SEQUENCEOF = 10, - TBL_SETOF = 11, - TBL_CHOICE = 12, - TBL_TYPEREF = 13, - - TBL_SEQUENCEOF_start, /* to mark potential sequence-of repeat */ - TBL_TYPEREF_nopop, /* typeref has been handled immediately */ - TBL_CHOICE_done, /* choice is finished */ - TBL_reserved, /* this sequence has been visited */ - TBL_CHOICE_immediate, /* immediate choice, no next */ - - TBL_INVALID /* incorrect value for this enum */ -} TBLTypeId; - -/* Universal tags mapped to snacc ASN.1 table types */ -static int asn1_uni_type[] = { - /* 0 */ TBL_INVALID, TBL_BOOLEAN, TBL_INTEGER, TBL_BITSTRING, - /* 4 */ TBL_OCTETSTRING, TBL_NULL, TBL_OID, TBL_INVALID, - /* 8 */ TBL_INVALID, TBL_REAL, TBL_ENUMERATED, TBL_INVALID, - /* 12 */ TBL_OCTETSTRING, TBL_INVALID, TBL_INVALID, TBL_INVALID, - /* 16 */ TBL_SEQUENCE, TBL_SET, TBL_OCTETSTRING, TBL_OCTETSTRING, - /* 20 */ TBL_OCTETSTRING, TBL_OCTETSTRING, TBL_OCTETSTRING, TBL_OCTETSTRING, - /* 24 */ TBL_OCTETSTRING, TBL_OCTETSTRING, TBL_OCTETSTRING, TBL_OCTETSTRING, - /* 28 */ TBL_OCTETSTRING, TBL_INVALID, TBL_OCTETSTRING, TBL_INVALID, -}; - - -#define TBL_REPEAT 0x00010000 /* This type may be repeated, a flag in word TBLTypeId */ -#define TBL_REPEAT_choice 0x00020000 /* repeating a choice */ -#define TBL_CHOICE_made 0x00040000 /* This was a choice entry */ -#define TBL_SEQUENCE_done 0x00080000 /* children have been processed */ -#define TBL_CHOICE_repeat 0x00100000 /* a repeating choice */ -#define TBL_REFERENCE 0x00200000 /* This entry is result of a typeref */ -#define TBL_REFERENCE_pop 0x00400000 /* reference handled, do pop i.s.o. next */ -#define TBL_SEQUENCE_choice 0x00800000 /* this sequence is a first of a repeating choice */ -#define TBL_CONSTRUCTED 0x01000000 /* unexpectedly constructed entry */ -#define TBL_TYPEmask 0x0000FFFF /* Mask just the type */ - -/* XXX - Should we use val_to_str here? */ -#define TBLTYPE(x) (tbl_types[x&TBL_TYPEmask]) - -/* text tables for debugging and GUI */ -static const char *tbl_types[] = { - /* 0 */ "tbl-boolean", - /* 1 */ "tbl-integer", - /* 2 */ "tbl-bitstring", - /* 2 */ "tbl-octetstring", - /* 4 */ "tbl-null", - /* 5 */ "tbl-oid", - /* 6 */ "tbl-real", - /* 7 */ "tbl-enumerated", - /* 8 */ "tbl-sequence", - /* 9 */ "tbl-set", - /* 10 */ "tbl-sequenceof", - /* 11 */ "tbl-setof", - /* 12 */ "tbl-choice", - /* 13 */ "tbl-typeref", - - /* 14 */ "tbl-sequenceof-start", - /* 15 */ "tbl-typeref-nopop", - /* 16 */ "tbl-choice-done", - /* 17 */ "tbl-reserved", - /* 18 */ "tbl-choice-immediate", - - /* 19 */ "tbl-invalid", -}; -static const char *tbl_types_asn1[] = { - /* 0 */ "BOOLEAN", - /* 1 */ "INTEGER", - /* 2 */ "BITSTRING", - /* 2 */ "OCTET STRING", - /* 4 */ "NULL", - /* 5 */ "OBJECT IDENTIFIER", - /* 6 */ "REAL", - /* 7 */ "ENUMERATED", - /* 8 */ "SEQUENCE", - /* 9 */ "SET", - /* 10 */ "SEQUENCE OF", - /* 11 */ "SET OF", - /* 12 */ "CHOICE", - /* 13 */ "TYPEREF", - - /* 14 */ "start-SEQUENCE OF", - /* 15 */ "TYPEREF nopop", - /* 16 */ "CHOICE done", - /* 17 */ "Reserved", - /* 18 */ "CHOICE immediate", - - /* 19 */ "INVALID entry", -}; -/* conversion from snacc type to appropriate wireshark type */ -static enum ftenum tbl_types_wireshark[] = { - /* 0 */ FT_BOOLEAN, /* TBL_BOOLEAN */ - /* 1 */ FT_UINT32, /* TBL_INTEGER */ - /* 2 */ FT_UINT32, /* TBL_BITSTRING */ - /* 2 */ FT_STRINGZ, /* TBL_OCTETSTRING */ - /* 4 */ FT_NONE, /* TBL_NULL */ - /* 5 */ FT_BYTES, /* TBL_OID */ - /* 6 */ FT_DOUBLE, /* TBL_REAL */ - /* 7 */ FT_UINT32, /* TBL_ENUMERATED */ - /* 8 */ FT_NONE, /* TBL_SEQUENCE */ - /* 9 */ FT_NONE, /* TBL_SET */ - /* 10 */ FT_NONE, /* TBL_SEQUENCEOF */ - /* 11 */ FT_NONE, /* TBL_SETOF */ - /* 12 */ FT_NONE, /* TBL_CHOICE */ - /* 13 */ FT_NONE, /* TBL_TYPEREF */ - - /* 14 */ FT_NONE, /* TBL_SEQUENCEOF_start */ - /* 15 */ FT_NONE, /* TBL_TYPEREF_nopop */ - /* 16 */ FT_NONE, /* TBL_CHOICE_done */ - /* 17 */ FT_NONE, /* TBL_reserved */ - /* 18 */ FT_NONE, /* TBL_CHOICE_immediate */ - - /* 19 */ FT_NONE, /* TBL_INVALID */ -}; - -/* conversion from snacc type to appropriate wireshark display type */ -static guint tbl_display_wireshark[] = { - /* 0 */ BASE_DEC, /* TBL_BOOLEAN */ - /* 1 */ BASE_DEC_HEX, /* TBL_INTEGER */ - /* 2 */ BASE_HEX, /* TBL_BITSTRING */ - /* 2 */ BASE_NONE, /* TBL_OCTETSTRING */ - /* 4 */ BASE_NONE, /* TBL_NULL */ - /* 5 */ BASE_DEC, /* TBL_OID */ - /* 6 */ BASE_DEC, /* TBL_REAL */ - /* 7 */ BASE_DEC, /* TBL_ENUMERATED */ - /* 8 */ BASE_NONE, /* TBL_SEQUENCE */ - /* 9 */ BASE_NONE, /* TBL_SET */ - /* 10 */ BASE_NONE, /* TBL_SEQUENCEOF */ - /* 11 */ BASE_NONE, /* TBL_SETOF */ - /* 12 */ BASE_NONE, /* TBL_CHOICE */ - /* 13 */ BASE_NONE, /* TBL_TYPEREF */ - - /* 14 */ BASE_NONE, /* TBL_SEQUENCEOF_start */ - /* 15 */ BASE_NONE, /* TBL_TYPEREF_nopop */ - /* 16 */ BASE_NONE, /* TBL_CHOICE_done */ - /* 17 */ BASE_NONE, /* TBL_reserved */ - /* 18 */ BASE_NONE, /* TBL_CHOICE_immediate */ - - /* 19 */ BASE_NONE, /* TBL_INVALID */ -}; - -static const char *tbl_types_wireshark_txt[] = { - /* 0 */ "FT_BOOLEAN", /* TBL_BOOLEAN */ - /* 1 */ "FT_UINT32", /* TBL_INTEGER */ - /* 2 */ "FT_UINT32", /* TBL_BITSTRING */ - /* 2 */ "FT_STRINGZ", /* TBL_OCTETSTRING */ - /* 4 */ "FT_NONE", /* TBL_NULL */ - /* 5 */ "FT_BYTES", /* TBL_OID */ - /* 6 */ "FT_DOUBLE", /* TBL_REAL */ - /* 7 */ "FT_UINT32", /* TBL_ENUMERATED */ - /* 8 */ "FT_NONE", /* TBL_SEQUENCE */ - /* 9 */ "FT_NONE", /* TBL_SET */ - /* 10 */ "FT_NONE", /* TBL_SEQUENCEOF */ - /* 11 */ "FT_NONE", /* TBL_SETOF */ - /* 12 */ "FT_NONE", /* TBL_CHOICE */ - /* 13 */ "FT_NONE", /* TBL_TYPEREF */ - - /* 14 */ "FT_NONE", /* TBL_SEQUENCEOF_start */ - /* 15 */ "FT_NONE", /* TBL_TYPEREF_nopop */ - /* 16 */ "FT_NONE", /* TBL_CHOICE_done */ - /* 17 */ "FT_NONE", /* TBL_reserved */ - /* 18 */ "FT_NONE", /* TBL_CHOICE_immediate */ - - /* 19 */ "FT_NONE", /* TBL_INVALID */ -}; - -typedef struct _PDUinfo PDUinfo; -struct _PDUinfo { - guint type; - const char *name; - const char *asn1typename; - const char *fullname; - guchar tclass; - guint tag; - guint flags; - GNode *reference; - gint typenum; - gint basetype; /* parent type */ - gint mytype; /* original type number, typenum may have gone through a reference */ - gint value_id; /* wireshark field id for the value in this PDU */ - gint type_id; /* wireshark field id for the type of this PDU */ - hf_register_info value_hf; /* wireshark field info for this value */ -}; - - -/* bits in the flags collection */ -#define PDU_OPTIONAL 1 -#define PDU_IMPLICIT 2 -#define PDU_NAMEDNUM 4 -#define PDU_REFERENCE 8 -#define PDU_TYPEDEF 0x10 -#define PDU_ANONYMOUS 0x20 -#define PDU_TYPETREE 0x40 - -#define PDU_CHOICE 0x08000000 /* manipulated by the PDUname routine */ - -static guint PDUinfo_initflags = 0; /* default flags for newly allocated PDUinfo structs */ - -/* description of PDU properties as passed from the matching routine - * to the decoder and GUI. - */ -typedef struct _PDUprops PDUprops; -struct _PDUprops { - guint type; /* value from enum TBLTypeId */ - const char *name; - const char *asn1typename; - const char *fullname; - guint flags; - gpointer data; - gint value_id; - gint type_id; -}; -/* flags defined in PDUprops.flags */ -#define OUT_FLAG_type 1 -#define OUT_FLAG_data 2 -#define OUT_FLAG_typename 4 -#define OUT_FLAG_dontshow 8 -#define OUT_FLAG_noname 0x10 -#define OUT_FLAG_constructed 0x20 - -static PDUprops *getPDUprops(PDUprops *out, guint offset, guint cls, guint tag, guint cons); -static const char *getPDUenum(PDUprops *props, guint offset, guint cls, guint tag, guint value); - -static const char empty[] = ""; /* address of the empt string, avoids many tests for NULL */ -#define MAX_OTSLEN 256 /* max printed size for an octet string */ - - -#undef NEST /* show nesting of asn.1 enties */ - -#ifdef NEST /* only for debugging */ -/* show nesting, only for debugging... */ -#define MAXTAGS MAX_NEST -static struct { - guchar cls; - guchar tag; -} taglist[MAXTAGS]; - -static char *showtaglist(guint level) -{ - static char tagtxt[BUFLM]; - guint i; - int idx; - - idx = 0; -#ifdef ALLTAGS - for(i=0; i<= level; i++) { - switch(taglist[i].cls) { - case BER_CLASS_UNI: - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "U"); - break; - case BER_CLASS_APP: - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "A"); - break; - case BER_CLASS_CON: - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "C"); - break; - case BER_CLASS_PRI: - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "P"); - break; - default: - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "x"); - break; - } - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "%d.", taglist[i].tag); - } -#else /* only context tags */ - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "C"); - for(i=0; i<= level; i++) { - if (taglist[i].cls == BER_CLASS_CON) { - idx += g_snprintf(&tagtxt[idx], BUFLM - idx, "%d.", taglist[i].tag); - } - } -#endif - idx--; - tagtxt[idx] = '\0'; /* remove trailing '.' */ - return tagtxt; -} - -static guint -get_context(guint level) -{ - guint ctx = 0; - guint i; - - for(i=0; i<=level; i++) { - if (taglist[i].cls == BER_CLASS_CON) - ctx = (ctx << 8) | taglist[i].tag; - } - return ctx; -} -#endif /* NEST, only for debugging */ - - -/* Convert a bit string to an ascii representation for printing - * -- not thread safe ... - */ -static const char *showbits(guchar *val, guint count) -{ - static char str[BUFLM]; - guint i; - char *p = str; - - if (count > 32) - return "*too many bits*"; - - if (val != 0) { - for(i=0; i<count; i++) { - if (i && ((i & 7) == 0)) *p++ = ' '; - *p++ = (val[i>>3] & (0x80 >> (i & 7))) ? '1' : '0'; - } - } - *p = 0; - return str; -} - -/* get bitnames string for bits set */ -static const char * -showbitnames(guchar *val, guint count, PDUprops *props, guint offset) -{ - static char str[BUFLL]; - guint i; - int idx; - - if (props->flags & OUT_FLAG_noname) - return empty; - - if (count > 32) - return "*too many bits, no names...*"; - - idx = 0; - if (val != NULL) { - for(i=0; i<count; i++) { - if (val[i>>3] & (0x80 >> (i & 7))) { /* bit i is set */ - idx += g_snprintf(&str[idx], BUFLL-idx, "%s,", getPDUenum(props, offset, 0, 0, i)); - } - } - if (idx > 0) - --idx; /* remove terminating , */ - } - str[idx] = '\0'; - return str; - - - -} -/* Convert an oid to its conventional text representation - * -- not thread safe... - */ -static char *showoid(subid_t *oid, guint len) -{ - static char str[BUFLM]; - guint i; - int idx; - - idx = 0; - if (oid != NULL) { - for(i=0; i<len; i++) { - if (i) - idx += g_snprintf(&str[idx], BUFLM - idx, "."); - idx += g_snprintf(&str[idx], BUFLM - idx, "%lu", (unsigned long)oid[i]); - } - } - str[idx] = '\0'; - return str; -} - -/* show octetstring, if all ascii, show that, else hex [returnrd string must be freed by caller] */ -static char * -showoctets(guchar *octets, guint len, guint hexlen) /* if len <= hexlen, always show hex */ -{ - guint dohex = 0; - guint i; - char *str; - int idx; - const char *endstr = empty; - - if (len == 0) { - str = (char *)g_malloc(1); - str[0] = 0; - } else { - for (i=0; i<len; i++) { - if (!isprint(octets[i])) /* maybe isblank() as well ... */ - dohex++; - } - if (len > MAX_OTSLEN) { /* limit the maximum output.... */ - len = MAX_OTSLEN; - endstr = "...."; /* this is 5 bytes !! */ - } - if (dohex) { - str = (char *)g_malloc(len*2 + 5); - idx = 0; - for (i=0; i<len; i++) { - idx += g_snprintf(&str[idx], len*2 - idx, "%2.2X", octets[i]); - } - g_snprintf(&str[idx], len*2 + 5 - idx, "%s", endstr); - } else { - if (len <= hexlen) { /* show both hex and ascii, assume hexlen < MAX_OTSLEN */ - str = (char *)g_malloc(len*3+2); - idx = 0; - for (i=0; i<len; i++) { - idx += g_snprintf(&str[idx], len*3 - idx, "%2.2X", octets[i]); - } - g_snprintf(&str[idx], len*3+2 - idx, " %s", octets); - } else { - /* g_strdup_printf("%*s%s", len, octets, endstr) does not work ?? */ - str = (char *)g_malloc(len+5); - g_snprintf(str, len*3+5, " %s%s", octets, endstr); - } - } - } - return str; -} - -/* allow NULL pointers in strcmp, handle them as empty strings */ -static int -g_strcmp(gconstpointer a, gconstpointer b) -{ - if (a == 0) a = empty; - if (b == 0) b = empty; - return strcmp((const char *)a, (const char *)b); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* WARNING WARNING WARNING WARNING WARNING WARNING */ -/* */ -/* Most of the following routine is guesswork in order to */ -/* speed up resynchronisation if the dissector lost the */ -/* encoding due to incomplete captures, or a capture that */ -/* starts in the middle of a fragmented ip packet */ -/* If this poses to many problems, these settings can be */ -/* made part of the protocol settings in the user interface */ -/*************************************************************/ - -/* check length for a reasonable value, return a corrected value */ -static int -checklength(int len, int def, int cls, int tag, char *lenstr, int strmax) -{ - int newlen = len; - - if ( ! def) { - g_snprintf(lenstr, strmax, "indefinite"); - return len; - } - - if (len < 0) /* negative ..... */ - newlen = 4; - - if (cls != BER_CLASS_UNI) { /* don't know about the tags */ - if (len > 131071) - newlen = 64; - } else { - switch (tag) { - case BER_UNI_TAG_EOC: /* End Of Contents */ - case BER_UNI_TAG_NULL: /* Null */ - newlen = 0; - break; - case BER_UNI_TAG_BOOLEAN: /* Boolean */ - newlen = 1; - break; - case BER_UNI_TAG_INTEGER: /* Integer */ - case BER_UNI_TAG_ENUMERATED: /* Enumerated */ - if (len > 8) - newlen = 4; - break; - case BER_UNI_TAG_BITSTRING: /* Bit String */ - if (len > 8) - newlen = 4; - break; - case BER_UNI_TAG_OCTETSTRING: /* Octet String */ - case BER_UNI_TAG_NumericString: /* Numerical String */ - case BER_UNI_TAG_PrintableString: /* Printable String */ - case BER_UNI_TAG_TeletexString: /* Teletext String */ - case BER_UNI_TAG_VideotexString: /* Video String */ - case BER_UNI_TAG_IA5String: /* IA5 String */ - case BER_UNI_TAG_GraphicString: /* Graphical String */ - case BER_UNI_TAG_VisibleString: /* Visible String */ - case BER_UNI_TAG_GeneralString: /* General String */ - if (len > 65535) - newlen = 32; - break; - case BER_UNI_TAG_OID: /* Object Identifier */ - case BER_UNI_TAG_ObjectDescriptor: /* Description */ - case ASN1_EXT: /* External */ - if (len > 64) - newlen = 16; - break; - case BER_UNI_TAG_REAL: /* Real */ - if (len >16) - newlen = 8; - break; - case BER_UNI_TAG_SEQUENCE: /* Sequence */ - case BER_UNI_TAG_SET: /* Set */ - if (len > 65535) - newlen = 64; - break; - case BER_UNI_TAG_UTCTime: /* Universal Time */ - case BER_UNI_TAG_GeneralizedTime: /* General Time */ - if (len > 32) - newlen = 15; - break; - - default: - if (len > 131071) - newlen = 64; - break; - } - } - - if (newlen != len) { - /* a change was needed.... */ - g_snprintf(lenstr, strmax, "%d(changed from %d)", newlen, len); - } else { - g_snprintf(lenstr, strmax, "%d", len); - } - return newlen; -} - -static guint decode_asn1_sequence(tvbuff_t *tvb, guint offset, guint len, proto_tree *pt, int level); -static void PDUreset(int count, int counr2); - -static int -dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct tcpinfo *info, gboolean is_tcp) { - ASN1_SCK asn1; - guint cls, con, tag, len, offset, reassembled; - gboolean def; - char lenstr[BUFLS]; - char tagstr[BUFLS]; - char headstr[BUFLL]; - char offstr[BUFLS]; - const char *name, *tname; - volatile guint boffset; - volatile int i = 0; /* PDU counter */ - proto_tree * volatile ti = 0, * volatile ti2 = 0, *asn1_tree, *tree2; - proto_item *hidden_item; - PDUprops props; - static guint lastseq; - gint delta; - - /* Reject the packet if info is NULL under conditions where it'll be used. */ - if (is_tcp && info == NULL) - return 0; - - pcount++; - boffset = 0; - - reassembled = 1; /* UDP is not a stream, and thus always reassembled .... */ - if (is_tcp) { /* we have tcpinfo */ - delta = info->seq - lastseq; - reassembled = info->is_reassembled; - lastseq = info->seq; - - if (asn1_verbose) - g_message("dissect_asn1: tcp - seq=%u, delta=%d, reassembled=%d", - info->seq, delta, reassembled); - } else { - if (asn1_verbose) - g_message("dissect_asn1: udp"); - } - - /* Set the protocol column */ - col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "ASN.1 %s", current_pduname); - - col_clear(pinfo->cinfo, COL_INFO); - - - offstr[0] = 0; - if ((first_pdu_offset > 0) && !reassembled) { - boffset = first_pdu_offset; - g_snprintf(offstr, sizeof(offstr), " at %d", boffset); - } - - /* open BER decoding */ - asn1_open(&asn1, tvb, boffset); - - asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - - asn1_close(&asn1, &offset); - - PDUreset(pcount, 0); /* arguments are just for debugging */ - getPDUprops(&props, boffset, cls, tag, con); - name = props.name; - tname = props.asn1typename; - - len = checklength(len, def, cls, tag, lenstr, sizeof(lenstr)); - - if (asn1_debug) { - - g_snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); - - g_snprintf(headstr, sizeof(headstr), "first%s: (%s)%s %d %s, %s, %s, len=%s, off=%d, size=%d ", - offstr, - tname, - name, - pcount, - asn1_cls[cls], - asn1_con[con], - ((cls == BER_CLASS_UNI) && (tag < 32)) ? asn1_tag[tag] : tagstr, - lenstr, - boffset, - tvb_length(tvb) - ); - } else { - if (props.flags & OUT_FLAG_noname) { - g_snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); - name = ((cls == BER_CLASS_UNI) && (tag < 32)) ? asn1_tag[tag] : tagstr; - } - g_snprintf(headstr, sizeof(headstr), "first pdu%s: (%s)%s ", offstr, tname, name ); - } - - /* Set the info column */ - col_add_str(pinfo->cinfo, COL_INFO, headstr ); - - /* - * If we have a non-null tree (ie we are building the proto_tree - * instead of just filling out the columns ), then add a BER - * tree node - */ - - /* ignore the tree here, must decode BER to know how to reassemble!! */ -/* if(tree) { */ - - TRY { /* catch incomplete PDU's */ - - ti = proto_tree_add_protocol_format(tree, proto_asn1, tvb, boffset, - def? (int) (offset - boffset + len) : -1, - "ASN.1 %s", current_pduname); - - tree2 = proto_item_add_subtree(ti, ett_asn1); - - switch (((PDUinfo *)PDUtree->data)->type) { - - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_BITSTRING: - case TBL_REAL: - case TBL_ENUMERATED: - hidden_item = proto_tree_add_item(tree2, ((PDUinfo *)PDUtree->data)->value_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_LITTLE_ENDIAN); - break; - - case TBL_OCTETSTRING: - hidden_item = proto_tree_add_item(tree2, ((PDUinfo *)PDUtree->data)->value_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(tree2, ((PDUinfo *)PDUtree->data)->value_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - - offset = boffset; /* the first packet */ - while((i < MAXPDU) && (tvb_length_remaining(tvb, offset) > 0)) { - ti2 = 0; - boffset = offset; - /* open BER decoding */ - asn1_open(&asn1, tvb, offset); - asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - asn1_close(&asn1, &offset); - - PDUreset(pcount, i+1); - getPDUprops(&props, boffset, cls, tag, con); - name = props.name; - tname = props.asn1typename; - - if (!def) - len = tvb_length_remaining(tvb, offset); - - len = checklength(len, def, cls, tag, lenstr, sizeof(lenstr)); - - if (asn1_debug) { - - g_snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); - - g_snprintf(headstr, sizeof(headstr), "%s, %s, %s, len=%s, off=%d, remaining=%d", - asn1_cls[cls], - asn1_con[con], - ((cls == BER_CLASS_UNI) && (tag < 32)) ? asn1_tag[tag] : tagstr, - lenstr, - boffset, - tvb_length_remaining(tvb, offset) ); - - if (props.value_id == -1) - ti2 = proto_tree_add_text(tree2, tvb, boffset, - def? (int) (offset - boffset + len) : -1, - "%s: (%s)%s %d-%d %s", current_pduname, - tname, name, pcount, i+1, headstr); - else { - ti2 = proto_tree_add_none_format(tree2, props.value_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, - "%s: (%s)%s %d-%d %s ~", current_pduname, - tname, name, pcount, i+1, headstr); - - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if (props.flags & OUT_FLAG_noname) { - g_snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); - name = ((cls == BER_CLASS_UNI) && (tag < 32)) ? asn1_tag[tag] : tagstr; - } - if (props.value_id == -1) - ti2 = proto_tree_add_text(tree2, tvb, boffset, - def? (int) (offset - boffset + len) : -1, - "%s: (%s)%s", current_pduname, tname, name); - else { - ti2 = proto_tree_add_none_format(tree2, props.value_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, - "%s: (%s)%s ~", current_pduname, tname, name); - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(tree2, props.type_id, tvb, boffset, - def? (int) (offset - boffset + len) : -1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - asn1_tree = proto_item_add_subtree(ti2, ett_pdu[i]); - -#ifdef NEST - taglist[0].cls = cls; - taglist[0].tag = tag; -#endif /* NEST */ - - if (!def) len++; /* make sure we get an exception if we run off the end! */ - - offset = decode_asn1_sequence(tvb, offset, len, asn1_tree, 1); - - proto_item_set_len(ti2, offset - boffset); /* mark length for hex display */ - - i++; /* one more full message handled */ - - if (ti2 && PDUerrcount && asn1_debug) /* show error counts only when in debug mode.... */ - proto_item_append_text(ti2," (%d error%s)", PDUerrcount, (PDUerrcount>1)?"s":empty); - } - col_append_fstr(pinfo->cinfo, COL_INFO, "[%d msg%s]", i, (i>1)?"s":empty); - if (ti) - proto_item_append_text(ti, ", %d msg%s", i, (i>1)?"s":empty); - } - CATCH(ReportedBoundsError) { - col_append_fstr(pinfo->cinfo, COL_INFO, "[%d+1 msg%s]", i, (i>0)?"s":empty); - if (ti) - proto_item_append_text(ti, ", %d+1 msg%s", i, (i>1)?"s":empty); - if (ti2) - proto_item_append_text(ti2, " (incomplete)"); - if (asn1_desegment) { - pinfo->desegment_offset = boffset; - pinfo->desegment_len = 1; - if (asn1_verbose) - g_message("ReportedBoundsError: offset=%d len=%d can_desegment=%d", - boffset, 1, pinfo->can_desegment); - } else { - RETHROW; - } - } - ENDTRY; -/* } */ - if (asn1_verbose) - g_message("dissect_asn1 finished: desegment_offset=%d desegment_len=%d can_desegment=%d", - pinfo->desegment_offset, pinfo->desegment_len, pinfo->can_desegment); - - return tvb_length(tvb); -} - -static int -dissect_asn1_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { - return dissect_asn1(tvb, pinfo, tree, (struct tcpinfo*)data, TRUE); -} - -static int -dissect_asn1_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - return dissect_asn1(tvb, pinfo, tree, NULL, FALSE); -} - -/* decode an ASN.1 sequence, until we have consumed the specified length */ -static guint -decode_asn1_sequence(tvbuff_t *tvb, guint offset, guint tlen, proto_tree *pt, int level) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, len, boffset, soffset, eos; - gboolean def; - guint value; - const char *clsstr, *constr, *tagstr; - char tagbuf[BUFLM]; - char lenbuf[BUFLM]; - char nnbuf[BUFLS]; - proto_tree *ti, *pt2; - proto_item *hidden_item; - guchar *octets, *bits, unused; - subid_t *oid; - /* the debugging formats */ - static char textfmt_d[] = "off=%d: [%s %s %s] (%s)%s: %d%s"; /* decimal */ - static char textfmt_e[] = "off=%d: [%s %s %s] (%s)%s: %d:%s%s"; /* enum */ - static char textfmt_s[] = "off=%d: [%s %s %s] (%s)%s: '%s'%s"; /* octet string */ - static char textfmt_b[] = "off=%d: [%s %s %s] (%s)%s: %s:%s%s"; /* bit field */ - static char textfmt_c[] = "off=%d: [%s %s %s] (%s)%s%s%s"; /* constructed */ - static char matchind[] = " ~"; /* indication of possible match */ - const char *name, *ename, *tname; - char *oname; - PDUprops props; - - ti = 0; /* suppress gcc warning */ - - soffset = offset; /* where this sequence starts */ - eos = offset + tlen; - while (offset < eos) { /* while this entity has not ended... */ - boffset = offset; - asn1_open(&asn1, tvb, offset); - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - asn1_close(&asn1, &offset); /* mark current position */ - if (ret != ASN1_ERR_NOERROR) { - proto_tree_add_text(pt, tvb, offset, 1, "ASN1 ERROR: %s", asn1_err_to_str(ret) ); - break; - } - - getPDUprops(&props, boffset, cls, tag, con); - name = props.name; - tname = props.asn1typename; - if (asn1_full) - name = &props.fullname[pabbrev_pdu_len]; /* no abbrev.pduname */ - if (asn1_debug) { /* show both names */ - g_snprintf(fieldname, sizeof(fieldname), "%s[%s]", props.name, props.fullname); - name = fieldname; - } - - clsstr = asn1_cls[cls]; - constr = asn1_con[con]; - if ((cls == BER_CLASS_UNI) && ( tag < 32 )) { - tagstr = asn1_tag[tag]; - } else { - g_snprintf(tagbuf, sizeof(tagbuf), "%ctag%d", tag_class[cls], tag); - tagstr = tagbuf; - } - - len = checklength(len, def, cls, tag, lenbuf, sizeof(lenbuf)); - - if (def) { - g_snprintf(nnbuf, sizeof(nnbuf), "NN%d", len); - } else { - g_snprintf(nnbuf, sizeof(nnbuf), "NN-"); - /* make sure we get an exception if we run off the end! */ - len = tvb_length_remaining(tvb, offset) + 1; - } - if ( ( ! asn1_debug) && (props.flags & OUT_FLAG_noname) ) { - /* just give type name if we don't know any better */ - tname = tagstr; - name = nnbuf; /* this is better than just empty.... */ - } - -#ifdef NEST - taglist[level].cls = cls; - taglist[level].tag = tag; -#endif /* NEST */ - - oname = 0; - if (level >= MAX_NEST) { /* nesting too deep..., handle as general octet string */ - cls = BER_CLASS_UNI; - tag = BER_UNI_TAG_GeneralString; - oname = (char *)g_malloc(strlen(name) + 32); - g_snprintf(oname, (gulong)(strlen(name) + 32), "%s ** nesting cut off **", name); - name = oname; - } - switch(cls) { - case BER_CLASS_UNI: /* fprintf(stderr, "Universal\n"); */ - switch(tag) { - case BER_UNI_TAG_INTEGER: - asn1_int32_value_decode(&asn1, len, &value); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are now */ - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected: just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, textfmt_d, boffset, - clsstr, constr, tagstr, tname, name, value, - empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, value, textfmt_d, boffset, - clsstr, constr, tagstr, tname, name, value, - matchind); - if (props.type_id != -1) { - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %d", tname, name, value); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, value, - "(%s)%s: %d ~", tname, name, value); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - - case BER_UNI_TAG_ENUMERATED: - asn1_int32_value_decode(&asn1, len, &value); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are now */ - ename = getPDUenum(&props, boffset, cls, tag, value); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - textfmt_e, boffset, clsstr, constr, tagstr, - tname, name, value, ename, empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, value, - textfmt_e, boffset, clsstr, constr, tagstr, - tname, name, value, ename, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %d:%s", tname, name, value, ename); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, value, - "(%s)%s: %d:%s ~", tname, name, value, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - - case BER_UNI_TAG_BOOLEAN: - asn1_bool_decode(&asn1, len, (gboolean *)&value); /* read value */ - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BOOLEAN) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, value? "true" : "false", empty); - else { - proto_tree_add_boolean_format(pt, props.value_id, tvb, boffset, - offset - boffset, value != 0, - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, value? "true" : "false", matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_boolean(pt, props.type_id, tvb, - boffset, offset - boffset, value != 0); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BOOLEAN) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %s", tname, name, - value? "true" : "false"); - else { - proto_tree_add_boolean_format(pt, props.value_id, tvb, boffset, - offset - boffset, value != 0, - "(%s)%s: %s ~", tname, name, - value? "true" : "false"); - if (props.type_id != -1){ - hidden_item = proto_tree_add_boolean(pt, props.type_id, tvb, - boffset, offset - boffset, value != 0); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - - case BER_UNI_TAG_OCTETSTRING: - case BER_UNI_TAG_NumericString: - case BER_UNI_TAG_PrintableString: - case BER_UNI_TAG_TeletexString: - case BER_UNI_TAG_IA5String: - case BER_UNI_TAG_GeneralString: - case BER_UNI_TAG_UTCTime: - case BER_UNI_TAG_GeneralizedTime: - /* read value, \0 terminated */ - asn1_string_value_decode(&asn1, len, &octets); - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - ename = showoctets(octets, len, (tag == BER_UNI_TAG_OCTETSTRING) ? 4 : 0 ); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_STRINGZ) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, ename, empty); - else { - proto_tree_add_string_format(pt, props.value_id, tvb, boffset, - offset - boffset, octets, /* \0 termnated */ - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, ename, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_string(pt, props.type_id, tvb, - boffset, offset - boffset, octets); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_STRINGZ) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %s", tname, name, ename); - else { - proto_tree_add_string_format(pt, props.value_id, tvb, boffset, - offset - boffset, octets, /* \0 terminated */ - "(%s)%s: %s ~", tname, name, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_string(pt, props.type_id, tvb, - boffset, offset - boffset, octets); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - g_free(octets); - g_free( (gpointer) ename); - break; - - case BER_UNI_TAG_BITSTRING: - asn1_bits_decode(&asn1, len, &bits, &con, &unused); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are now */ - ename = showbitnames(bits, (con*8)-unused, &props, offset); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - textfmt_b, boffset, clsstr, constr, tagstr, - tname, name, - showbits(bits, (con*8)-unused), ename, empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, *bits, /* XXX length ? XXX */ - textfmt_b, boffset, clsstr, constr, tagstr, - tname, name, - showbits(bits, (con*8)-unused),ename, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, *bits); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %s:%s", tname, name, - showbits(bits, (con*8)-unused), ename); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, boffset, - offset - boffset, *bits, /* XXX length ? XXX */ - "(%s)%s: %s:%s ~", tname, name, - showbits(bits, (con*8)-unused), ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, tvb, - boffset, offset - boffset, *bits); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - g_free(bits); - break; - - case BER_UNI_TAG_SET: - case BER_UNI_TAG_SEQUENCE: - /* show full sequence length */ - if (asn1_debug) { - ename = empty; - if ( (props.flags & OUT_FLAG_dontshow) || asn1_full) - ename = ", noshow"; - if ( (props.flags & OUT_FLAG_constructed)) - ename = ", unexpected constructed"; - - if (props.value_id == -1) - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - textfmt_c, boffset, clsstr, constr, tagstr, - tname, name, ename, empty); - else { - switch (props.type) { - - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_BITSTRING: - case TBL_REAL: - case TBL_ENUMERATED: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case TBL_OCTETSTRING: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_NA); - break; - } - /* change te text to to what I really want */ - proto_item_set_text(ti, textfmt_c, boffset, clsstr, constr, - tagstr, tname, name, ename, matchind); - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if (props.value_id == -1) { - if ( (! asn1_full) && ((props.flags & OUT_FLAG_dontshow) == 0) ) - ti = proto_tree_add_text(pt, tvb, boffset, - offset - boffset + len, - "(%s)%s", tname, name); - } else { - if ( (! asn1_full) && ((props.flags & OUT_FLAG_dontshow) == 0) ) - ti = proto_tree_add_none_format(pt, props.value_id, tvb, - boffset, offset - boffset + len, - "(%s)%s ~", tname, name); - else { - /* don't care about the text */ - switch (props.type) { - - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_BITSTRING: - case TBL_REAL: - case TBL_ENUMERATED: - ti = hidden_item = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case TBL_OCTETSTRING: - ti = hidden_item = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - ti = hidden_item = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - if (len == 0) return offset; /* don't recurse if offset isn't going to change */ - - if ( ( ! asn1_full) && (asn1_debug || ((props.flags & OUT_FLAG_dontshow) == 0))) - pt2 = proto_item_add_subtree(ti, ett_seq[level]); - else - pt2 = pt; - - offset = decode_asn1_sequence(tvb, offset, len, pt2, level+1); /* recurse */ - - if ( ( ! asn1_full) && (asn1_debug || ((props.flags & OUT_FLAG_dontshow) == 0))) - proto_item_set_len(ti, offset - boffset); - - break; - - case BER_UNI_TAG_EOC: - if (asn1_debug) { /* don't show if not debugging */ - proto_tree_add_text(pt, tvb, boffset, offset - boffset, textfmt_d, - boffset, clsstr, constr, tagstr, tname, name, - offset - soffset, empty); - } - getPDUprops(&props, soffset, ASN1_EOI, 1, 0); /* mark end of this sequence */ - return offset; - - case BER_UNI_TAG_OID: - asn1_oid_value_decode(&asn1, len, &oid, &con); - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - ename = showoid(oid, con); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BYTES) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, offset - boffset, textfmt_s, - boffset, clsstr, constr, tagstr, tname, name, - ename, empty); - else { - proto_tree_add_bytes_format(pt, props.value_id, tvb, boffset, - offset - boffset, ename,/* XXX length?*/ - "(%s)%s: %s ~", tname, name, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_bytes(pt, props.type_id, tvb, - boffset, offset - boffset, ename); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BYTES) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, - offset - boffset, - "(%s)%s: %s", tname, name, ename); - else { - proto_tree_add_bytes_format(pt, props.value_id, tvb, boffset, - offset - boffset, ename, /* XXX length ? */ - "(%s)%s: %s ~", tname, name, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_bytes(pt, props.type_id, tvb, - boffset, offset - boffset, ename); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - g_free(oid); - break; - - case BER_UNI_TAG_NULL: - if (asn1_debug) { - proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, textfmt_s, - boffset, clsstr, constr, tagstr, tname, name, - "[NULL]", empty); - } else { - proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - "(%s)%s: [NULL]", tname, name); - } - offset += len; /* skip value ... */ - break; - - case BER_UNI_TAG_ObjectDescriptor: - case ASN1_EXT: - case BER_UNI_TAG_REAL: - case BER_UNI_TAG_VideotexString: - case BER_UNI_TAG_GraphicString: - case BER_UNI_TAG_VisibleString: - - default: - if (asn1_debug) { - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, lenbuf, empty); - } else { - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - "(%s)%s: %s bytes", tname, name, lenbuf); - } - proto_item_append_text(ti, " *"); /* indicate default is used */ - offset += len; /* skip value ... */ - break; - }; - break; - - case BER_CLASS_CON: /* fprintf(stderr, "Context\n"); */ - case BER_CLASS_APP: /* fprintf(stderr, "Application\n"); */ - case BER_CLASS_PRI: /* fprintf(stderr, "Private\n"); */ - - if (def && !con) { - if (props.value_id == -1) /* type unknown, handle as string */ - goto dostring; - switch(props.type) { - /* this is via the asn1 description, don't trust the length */ - case TBL_INTEGER: - if (len > 4) - goto dostring; - asn1_int32_value_decode(&asn1, len, (gint32 *)&value); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are now */ - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - textfmt_d, boffset, clsstr, constr, - tagstr, tname, name, value, empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, value, - textfmt_d, boffset, clsstr, constr, - tagstr, tname, name, value, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - "(%s)%s: %d", tname, name, value); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, value, - "(%s)%s: %d ~", tname, name, value); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - - case TBL_ENUMERATED: - if (len > 4) - goto dostring; - asn1_int32_value_decode(&asn1, len, &value); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are now */ - ename = getPDUenum(&props, boffset, cls, tag, value); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - textfmt_e, boffset, clsstr, constr, - tagstr, tname, name, value, ename, empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, value, - textfmt_e, boffset, clsstr, constr, - tagstr, tname, name, value, ename, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - "(%s)%s: %d:%s", tname, name, value, ename); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, value, - "(%s)%s: %d:%s ~", tname, name, value, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, value); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - case TBL_BITSTRING: - if (len > (1+4)) /* max 32 bits ...?.. */ - goto dostring; - /* read value */ - asn1_bits_decode(&asn1, len, &bits, &con, &unused); - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - ename = showbitnames(bits, (con*8)-unused, &props, offset); - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - textfmt_b, boffset, clsstr, constr, - tagstr, tname, name, - showbits(bits, (con*8)-unused), ename, - empty); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, *bits, - textfmt_b, boffset, clsstr, constr, - tagstr, tname, name, - showbits(bits, (con*8)-unused), ename, - matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, *bits); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_UINT32) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, offset - boffset, - "(%s)%s: %s:%s", tname, name, - showbits(bits, (con*8)-unused), ename); - else { - proto_tree_add_uint_format(pt, props.value_id, tvb, - boffset, offset - boffset, *bits, - "(%s)%s: %s:%s ~", tname, name, - showbits(bits, (con*8)-unused), ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_uint(pt, props.type_id, - tvb, boffset, offset - boffset, *bits); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - g_free(bits); - break; - case TBL_BOOLEAN: - if (len > 1) - goto dostring; - asn1_bool_decode(&asn1, len, (gboolean *)&value); /* read value */ - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BOOLEAN) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - textfmt_s, boffset, clsstr, constr, - tagstr, tname, name, - value? "true" : "false", empty); - else { - proto_tree_add_boolean_format(pt, props.value_id, tvb, - boffset, offset - boffset, value != 0, - textfmt_s, boffset, clsstr, constr, - tagstr, tname, name, - value? "true" : "false", matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_boolean(pt, props.type_id, - tvb, boffset, offset - boffset, value != 0); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_BOOLEAN) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - "(%s)%s: %s", tname, name, - value? "true" : "false"); - else { - proto_tree_add_boolean_format(pt, props.value_id, tvb, - boffset, offset - boffset, value != 0, - "(%s)%s: %s ~", tname, name, - value? "true" : "false"); - if (props.type_id != -1){ - hidden_item = proto_tree_add_boolean(pt, props.type_id, - tvb, boffset, offset - boffset, value != 0); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - break; - case TBL_NULL: - if (len > 0) - goto dostring; - if (asn1_debug) { - proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - textfmt_s, boffset, clsstr, constr, - tagstr, tname, name, "[NULL]", empty); - } else { - proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - "(%s)%s: [NULL]", tname, name); - } - offset += len; /* skip value ... */ - break; - default: - dostring: - props.value_id = -1; /* unlikely this is correct, dont use it */ - /* fallthrough */ - case TBL_OCTETSTRING: - /* defined length, not constructed, must be a string.... */ - asn1_string_value_decode(&asn1, len, &octets); /* read value */ - asn1_close(&asn1, (gint *)&offset); /* mark where we are now */ - ename = showoctets(octets, len, 2); /* convert octets to printable */ - if (asn1_debug) { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_STRINGZ) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, - boffset, offset - boffset, - textfmt_s, boffset, clsstr, constr, - tagstr, tname, name, ename, empty); - else { - proto_tree_add_string_format(pt, props.value_id, tvb, - boffset, offset - boffset, (gchar *)octets, /* XXX */ - textfmt_s, boffset, clsstr, constr, - tagstr, tname, name, ename, matchind); - if (props.type_id != -1){ - hidden_item = proto_tree_add_string(pt, props.type_id, - tvb, boffset, offset - boffset, (gchar *)octets); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } else { - if ( (props.value_id == -1) || - (tbl_types_wireshark[props.type] != FT_STRINGZ) ) - /* unknown or unexpected, just text */ - proto_tree_add_text(pt, tvb, boffset, offset - boffset, - "(%s)%s: %s", tname, name, ename); - else { - proto_tree_add_string_format(pt, props.value_id, tvb, - boffset, offset - boffset, (gchar *)octets, /* XXX */ - "(%s)%s: %s ~", tname, name, ename); - if (props.type_id != -1){ - hidden_item = proto_tree_add_string(pt, props.type_id, - tvb, boffset, offset - boffset, (gchar *)octets); - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - g_free(octets); - g_free( (gpointer) ename); - break; - } - } else { - /* indefinite length or constructed.... must be a sequence .... */ - /* show full sequence length */ - if (asn1_debug) { - ename = empty; - if ( (props.flags & OUT_FLAG_dontshow) || asn1_full) - ename = ", noshow"; - if ( (props.flags & OUT_FLAG_constructed)) - ename = ", unexpected constructed"; - - if (props.value_id == -1) - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - textfmt_c, boffset, clsstr, constr, - tagstr, tname, name, ename, empty); - else { - switch (props.type) { - - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_BITSTRING: - case TBL_REAL: - case TBL_ENUMERATED: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case TBL_OCTETSTRING: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - ti = proto_tree_add_item(pt, props.value_id, tvb, - boffset, 1, ENC_NA); - break; - } - /* change te text to to what I really want */ - if (ti) { - proto_item_set_text(ti, textfmt_c, boffset, clsstr, constr, - tagstr, tname, name, ename, matchind); - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(pt, props.type_id, tvb, - boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } else { - ti = proto_tree_add_text(pt, tvb, boffset, - offset - boffset + len, - textfmt_c, boffset, clsstr, constr, - tagstr, tname, name, ename, empty); - } - } - } else { - if (props.value_id == -1) { - if ( ( ! asn1_full) && ((props.flags & OUT_FLAG_dontshow) == 0)) - ti = proto_tree_add_text(pt, tvb, boffset, - offset - boffset + len, "(%s)%s", tname, name); - } else { - if ( ( ! asn1_full) && ((props.flags & OUT_FLAG_dontshow) == 0)) - ti = proto_tree_add_none_format(pt, props.value_id, tvb, - boffset, 1, - "(%s)%s ~", tname, name); - else { - /* don't care about the text */ - switch (props.type) { - - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_BITSTRING: - case TBL_REAL: - case TBL_ENUMERATED: - ti = proto_tree_add_item(pt, props.value_id, - tvb, boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case TBL_OCTETSTRING: - ti = proto_tree_add_item(pt, props.value_id, - tvb, boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - ti = proto_tree_add_item(pt, props.value_id, - tvb, boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(ti); - } - if (props.type_id != -1){ - switch (proto_registrar_get_ftype(props.type_id)) { - - case FT_INT8: - case FT_INT16: - case FT_INT24: - case FT_INT32: - case FT_INT64: - case FT_UINT8: - case FT_UINT16: - case FT_UINT24: - case FT_UINT32: - case FT_UINT64: - case FT_BOOLEAN: - case FT_FLOAT: - case FT_DOUBLE: - case FT_IPv4: - hidden_item = proto_tree_add_item(pt, props.type_id, - tvb, boffset, 1, ENC_LITTLE_ENDIAN); - break; - - case FT_STRING: - case FT_STRINGZ: - hidden_item = proto_tree_add_item(pt, props.type_id, - tvb, boffset, 1, ENC_ASCII|ENC_NA); - break; - - default: - hidden_item = proto_tree_add_item(pt, props.type_id, - tvb, boffset, 1, ENC_NA); - break; - } - PROTO_ITEM_SET_HIDDEN(hidden_item); - } - } - } - - if (len == 0) return offset; /* don't recurse if offset isn't going to change */ - - if ( ( ! asn1_full) && (asn1_debug || ((props.flags & OUT_FLAG_dontshow) == 0))) - pt2 = proto_item_add_subtree(ti, ett_seq[level]); - else - pt2 = pt; - - offset = decode_asn1_sequence(tvb, offset, len, pt2, level+1); /* recurse */ - - if ( ( ! asn1_full) && (asn1_debug || ((props.flags & OUT_FLAG_dontshow) == 0))) - proto_item_set_len(ti, offset - boffset); - } - break; - - default: /* fprintf(stderr, "Other\n"); */ - if (asn1_debug) { - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - textfmt_s, boffset, clsstr, constr, tagstr, - tname, name, lenbuf, empty); - } else { - ti = proto_tree_add_text(pt, tvb, boffset, offset - boffset + len, - "(%s)%s: %s bytes %s data", tname, name, - lenbuf, clsstr); - } - proto_item_append_text(ti, " *"); /* indicate default is used */ - offset += len; /* skip value ... */ - break; - } - g_free(oname); /* XXX, memory management ? */ - } - /* proto_tree_add_text(pt, tvb, offset, 1, "Marker: offset=%d", offset); */ - - getPDUprops(&props, soffset, ASN1_EOI, 0, 0); /* mark end of this sequence */ - - return offset; -} -#define READSYNTAX -#ifdef READSYNTAX - -/************************************************************************************************/ -/* search throug the ASN.1 description for appropriate names */ -/************************************************************************************************/ - -guint lev_limit = G_MAXINT; - -int icount = 0; /* item counter */ - -static guint -parse_tt3(tvbuff_t *tvb, guint offset, guint size, guint level, GNode *ptr) -{ - ASN1_SCK asn1; - guint eos, cls, con, tag, len, value; - gboolean def; - guchar *octets, *bits, unused; - subid_t *oid; - GNode *cur_node = 0; - - eos = offset + size; - - if (level > lev_limit) - return eos; - - while(offset < eos) { - if (ptr) /* build pointer tree to all asn1 entities */ - cur_node = g_node_append_data(ptr, GUINT_TO_POINTER(offset)); - - asn1_open(&asn1, tvb, offset); - asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - asn1_close(&asn1, (gint *)&offset); /* mark where we are */ - icount++; - if (!def) { - len = tvb_length_remaining(tvb, offset); - } - - switch(cls) { - case BER_CLASS_UNI: /* fprintf(stderr, "Universal\n"); */ - switch(tag) { - case BER_UNI_TAG_INTEGER: - case BER_UNI_TAG_ENUMERATED: - asn1_int32_value_decode(&asn1, len, (gint32 *)&value); /* read value */ - asn1_close(&asn1, (gint *)&offset); /* mark where we are */ - break; - - case BER_UNI_TAG_BOOLEAN: - asn1_bool_decode(&asn1, len, (gboolean *)&value); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are */ - break; - - case BER_UNI_TAG_OCTETSTRING: - case BER_UNI_TAG_NumericString: - case BER_UNI_TAG_PrintableString: - case BER_UNI_TAG_TeletexString: - case BER_UNI_TAG_IA5String: - case BER_UNI_TAG_GeneralString: - case BER_UNI_TAG_UTCTime: - case BER_UNI_TAG_GeneralizedTime: - asn1_string_value_decode(&asn1, len, &octets); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are */ - g_free(octets); - break; - - case BER_UNI_TAG_BITSTRING: - asn1_bits_decode(&asn1, len, &bits, &con, &unused); - asn1_close(&asn1, &offset); /* mark where we are */ - g_free(bits); - break; - - case BER_UNI_TAG_SET: - case BER_UNI_TAG_SEQUENCE: - if (len == 0) /* don't recurse if offset isn't going to change */ - return offset; - - offset = parse_tt3(tvb, offset, len, level+1, cur_node); /* recurse */ - break; - - case BER_UNI_TAG_EOC: - return offset; - - case BER_UNI_TAG_OID: - asn1_oid_value_decode(&asn1, len, &oid, &con); - asn1_close(&asn1, &offset); /* mark where we are */ - g_free(oid); - break; - - case BER_UNI_TAG_NULL: - offset += len; - break; - - case BER_UNI_TAG_ObjectDescriptor: - case ASN1_EXT: - case BER_UNI_TAG_REAL: - case BER_UNI_TAG_VideotexString: - case BER_UNI_TAG_GraphicString: - case BER_UNI_TAG_VisibleString: - - default: - if (asn1_verbose) g_message("%d skip1 %d", offset, len); - offset += len; /* skip value ... */ - break; - }; - break; - - case BER_CLASS_CON: /* fprintf(stderr, "Context\n"); */ - if (def && !con) { - /* defined length, not constructed, must be a string.... */ - asn1_string_value_decode(&asn1, len, &octets); /* read value */ - asn1_close(&asn1, &offset); /* mark where we are */ - g_free(octets); - } else { - /* indefinite length or constructed.... must be a sequence .... */ - if (len == 0) /* don't recurse if offset isn't going to change */ - return offset; - - offset = parse_tt3(tvb, offset, len, level+1, cur_node); /* recurse */ - } - break; - - default: /* fprintf(stderr, "Other\n"); */ - if (asn1_verbose) g_message("%d skip2 %d", offset, len); - offset += len; /* skip value ... */ - break; - } - } - return offset; -} - -static void showGNodes(GNode *p, int n); - -#if 0 -static gboolean -myLeaf(GNode *node, gpointer data) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, def, len; - char *clsstr, *constr, *tagstr; - char tagbuf[BUFLM]; - char lenbuf[BUFLM]; - - (void) data; /* make a reference */ - asn1_open(&asn1, asn1_desc, (int)node->data); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - - clsstr = asn1_cls[cls]; - constr = asn1_con[con]; - if ((cls == BER_CLASS_UNI) && ( tag < 32 )) { - tagstr = asn1_tag[tag]; - } else { - g_snprintf(tagbuf, sizeof(tagbuf), "tag%d", tag); - tagstr = tagbuf; - } - if (def) { - g_snprintf(lenbuf, sizeof(lenbuf), "%d", len); - } else { - g_snprintf(lenbuf, sizeof(lenbuf), "indefinite"); - } - - if (asn1_verbose) - g_message("off=%d: [%s %s %s] len=%s", (int)node->data, clsstr, constr, tagstr, lenbuf); - - return FALSE; -} - -static void -list_modules(void) -{ - if (asn1_verbose) g_message("build GNode tree:"); - showGNodes(g_node_first_child(asn1_nodes), 0); - if (asn1_verbose) g_message("end of tree: %d nodes, %d deep, %d leafs, %d branches", - g_node_n_nodes(asn1_nodes, G_TRAVERSE_ALL), - g_node_max_height (asn1_nodes), - g_node_n_nodes(asn1_nodes, G_TRAVERSE_LEAFS), - g_node_n_nodes(asn1_nodes, G_TRAVERSE_NON_LEAFS) ); - - g_node_traverse(g_node_first_child(asn1_nodes), G_PRE_ORDER, G_TRAVERSE_LEAFS, -1, myLeaf, 0); - -} -#endif - -static void -tt_build_tree(void) /* build a GNode tree with all offset's to ASN.1 entities */ -{ - if (asn1_nodes) - g_node_destroy(asn1_nodes); - asn1_nodes = g_node_new(0); - icount = 0; - parse_tt3(asn1_desc, 0, tvb_length(asn1_desc), 0, asn1_nodes); -} - - -/*****************************************************************************************************/ - -static guint anonCount; /* for naming anonymous types */ - -typedef struct _TBLModule TBLModule; -typedef struct _TBLTypeDef TBLTypeDef; -typedef struct _TBLTag TBLTag; -typedef struct _TBLType TBLType; -typedef struct _TBLTypeRef TBLTypeRef; -typedef struct _TBLNamedNumber TBLNamedNumber; -typedef struct _TBLRange TBLRange; - -enum _tbl_t { - TBLTYPE_Module, - TBLTYPE_TypeDef, - TBLTYPE_Tag, - TBLTYPE_Type, - TBLTYPE_TypeRef, - TBLTYPE_NamedNumber, - TBLTYPE_Range -}; -typedef enum _tbl_t tbl_t; -/* text for 'tbl_t' type for debugging */ -static const char *data_types[] = { - "Module", - "TypeDef", - "Tag", - "Type", - "TypeRef", - "NamedNumber", - "Range", -}; - -enum _TBLTypeContent_t { - TBLTYPETYPE_None, - TBLTYPETYPE_Primitive, - TBLTYPETYPE_Elements, - TBLTYPETYPE_TypeRef -}; -typedef enum _TBLTypeContent_t TBLTypeContent_t; - -struct _TBLNamedNumber { - tbl_t type; - guchar *name; - guint value; -}; - -struct _TBLRange { - tbl_t type; - guint from; - guint to; -}; - -struct _TBLTypeRef { - tbl_t type; - guint typeDefId; - gboolean implicit; -}; - -struct _TBLTag { - tbl_t type; - guint tclass; - guint code; -}; - -struct _TBLType { - tbl_t type; - guint typeId; - gboolean optional; - TBLTypeContent_t content; - guchar *fieldName; - gboolean anonymous; - gboolean constraint; -}; - -struct _TBLTypeDef { - tbl_t type; - guint typeDefId; - guchar *typeName; - guchar isPdu; -}; - -struct _TBLModule { - tbl_t type; - guchar *name; - subid_t *id; - guint isUseful; -}; - -struct _TT { - guint totalNumModules; - guint totalNumTypeDefs; - guint totalNumTypes; - guint totalNumTags; - guint totalNumStrings; - guint totalLenStrings; -} TT; - -#define CHECKP(p) {if (p==0){g_warning("pointer==0, line %d **********", __LINE__);return;}} - -static guint -get_asn1_int(guint want_tag, guint offset) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, len; - gboolean def; - guint value; - - /* g_message("%d get_asn1_int", offset); */ - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - if (ret == ASN1_ERR_NOERROR) { - /* do not check class, both Unversal and Context are OK */ - if (con == ASN1_PRI && tag == want_tag) { - if (def) { - asn1_uint32_value_decode(&asn1, len, &value); - return value; - } else - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - } else - ret = ASN1_ERR_WRONG_TYPE; - } - g_warning("ASN.1 int mismatch at offset %d, %s", offset, asn1_err_to_str(ret)); - - return 0; -} - -static subid_t * /* with prepended length ..... */ -get_asn1_oid(guint want_tag, guint offset) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, len; - gboolean def; - subid_t *oid; - - /* g_message("%d get_asn1_oid", offset); */ - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - if (ret == ASN1_ERR_NOERROR) { - /* do not check class, both Unversal and Context are OK */ - if ((con == ASN1_PRI) && (tag == want_tag)) { - if (def) { - asn1_oid_value_decode(&asn1, len, &oid, &con); - oid = (subid_t *)g_realloc(oid, con + sizeof(guint)); /* prepend the length */ - memmove(&oid[1], oid, con*sizeof(guint)); - oid[0] = con; - return oid; - } else - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - } else - ret = ASN1_ERR_WRONG_TYPE; - } - g_warning("ASN.1 oid mismatch at offset %d, %s", offset, asn1_err_to_str(ret)); - - return 0; -} - -static guchar * /* 0 terminated string */ -get_asn1_string(guint want_tag, guint offset) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, len; - gboolean def; - guchar *octets; - - /* g_message("%d get_asn1_string", offset); */ - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - if (ret == ASN1_ERR_NOERROR) { - /* do not check class, both Unversal and Context are OK */ - if ((con == ASN1_PRI) && (tag == want_tag)) { - if (def) { - asn1_string_value_decode(&asn1, len, &octets); - octets = (guchar *)g_realloc(octets, len+1); /* need space for sentinel */ - octets[len] = 0; - return octets; - } else - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - } else - ret = ASN1_ERR_WRONG_TYPE; - } - g_warning("ASN.1 string mismatch at offset %d, %s", offset, asn1_err_to_str(ret)); - - return 0; -} - -static guint -get_asn1_uint(guint offset) -{ - ASN1_SCK asn1; - guint ret, len, value; - - /* g_message( "%d get_asn1_uint", offset); */ - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_uint32_decode(&asn1, &value, &len); - - if (ret != ASN1_ERR_NOERROR) { - g_warning("ASN.1 uint mismatch at offset %d, %s", offset, asn1_err_to_str(ret)); - value = 0; - } - return value; -} - -static gboolean -check_tag(guint want_tag, guint offset) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, len; - gboolean def; - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - if (ret == ASN1_ERR_NOERROR) { - ret = (tag == want_tag) ? TRUE : FALSE; - /* g_message("%d check tag %d, %s", offset, want_tag, ret? "true" : "false"); */ - return ret; - } - g_warning("ASN.1 check_tag at offset %d, %s", offset, asn1_err_to_str(ret)); - - return FALSE; -} - -#if 0 -static gboolean -constructed(guint offset) -{ - ASN1_SCK asn1; - guint ret, cls, con, tag, def, len; - - /* g_message("%d constructed?", offset); */ - - asn1_open(&asn1, asn1_desc, offset); - - ret = asn1_header_decode(&asn1, &cls, &con, &tag, &def, &len); - if (ret == ASN1_ERR_NOERROR) { - if (con) { - return TRUE; - } - return FALSE; - } - /* g_warning("ASN.1 constructed? at offset %d, %s", offset, asn1_err_to_str(ret)); */ - - return FALSE; -} -#endif - -static void -define_constraint(GNode *p, GNode *q) -{ - TBLRange *range = (TBLRange *)g_malloc(sizeof(TBLRange)); - g_node_append_data(q, range); - - range->type = TBLTYPE_Range; - - /* g_message("define_constraint %p, %p", p, q); */ - - p = g_node_first_child(p); - - if (!p) { - return; - } - - range->from = get_asn1_int(0, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - range->to = get_asn1_int(1, GPOINTER_TO_UINT(p->data)); - -} - -static void -define_namednumber(GNode *p, GNode *q) -{ - TBLNamedNumber *num = (TBLNamedNumber *)g_malloc(sizeof(TBLNamedNumber)); - g_node_append_data(q, num); - - num->type = TBLTYPE_NamedNumber; - - /* g_message("define_namednumber %p, %p", p, q); */ - - p = g_node_first_child(p); - - if (!p) { - return; - } - - num->name = get_asn1_string(0, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - num->value = get_asn1_int(1, GPOINTER_TO_UINT(p->data)); -} - -static void -define_typeref(GNode *p, GNode *q) -{ - TBLTypeRef *ref = (TBLTypeRef *)g_malloc(sizeof(TBLTypeRef)); - g_node_append_data(q, ref); - - ref->type = TBLTYPE_TypeRef; - - /* g_message("define_typeref %p, %p", p, q); */ - - p = g_node_first_child(p); - - if (!p) { - return; - } - - ref->typeDefId = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - ref->implicit = get_asn1_int(BER_UNI_TAG_BOOLEAN, GPOINTER_TO_UINT(p->data)); -} - -static void -define_tag(GNode *p, GNode *q) -{ - TBLTag *type = (TBLTag *)g_malloc(sizeof(TBLTag)); - g_node_append_data(q, type); - - type->type = TBLTYPE_Tag; - - /* g_message("define_tag %p, %p", p, q); */ - - p = g_node_first_child(p); - - if (!p) { - return; - } - - type->tclass = get_asn1_int(BER_UNI_TAG_ENUMERATED, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - type->code = get_asn1_int(BER_UNI_TAG_INTEGER, GPOINTER_TO_UINT(p->data)); - -} - -static void -define_type(GNode *p, GNode *q) -{ - GNode *r; - TBLType *type = (TBLType *)g_malloc(sizeof(TBLType)); - - GNode *t = g_node_append_data(q, type); - - type->type = TBLTYPE_Type; - - /* g_message("define_type %p, %p", p, q); */ - - type->typeId = get_asn1_int(0, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - type->optional = get_asn1_int(1, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (check_tag(2, GPOINTER_TO_UINT(p->data))) { /* optional, need empty node if not there ?*/ - r = g_node_first_child(p); - while (r) { - define_tag(r, t); - r = g_node_next_sibling(r); - } - p = g_node_next_sibling(p); - } - - if (!check_tag(3, GPOINTER_TO_UINT(p->data))) { - g_warning("expect tag 3, ERROR"); - } - r = g_node_first_child(p); - /* a choice ... */ - type->content = TBLTYPETYPE_None; - if (check_tag(0, GPOINTER_TO_UINT(r->data))) type->content = TBLTYPETYPE_Primitive; - if (check_tag(1, GPOINTER_TO_UINT(r->data))) type->content = TBLTYPETYPE_Elements; - if (check_tag(2, GPOINTER_TO_UINT(r->data))) type->content = TBLTYPETYPE_TypeRef; - switch(type->content) { - case TBLTYPETYPE_Primitive: - break; - case TBLTYPETYPE_Elements: - r = g_node_first_child(r); - while (r) { - define_type(g_node_first_child(r), t); - r = g_node_next_sibling(r); - } - break; - case TBLTYPETYPE_TypeRef: - define_typeref(r, t); - break; - case TBLTYPETYPE_None: - g_warning("expected a contents choice, error"); - break; - } - p = g_node_next_sibling(p); - - type->fieldName = 0; - type->anonymous = FALSE; - if (p && check_tag(4, GPOINTER_TO_UINT(p->data))) { - type->fieldName = get_asn1_string(4, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - } else { - type->anonymous = TRUE; - } - - type->constraint = FALSE; - if (p && check_tag(5, GPOINTER_TO_UINT(p->data))) { - type->constraint = TRUE; - define_constraint(p, t); - p = g_node_next_sibling(p); - } - - if (p && check_tag(6, GPOINTER_TO_UINT(p->data))) { - r = g_node_first_child(p); - while(r) { - define_namednumber(r, t); - r = g_node_next_sibling(r); - } - } -} - -static void -define_typedef(GNode *p, GNode *q) -{ - TBLTypeDef *type_def = (TBLTypeDef *)g_malloc(sizeof(TBLTypeDef)); - - GNode *t = g_node_append_data(q, type_def); - - /* g_message("define_typedef %p, %p", p, q); */ - - type_def->type = TBLTYPE_TypeDef; - - p = g_node_first_child(p); - - if (!p) { - return; - } - - type_def->typeDefId = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - type_def->typeName = get_asn1_string(BER_UNI_TAG_PrintableString, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - if (!p) { - return; - } - - define_type(g_node_first_child(p), t); - p = g_node_next_sibling(p); - - type_def->isPdu = (p != 0); /* true if it exists, value ignored */ -} - -static void -define_module(GNode *p, GNode *q) -{ - TBLModule *module = (TBLModule *)g_malloc(sizeof(TBLModule)); - - GNode *m = g_node_append_data(q, module); - - /* g_message("define_module %p %p", p, q); */ - - module->type = TBLTYPE_Module; - - p = g_node_first_child(p); - - if (!p) { - return; - } - - module->name = get_asn1_string(0, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - module->id = 0; - if (check_tag(1, GPOINTER_TO_UINT(p->data))) { /* optional */ - module->id = get_asn1_oid(1, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - } - - module->isUseful = get_asn1_int(2, GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - p = g_node_first_child(p); - while (p) { - define_typedef(p, m); - p = g_node_next_sibling(p); - } -} - -typedef struct _SearchDef SearchDef; -struct _SearchDef { - const char *key; - GNode *here; -}; - -static gboolean -is_typedef(GNode *node, gpointer data) -{ - TBLTypeDef *d = (TBLTypeDef *)node->data; - SearchDef *s = (SearchDef *)data; - - if (d == 0) return FALSE; - if (d->type != TBLTYPE_TypeDef) return FALSE; - if (strcmp(s->key, d->typeName) == 0) { - s->here = node; - return TRUE; - } - return FALSE; -} - -typedef struct _TypeRef TypeRef; -struct _TypeRef { - GNode *type; - char *name; - guchar defclass; - guint deftag; - GNode *pdu; /* location in PDU descriptor tree */ - guint level; /* recursion counter */ - GNode *typetree; - GPtrArray *refs; /* pointers to PDUinfo structures teferencing this entry */ -}; - -typedef struct _NameDefs NameDefs; -struct _NameDefs { - guint max; - guint used; - TypeRef *info; -}; -#define ALLOC_INCR 4 -#define CLASSREF (BER_CLASS_PRI+1) - -static gboolean -is_named(GNode *node, gpointer data) -{ - TBLNamedNumber *num = (TBLNamedNumber *)node->data; - NameDefs *n = (NameDefs *)data; - guint oldmax; - - if (num == 0) return FALSE; - if (num->type != TBLTYPE_NamedNumber) return FALSE; - - if (num->value >= n->max) { /* need larger array */ - oldmax = n->max; - n->max = num->value + ALLOC_INCR; - n->info = (TypeRef *)g_realloc(n->info, n->max * sizeof(TypeRef)); - memset(&n->info[oldmax], 0, (n->max - oldmax) * sizeof(TypeRef)); - } - if (num->value > n->used) /* track max used value, there may be holes... */ - n->used = num->value; - - n->info[num->value].name = num->name; - - return FALSE; -} - -static gboolean -index_typedef(GNode *node, gpointer data) -{ - TBLTypeDef *d = (TBLTypeDef *)node->data; - NameDefs *n = (NameDefs *)data; - TypeRef *t; - TBLTag *tag; - guint oldmax; - - if (d == 0) return FALSE; - if (d->type != TBLTYPE_TypeDef) return FALSE; - - if (d->typeDefId >= n->max) { /* need larger array */ - oldmax = n->max; - n->max = d->typeDefId + ALLOC_INCR; - n->info = (TypeRef *)g_realloc(n->info, n->max * sizeof(TypeRef)); - memset(&n->info[oldmax], 0, (n->max - oldmax) * sizeof(TypeRef)); - } - if (d->typeDefId > n->used) /* track max used value, there may be holes... */ - n->used = d->typeDefId; - - t = &(n->info[d->typeDefId]); - t->name = d->typeName; - t->type = node; - t->refs = g_ptr_array_new(); /* collect references here */ - node = g_node_first_child(node); /* the real type */ - tag = (TBLTag *)node->data; - if ((tag->type == TBLTYPE_Type) && (((TBLType *)(void *)tag)->typeId == TBL_CHOICE)) { - /* no reasonable default... ! */ - t->defclass = 3; /* Private .... */ - t->deftag= 9999; /* a random value */ - } else { - node = g_node_first_child(node); /* the default tag */ - tag = (TBLTag *)node->data; - switch(tag->type) { - case TBLTYPE_Tag: - t->defclass = tag->tclass; - t->deftag = tag->code; - break; - case TBLTYPE_TypeRef: /* take values from another one, may not be defined yet... */ - t->defclass = CLASSREF; /* invalid class.. */ - t->deftag = ((TBLTypeRef *)tag)->typeDefId; - break; - default: - g_warning("***** index_typedef: expecting a tag or typeref, found %s *****", - data_types[tag->type]); - t->defclass = 3; /* Private .... */ - t->deftag= 9998; /* another random value */ - break; - } - } - - return FALSE; -} - -static TypeRef *typeDef_names = 0; -static guint numTypedefs = 0; - -static gboolean -free_node_data(GNode *node, gpointer data _U_) -{ - g_free(node->data); - return FALSE; -} - -static void -get_values(void) /* collect values from ASN.1 tree */ - /* coded according to the tbl.asn1 description of snacc output */ -{ /* This routine does not leave references to the tvbuff or */ - /* to the asn1_nodes, both can be freed by the caller of this.*/ - GNode *p; - SearchDef sd; - NameDefs nd; - guint i; - char X; - const char *t, *s, *E; - static char missing[] = " **missing** "; - - if (asn1_verbose) g_message("interpreting tree"); - typeDef_names = 0; /* just forget allocated any data .... */ - - if (data_nodes) { - g_node_traverse(data_nodes, G_POST_ORDER, G_TRAVERSE_ALL, -1, - free_node_data, NULL); - g_node_destroy(data_nodes); - } - - data_nodes = g_node_new(0); - - p = g_node_first_child(asn1_nodes); /* top of the data tree */ - - p = g_node_first_child(p); - if (!p) return; - TT.totalNumModules = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - if (!p) return; - TT.totalNumTypeDefs = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - if (!p) return; - TT.totalNumTypes = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - if (!p) return; - TT.totalNumTags = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - if (!p) return; - TT.totalNumStrings = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - if (!p) return; - TT.totalLenStrings = get_asn1_uint(GPOINTER_TO_UINT(p->data)); - p = g_node_next_sibling(p); - - p = g_node_first_child(p); - while (p) { - define_module(p, data_nodes); - p = g_node_next_sibling(p); - } - - /* g_message("finished with tree"); */ - - if (!tbl_types_verified) { /* verify snacc TBLTypeId contents */ - sd.key = "TBLTypeId"; - sd.here = 0; - g_node_traverse(data_nodes, G_PRE_ORDER, G_TRAVERSE_ALL, -1, is_typedef, (gpointer)&sd); - if (asn1_verbose) g_message("%s %sfound, %p", sd.key, sd.here?empty:"not ", (void *)sd.here); - if (sd.here) { - nd.max = 8; - nd.used = 0; - nd.info = (TypeRef *)g_malloc0(nd.max * sizeof(TypeRef)); - g_node_traverse(sd.here, G_PRE_ORDER, G_TRAVERSE_ALL, -1, is_named, - (gpointer)&nd); - if (asn1_verbose) g_message("tbltypenames: max=%d, info=%p", nd.max, (void *)nd.info); - E = empty; - for (i=0; i<=nd.used; i++) { /* we have entries in addition to snacc's */ - X = 'X'; - t = TBLTYPE(i); - s = nd.info[i].name; - if (s == 0) s = missing; - if (g_strcmp(t, s) == 0) { /* OK ! */ - X = ' '; - t = empty; - } else { - E = ", X with errors X"; - } - if (asn1_verbose) g_message(" %c %2d %s %s", X, i, s, t); - } - if (asn1_verbose) g_message("OK, TBLTypeId's index verified%s", E); - } - tbl_types_verified = TRUE; - } - /* build table with typedef names */ - nd.max = 8; - nd.used = 0; - nd.info = (TypeRef *)g_malloc0(nd.max * sizeof(TypeRef)); - g_node_traverse(data_nodes, G_PRE_ORDER, G_TRAVERSE_ALL, -1, index_typedef, (gpointer)&nd); - if (asn1_verbose) g_message("tbltypedefs: max=%d, info=%p", nd.max, (void *)nd.info); - - for (i=0; i<=nd.used; i++) { /* show what we have in the index now */ - TypeRef *ref = &(nd.info[i]); - t = ref->name; - if (t == 0) { - t = ref->name = missing; - if (asn1_verbose) g_message(" %3d %s", i, t); - } else { - if (asn1_verbose) g_message(" %3d %s, %c%d", i, t, - tag_class[ref->defclass], ref->deftag); - } - if (ref->pdu) { /* should be 0 */ - if (asn1_verbose) g_message("* %3d %s pdu=%p", i, t, (void *)ref->pdu); - } - } - typeDef_names = nd.info; - numTypedefs = i; - if (asn1_verbose) g_message("OK, %d TBLTypeDef's index set up", numTypedefs); - -} - -static void -showGNode(GNode *p, int n) -{ - - const char *fn, *s = empty; - if (p == 0) return; - n *=2; /* 2 spaces per level */ - if (p->data) { /* show value ... */ - /* g_message("show %p, type %d", p, ((TBLTag *)p->data)->type); */ - switch (((TBLTag *)p->data)->type) { - case TBLTYPE_Module: { - TBLModule *m = (TBLModule *)p->data; - if (asn1_verbose) - g_message("%*smodule %s%s", n, empty, m->name, - m->isUseful ? ", useful" : empty); - }; - break; - case TBLTYPE_TypeDef: { - TBLTypeDef *t = (TBLTypeDef *)p->data; - if (asn1_verbose) - g_message("%*stypedef %d %s%s", n, empty, t->typeDefId, t->typeName, - t->isPdu ? ", isPDU" : empty); - }; - break; - case TBLTYPE_Type: { - TBLType *t = (TBLType *)p->data; - if (t->fieldName) - s = t->fieldName; - /* typeId is a value from enum TBLTypeId */ - fn = TBLTYPE(t->typeId); - if (asn1_verbose) g_message("%*stype %d[%s]%s [%s]", n, empty, t->typeId, fn, - t->optional ? " opt" : empty, s ); - }; - break; - case TBLTYPE_Tag: { - TBLTag *t = (TBLTag *)p->data; - if ((t->tclass == BER_CLASS_UNI) && (t->code < 32)) - s = asn1_tag[t->code]; - if (asn1_verbose) g_message("%*stag %c%d[%s]", n, empty, - tag_class[t->tclass], t->code, s); - }; - break; - case TBLTYPE_NamedNumber: { - TBLNamedNumber *nn = (TBLNamedNumber *)p->data; - if (asn1_verbose) g_message("%*snamednumber %2d %s", n, empty, - nn->value, nn->name); - }; - break; - case TBLTYPE_Range: { - TBLRange *r = (TBLRange *)p->data; - if (asn1_verbose) g_message("%*srange %d .. %d", n, empty, - r->from, r->to ); - }; - break; - case TBLTYPE_TypeRef: { - TBLTypeRef *r = (TBLTypeRef *)p->data; - if (typeDef_names) - s = typeDef_names[r->typeDefId].name; - if (asn1_verbose) g_message("%*styperef %d[%s]%s", n, empty, - r->typeDefId, s, r->implicit ? ", implicit" : empty ); - }; - break; - default: { - TBLTag *x = (TBLTag *)p->data; - if (asn1_verbose) g_message("%*s--default-- type=%d", n, empty, x->type); - }; - break; - } - } else { /* just show tree */ - if (asn1_verbose) - g_message("%*snode=%p, data=%p, next=%p, prev=%p, parent=%p, child=%p", - n, empty, (void *)p, (void *)p->data, (void *)p->next, (void *)p->prev, (void *)p->parent, (void *)p->children); - } -} - -static void -showGNodes(GNode *p, int n) -{ - if (p == 0) return; - showGNode(p, n); - showGNodes(p->children, n+1); - showGNodes(p->next, n); -} - -#if 0 -static void showGenv(GNode *p, int n, int m) -{ - int i; - - if (p == 0) return; - if (n > m) { - if (asn1_verbose) g_message("%*s.....", n*2, empty); - return; - } - - for(i=0; p && (i < 3); p = p->next, i++) { - showGNode(p, n); - showGenv(p->children, n+1, m); - } - if (p && asn1_verbose) g_message("%*s.....", n*2, empty); - -} -#endif - -static void -debug_dump_TT(void) /* dump contents of TT struct, for debugging */ -{ - if (asn1_verbose) - g_message("modules=%d, defs=%d, types=%d, tags=%d, strings=%d, lenstrings=%d", - TT.totalNumModules, - TT.totalNumTypeDefs, - TT.totalNumTypes, - TT.totalNumTags, - TT.totalNumStrings, - TT.totalLenStrings); -} - -static void -my_log_handler(const gchar *log_domain, GLogLevelFlags log_level, - const gchar *message, gpointer user_data) -{ -static FILE* logf = 0; -static char eol[] = "\r\n"; - - (void) log_domain; (void) log_level; (void) user_data; /* make references */ - - if (logf == NULL && asn1_logfile) { - logf = ws_fopen(asn1_logfile, "w"); - } - if (logf) { - fputs(message, logf); - fputs(eol, logf); - fflush(logf); /* debugging ... */ - } -} - -static void -read_asn1_type_table(const char *filename) -{ - FILE *f; - int ret; - guint size = 0; - guchar *data; - ws_statb64 file_stat; - static guint mylogh = 0; - - if ((filename == 0) || (strlen(filename) == 0)) - return; /* no filename provided */ - - f = ws_fopen(filename, "rb"); - if (f == 0) { - /* - * Ignore "file not found" errors if it's the old default - * ASN.1 file name, as we never shipped such a file. - * Also, on Win32, ignore the earlier default, which - * had a "/" rather than a "\" as the last pathname - * separator. - */ -#ifdef _WIN32 - if (strcmp(filename, bad_separator_old_default_asn1_filename) != 0) -#endif - if ((strcmp(filename, old_default_asn1_filename) != 0) || errno != ENOENT) - report_open_failure(filename, errno, FALSE); - return; - } - ret = ws_fstat64(fileno(f), &file_stat); - if (ret!=-1) - size = (int)file_stat.st_size; - if (size == 0) { - if (asn1_verbose) g_message("file %s is empty or size is unknown, ignored", filename); - fclose(f); - return; - } - if (asn1_verbose) g_message("reading %d bytes from %s", size, filename); - - data = (guchar *)g_malloc(size); - if (fread(data, size, 1, f) < 1) { - g_warning("error reading %s, %s", filename, g_strerror(errno)); - } - fclose(f); - - if (asn1_verbose) { - /* ***** from the time when logging was just in a console... ***** - * g_message("******* Type ^S and change console buffer size to 9999 and type ^Q *******\n" - * " Sleep 5 sec..."); - * Sleep(5 * 1000); - */ - - - g_message("logging to file %s", asn1_logfile); - - if (mylogh == 0) { - mylogh = g_log_set_handler (NULL, (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL - | G_LOG_FLAG_RECURSION), my_log_handler, NULL); - } - } - - asn1_desc = tvb_new_real_data(data, size, size); - - tt_build_tree(); - if (asn1_verbose) g_message("read %d items from %s", icount, filename); - -#if 0 - list_modules(); -#endif - - get_values(); - - g_node_destroy(asn1_nodes); - asn1_nodes = NULL; - - tvb_free(asn1_desc); - asn1_desc = NULL; - - g_free(data); - data = NULL; - - showGNodes(data_nodes, 0); - - debug_dump_TT(); -} - - -/* XXX - Shoudn't we make sure we're not dereferencing a NULL pointer here? */ -#define CHECKTYPE(p,x) {if (((TBLTag *)(p)->data)->type != (x)) \ - g_warning("**** unexpected type %s, want %s, at line %d", \ - data_types[((TBLTag *)p->data)->type], data_types[(x)], __LINE__);} - - -static void -save_reference(PDUinfo *p) -{ - gint i = p->mytype; - - if (i == -1) - i = p->basetype; - - g_ptr_array_add(typeDef_names[i].refs, (gpointer)p); -} - -static void -tbl_type(gint n, GNode *pdu, GNode *list, guint fullindex); - - - - /* evaluate typeref, pointer to current pdu node and typedef */ -static void -tbl_typeref(gint n, GNode *pdu, GNode *tree, guint fullindex) -{ - GNode *q; - PDUinfo *p = (PDUinfo *)pdu->data, *p1; - guint nvals; - value_string *v; - char ss[128]; - int i; - - if (n > 40) { /* don't believe this....! ...... stop recursion ...... */ - g_warning("****tbl_typeref: n>40, return [recursion too deep] ****************"); - return; - } - - CHECKTYPE(tree, TBLTYPE_TypeDef); - - if (asn1_verbose) g_message("%*s+tbl_typeref %s [%s, tag %c%d]", n*2, empty, - p->name, TBLTYPE(p->type), tag_class[p->tclass], p->tag); - - p->typenum = ((TBLTypeDef *)tree->data)->typeDefId; /* name of current type */ - p->flags |= PDU_TYPEDEF; - - tree = g_node_first_child(tree); /* move to its underlying type */ - CHECKTYPE(tree, TBLTYPE_Type); - p->type = ((TBLType *)tree->data)->typeId; - - q = g_node_first_child(tree); /* the tag of this type entry ... is optional... */ - if (((TBLTag *)q->data)->type == TBLTYPE_Tag) { - if ((p->flags & PDU_IMPLICIT) == 0) { /* not implicit, use this tag */ - guint xcls, xtag; - xcls = p->tclass; - xtag = p->tag; - /* XXX -- hack -- hack -- hack -- hack -- hack -- - * only change tag when class+tag == EOC, - * or class is a reference, - * or new class is not universal. - */ - if ( ((xcls|xtag) == 0) || (xcls == CLASSREF) || - (((TBLTag *)q->data)->tclass != BER_CLASS_UNI) ) { - p->tclass = ((TBLTag *)q->data)->tclass; - p->tag = ((TBLTag *)q->data)->code; - if (asn1_verbose) - g_message("%*s*change typeref tag from %c%d to %c%d", - n*2, empty, - tag_class[xcls], - xtag, - tag_class[p->tclass], - p->tag); - } else { - if (asn1_verbose) - g_message("%*sNOT changing tag from %c%d to %c%d", - n*2, empty, - tag_class[xcls], - xtag, - tag_class[((TBLTag *)q->data)->tclass], - ((TBLTag *)q->data)->code); - - } - } - } else { - - ss[0] = 0; - if (p->tclass==CLASSREF) - g_snprintf(ss, 128, ", CLASSREF %d", p->tag); - if (asn1_verbose) g_message("%*sno typeref tag%s", n*2, empty, ss); - - if (p->tclass==CLASSREF) { - TypeRef *tr; - i = p->basetype; - /* CLASSREF....., get it defined using type of the reference */ - - /* p->basetype may be -1 .... ? XXX */ - if (i == -1) - i = p->tag; - tr = &typeDef_names[i]; - if (asn1_verbose) - g_message("%*s*refer2 to type#%d %s, %p", n*2, empty, - p->tag, tr->name, (void *)tr->pdu); - - tbl_typeref(n+1, pdu, tr->type, fullindex); - - return; - } - } - - if (asn1_verbose) - g_message("%*sinclude typedef %d %s %s [%p:%s, tag %c%d]", n*2, empty, p->typenum, - p->name, p->asn1typename, (void *)p, TBLTYPE(p->type), tag_class[p->tclass], p->tag); - - switch(p->type) { - case TBL_BITSTRING: - case TBL_ENUMERATED: - /* names do not have a fullname */ - if (asn1_verbose) g_message("%*s*collection T %s", n*2, empty, p->name); - /* read the enumeration [save min-max somewhere ?] */ - p->value_hf.hfinfo.type = tbl_types_wireshark[p->type]; /* XXX change field type... */ - p->value_hf.hfinfo.display = tbl_display_wireshark[p->type]; - - proto_register_field_array(proto_asn1, &(p->value_hf) , 1); - - save_reference(p); - - if (asn1_verbose) - g_message("regtype1: %3d %3d [%3d] F%2.2x (%s)%s %s %s -> id=%d", - p->mytype, p->typenum, p->basetype, p->flags, p->asn1typename, - p->name, p->fullname, - tbl_types_wireshark_txt[p->type], p->value_id); - p1 = p; - nvals = 0; - while((q = g_node_next_sibling(q))) { - CHECKTYPE(q, TBLTYPE_NamedNumber); - p = (PDUinfo *)g_malloc0(sizeof(PDUinfo)); - nvals++; - p->type = TBL_ENUMERATED; - p->name = (((TBLNamedNumber *)q->data)->name); - p->tag = (((TBLNamedNumber *)q->data)->value); - p->flags = PDU_NAMEDNUM; - if (asn1_verbose) g_message("%*s %3d %s", n*2, empty, p->tag, p->name); - g_node_append_data(pdu, p); - } - - /* list all enum values in the field structure for matching */ - p1->value_hf.hfinfo.strings = v = (value_string *)g_malloc0((nvals+1) * sizeof(value_string)); - q = g_node_first_child(pdu); - nvals = 0; - while(q) { - p = (PDUinfo *)q->data; - v[nvals].value = p->tag; - v[nvals].strptr = p->name; -/* g_message("enumval2: %d %s %d %s %s", nvals, p1->name, p->tag, p->name, tbl_types_asn1[p1->type]); */ - nvals++; - q = g_node_next_sibling(q); - } - /* last entry is already initialized to { 0, NULL } */ - - break; - - case TBL_CHOICE: - if (p->value_id == -1) { /* not yet registered ..... */ - p->value_hf.hfinfo.type = tbl_types_wireshark[p->type]; - p->value_hf.hfinfo.display = tbl_display_wireshark[p->type]; - proto_register_field_array(proto_asn1, &(p->value_hf) , 1); - - save_reference(p); - - if (asn1_verbose) - g_message("regtype2: %3d %3d [%3d] F%2.2x (%s)%s %s %s -> id=%d", - p->mytype, p->typenum, p->basetype, p->flags, p->asn1typename, - p->name, p->fullname, - tbl_types_wireshark_txt[p->type], p->value_id); - } - tbl_type(n, pdu, q, fullindex); - break; - - default: - if (p->value_id == -1) { /* not yet registered ..... */ - p->value_hf.hfinfo.type = tbl_types_wireshark[p->type]; - p->value_hf.hfinfo.display = tbl_display_wireshark[p->type]; - proto_register_field_array(proto_asn1, &(p->value_hf) , 1); - - save_reference(p); - - if (asn1_verbose) - g_message("regtype3: %3d %3d [%3d] F%2.2x (%s)%s %s %s -> id=%d", - p->mytype, p->typenum, p->basetype, p->flags, p->asn1typename, - p->name, p->fullname, - tbl_types_wireshark_txt[p->type], p->value_id); - } - tbl_type(n, pdu, g_node_next_sibling(q), fullindex); - } -} - -static void -tbl_type(gint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, source type node list */ -{ - GNode *q, *pdu1; - PDUinfo *p, *p1; - guint ni; - guint nvals; - value_string *v; - - if (n > 40) { /* don't believe this....! ...... stop recursion ...... */ - g_warning("****tbl_type: n>40, return [recursion too deep] ****************"); - return; - } - - /* showGenv(list, n, n+1); */ - - ni = fullindex; - pdu1 = pdu; /* save start location for append */ - while (list) { /* handle all entries */ - if (asn1_verbose) - g_message("%*s+handle a %s, list=%p", n*2, empty, - data_types[((TBLTag *)list->data)->type], (void *)list); - - if (((TBLTag *)list->data)->type == TBLTYPE_Range) { /* ignore this ..... */ - list = g_node_next_sibling(list); - if (asn1_verbose) g_message("%*s*skip range", n*2, empty); - if (list == 0) - break; - } - - /******* change to positive comparation, but leave comment for reference - * if (((TBLTag *)list->data)->type != TBLTYPE_TypeRef) { - * CHECKTYPE(list, TBLTYPE_Type); - */ - - if (((TBLTag *)list->data)->type == TBLTYPE_Type) { - CHECKTYPE(list, TBLTYPE_Type); - - p = (PDUinfo *)g_malloc0(sizeof(PDUinfo)); - pdu = g_node_append_data(pdu1, p); - - p->type = ((TBLType *)list->data)->typeId; - p->asn1typename = tbl_types_asn1[p->type]; /* the default type */ - p->typenum = -1; - p->mytype = -1; - p->basetype = ((PDUinfo *)pdu1->data)->typenum; - p->flags = PDUinfo_initflags; - p->flags |= (((TBLType *)list->data)->anonymous ? PDU_ANONYMOUS : 0); - p->flags |= (((TBLType *)list->data)->optional ? PDU_OPTIONAL : 0); - - if (((TBLType *)list->data)->fieldName == 0) { /* no name assigned */ - /* assign an anonymous name [XXX refer to parent asn1typename...] */ - ((TBLType *)list->data)->fieldName = - g_strdup_printf("anon%d", anonCount++); - } - p->name = ((TBLType *)list->data)->fieldName; - - ni = fullindex; - ni += g_snprintf(&fieldname[ni], sizeof(fieldname) - ni, ".%s", p->name); - p->fullname = g_strdup(fieldname); - - /* initialize field info */ - p->value_id = -1; - p->type_id = -1; - p->value_hf.p_id = &(p->value_id); - p->value_hf.hfinfo.name = p->fullname; - p->value_hf.hfinfo.abbrev = p->fullname; - p->value_hf.hfinfo.type = tbl_types_wireshark[p->type]; - p->value_hf.hfinfo.display = tbl_display_wireshark[p->type]; - p->value_hf.hfinfo.blurb = p->fullname; - /* all the other fields are already 0 ! */ - - if (p->type < TBL__SIMPLE) { - /* only register fields with a value here, postpone others */ - proto_register_field_array(proto_asn1, &(p->value_hf) , 1); - - save_reference(p); - - if (asn1_verbose) - g_message("register: %3d %3d [%3d] F%2.2x (%s)%s %s %s -> id=%d", - p->mytype, p->typenum, p->basetype, p->flags, - p->asn1typename, p->name, p->fullname, - tbl_types_wireshark_txt[p->type], p->value_id); - } - - q = g_node_first_child(list); - } else { - p = (PDUinfo *)pdu->data; - q = list; - } - - - if (asn1_verbose) g_message("%*s*switch %s %s", n*2, empty, p->name, TBLTYPE(p->type)); - - switch (p->type) { - case TBL_BOOLEAN: - case TBL_INTEGER: - case TBL_OCTETSTRING: - case TBL_NULL: - case TBL_OID: - case TBL_REAL: - CHECKTYPE(q, TBLTYPE_Tag); - p->tclass = ((TBLTag *)q->data)->tclass; - p->tag = ((TBLTag *)q->data)->code; - break; - - case TBL_BITSTRING: - case TBL_ENUMERATED: - CHECKTYPE(q, TBLTYPE_Tag); - p->tclass = ((TBLTag *)q->data)->tclass; - p->tag = ((TBLTag *)q->data)->code; - if (asn1_verbose) g_message("%*s*collection %s", n*2, empty, p->name); - /* read the enumeration [save min-max somewhere ?] */ - nvals = 0; - p1 = p; - while((q = g_node_next_sibling(q))) { - CHECKTYPE(q, TBLTYPE_NamedNumber); - p = (PDUinfo *)g_malloc0(sizeof(PDUinfo)); - nvals++; - p->type = TBL_ENUMERATED; - p->name = (gchar *)(((TBLNamedNumber *)q->data)->name); - p->tag = (((TBLNamedNumber *)q->data)->value); - p->flags = PDU_NAMEDNUM; - if (asn1_verbose) g_message("%*s %3d %s", n*2, empty, p->tag, p->name); - g_node_append_data(pdu, p); - } - - /* list all enum values in the field structure for matching */ - p1->value_hf.hfinfo.strings = v = (value_string *)g_malloc0((nvals+1) * sizeof(value_string)); - q = g_node_first_child(pdu); - nvals = 0; - while(q) { - p = (PDUinfo *)q->data; - v[nvals].value = p->tag; - v[nvals].strptr = p->name; - /* g_message("enumval1: %d %s %d %s", nvals, p1->name, p->tag, p->name); */ - nvals++; - q = g_node_next_sibling(q); - } - /* last entry is already initialized to { 0, NULL } */ - - break; - - case TBL_SEQUENCE: - case TBL_SET: - case TBL_SEQUENCEOF: - case TBL_SETOF: - case TBL_CHOICE: - CHECKTYPE(q, TBLTYPE_Tag); - q = g_node_first_child(list); - tbl_type(n+1, pdu, q, ni); - break; - - case TBL_TYPEREF: { /* may have a tag ... */ - TypeRef *tr; - guint i; - if(!q){ - break; - } - if ( ((TBLTag *)q->data)->type == TBLTYPE_Tag) { - if ((p->flags & PDU_IMPLICIT) == 0) { /* not implicit, use this tag */ - p->tclass = ((TBLTag *)q->data)->tclass; - p->tag = ((TBLTag *)q->data)->code; - if (asn1_verbose) - g_message("%*s*insert type tag %c%d", n*2, empty, - tag_class[p->tclass], p->tag); - } - q = g_node_next_sibling(q); - } else { /* use default tag for this type */ - tr = &typeDef_names[((TBLTypeRef *)q->data)->typeDefId]; - if ((((p->flags & PDU_IMPLICIT) == 0) && (tr->defclass != BER_CLASS_UNI)) || - ((p->tclass | p->tag) == 0 )) { - /* not implicit, use this tag */ - p->tclass = tr->defclass; - p->tag = tr->deftag; - if (asn1_verbose) g_message("%*s*set tag %c%d", n*2, empty, - tag_class[p->tclass], p->tag); - } - } - CHECKTYPE(q, TBLTYPE_TypeRef); - i = ((TBLTypeRef *)q->data)->typeDefId; - p->mytype = i; - tr = &typeDef_names[i]; - if (asn1_verbose) - g_message("%*s*type#%d %s, %p", n*2, empty, i, tr->name, (void *)tr->pdu); - p->asn1typename = tr->name; - - if (tr->defclass == CLASSREF) { - if (tr->pdu == 0) - tr->pdu = pdu; /* remember this reference */ - i = tr->deftag; - tr = &typeDef_names[i]; - if (asn1_verbose) - g_message("%*s*refer to type#%d %s, %p", n*2, empty, - i, tr->name, (void *)tr->pdu); - } - /* evaluate reference if not done before or when below recursion limit */ - if ((tr->pdu == 0) || (tr->level < type_recursion_level)) { - tr->level++; - if (tr->pdu == 0) { - tr->pdu = pdu; /* save for references we leave */ - } - p->flags |= ((TBLTypeRef *)q->data)->implicit? PDU_IMPLICIT : 0; - if (asn1_verbose) - g_message("%*s*typeref %s > %s%s at %p", n*2, empty, - p->name, - ((TBLTypeRef *)q->data)->implicit?"implicit ":empty, - tr->name, - (void *)pdu); - tbl_typeref(n+1, pdu, tr->type, ni); - tr->level--; - } else { - if (asn1_verbose) - g_message("%*s*typeref %s > %s already at %p", n*2, empty, - p->name, tr->name, (void *)tr->pdu); - p->flags |= PDU_REFERENCE; - p->reference = tr->pdu; - } - }; - break; - default: - g_warning("**** unknown tbl-type %d at line %d", p->type, __LINE__); - break; - } - - if (asn1_verbose) - g_message("%*sinclude type %s %s [%p:%s, tag %c%d]", - n*2, empty, p->name, p->asn1typename, (void *)p, TBLTYPE(p->type), - tag_class[p->tclass], p->tag); - - if (p->value_id == -1) { /* not registered before, do it now */ - proto_register_field_array(proto_asn1, &(p->value_hf) , 1); - - save_reference(p); - - if (asn1_verbose) - g_message("regist-2: %3d %3d [%3d] F%2.2x (%s)%s %s %s -> id=%d", - p->mytype, p->typenum, p->basetype, p->flags, p->asn1typename, - p->name, p->fullname, - tbl_types_wireshark_txt[p->type], p->value_id); - } - list = g_node_next_sibling(list); - } -} - -static void -PDUtext(char *txt, gulong txt_size, PDUinfo *info) /* say everything we know about this entry */ -{ - PDUinfo *rinfo; - const char *tt, *nn, *tn, *fn, *oo, *ii, *an, *tr, *ty; - int idx; - - idx = 0; - if (info) { - tt = TBLTYPE(info->type); - nn = info->name; - tn = info->asn1typename; - fn = info->fullname; - if (info->flags & PDU_NAMEDNUM) - g_snprintf(&txt[idx], txt_size - idx, "name: %2d %s", info->tag, nn); - else { - if (info->flags & PDU_TYPEDEF) - idx += g_snprintf(&txt[idx], txt_size - idx, "def %d: ", info->typenum); - else - idx += g_snprintf(&txt[idx], txt_size - idx, " "); - ty = (info->flags & PDU_TYPETREE) ? "typ" : "val"; - idx += g_snprintf(&txt[idx], txt_size - idx, "%s %s (%s)%s [%s] tag %c%d hf=%d tf=%d",ty,tt, tn, nn, fn, - tag_class[info->tclass], info->tag, info->value_id, info->type_id); - idx += g_snprintf(&txt[idx], txt_size - idx, ", mt=%d, bt=%d", info->mytype, info->basetype); - oo = (info->flags & PDU_OPTIONAL) ? ", optional" : empty; - ii = (info->flags & PDU_IMPLICIT) ? ", implicit" : empty; - nn = (info->flags & PDU_NAMEDNUM) ? ", namednum" : empty; - an = (info->flags & PDU_ANONYMOUS) ? ", anonymous" : empty; - idx += g_snprintf(&txt[idx], txt_size - idx, "%s%s%s%s", oo, ii, nn, an); - if (info->flags & PDU_REFERENCE) { - rinfo = (PDUinfo *)((GNode *)(info->reference))->data; - tt = TBLTYPE(rinfo->type); - nn = rinfo->name; - tn = rinfo->asn1typename; - fn = rinfo->fullname; - idx += g_snprintf(&txt[idx], txt_size - idx, ", reference to %s (%s)%s [%s]", tt, tn, nn, fn); - if (rinfo->flags & PDU_TYPEDEF) - idx += g_snprintf(&txt[idx], txt_size - idx, " T%d", rinfo->typenum); - idx += g_snprintf(&txt[idx], txt_size - idx, " tag %c%d", tag_class[rinfo->tclass], rinfo->tag); - oo = (rinfo->flags & PDU_OPTIONAL) ? ", optional" : empty; - ii = (rinfo->flags & PDU_IMPLICIT) ? ", implicit" : empty; - nn = (rinfo->flags & PDU_NAMEDNUM) ? ", namednum" : empty; - tn = (rinfo->flags & PDU_REFERENCE) ? ", reference" : empty; - tt = (rinfo->flags & PDU_TYPEDEF) ? ", typedef" : empty; - an = (rinfo->flags & PDU_ANONYMOUS) ? ", anonymous" : empty; - tr = (rinfo->flags & PDU_TYPETREE) ? ", typetree" : empty; - g_snprintf(&txt[idx], txt_size - idx, "%s%s%s%s%s%s%s", oo, ii, nn, tn, tt, an, tr); - } - } - } else { - g_snprintf(&txt[idx], txt_size - idx, "no info available"); - } - - return; -} - - -static void -showPDUtree(GNode *p, int n) -{ - PDUinfo *info; - char text[400]; - - while (p != 0) { - info = (PDUinfo *)p->data; - - PDUtext(text, sizeof(text), info); - - if (asn1_verbose) g_message("%*s%s", n*2, empty, text); - - showPDUtree(g_node_first_child(p), n+1); - - p = g_node_next_sibling(p); - } - - return; -} - -static gboolean -build_pdu_tree(const char *pduname) -{ - SearchDef sd; - guint pdudef, i, tcount; - guint sav_len; - PDUinfo *info; - char text[400]; - guint j, k; - gint defid; - PDUinfo *p, *q; - TypeRef *tr; - - if (asn1_verbose) g_message("build msg tree from '%s' for '%s'", current_asn1, pduname); - - if (!data_nodes) { - if (asn1_verbose) g_message("no data nodes"); - return FALSE; - } - sd.key = pduname; - sd.here = 0; - g_node_traverse(data_nodes, G_PRE_ORDER, G_TRAVERSE_ALL, -1, is_typedef, (gpointer)&sd); - if (sd.here) { - pdudef = ((TBLTypeDef *)(sd.here->data))->typeDefId; - if (asn1_verbose) g_message("%s found, %p, typedef %d", sd.key, (void *)sd.here, pdudef); - } else { - if (asn1_verbose) g_message("%s not found, ignored", sd.key); - return FALSE; - } - - /* If there's an existing PDU tree, free it */ - if (PDUtree) { - g_node_traverse(PDUtree, G_POST_ORDER, G_TRAVERSE_ALL, -1, - free_node_data, NULL); - g_node_destroy(PDUtree); - } - - /* initialize the PDU tree, hand craft the root entry */ - - info = (PDUinfo *)g_malloc0(sizeof(PDUinfo)); - info->name = pduname; - info->asn1typename = pduname; - info->type = TBL_SEQUENCEOF; - info->fullname = g_strdup_printf("%s.%s", pabbrev, pduname); - info->flags = PDUinfo_initflags = 0; - info->value_id = -1; - info->type_id = -1; - info->basetype = -1; - info->mytype = pdudef; - - info->value_hf.p_id = &(info->value_id); - info->value_hf.hfinfo.name = info->fullname; - info->value_hf.hfinfo.abbrev = info->fullname; - info->value_hf.hfinfo.type = tbl_types_wireshark[info->type]; - info->value_hf.hfinfo.display = tbl_display_wireshark[info->type]; - info->value_hf.hfinfo.blurb = info->fullname; - - anonCount = 0; /* anonymous types counter */ - - PDUtree = g_node_new(info); - pabbrev_pdu_len = g_snprintf(fieldname, sizeof(fieldname), "%s.%s.", pabbrev, pduname); - sav_len = pabbrev_pdu_len; - - /* Now build the tree for this top level PDU */ - if (asn1_verbose) - g_message("******** Define main type %d, %s", pdudef, pduname); - tbl_typeref(0, PDUtree, sd.here, pabbrev_pdu_len-1); /* strip initial . for new names */ - - if (asn1_verbose) - g_message("%d anonymous types", anonCount); - - /* Now make all types used available for matching */ - if (asn1_verbose) - g_message("Define the types that are actually referenced through the top level PDU"); - for (i=0, tcount=0; i<numTypedefs; i++) { - tr = &(typeDef_names[i]); - - if (tr->pdu) { /* ignore if not used in main pdu */ - tcount++; - if (i == pdudef) - g_warning("pdu %d %s defined twice, TopLevel & type", pdudef, pduname); - if (asn1_verbose) - g_message("******** Define type %d, %s", i, tr->name); - - /* .... do definition ..... */ - info = (PDUinfo *)g_malloc0(sizeof(PDUinfo)); - info->name = tr->name; - info->asn1typename = tr->name; - info->tclass = tr->defclass; - info->tag = tr->deftag; - info->type = TBL_TYPEREF; - info->fullname = g_strdup_printf("%s.--.%s", pabbrev, tr->name); - info->flags = PDUinfo_initflags = PDU_TYPETREE; - info->value_id = -1; - info->type_id = -1; - info->basetype = -1; - info->mytype = i; - - info->value_hf.p_id = &(info->value_id); - info->value_hf.hfinfo.name = info->fullname; - info->value_hf.hfinfo.abbrev = info->fullname; - info->value_hf.hfinfo.type = tbl_types_wireshark[info->type]; - info->value_hf.hfinfo.display = tbl_display_wireshark[info->type]; - info->value_hf.hfinfo.blurb = info->fullname; - - tr->typetree = g_node_new(info); - pabbrev_pdu_len = g_snprintf(fieldname, sizeof(fieldname), "%s.--.%s.", pabbrev, tr->name); - tbl_typeref(0, tr->typetree, tr->type, pabbrev_pdu_len-1); - } - } - if (asn1_verbose) - g_message("%d types used", tcount); - - pabbrev_pdu_len = sav_len; - - /* and show the result */ - if (asn1_verbose) - g_message("Type index:"); - for (i=0; i<numTypedefs; i++) { - tr = &(typeDef_names[i]); - - if (tr->pdu == 0) /* skip if not used */ - continue; - - if (asn1_verbose) - g_message(" %3d %s, %c%d, refs: %d", - i, tr->name, tag_class[tr->defclass], tr->deftag, - g_ptr_array_len(tr->refs)); - - /* get defining node for this type */ - defid = -1; - if (tr->typetree) { - p = (PDUinfo *)(tr->typetree->data); - defid = p->value_id; - if (asn1_verbose) - g_message(" -- defining id=%d", defid); - } - for(j=0; j < g_ptr_array_len(tr->refs); j++) { /* show refs, and set type_id */ - p = (PDUinfo *)g_ptr_array_index(tr->refs, j); - if (p->mytype == (gint)i) - p->type_id = defid; /* normal reference */ - else { - if ((p->flags & PDU_TYPETREE) == 0) { - /* we have a primitive value, find its real type */ - for(k=0; k < g_ptr_array_len(tr->refs); k++) { - /* look at all refs */ - q = (PDUinfo *)g_ptr_array_index(tr->refs, k); - if ((q->flags & PDU_TYPETREE) == 0) - continue; /* only type trees are interresting */ - if (q->type != p->type) - continue; /* must be same types */ - if (strcmp(q->name, p->name) == 0) { - /* OK, take the first we find, not entirely - * correct, it may be from a different - * base-base type...... XXX */ - p->type_id = q->value_id; - break; - } - } - } - } - - if (asn1_verbose) { - PDUtext(text, sizeof(text), p); - g_message(" %s", text); - } - } - } - - if (asn1_verbose) - g_message("The resulting PDU tree:"); - showPDUtree(PDUtree, 0); - - return TRUE; -} - - -#ifdef DISSECTOR_WITH_GUI -/* This cannot work in tshark.... don't include for now */ -#define SHOWPDU -#endif /* DISSECTOR_WITH_GUI */ -#ifdef SHOWPDU - -static GtkWidget *window = NULL; - -/* the columns in the tree view */ -enum -{ - TITLE_COLUMN, /* text in this row */ - DEF_COLUMN, /* definition in this row, if any */ - REF_COLUMN, /* referennce from this column, if any */ - VALUE_COLUMN, /* indicate this is a value */ - NAME_COLUMN, /* name of this row */ - N_COLUMNS -}; - -static FILE *namelist = 0; - -static void -build_tree_view(GtkTreeStore *store, GNode *p, GtkTreeIter *iter) -{ - GtkTreeIter iter2; - PDUinfo *info, *rinfo; - gint def, ref; - guchar *pb; - - char text[400]; - - while (p != 0) { - info = (PDUinfo *)p->data; - - gtk_tree_store_append (store, &iter2, iter); /* Acquire iterator */ - - PDUtext(text, sizeof(text), info); - - def = ref = -1; - if (info->flags & PDU_TYPEDEF) - def = info->typenum; - - if (info->flags & PDU_REFERENCE) { - rinfo = (PDUinfo *)((GNode *)(info->reference))->data; - ref = rinfo->typenum; - } - pb = GTK_STOCK_CANCEL; - if (G_NODE_IS_LEAF(p)) { - if (info->flags & PDU_NAMEDNUM) - pb = GTK_STOCK_BOLD; - else { - pb = GTK_STOCK_YES; - if (namelist) - fprintf(namelist, "%16s %s\n", - &(TBLTYPE(info->type)[4]), info->fullname); - } - } else { - switch (info->type) { - case TBL_ENUMERATED: - case TBL_BITSTRING: - pb = GTK_STOCK_ADD; - if (namelist) - fprintf(namelist, "%16s %s\n", - &(TBLTYPE(info->type)[4]), info->fullname); - break; - default: - break; - } - } - - gtk_tree_store_set (store, &iter2, - TITLE_COLUMN, text, - DEF_COLUMN, def, - REF_COLUMN, ref, - VALUE_COLUMN, pb, - NAME_COLUMN, info->fullname, - -1); - - build_tree_view(store, g_node_first_child(p), &iter2); - - p = g_node_next_sibling(p); - } - - return; -} - - -struct DefFind { - gint def; - GtkTreePath *path; -}; - -#define PATHSTACKMAX 10 -static GtkTreePath *pathstack[PATHSTACKMAX]; -static gint pathstackp = 0; - -static void add_path(GtkTreePath *p) -{ - if (pathstackp >= PATHSTACKMAX) { /* shift old contents */ - gtk_tree_path_free(pathstack[0]); /* we forget about this one */ - memmove(&pathstack[0], &pathstack[1], (PATHSTACKMAX-1)*sizeof(GtkTreePath *)); - pathstackp--; - } - pathstack[pathstackp++] = p; -} - -static GtkTreePath *pop_path(void) -{ - if (pathstackp > 0) - return pathstack[--pathstackp]; - return 0; -} - -static gboolean -find_definition(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) -{ - gint def; - - struct DefFind *df = (struct DefFind *)data; - - gtk_tree_model_get (model, iter, DEF_COLUMN, &def, -1); - - if (def == df->def) { - df->path = gtk_tree_path_copy (path); - return TRUE; - } - return FALSE; - -} - -static void -my_signal_handler(GtkTreeView *treeview, GtkTreePath *spath, GtkTreeViewColumn *arg2, gpointer model) -{ - GtkTreeIter iter; - GtkTreePath *path, *path2; - gchar *text, *oldpath, *newpath; - gint def, ref; - struct DefFind df; - - (void) arg2; - - path = gtk_tree_path_copy (spath); - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, TITLE_COLUMN, &text, DEF_COLUMN, &def, REF_COLUMN, &ref, -1); - - oldpath = gtk_tree_path_to_string(path); - path2 = gtk_tree_path_copy (path); - - add_path(gtk_tree_path_copy(path)); - - if (ref != -1) { /* this is a reference, find matching definition */ - df.def = ref; - df.path = 0; - gtk_tree_model_foreach (model, find_definition, &df); - if (df.path) { - gtk_tree_path_free(path); - path = df.path; - } - } else { /* just move to the next entry, if it exists */ - gtk_tree_path_next(path2); - - if (gtk_tree_model_get_iter (model, &iter, path2)) { - gtk_tree_path_free(path); - path = path2; /* OK */ - } else { - if (gtk_tree_path_get_depth (path) > 1) - gtk_tree_path_up (path); - } - } - - if (path != path2) - gtk_tree_path_free (path2); - - gtk_tree_view_expand_to_path (treeview, path); - gtk_tree_view_expand_row (treeview, path, FALSE); - - gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.2, 0.0); - - gtk_tree_view_set_cursor (treeview, path, NULL, FALSE); - - newpath = gtk_tree_path_to_string(path); - - if (asn1_debug) - g_message("my_signal_handler: treeview=%p, moving from %s to %s", - treeview, oldpath, newpath); - - g_free(text); - g_free(oldpath); - g_free(newpath); - /* if (df.path) */ - /* gtk_tree_path_free(df.path); */ -} - - -static void -menuitem_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *dialog; - GtkTreeModel *model; - GtkTreeView *treeview = gtk_item_factory_popup_data_from_widget(widget); - GtkTreeSelection *selection; - GtkTreeIter iter; - gchar *text, *name; - gint def, ref; - GtkTreePath *path; - gchar *oldpath, *newpath; - GtkTreeViewColumn *focus_column; - - selection = gtk_tree_view_get_selection(treeview); - - model = gtk_tree_view_get_model(treeview); - gtk_tree_view_get_cursor (treeview, &path, &focus_column); - - if (gtk_tree_model_get_iter (model, &iter, path)) { - - gtk_tree_model_get (model, &iter, TITLE_COLUMN, &text, DEF_COLUMN, &def, REF_COLUMN, &ref, - NAME_COLUMN, &name, -1); - oldpath = gtk_tree_path_to_string(path); - newpath = empty; - - switch (callback_action) { - case 0: /* Select */ - gtk_tree_selection_select_path (selection, path); - break; - case 1: /* back */ - path = pop_path(); - if (path) { - gtk_tree_view_expand_to_path (treeview, path); - gtk_tree_view_expand_row (treeview, path, FALSE); - - gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.2, 0.0); - - gtk_tree_view_set_cursor (treeview, path, NULL, FALSE); - - newpath = gtk_tree_path_to_string(path); - - gtk_tree_path_free(path); - } else - newpath = g_strdup("** no path **"); - if (asn1_debug) - g_message("menueitem_cb: treeview=%p, moving from %s to %s", - treeview, oldpath, newpath); - break; - - case 2: /* Find */ - /* get all non anonymous names to the root */ - - default: - dialog = gtk_message_dialog_new (GTK_WINDOW (callback_data), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - "You selected the menu item: \"%s\" [%d]\n%s\npath=%s, %s\nname='%s'", - gtk_item_factory_path_from_widget (widget), - callback_action, text, oldpath, newpath, name); - - /* Close dialog on user response */ - g_signal_connect (dialog, - "response", - G_CALLBACK (gtk_widget_destroy), - NULL); - - gtk_widget_show (dialog); - break; - } - g_free(text); - g_free(name); - if (newpath != empty) - g_free(newpath); - g_free(oldpath); - } else - g_message("menuitem_cb: no iterator..."); -} - -static GtkItemFactoryEntry menu_items[] = { - { "/Select", NULL, menuitem_cb, 0, NULL, 0 }, - { "/Back", "<control>B", menuitem_cb, 1, NULL, 0 }, - { "/Find", "<control>F", menuitem_cb, 2, NULL, 0 }, - { "/Save", "<control>S", menuitem_cb, 3, NULL, 0 }, -}; - -static gint button_press_callback( GtkWidget *widget, - GdkEventButton *event, - gpointer data ) -{ - GtkTreeView *treeview = GTK_TREE_VIEW(widget); - - /* g_message("button_press_callback, widget=%p, button=%d, type=%d, x=%g, y=%g, x_root=%g," - * " y_root=%g", widget, event->button, event->type, event->x, event->y, event->x_root, - * event->y_root ); - */ - if (event->button == 3) { - gtk_item_factory_popup_with_data ((GtkItemFactory *)data, treeview, NULL, - event->x_root, - event->y_root, - event->button, - event->time); - return TRUE; - } - return FALSE; /* continue handling this event */ -} - - -static void -create_message_window(void) -{ - GtkCellRenderer *renderer; - GtkTreeStore *model; - GtkWidget *vbox; - GtkWidget *sw; - GtkWidget *treeview; - gchar *text; - GtkItemFactory *item_factory; - GtkAccelGroup *accel_group; - gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); - - if ( ! window) { - - /* create window, etc */ - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), current_pduname); - g_signal_connect (window, "destroy", - G_CALLBACK (gtk_widget_destroyed), &window); - - vbox = gtk_vbox_new (FALSE, 8); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); - gtk_container_add (GTK_CONTAINER (window), vbox); - - text = g_strdup_printf("ASN.1 message structure from %s, %s", current_asn1, current_pduname); - - gtk_box_pack_start (GTK_BOX (vbox), - gtk_label_new (text), - FALSE, FALSE, 0); - g_free(text); - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_ETCHED_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); - - model = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, - G_TYPE_STRING, G_TYPE_STRING); - - namelist = ws_fopen("namelist.txt", "w"); - if (!namelist) - fprintf(stderr, "unable to open file: namelist.txt for writing!\n"); - build_tree_view(model, PDUtree, NULL); - if (namelist) { - fclose(namelist); - namelist = 0; - } - - /* create tree view */ - treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); - g_object_unref (model); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), - GTK_SELECTION_MULTIPLE); - - renderer = gtk_cell_renderer_text_new (); - -#if 0 /* testing pango attributes */ -{ - PangoAttribute* bg; - PangoAttrList* attr; - - attr = pango_attr_list_new(); - bg = pango_attr_background_new(50000,55000,50000); - bg->start_index = 0; - bg->end_index = 10000; - pango_attr_list_insert(attr, bg); - - g_object_set(renderer, "attributes", attr, NULL); -} -#endif /* testing pango attributes */ - - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), - TITLE_COLUMN, "asn1 entities", renderer, - "text", TITLE_COLUMN, NULL ); - - /* renderer = gtk_cell_renderer_text_new (); - * gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), - * DEF_COLUMN, "type definition", renderer, - * "text", DEF_COLUMN, NULL ); - * - * renderer = gtk_cell_renderer_text_new (); - * gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), - * REF_COLUMN, "reference", renderer, - * "text", REF_COLUMN, NULL ); - */ - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), - VALUE_COLUMN, "value", renderer, - "stock_id", VALUE_COLUMN, NULL ); - - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(treeview), - NAME_COLUMN, "fieldname", renderer, - "text", NAME_COLUMN, NULL ); - - gtk_container_add (GTK_CONTAINER (sw), treeview); - - /* gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); */ - - /* create menu */ - - accel_group = gtk_accel_group_new (); - - /* This function initializes the item factory. - * Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, - * or GTK_TYPE_OPTION_MENU. - * Param 2: The path of the menu. - * Param 3: A pointer to a gtk_accel_group. The item factory sets up - * the accelerator table while generating menus. - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "<menu>", accel_group); - - /* This function generates the menu items. Pass the item factory, - the number of items in the array, the array itself, and any - callback data for the the menu items. */ - gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); - - /* Attach the new accelerator group to the window. */ - gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - - - /* expand all rows after the treeview widget has been realized */ - g_signal_connect (treeview, "realize", - G_CALLBACK (gtk_tree_view_expand_all), NULL); - g_signal_connect (treeview, "row-activated", - G_CALLBACK (my_signal_handler), (gpointer)model); - - g_signal_connect (treeview, "button_press_event", - G_CALLBACK (button_press_callback), item_factory); - - /* g_signal_connect_swapped (treeview, "event", - * G_CALLBACK (button_press_handler), - * menu); - */ - gtk_window_set_default_size (GTK_WINDOW (window), 650, 400); - } - - if (!GTK_WIDGET_VISIBLE (window)) - gtk_widget_show_all (window); - else - { - gtk_widget_destroy (window); - window = NULL; - } -} -#endif /* SHOWPDU */ - -/************************************************************************************************ - * routines to find names to go with the decoded data stream * - ************************************************************************************************/ -#define PDUSTATE_STACK_SIZE 1024 -typedef struct _statestack statestack; -static struct _statestack { - GNode *node; - guint type; - guint offset; - const char *name; -} PDUstate[PDUSTATE_STACK_SIZE]; -static gint PDUstatec = 0; - -/* XXX - Shouldn't we do bounds checking here? */ -#define PUSHNODE(x) { PDUstate[PDUstatec++] = (x); } -#define POPSTATE PDUstate[--PDUstatec] - -static const char * -getname(GNode *node) { - if (node == NULL || node->data == NULL) - THROW(ReportedBoundsError); - - return ((PDUinfo *)node->data)->name; -} - -static guint -gettype(GNode *node) { - if (node == NULL || node->data == NULL) - THROW(ReportedBoundsError); - - return ((PDUinfo *)node->data)->type & TBL_TYPEmask; -} - -static PDUinfo * -getinfo(GNode *node) { - if (node == NULL) - THROW(ReportedBoundsError); - - return (PDUinfo *)node->data; -} - -#define NEXT {pos.node = g_node_next_sibling(pos.node);pos.type=0;} -#define CHILD {pos.node = g_node_first_child(pos.node);pos.type=0;} -#define MATCH (info && (cls == info->tclass) && (tag == info->tag)) -#define ISOPTIONAL (info && (info->flags & PDU_OPTIONAL)) -#define ISIMPLICIT (info && (info->flags & PDU_IMPLICIT)) -#define ISREFERENCE (info && (info->flags & PDU_REFERENCE)) -#define ISCHOICE (info && (info->flags & PDU_CHOICE)) -#define ISANONYMOUS (info && (info->flags & PDU_ANONYMOUS)) - -#undef CHECKP -#define CHECKP(p) {if ((p==0)||(PDUstatec<0)){g_warning("pointer==0, line %d **********", __LINE__);\ - pos.node=NULL;PUSHNODE(pos);return ret;}} - - -static void -showstack(statestack *pos, char *txt, int n) -{ - char buf[1024]; - const char /* *name, *type,*/ *stype; - const char *rep, *chs, *done, *ref, *pop, *chr, *rch, *sch, *con; - int i, j; - /* GNode *g;*/ - statestack *p; - guint typef; - - if ( ! asn1_verbose) - return; - - if (n>PDUstatec) - n = PDUstatec; - if (n<0) { - g_message("==underflow"); - return; - } - rep = chs = done = ref = pop = chr = rch = sch = con = empty; - -#if 0 /* XXX: not used ??? */ - g = pos->node; - if (g) { - name = ((PDUinfo *)g->data)->name; - type = TBLTYPE(((PDUinfo *)g->data)->type); - } else { - name = "node<null>"; - type = "?"; - } -#endif - typef = pos->type; - stype = TBLTYPE(typef); - if (typef & TBL_REPEAT) rep = "[repeat]"; - if (typef & TBL_CHOICE_made) chs = "[choice]"; - if (typef & TBL_SEQUENCE_done) done = "[done]"; - if (typef & TBL_REFERENCE) ref = "[ref]"; - if (typef & TBL_REFERENCE_pop) pop = "[ref-pop]"; - if (typef & TBL_CHOICE_repeat) chr = "[chs-rep]"; - if (typef & TBL_REPEAT_choice) rch = "[rep-chs]"; - if (typef & TBL_SEQUENCE_choice)sch = "[seq-chs]"; - if (typef & TBL_CONSTRUCTED) con = "[constr]"; - - i = g_snprintf(buf, sizeof(buf), "%s sp=%d,pos=%p,%s%s%s%s%s%s%s%s%s%s:%s,%d", txt, PDUstatec, - (void *)pos->node, stype, rep, chs, done, ref, pop, chr, rch, sch, con, - pos->name, pos->offset); - - for(j=1, n--; n>0; j++, n--) { - p = &PDUstate[PDUstatec-j]; - typef = p->type; - stype = TBLTYPE(typef); - rep = (typef & TBL_REPEAT) ? "[repeat]" : empty; - chs = (typef & TBL_CHOICE_made) ? "[choice]" : empty; - done = (typef & TBL_SEQUENCE_done) ? "[done]" : empty; - ref = (typef & TBL_REFERENCE) ? "[ref]" : empty; - pop = (typef & TBL_REFERENCE_pop) ? "[ref-pop]" : empty; - chr = (typef & TBL_CHOICE_repeat) ? "[chs-rep]" : empty; - rch = (typef & TBL_REPEAT_choice) ? "[rep-chs]" : empty; - sch = (typef & TBL_SEQUENCE_choice)? "[seq-chs]" : empty; - con = (typef & TBL_CONSTRUCTED) ? "[constr]" : empty; - - i += g_snprintf(&buf[i], sizeof(buf) - i, "| sp=%d,st=%p,%s%s%s%s%s%s%s%s%s%s:%s,%d", PDUstatec-j, - (void *)p->node, stype, rep, chs, done, ref, pop, chr, rch, sch, con, - p->name, p->offset); - } - g_message("%s", buf); -} - -#if 0 -static void -showrefNode(GNode *node, int n) -{ - const char *name = empty, *type = empty, *tname = empty; - int cls = 0, tag = 0; - PDUinfo *info; - GNode *ref = 0; - - if (n > 10) { - g_message("%*sstop, nesting too deep", 2*n, empty); - return; - } - if (node->data) { - info = (PDUinfo *)(node->data); - type = TBLTYPE(info->type); - name = info->name; - tname = info->asn1typename; - ref = info->reference; - cls = info->tclass; - tag = info->tag; - } - g_message("%*sreference '(%s)%s:%s' at %p: data=%p, reference=%p, %c%d", - 2*n, empty, tname, type, name, node, node->data, - ref, tag_class[cls], tag); - - if (ref) - showrefNode(ref, n+1); -} -#endif - -#if 0 -static void -showNode(GNode *node, int n, int m) -{ - const char *name = empty, *type = empty; - GNode *ref = 0; - - if (n > m) - return; - - if (node->data) { - type = TBLTYPE(((PDUinfo *)(node->data))->type); - name = ((PDUinfo *)(node->data))->name; - ref = ((PDUinfo *)(node->data))->reference; - } - g_message("%*snode '%s:%s' at %p: data=%p, next=%p, prev=%p, parent=%p, child=%p", - 2*n, empty, type, name, node, node->data, node->next, node->prev, - node->parent, node->children); - - if (m > 10) { - g_message("%*sstop, nesting too deep", 2*n, empty); - return; - } - - if (ref) showrefNode(ref, n+2); - - if (node->children) showNode(node->children, n+1, m); - if (node->next) showNode(node->next, n, m); -} -#endif - -static void -PDUreset(int count, int count2) -{ - statestack pos; - - if (asn1_verbose) g_message("PDUreset %d-%d", count, count2); - - PDUstatec = 0; /* stackpointer */ - PDUerrcount = 0; /* error counter per asn.1 message */ - - pos.node = NULL; /* sentinel */ - pos.name = "sentinel"; - pos.type = TBL_SEQUENCEOF; - pos.offset = 0; - PUSHNODE(pos); - - if (PDUtree) { - pos.node = PDUtree; /* root of the tree */ - pos.name = getname(pos.node); - pos.type = gettype(pos.node) | TBL_REPEAT; - pos.offset = 0; - PUSHNODE(pos); - } -} - -static GNode * /* find GNode for a choice element, 0 if none */ -makechoice(GNode *p, guint cls, guint tag) -{ - GNode *q; - PDUinfo *info; - - p = g_node_first_child(p); /* the list of choices */ - info = 0; /* avoid gcc warning */ - - while (p) { - info = ((PDUinfo *)p->data); - - if (info->type == TBL_CHOICE) { - if (asn1_verbose) - g_message(" using sub choice (%s)%s", info->asn1typename, info->name); - - q = makechoice(p, cls, tag); - if (q) { /* found it */ - p = q; - info = ((PDUinfo *)p->data); - break; - } /* continue with this level */ - - } else { - if (asn1_verbose) - g_message(" have %c%d, found %c%d, %s", tag_class[cls], tag, - tag_class[info->tclass], info->tag, info->name); - - if ((cls == info->tclass) && (tag == info->tag)) - break; /* found it */ - } - - p = g_node_next_sibling(p); - } - if (asn1_verbose) { - if (p) g_message(" OK, '%s:(%s)%s' chosen", tbl_types[info->type], info->asn1typename, - info->name); - else g_message(" ...no matching choice..."); - } - return p; -} - - /* offset is for debugging only, a reference to output on screen */ -static PDUprops * -getPDUprops(PDUprops *out, guint offset, guint cls, guint tag, guint cons) -{ - statestack pos, pos2, save_pos; - PDUinfo *info; - const char *ret, *tmp; - int typeflags = 0, donext = 0, pushed = 0, cons_handled = 0; - static char namestr[64]; /* enough ? */ - static char posstr[40]; - static char noname[] = "*noname*"; - static PDUprops constructed_save; /* for unexpectedly constructed entities */ - - if (PDUstatec > 0) /* don't read from below the stack */ - pos = POPSTATE; - /* pos refers to the last asn1 node handled */ - - /* a very simple, too simple??, way to handle constructed entities */ - if ((PDUstatec > 0) && (pos.type & TBL_CONSTRUCTED)) { - /* unexpectedly constructed, return same info as last time */ - g_snprintf(posstr, sizeof(posstr), "==off=%d %c%d%c", offset, tag_class[cls], tag, cons?'c':'p'); - showstack(&pos, posstr, 3); - pos.offset = offset; - pos.type &= ~TBL_CONSTRUCTED; /* remove the flag */ - PUSHNODE(pos); /* push extra, to match with a EOI operation */ - PUSHNODE(pos); /* restore the stack */ - *out = constructed_save; - if (asn1_verbose) - g_message(" return for constructed %s (%s)%s", - TBLTYPE(out->type), out->asn1typename, out->name); - return out; - } - - save_pos = pos; /* may need it again */ - - out->type = 0; - out->name = 0; - out->asn1typename = "*error*"; - out->fullname = 0; - out->flags = 0; - out->data = 0; - out->value_id = -1; - out->type_id = -1; - - if (PDUstatec <= 0) { - if (PDUstatec > -10) { - if (asn1_verbose) - g_message(">>off=%d stack underflow, return", offset); - } - if (PDUstatec == -10) { - if (asn1_verbose) - g_message(">>off=%d stack underflow, return, no more messages", offset); - } - out->name = "*underflow*"; - out->flags |= OUT_FLAG_noname; - PDUerrcount++; - return out; - } - g_snprintf(posstr, sizeof(posstr), "==off=%d %c%d%c", offset, tag_class[cls], tag, cons?'c':'p'); - - showstack(&pos, posstr, 3); - - if (cls == ASN1_EOI) { /* end of this input sequence */ - - if (pos.type & TBL_REFERENCE_pop) { /* reference finished, return to caller */ - if (asn1_verbose) g_message(" EOI: reference pop"); - pos = POPSTATE; - } else - switch(pos.type & TBL_TYPEmask) { - case TBL_TYPEREF: - if (asn1_verbose) g_message(" EOI: pop typeref"); - pos = POPSTATE; /* remove typeref */ - break; - case TBL_CHOICE_done: - if (asn1_verbose) g_message(" EOI: mark choice"); - pos = POPSTATE; - pos.type |= TBL_CHOICE_made; /* poropagate this up the stack */ - PUSHNODE(pos); - break; - default: - break; - } - - - pos = POPSTATE; /* this is pushed back on the stack later */ - if (pos.node == NULL) { - if (asn1_verbose) g_message(" EOI, pos.node == NULL"); - out->name = "*no-name-EOI*"; - out->flags |= OUT_FLAG_noname; - PDUerrcount++; - return out; - } - - info = getinfo(pos.node); - ret = info->name; - tmp = TBLTYPE(info->type); - if (offset != pos.offset) { - if (asn1_verbose) - g_message(" *EOI %s:%s mismatch, EOIoffset=%d, stack=%d", - tmp, ret, offset, pos.offset); - while ((offset < pos.offset) && (PDUstatec > 0)) { - pos = POPSTATE; - if (asn1_verbose) - g_message(" EOI extra pop, EOIoffset=%d, stack=%d", - offset, pos.offset); - } - if (offset != pos.offset) - PDUerrcount++; /* only count if still unequal */ - } else { - if (asn1_verbose) g_message(" EOI %s:%s OK, offset=%d", tmp, ret, offset); - } - } else { - /* EOC is only present for indefinite length sequences, etc. end of sequence is always - * indicated by the synthetic EOI call. */ - if ((cls == BER_CLASS_UNI) && (tag == BER_UNI_TAG_EOC)) { /* explicit EOC never has a name */ - PUSHNODE(pos); /* restore stack */ - ret = "explicit-EOC"; - if (asn1_verbose) g_message(" return '%s', ignore", ret); - out->name = ret; - out->asn1typename = "ASN1"; - return out; - } - - /* find appropriate node for this tag */ - - if (pos.node == NULL) { - if (asn1_verbose) g_message(" pos.node == NULL"); - out->name = "*no-name*"; - out->flags |= OUT_FLAG_noname; - PDUerrcount++; - return out; - } - - /* showNode(pos.node, 3, 4); */ - - switch (pos.type & TBL_TYPEmask) { - case TBL_SEQUENCE: /* avoid finishing a choice when we have to do a sequence first */ - case TBL_SET: - break; - default: - if (pos.type & TBL_CHOICE_made) { - if (asn1_verbose) g_message(" finish choice"); - donext = 1; - } - break; - } - - info = getinfo(pos.node); - - if (pos.type & TBL_REPEAT) { /* start of a repeat */ - switch(pos.type & TBL_TYPEmask) { /* type of previous node */ - case TBL_CHOICE: - if (asn1_verbose) g_message(" repeating choice"); /* ignore repeat */ - break; - default: - if (asn1_verbose) g_message(" seqof: repeat start"); - /* decide how to continue, CHILD for next instance of sequence - * or NEXT for end of repeated sequence. - * use the tag to make a descision */ - if (asn1_verbose) g_message(" seqof: first got %c%d, found %c%d", - tag_class[cls], tag, - tag_class[info->tclass], info->tag); - if ( MATCH ) { - /* This is the start of repeating */ - PUSHNODE(pos); - ret = getname(pos.node); - if (asn1_verbose) g_message(" return for repeat '%s'", ret); - out->type = (pos.type & TBL_TYPEmask); - out->asn1typename = info->asn1typename; - out->name = ret; - out->value_id = info->value_id; - out->type_id = info->type_id; - if (ISANONYMOUS) { - if (asn1_verbose) g_message(" anonymous: dontshow"); - if (asn1_debug) - out->flags |= OUT_FLAG_dontshow; - else - out->name = empty; - } - return out; - } else { - /* find out where to go .... */ - pos2 = pos; - CHILD; /* assume sequence is repeated */ - if (pos.node) { - info = getinfo(pos.node); /* needed for MATCH to look ahead */ - if (asn1_verbose) - g_message(" seqof: child: got %c%d, found %c%d", - tag_class[cls], tag, - tag_class[info->tclass], info->tag); - } - if (pos2.type & TBL_CHOICE_repeat) { - pos = POPSTATE; - if (asn1_verbose) - g_message(" repeating a choice, %s", - getname(pos.node)); - pos.type = TBL_CHOICE_immediate; - } else { - if ( pos.node && ! MATCH) { /* no, repeat ends, */ - donext = 1; /* move on */ - if (asn1_verbose) - g_message(" seqof: no repeat, force next"); - } - /* following code will take the child again */ - pos = pos2; - } - } - break; - } - } else if (pos.type & TBL_REFERENCE_pop) { /* reference finished, return to caller */ - if (asn1_verbose) g_message(" reference pop, donext"); - pos = POPSTATE; - donext = 1; - } else if (pos.type & TBL_SEQUENCE_done) { /* Children have been processed */ - if (pos.type & TBL_SEQUENCE_choice) { - pos = POPSTATE; /* expect to find a repeat here */ - } else { - donext = 1; - if (asn1_verbose) g_message(" sequence done, donext"); - } - } - - if (pos.type & TBL_REFERENCE) { - if (asn1_verbose) g_message(" reference change ref -> pop"); - pos.type ^= (TBL_REFERENCE | TBL_REFERENCE_pop); - } - - pos.offset = offset; - - if (donext) { - if (asn1_verbose) g_message(" donext"); - NEXT; - } else { - switch(pos.type & TBL_TYPEmask) { /* type of previous node */ - case TBL_SETOF: /* ?? */ - case TBL_SEQUENCEOF: - if ((pos.type & TBL_REPEAT) == 0) { /* start repeating */ - pos.type |= TBL_REPEAT; - PUSHNODE(pos); - CHILD; - pushed++; - /* remember this is the start of a repeat cycle */ - typeflags |= TBL_REPEAT; - if (asn1_verbose) - g_message(" seqof: set repeat mark [push,child]"); - } else { - if (asn1_verbose) - g_message(" seqof: end of repeat loop [next]"); - NEXT; - } - break; - case TBL_SET: /* ?? */ - case TBL_SEQUENCE: - pos.type |= TBL_SEQUENCE_done; - PUSHNODE(pos); - CHILD; - pushed++; - if (asn1_verbose) g_message(" seq [push,child]"); - break; - case TBL_CHOICE: - /* no more choice */ - pos.type = (TBL_CHOICE_done | (pos.type & ~TBL_TYPEmask)); - PUSHNODE(pos); - - pos.type = 0; /* clear all type flags */ - if (asn1_verbose) - g_message(" choice [push], %c%d, %s", - tag_class[info->tclass], info->tag, getname(pos.node)); - pos.node = makechoice(pos.node, cls, tag); - if (pos.node == NULL) { - pos = POPSTATE; - out->flags |= OUT_FLAG_noname; - PDUerrcount++; - } - info = getinfo(pos.node); - - ret = getname(pos.node); - if (asn1_verbose) - g_message(" '%s' %c%d will be used", - ret, tag_class[info->tclass], info->tag); - break; - case TBL_CHOICE_done: - NEXT; - break; - case TBL_TYPEREF: - pos = POPSTATE; - NEXT; - if (asn1_verbose) g_message(" typeref [pop,next]"); - break; - case TBL_ENUMERATED: - case TBL_BITSTRING: - /* skip named numbers now, call to PDUenum() will retrieve a name */ - NEXT; - break; - case TBL_CHOICE_immediate: - if (asn1_verbose) g_message(" immediate choice [no next]"); - /* nothing */ - break; - default: - NEXT; - break; - } - } - - if (pos.node == NULL) { - ret = "*no-name-2*"; - if (asn1_verbose) g_message(" return '%s'", ret); - out->name = ret; - out->flags |= OUT_FLAG_noname; - PDUerrcount++; - return out; - } - ret = pos.name = getname(pos.node); - pos.type = gettype(pos.node) | (pos.type & ~TBL_TYPEmask); - info = getinfo(pos.node); - - /* pos now points to the prospective current node, go check it ********************/ - if (asn1_verbose && info) g_message(" candidate %s '%s'%s%s, %c%d", TBLTYPE(pos.type), ret, - (ISOPTIONAL)?", optional":empty, - (ISIMPLICIT)?", implicit":empty, - tag_class[info->tclass], info->tag ); - - if (ISOPTIONAL) { /* must check the tag */ - while(! MATCH) { /* check optional here again...? */ - if (asn1_verbose && info) - g_message(" got %c%d, found %c%d", tag_class[cls], tag, - tag_class[info->tclass], info->tag); - NEXT; - if (pos.node == NULL) { - ret = "------"; - if (cons) { - pos = save_pos; /* reset for next time */ - pos.type |= TBL_SEQUENCE_done; - PUSHNODE(pos); - pos.type &= ~TBL_SEQUENCE_done; - cons_handled = 1; - out->flags |= OUT_FLAG_dontshow; - if (asn1_verbose) - g_message(" end of optional list, constructed, expect value next time"); - } else { - PDUerrcount++; - out->flags |= OUT_FLAG_noname; - if (asn1_verbose) - g_message(" *end of optional list..."); - info = NULL; /* this is not valid any more... */ - } - break; /* end of list */ - } - info = getinfo(pos.node); - if (asn1_verbose) g_message(" optional, %s", getname(pos.node)); - } - if (pos.node && ! cons_handled) { - ret = pos.name = getname(pos.node); - pos.type = gettype(pos.node); - } - /* pos now refers to node with name we want, optional nodes skipped */ - } - - if (pos.type == TBL_CHOICE) { /* may be an immediate choice */ - pos2 = pos; /* save current state */ - if ( ! MATCH) { - if (! pushed) { - if (asn1_verbose) - g_message(" already pushed, skip next push"); - PUSHNODE(pos); - typeflags &= ~TBL_CHOICE_made; - } - - if (asn1_verbose && info) - g_message(" immediate choice [push], %c%d, %s", - tag_class[info->tclass], info->tag, getname(pos.node)); - if (pos.node) { - pos.node = makechoice(pos.node, cls, tag); - } - if (pos.node == NULL) { - pos = POPSTATE; - PDUerrcount++; - } - info = getinfo(pos.node); - pos.type = gettype(pos.node); - out->type = (pos.type & TBL_TYPEmask); - out->flags |= OUT_FLAG_type; - - g_snprintf(namestr, sizeof(namestr), "%s!%s", ret, getname(pos.node)); - ret = namestr; - if (asn1_verbose) - g_message(" %s:%s will be used", TBLTYPE(pos.type), ret); - if (typeflags & TBL_REPEAT) { - pos2.type |= TBL_REPEAT | TBL_REPEAT_choice; - PUSHNODE(pos2); - pos.type |= TBL_SEQUENCE_choice; - PUSHNODE(pos); - if (asn1_verbose) - g_message(" return from immediate choice [%s] '%s'", - TBLTYPE(pos.type), ret); - - out->data = pos.node; /* for access to named numbers... */ - - out->type = (pos.type & TBL_TYPEmask); - out->name = ret; - if (info) { - out->asn1typename = info->asn1typename; - out->fullname = info->fullname; - out->value_id = info->value_id; - out->type_id = info->type_id; - } - - return out; - } else { - typeflags |= TBL_CHOICE_made; - } - } else { - if (asn1_verbose) g_message(" matching choice '%s'", ret); - } - if ( ! cons ) { /* ISIMPLICIT was not OK for all */ - pos = pos2; /* reset for continuation */ - } - } - if (asn1_verbose) { - if (info) - g_message(" using: %s '%s'%s%s, %c%d", TBLTYPE(pos.type), ret, - (ISOPTIONAL)?", optional":empty, - (ISIMPLICIT)?", implicit":empty, - tag_class[info->tclass], info->tag ); - else - g_message(" using: unknown '%s'", ret); - } - - /* must follow references now */ - if (pos.type == TBL_TYPEREF && info) { - out->asn1typename = info->asn1typename; - out->type_id = info->typenum; - out->flags |= OUT_FLAG_typename; - PUSHNODE(pos); /* remember where we were */ - if (asn1_verbose) g_message(" typeref [push]"); - typeflags |= TBL_REFERENCE; - if (info->reference == 0) { /* resolved ref to universal type.... */ - /* showNode(pos.node, 3, 4); */ - pos.type = gettype(pos.node); /* the resulting type */ - info = getinfo(pos.node); - tmp = "unknown tag"; - if (info && (info->tclass == BER_CLASS_UNI) && (info->tag < 31)) { - tmp = asn1_tag[info->tag]; - pos.type = asn1_uni_type[info->tag]; /* get univsrsal type */ - } - if (asn1_verbose && info) - g_message(" indirect typeref to %s:%s, %s [%c%d]", - TBLTYPE(pos.type), info->asn1typename, tmp, - tag_class[info->tclass], info->tag ); - } else { - out->fullname = info->fullname; - donext = (ISANONYMOUS); /* refereing entity has no name ? */ - pos.node = info->reference; - pos.type = gettype(pos.node); - info = getinfo(pos.node); - if (asn1_verbose) - g_message(" typeref %s %s", TBLTYPE(pos.type), getname(pos.node)); - /* keep name from before going through the reference, unless anonymous */ - if (donext) /* refering entity has no name */ - ret = getname(pos.node); /* a better name */ - - /* handle choice here ? !!mm!! */ - - out->type = (pos.type & TBL_TYPEmask); - out->flags |= OUT_FLAG_type; - /* showNode(pos.node, 3, 4); */ - /* ret = getname(pos.node);*/ - - out->data = pos.node; - out->flags |= OUT_FLAG_data; - if (asn1_verbose) - g_message(" typeref set named number list node %p", (void *)pos.node); - - if ( ! cons) { - pos = POPSTATE; - pos.type = TBL_TYPEREF_nopop; - if (asn1_verbose) g_message(" typeref pop"); - } else if ((pos.type == TBL_ENUMERATED) || (pos.type == TBL_BITSTRING)){ - /* do not enter the named-number list */ - pos = POPSTATE; - pos.type = TBL_TYPEREF_nopop; - if (asn1_verbose) g_message(" typeref [pop]"); - } else { - typeflags |= TBL_REFERENCE; - } - } - } - - if (cons && ! cons_handled) { /* This entity is constructed, expected ? */ - switch(pos.type) { - case TBL_BOOLEAN: /* these are not expected to be constructed */ - case TBL_INTEGER: - case TBL_OCTETSTRING: - case TBL_NULL: - case TBL_OID: - case TBL_REAL: - case TBL_ENUMERATED: - case TBL_TYPEREF: - typeflags |= TBL_CONSTRUCTED; - /* this entry has no extra info, next is the same */ - out->flags |= (OUT_FLAG_dontshow | OUT_FLAG_constructed); - if (asn1_verbose) g_message(" dontshow and set constructed flag"); - break; - default: /* others, such as sequences, are expected to be constructed */ - break; - } - } - } - - if (ISANONYMOUS) { - if (asn1_verbose) g_message(" anonymous: dontshow"); - if (asn1_debug) /* this entry has no extra info, next is the same */ - out->flags |= OUT_FLAG_dontshow; - else - out->name = empty; /* show it, but no name */ - } - - if (out->name != empty) - out->name = ret; - - if ( ! (out->flags & OUT_FLAG_data)) - out->data = pos.node; /* for access to named numbers... */ - - pos.type |= typeflags; - PUSHNODE(pos); - - if ( ! (out->flags & OUT_FLAG_type)) - out->type = pos.type; - - out->type &= TBL_TYPEmask; - - if (ret == noname) { - PDUerrcount++; - out->flags |= OUT_FLAG_noname; - } - - if (info && ((out->flags & OUT_FLAG_typename) == 0)) { - out->asn1typename = info->asn1typename; - out->type_id = info->typenum; - } - - if (info && (out->value_id == -1)) { - out->value_id = info->value_id; - out->type_id = info->type_id; - } - - if ((out->fullname == 0) && info) - out->fullname = info->fullname; - - if (typeflags & TBL_CONSTRUCTED) - constructed_save = *out; - - if (asn1_verbose) - g_message(" return [%s] '%s' vid=%d, tid=%d", TBLTYPE(out->type), out->name, - out->value_id, out->type_id); - - return out; -} - -static const char * -getPDUenum(PDUprops *props, guint offset, guint cls, guint tag, guint value) -{ - GNode *list; - PDUinfo *info; - const char *ret, *name; - static char unnamed[] = "*unnamed*"; - - (void) cls; (void) tag; /* make a reference */ - - if (props->flags & OUT_FLAG_noname) - return empty; - - ret = unnamed; - list = (GNode *)props->data; - - if (list == 0) { - if (asn1_verbose) g_message("--off=%d named number list not initialized", offset); - PDUerrcount++; - return "*list-still-0*"; - } - - if ((PDUinfo *)list->data) - name = ((PDUinfo *)list->data)->name; - else - name = ret; - - for(list = g_node_first_child(list); list; list = g_node_next_sibling(list)) { - info = (PDUinfo *)list->data; - if (value == info->tag) { - ret = info->name; - break; - } - } - if (ret == unnamed) - PDUerrcount++; - - if (asn1_verbose) - g_message("--off=%d namednumber %d=%s from list %s", offset, value, ret, name); - return ret; -} - -#endif /* READSYNTAX */ - -void -proto_register_asn1(void) { - - static const enum_val_t type_recursion_opts[] = { - { "0", "0", 0 }, - { "1", "1", 1 }, - { "2", "2", 2 }, - { "3", "3", 3 }, - { "4", "4", 4 }, - { "4", "5", 5 }, - { "6", "6", 6 }, - { "7", "7", 7 }, - { "8", "8", 8 }, - { "9", "9", 9 }, - { NULL, NULL, -1}, - }; - - gint *ett[1+MAX_NEST+MAXPDU]; - - module_t *asn1_module; - int i, j; - const char *orig_ptr; - - asn1_logfile = get_tempfile_path(ASN1LOGFILE); - - current_asn1 = g_strdup(""); - asn1_filename = g_strdup(current_asn1); - - current_pduname = g_strdup("ASN1"); - asn1_pduname = g_strdup(current_pduname); - - proto_asn1 = proto_register_protocol("ASN.1 decoding", - "ASN1", pabbrev); - - ett[0] = &ett_asn1; - for (i=0, j=1; i<MAX_NEST; i++, j++) { - ett[j] = &ett_seq[i]; - ett_seq[i] = -1; - } - for(i=0; i<MAXPDU; i++, j++) { - ett[j] = &ett_pdu[i]; - ett_pdu[i] = -1; - } - - proto_register_subtree_array(ett, array_length(ett)); - - asn1_module = prefs_register_protocol(proto_asn1, - proto_reg_handoff_asn1); -#ifdef JUST_ONE_PORT - prefs_register_uint_preference(asn1_module, "tcp_port", - "ASN.1 TCP Port", - "The TCP port on which " - "ASN.1 messages will be read", - 10, &global_tcp_port_asn1); - prefs_register_uint_preference(asn1_module, "udp_port", - "ASN.1 UDP Port", - "The UDP port on which " - "ASN.1 messages will be read", - 10, &global_udp_port_asn1); - prefs_register_uint_preference(asn1_module, "sctp_port", - "ASN.1 SCTP Port", - "The SCTP port on which " - "ASN.1 messages will be read", - 10, &global_sctp_port_asn1); -#else - range_convert_str(&global_tcp_ports_asn1, "0", 65535); - range_convert_str(&global_udp_ports_asn1, "0", 65535); - range_convert_str(&global_sctp_ports_asn1, "0", 65535); - - prefs_register_range_preference(asn1_module, "tcp_ports", - "ASN.1 TCP Ports", - "The TCP ports on which " - "ASN.1 messages will be read", - &global_tcp_ports_asn1, 65535); - prefs_register_range_preference(asn1_module, "udp_ports", - "ASN.1 UDP Ports", - "The UDP ports on which " - "ASN.1 messages will be read", - &global_udp_ports_asn1, 65535); - prefs_register_range_preference(asn1_module, "sctp_ports", - "ASN.1 SCTP Ports", - "The SCTP ports on which " - "ASN.1 messages will be read", - &global_sctp_ports_asn1, 65535); -#endif /* JUST_ONE_PORT */ - - prefs_register_bool_preference(asn1_module, "desegment_messages", - "Desegment TCP", - "Desegment ASN.1 messages that span TCP segments", - &asn1_desegment); - - old_default_asn1_filename = get_datafile_path(OLD_DEFAULT_ASN1FILE); -#ifdef _WIN32 - bad_separator_old_default_asn1_filename = get_datafile_path(BAD_SEPARATOR_OLD_DEFAULT_ASN1FILE); -#endif - - orig_ptr = asn1_filename; - prefs_register_filename_preference(asn1_module, "file", - "ASN.1 type table file", - "Compiled ASN.1 description of ASN.1 types", - &asn1_filename); - /* prefs_register_string_preference just overwrite our pointer with a pointer - * to a _copy_ of our string. Free the original string. - */ - g_free((char *)orig_ptr); - - orig_ptr = asn1_pduname; - prefs_register_string_preference(asn1_module, "pdu_name", - "ASN.1 PDU name", - "Name of top level PDU", - &asn1_pduname); - g_free((char *)orig_ptr); - - prefs_register_uint_preference(asn1_module, "first_pdu_offset", - "Offset to first PDU in first tcp packet", - "Offset for non-reassembled packets, " - "wrong if this happens on other than the first packet!", - 10, &first_pdu_offset); - prefs_register_bool_preference(asn1_module, "flat", - "Show full names", - "Show full names for all values", - &asn1_full); - prefs_register_enum_preference(asn1_module, "type_recursion", - "Eliminate references to level", - "Allow this recursion level for eliminated type references", - &type_recursion_level, - type_recursion_opts, FALSE); - prefs_register_bool_preference(asn1_module, "debug", - "ASN.1 debug mode", - "Extra output useful for debugging", - &asn1_debug); -#if 0 - prefs_register_bool_preference(asn1_module, "message_win", - "Show ASN.1 tree", - "show full message description", - &asn1_message_win); -#else - prefs_register_obsolete_preference(asn1_module, "message_win"); -#endif - prefs_register_bool_preference(asn1_module, "verbose_log", - "Write very verbose log", - "log to file $TMP/" ASN1LOGFILE, - &asn1_verbose); -} - -/* The registration hand-off routing */ - -static dissector_handle_t asn1_tcp_handle; -static dissector_handle_t asn1_udp_handle; - -static void -register_tcp_port(guint32 port) -{ - if (port != 0) - dissector_add_uint("tcp.port", port, asn1_tcp_handle); -} - -static void -unregister_tcp_port(guint32 port) -{ - if (port != 0) - dissector_delete_uint("tcp.port", port, asn1_tcp_handle); -} - -static void -register_udp_port(guint32 port) -{ - if (port != 0) - dissector_add_uint("udp.port", port, asn1_udp_handle); -} - -static void -unregister_udp_port(guint32 port) -{ - if (port != 0) - dissector_delete_uint("udp.port", port, asn1_udp_handle); -} - -static void -register_sctp_port(guint32 port) -{ - if (port != 0) - dissector_add_uint("sctp.port", port, asn1_udp_handle); -} - -static void -unregister_sctp_port(guint32 port) -{ - if (port != 0) - dissector_delete_uint("sctp.port", port, asn1_udp_handle); -} - -void -proto_reg_handoff_asn1(void) { - static gboolean asn1_initialized = FALSE; -/* XXX: Note that the "saved" ports [or port ranges] will not be initialized the first time */ -/* thru pro_reg_handoff_asn1 if no PDUtree is built; So: we init with the definition. */ -#ifdef JUST_ONE_PORT - static guint tcp_port_asn1 = 0; - static guint udp_port_asn1 = 0; - static guint sctp_port_asn1 = 0; -#else - static range_t *tcp_ports_asn1 = NULL; - static range_t *udp_ports_asn1 = NULL; - static range_t *sctp_ports_asn1 = NULL; -#endif - - pcount = 0; - -#ifdef JUST_ONE_PORT - if (asn1_verbose) g_message("prefs change: tcpport=%u, udpport=%u, sctpport=%u, desegment=%d, " - "asn1file=%s, pduname=%s, first_offset=%d, debug=%d, msg_win=%d, verbose=%d", - global_tcp_port_asn1, global_udp_port_asn1, global_sctp_port_asn1, asn1_desegment, - asn1_filename, asn1_pduname, first_pdu_offset, asn1_debug, asn1_message_win, asn1_verbose); -#else - if (asn1_verbose) { - char *tcp_ports_asn1_string, *udp_ports_asn1_string, *sctp_ports_asn1_string; - tcp_ports_asn1_string = range_convert_range(global_tcp_ports_asn1); - udp_ports_asn1_string = range_convert_range(global_udp_ports_asn1); - sctp_ports_asn1_string = range_convert_range(global_sctp_ports_asn1); - g_message("prefs change: tcpports=%s, udpports=%s, sctpports=%s, desegment=%d, " - "asn1file=%s, pduname=%s, first_offset=%d, debug=%d, msg_win=%d, verbose=%d", - tcp_ports_asn1_string, udp_ports_asn1_string, sctp_ports_asn1_string, asn1_desegment, - asn1_filename, asn1_pduname, first_pdu_offset, asn1_debug, asn1_message_win, asn1_verbose); - } -#endif /* JUST_ONE_PORT */ - - if(!asn1_initialized) { - asn1_tcp_handle = new_create_dissector_handle(dissect_asn1_tcp,proto_asn1); - asn1_udp_handle = new_create_dissector_handle(dissect_asn1_udp,proto_asn1); - asn1_initialized = TRUE; - } else { /* clean up ports and their lists */ -#ifdef JUST_ONE_PORT - unregister_tcp_port(tcp_port_asn1); - unregister_udp_port(udp_port_asn1); - unregister_sctp_port(sctp_port_asn1); -#else - if (tcp_ports_asn1 != NULL) { - range_foreach(tcp_ports_asn1, unregister_tcp_port); - g_free(tcp_ports_asn1); - } - - if (udp_ports_asn1 != NULL) { - range_foreach(udp_ports_asn1, unregister_udp_port); - g_free(udp_ports_asn1); - } - - if (sctp_ports_asn1 != NULL) { - range_foreach(sctp_ports_asn1, unregister_sctp_port); - g_free(sctp_ports_asn1); - } -#endif /* JUST_ONE_PORT */ - } - - if (strcmp(asn1_filename, current_asn1) != 0) { - /* new definitions, parse the file if we have one */ - /* !!! should be postponed until we really need it !!! */ -#ifdef READSYNTAX - read_asn1_type_table(asn1_filename); -#endif /* READSYNTAX */ - g_free(current_asn1); - current_asn1 = g_strdup(asn1_filename); - } - if (!PDUtree || /* no tree built yet for PDU type */ - strcmp(asn1_pduname, current_pduname) != 0) { /* new PDU type, build tree for it */ - if (build_pdu_tree(asn1_pduname)) { - g_free(current_pduname); - current_pduname = g_strdup(asn1_pduname); - } - } -#ifdef SHOWPDU - if (asn1_message_win) { /* show what we are prepared to recognize */ - if (window) { - gtk_widget_destroy (window); - window = NULL; - } - create_message_window(); - } -#endif /* SHOWPDU */ - - /* If we now have a PDU tree, register for the port or ports we have */ - if (PDUtree) { -#ifdef JUST_ONE_PORT - tcp_port_asn1 = global_tcp_port_asn1; - udp_port_asn1 = global_udp_port_asn1; - sctp_port_asn1 = global_sctp_port_asn1; - - register_tcp_port(tcp_port_asn1); - register_udp_port(udp_port_asn1); - register_sctp_port(sctp_port_asn1); -#else - tcp_ports_asn1 = range_copy(global_tcp_ports_asn1); - udp_ports_asn1 = range_copy(global_udp_ports_asn1); - sctp_ports_asn1 = range_copy(global_sctp_ports_asn1); - - range_foreach(tcp_ports_asn1, register_tcp_port); - range_foreach(udp_ports_asn1, register_udp_port); - range_foreach(sctp_ports_asn1, register_sctp_port); -#endif /* JUST_ONE_PORT */ - } -} |