diff options
author | Guy Harris <guy@alum.mit.edu> | 2004-07-30 07:28:31 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2004-07-30 07:28:31 +0000 |
commit | 0ee683e0b898df467b68274bd358f108234d1191 (patch) | |
tree | 03375ed90570e52c5959490157c302fed06381c9 /plugins | |
parent | 4b9d2228e395aeee1b8c414b278e4c22baada3a5 (diff) |
From Matthijs Melchior:
add SCTP support;
allow more than one port number to be specified;
add recovery from garbled or incomplete ASN.1 messages.
svn path=/trunk/; revision=11572
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/asn1/packet-asn1.c | 531 |
1 files changed, 455 insertions, 76 deletions
diff --git a/plugins/asn1/packet-asn1.c b/plugins/asn1/packet-asn1.c index 41f01e2c8c..1628e19cec 100644 --- a/plugins/asn1/packet-asn1.c +++ b/plugins/asn1/packet-asn1.c @@ -90,7 +90,6 @@ #ifdef DISSECTOR_WITH_GUI #include <gtk/gtk.h> -#include "ui_util.h" #endif #include <ipproto.h> @@ -110,6 +109,7 @@ G_MODULE_EXPORT const gchar version[] = VERSION; #define TCP_PORT_ASN1 801 #define UDP_PORT_ASN1 801 +#define SCTP_PORT_ASN1 801 void proto_reg_handoff_asn1(void); @@ -131,10 +131,22 @@ 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; static guint tcp_port_asn1 = TCP_PORT_ASN1; static guint udp_port_asn1 = UDP_PORT_ASN1; +static guint sctp_port_asn1 = SCTP_PORT_ASN1; +#else +static char *global_tcp_ports_asn1 = NULL; +static char *global_udp_ports_asn1 = NULL; +static char *global_sctp_ports_asn1 = NULL; + +static GSList *tcp_ports_asn1 = 0; +static GSList *udp_ports_asn1 = 0; +static GSList *sctp_ports_asn1 = 0; +#endif /* JUST_ONE_PORT */ static gboolean asn1_desegment = TRUE; static char *asn1_filename = NULL; @@ -356,6 +368,38 @@ char *tbl_types_ethereal_txt[] = { /* 19 */ "FT_NONE", /* TBL_INVALID */ }; +typedef struct _PDUinfo PDUinfo; +struct _PDUinfo { + guint type; + char *name; + char *typename; + 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; /* ethereal field id for the value in this PDU */ + gint type_id; /* ethereal field id for the type of this PDU */ + hf_register_info value_hf; /* ethereal 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 */ + +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. */ @@ -563,6 +607,100 @@ g_strcmp(gconstpointer a, gconstpointer b) return strcmp(a, 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 */ +int checklength(int len, int def, int cls, int tag, char *lenstr, int strmax) +{ + int newlen = len; + + if ( ! def) { + snprintf(lenstr, strmax, "indefinite"); + return len; + } + + if (len < 0) /* negative ..... */ + newlen = 4; + + if (cls != ASN1_UNI) { /* don't know about the tags */ + if (len > 131071) + newlen = 64; + } else { + switch (tag) { + case ASN1_EOC: /* End Of Contents */ + case ASN1_NUL: /* Null */ + newlen = 0; + break; + case ASN1_BOL: /* Boolean */ + newlen = 1; + break; + case ASN1_INT: /* Integer */ + case ASN1_ENUM: /* Enumerated */ + if (len > 8) + newlen = 4; + break; + case ASN1_BTS: /* Bit String */ + if (len > 8) + newlen = 4; + break; + case ASN1_OTS: /* Octet String */ + case ASN1_NUMSTR: /* Numerical String */ + case ASN1_PRNSTR: /* Printable String */ + case ASN1_TEXSTR: /* Teletext String */ + case ASN1_VIDSTR: /* Video String */ + case ASN1_IA5STR: /* IA5 String */ + case ASN1_GRASTR: /* Graphical String */ + case ASN1_VISSTR: /* Visible String */ + case ASN1_GENSTR: /* General String */ + if (len > 65535) + newlen = 32; + break; + case ASN1_OJI: /* Object Identifier */ + case ASN1_OJD: /* Description */ + case ASN1_EXT: /* External */ + if (len > 64) + newlen = 16; + break; + case ASN1_REAL: /* Real */ + if (len >16) + newlen = 8; + break; + case ASN1_SEQ: /* Sequence */ + case ASN1_SET: /* Set */ + if (len > 65535) + newlen = 64; + break; + case ASN1_UNITIM: /* Universal Time */ + case ASN1_GENTIM: /* General Time */ + if (len > 32) + newlen = 15; + break; + + default: + if (len > 131071) + newlen = 64; + break; + } + } + + if (newlen != len) { + /* a change was needed.... */ + snprintf(lenstr, strmax, "%d(changed from %d)", newlen, len); + } else { + snprintf(lenstr, strmax, "%d", len); + } + return newlen; +} + guint decode_asn1_sequence(tvbuff_t *tvb, guint offset, guint len, proto_tree *pt, int level); void PDUreset(int count, int counr2); @@ -575,7 +713,7 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { char tagstr[BUFLS]; char headstr[BUFLL]; char offstr[BUFLS]; - char *name; + char *name, *tname; volatile guint boffset; volatile int i = 0; /* PDU counter */ proto_tree * volatile ti = 0, * volatile ti2 = 0, *asn1_tree, *tree2; @@ -625,17 +763,17 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { PDUreset(pcount, 0); /* arguments are just for debugging */ getPDUprops(&props, boffset, cls, tag, con); name = props.name; + tname = props.typename; + + len = checklength(len, def, cls, tag, lenstr, sizeof(lenstr)); if (asn1_debug) { - if (def) { - snprintf(lenstr, sizeof(lenstr), "%d", len); - } else { - strncpy(lenstr, "indefinite", sizeof(lenstr) ); - } + snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); - snprintf(headstr, sizeof(headstr), "first%s: %s %d %s, %s, %s, len=%s, off=%d, size=%d ", + 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], @@ -650,9 +788,9 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); name = ((cls == ASN1_UNI) && (tag < 32)) ? asn1_tag[tag] : tagstr; } - snprintf(headstr, sizeof(headstr), "first pdu%s: %s ", offstr, name ); + snprintf(headstr, sizeof(headstr), "first pdu%s: (%s)%s ", offstr, tname, name ); } - + /* Set the info column */ if(check_col(pinfo->cinfo, COL_INFO)){ col_add_str(pinfo->cinfo, COL_INFO, headstr ); @@ -675,6 +813,9 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { tree2 = proto_item_add_subtree(ti, ett_asn1); + proto_tree_add_item_hidden(tree2, ((PDUinfo *)PDUtree->data)->value_id, tvb, boffset, + def? (int) (offset - boffset + len) : -1, TRUE); + offset = boffset; /* the first packet */ while((i < MAXPDU) && (tvb_length_remaining(tvb, offset) > 0)) { ti2 = 0; @@ -687,16 +828,15 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { PDUreset(pcount, i+1); getPDUprops(&props, boffset, cls, tag, con); name = props.name; + tname = props.typename; if (!def) len = tvb_length_remaining(tvb, offset); + len = checklength(len, def, cls, tag, lenstr, sizeof(lenstr)); + if (asn1_debug) { - if (def) { - snprintf(lenstr, sizeof(lenstr), "%d", len); - } else { - strncpy(lenstr, "indefinite", sizeof(lenstr)); - } + snprintf(tagstr, sizeof(tagstr), "%ctag%d", tag_class[cls], tag); snprintf(headstr, sizeof(headstr), "%s, %s, %s, len=%s, off=%d, remaining=%d", @@ -710,13 +850,13 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { if (props.value_id == -1) ti2 = proto_tree_add_text(tree2, tvb, boffset, def? (int) (offset - boffset + len) : -1, - "%s: %s %d-%d %s", current_pduname, name, - pcount, i+1, headstr); + "%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 %d-%d %s ~", current_pduname, name, - pcount, i+1, headstr); + "%s: (%s)%s %d-%d %s ~", current_pduname, + tname, name, pcount, i+1, headstr); if (props.type_id != -1) proto_tree_add_item_hidden(tree2, props.type_id, tvb, boffset, @@ -731,11 +871,11 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { if (props.value_id == -1) ti2 = proto_tree_add_text(tree2, tvb, boffset, def? (int) (offset - boffset + len) : -1, - "%s: %s", current_pduname, name); + "%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 ~", current_pduname, name); + "%s: (%s)%s ~", current_pduname, tname, name); if (props.type_id != -1) proto_tree_add_item_hidden(tree2, props.type_id, tvb, boffset, def? (int) (offset - boffset + len) : -1, TRUE); @@ -749,7 +889,9 @@ dissect_asn1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { #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 */ @@ -845,11 +987,12 @@ decode_asn1_sequence(tvbuff_t *tvb, guint offset, guint tlen, proto_tree *pt, in snprintf(tagbuf, sizeof(tagbuf), "%ctag%d", tag_class[cls], tag); tagstr = tagbuf; } + + len = checklength(len, def, cls, tag, lenbuf, sizeof(lenbuf)); + if (def) { - snprintf(lenbuf, sizeof(lenbuf), "%d", len); snprintf(nnbuf, sizeof(nnbuf), "NN%d", len); } else { - strncpy(lenbuf, "indefinite", sizeof(lenbuf)); strncpy(nnbuf, "NN-", sizeof(nnbuf)); /* make sure we get an exception if we run off the end! */ len = tvb_length_remaining(tvb, offset) + 1; @@ -1600,7 +1743,7 @@ parse_tt3(tvbuff_t *tvb, guint offset, guint size, guint level, GNode *ptr) snprintf(lenbuf, sizeof(lenbuf), "%d", len); } else { strncpy(lenbuf, "indefinite", sizeof(lenbuf)); - len = tvb_length_remaining(tvb, offset);; + len = tvb_length_remaining(tvb, offset); } switch(cls) { @@ -1905,7 +2048,7 @@ get_asn1_oid(guint want_tag, guint offset) asn1_oid_value_decode(&asn1, len, &oid, &con); oid = g_realloc(oid, con + sizeof(guint)); /* prepend the length */ memmove(&oid[1], oid, con*sizeof(guint)); - oid[0] = con;; + oid[0] = con; return oid; } else ret = ASN1_ERR_LENGTH_NOT_DEFINITE; @@ -2574,7 +2717,8 @@ static char eol[] = "\r\n"; if (logf) { fputs(message, logf); fputs(eol, logf); -} + fflush(logf); /* debugging ... */ + } } void @@ -2616,7 +2760,7 @@ read_asn1_type_table(char *filename) data = g_malloc(size); if (fread(data, size, 1, f) < 1) { - report_read_failure(filename, errno); + g_warning("error reading %s, %s", filename, strerror(errno)); } fclose(f); @@ -2658,37 +2802,6 @@ read_asn1_type_table(char *filename) debug_dump_TT(); } -typedef struct _PDUinfo PDUinfo; -struct _PDUinfo { - guint type; - char *name; - char *typename; - 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; /* ethereal field id for the value in this PDU */ - gint type_id; /* ethereal field id for the type of this PDU */ - hf_register_info value_hf; /* ethereal 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 */ - -guint PDUinfo_initflags = 0; /* default flags for newly allocated PDUinfo structs */ #define CHECKTYPE(p,x) {if (((TBLTag *)(p)->data)->type != (x)) \ g_warning("**** unexpected type %s, want %s, at line %d", \ @@ -2719,6 +2832,11 @@ tbl_typeref(guint n, GNode *pdu, GNode *tree, guint fullindex) PDUinfo *p = (PDUinfo *)pdu->data, *p1; guint nvals; value_string *v; + + if (n > 40) { /* don't believe this....! ...... stop recursion ...... */ + g_warning("****tbl_typeref: n>40, return [recursion too deep] ****************"); + return; + } CHECKTYPE(tree, TBLTYPE_TypeDef); @@ -2775,9 +2893,13 @@ tbl_typeref(guint n, GNode *pdu, GNode *tree, guint fullindex) if (p->tclass==CLASSREF) { TypeRef *tr; + int i = p->basetype; /* CLASSREF....., get it defined using type of the reference */ - tr = &typeDef_names[p->tag]; + /* 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, tr->pdu); @@ -2882,7 +3004,7 @@ tbl_type(guint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, sour value_string *v; if (n > 40) { /* don't believe this....! ...... stop recursion ...... */ - g_warning("**** n>40, return [recursion too deep] ****************"); + g_warning("****tbl_type: n>40, return [recursion too deep] ****************"); return; } @@ -2892,8 +3014,8 @@ tbl_type(guint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, sour pdu1 = pdu; /* save start location for append */ while (list) { /* handle all entries */ if (asn1_verbose) - g_message("%*s+handle a %s", n*2, empty, - data_types[((TBLTag *)list->data)->type]); + g_message("%*s+handle a %s, list=%p", n*2, empty, + data_types[((TBLTag *)list->data)->type], list); if (((TBLTag *)list->data)->type == TBLTYPE_Range) { /* ignore this ..... */ list = g_node_next_sibling(list); @@ -2902,7 +3024,11 @@ tbl_type(guint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, sour break; } - if (((TBLTag *)list->data)->type != TBLTYPE_TypeRef) { + /******* 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 = g_malloc0(sizeof(PDUinfo)); @@ -2925,7 +3051,7 @@ tbl_type(guint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, sour p->name = ((TBLType *)list->data)->fieldName; ni = fullindex; - ni += sprintf(&fieldname[ni], ".%s", p->name); + ni += snprintf(&fieldname[ni], sizeof(fieldname) - ni, ".%s", p->name); p->fullname = g_strdup(fieldname); /* initialize field info */ @@ -3016,6 +3142,7 @@ tbl_type(guint n, GNode *pdu, GNode *list, guint fullindex) /* indent, pdu, sour case TBL_SETOF: case TBL_CHOICE: CHECKTYPE(q, TBLTYPE_Tag); + q = g_node_first_child(list); tbl_type(n+1, pdu, q, ni); break; @@ -3687,9 +3814,12 @@ create_message_window() FALSE, FALSE, 0); g_free(text); - sw = scrolled_window_new(NULL, NULL); + sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_IN); + 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, @@ -3978,7 +4108,7 @@ PDUreset(int count, int count2) if (PDUtree) { pos.node = PDUtree; /* root of the tree */ - pos.name = GETNAME;; + pos.name = GETNAME; pos.type = GETTYPE | TBL_REPEAT; pos.offset = 0; PUSHNODE(pos); @@ -4633,6 +4763,142 @@ getPDUenum(PDUprops *props, guint offset, guint cls, guint tag, guint value) #endif /* READSYNTAX */ +/* * * * * * * * * * * * * * * * * * * * * * * * */ +/* Routines to handle parsing a list of ports */ +/* * * * * * * * * * * * * * * * * * * * * * * * */ + +#define SKIPWHITE(_s) { while(isspace(*(_s))) { (_s)++; } } + +/* insert error text in front of spec + * with a delimeter we can recognize on next attempt + */ +void insert_error(gchar *s, int len, gchar *err, guint mark) +{ + gchar *news; + guint slen; + + news = malloc(len); + slen = strlen(s); + + mark = (mark < slen) ? mark : slen; /* clamp mark within the string */ + + snprintf(news, len, "[%s] %.*s|%s", err, (int)mark, s, s + mark); + strncpy(s, news, len); + free(news); +} + +/* parse a range of port numbers: a,b-c,d + */ +GSList *parse_port_range(gchar *s, int len) +{ + GSList *list = NULL; + guint n, count, fill, fillstart = 0; + gchar *es, *orgs; + + count = fill = 0; + + if (s == 0) return 0; + + orgs = es = s; + + SKIPWHITE(es); + if (*es == '[') { /* an old error message */ + while(*es != ']') { es++; }; + es++; + SKIPWHITE(es); + } + memmove(orgs, es, strlen(es)+1); /* remove old error message */ + + es = orgs; + + while(1) { + s = es; + SKIPWHITE(s); /* for better position of error indicator */ + n = strtoul(s, &es, 0); + if ( (s == es) || /* no character processed */ + (n > 0xffff) ) { /* port number out of range */ + /* syntax error */ + if (s == es) es++; /* err indicator after error pos */ + insert_error(orgs, len, "syntax error", es - orgs); + g_slist_free (list); + return 0; + } else { /* OK, have a port number */ + if (fill) { /* create a range of numbers */ + fill = 0; + while(++fillstart < n) { + list = g_slist_append (list, GINT_TO_POINTER (fillstart)); + count++; + if (count > 100) { + insert_error(orgs, len, "too many ports", es - orgs); + g_slist_free (list); + return 0; + } + } + } + list = g_slist_append (list, GINT_TO_POINTER (n)); + count++; + + SKIPWHITE(es); + + if (isdigit(*es)) + continue; /* a missig comma is OK */ + + switch(*es++) { + case ',': /* on to the next port number */ + continue; + case '-': /* start a port range */ + fill = 1; + fillstart = n; + continue; + case '\0': /* OK, finished */ + break; + default: /* some error */ + insert_error(orgs, len, "invalid character", es - orgs); + g_slist_free (list); + return 0; + } + break; + } + } + return list; +} + +/* build text representation of given port list + */ +void show_port_range(GSList *list, gchar *buf, int len) +{ + gchar delim = 0; + int this, last, size; + + last = -2; + size = 0; + while(list) { + this = GPOINTER_TO_INT(list->data); + if ((last+1) == this) { + delim = '-'; + last++; + } else { + if (delim == '-') { + size += snprintf(&buf[size], len - size, "%c%d", delim, last); + delim = ','; + } + if (delim) + buf[size++] = delim; + size += snprintf(&buf[size], len - size, "%d", this); + delim = ','; + last = this; + } + list = g_slist_next(list); + + } + + if (delim == '-') + size += snprintf(&buf[size], len - size, "%c%d", delim, last); +} + +/* end of port list management routines */ + + void proto_register_asn1(void) { @@ -4652,6 +4918,8 @@ proto_register_asn1(void) { static gint *ett[1+MAX_NEST+MAXPDU]; + char tmpstr[64]; + module_t *asn1_module; int i, j; @@ -4677,16 +4945,49 @@ proto_register_asn1(void) { 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 packets will be read", + "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 packets will be read", + "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 + snprintf(tmpstr, sizeof(tmpstr), "%d", TCP_PORT_ASN1); + global_tcp_ports_asn1 = strdup(tmpstr); + + snprintf(tmpstr, sizeof(tmpstr), "%d", UDP_PORT_ASN1); + global_udp_ports_asn1 = strdup(tmpstr); + + snprintf(tmpstr, sizeof(tmpstr), "%d", SCTP_PORT_ASN1); + global_sctp_ports_asn1 = strdup(tmpstr); + + prefs_register_string_preference(asn1_module, "tcp_ports", + "ASN.1 TCP Ports", + "The TCP ports on which " + "ASN.1 messages will be read", + &global_tcp_ports_asn1); + prefs_register_string_preference(asn1_module, "udp_ports", + "ASN.1 UDP Ports", + "The UDP ports on which " + "ASN.1 messages will be read", + &global_udp_ports_asn1); + prefs_register_string_preference(asn1_module, "sctp_ports", + "ASN.1 SCTP Ports", + "The SCTP ports on which " + "ASN.1 messages will be read", + &global_sctp_ports_asn1); +#endif /* JUST_ONE_PORT */ + prefs_register_bool_preference(asn1_module, "desegment_messages", "Desegment TCP", "Desegment ASN.1 messages that span TCP segments", @@ -4723,11 +5024,12 @@ proto_register_asn1(void) { "ASN.1 debug mode", "Extra output useful for debuging", &asn1_debug); - +/* prefs_register_bool_preference(asn1_module, "message_win", "Show ASN.1 tree", "show full message description", &asn1_message_win); +*/ prefs_register_bool_preference(asn1_module, "verbose_log", "Write very verbose log", "log to file $TMP/" ASN1LOGFILE, @@ -4740,27 +5042,104 @@ void proto_reg_handoff_asn1(void) { static int asn1_initialized = FALSE; static dissector_handle_t asn1_handle; + GSList *list; + gint len; pcount = 0; - if (asn1_verbose) g_message("prefs change: tcpport=%d, udpport=%d, desegnment=%d, asn1file=%s, " - "pduname=%s, first_offset=%d, debug=%d, msg_win=%d, verbose=%d", - global_tcp_port_asn1, global_udp_port_asn1, asn1_desegment, asn1_filename, - asn1_pduname, first_pdu_offset, asn1_debug, asn1_message_win, asn1_verbose); +#ifdef JUST_ONE_PORT + if (asn1_verbose) g_message("prefs change: tcpport=%d, udpport=%d, sctpport=%d, desegnment=%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) g_message("prefs change: tcpports=%s, udpports=%s, sctpports=%s, desegnment=%d, " + "asn1file=%s, pduname=%s, first_offset=%d, debug=%d, msg_win=%d, verbose=%d", + global_tcp_ports_asn1, global_udp_ports_asn1, global_sctp_ports_asn1, asn1_desegment, + asn1_filename, asn1_pduname, first_pdu_offset, asn1_debug, asn1_message_win, asn1_verbose); +#endif /* JUST_ONE_PORT */ if(!asn1_initialized) { asn1_handle = create_dissector_handle(dissect_asn1,proto_asn1); asn1_initialized = TRUE; - } else { + } else { /* clean up ports and their lists */ +#ifdef JUST_ONE_PORT dissector_delete("tcp.port", tcp_port_asn1, asn1_handle); dissector_delete("udp.port", udp_port_asn1, asn1_handle); + dissector_delete("sctp.port", sctp_port_asn1, asn1_handle); +#else + list = tcp_ports_asn1; + while (list) { + dissector_delete("tcp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } + g_slist_free(tcp_ports_asn1); + + list = udp_ports_asn1; + while (list) { + dissector_delete("udp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } + g_slist_free(udp_ports_asn1); + + list = sctp_ports_asn1; + while (list) { + dissector_delete("sctp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } + g_slist_free(sctp_ports_asn1); +#endif /* JUST_ONE_PORT */ } +#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; + dissector_add("tcp.port", global_tcp_port_asn1, asn1_handle); dissector_add("udp.port", global_udp_port_asn1, asn1_handle); + dissector_add("sctp.port", global_sctp_port_asn1, asn1_handle); +#else + len = strlen(global_tcp_ports_asn1) + 32; /* extra for possible error message */ + global_tcp_ports_asn1 = realloc(global_tcp_ports_asn1, len); + tcp_ports_asn1 = parse_port_range(global_tcp_ports_asn1, len); + if (tcp_ports_asn1) /* no error, normalize presentation */ + show_port_range(tcp_ports_asn1, global_tcp_ports_asn1, len); + else + g_message("tcp_ports: %s\n", global_tcp_ports_asn1); + + len = strlen(global_udp_ports_asn1) + 32; /* extra for possible error message */ + global_udp_ports_asn1 = realloc(global_udp_ports_asn1, len); + udp_ports_asn1 = parse_port_range(global_udp_ports_asn1, len); + if (udp_ports_asn1) /* no error, normalize presentation */ + show_port_range(udp_ports_asn1, global_udp_ports_asn1, len); + else + g_message("udp_ports: %s\n", global_udp_ports_asn1); + + len = strlen(global_sctp_ports_asn1) + 32; /* extra for possible error message */ + global_sctp_ports_asn1 = realloc(global_sctp_ports_asn1, len); + sctp_ports_asn1 = parse_port_range(global_sctp_ports_asn1, len); + if (sctp_ports_asn1) /* no error, normalize presentation */ + show_port_range(sctp_ports_asn1, global_sctp_ports_asn1, len); + else + g_message("sctp_ports: %s\n", global_sctp_ports_asn1); + + list = tcp_ports_asn1; + while (list) { + dissector_add("tcp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } + list = udp_ports_asn1; + while (list) { + dissector_add("udp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } + list = sctp_ports_asn1; + while (list) { + dissector_add("sctp.port", GPOINTER_TO_INT(list->data), asn1_handle); + list = g_slist_next(list); + } +#endif /* JUST_ONE_PORT */ if ( g_strcmp(asn1_filename, current_asn1) != 0) { /* new defintions, parse it */ /* !!! should be postponed until we really need it !!! */ |