diff options
-rwxr-xr-x | ncp2222.py | 293 | ||||
-rw-r--r-- | packet-ncp-int.h | 21 | ||||
-rw-r--r-- | packet-ncp2222.inc | 52 | ||||
-rw-r--r-- | ptvcursor.c | 29 | ||||
-rw-r--r-- | ptvcursor.h | 16 |
5 files changed, 312 insertions, 99 deletions
diff --git a/ncp2222.py b/ncp2222.py index 96d913fa81..7d920630a3 100755 --- a/ncp2222.py +++ b/ncp2222.py @@ -20,7 +20,7 @@ http://developer.novell.com/ndk/doc/docui/index.htm#../ncp/ncp__enu/data/ for a badly-formatted HTML version of the same PDF. -$Id: ncp2222.py,v 1.11 2001/11/13 23:55:29 gram Exp $ +$Id: ncp2222.py,v 1.12 2002/01/10 04:44:34 gram Exp $ Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu> @@ -89,7 +89,10 @@ class UniqueCollection: return 0 - +# This list needs to be defined before the NCP types are defined, +# because the NCP types are defined in the global scope, not inside +# a function's scope. +ptvc_lists = UniqueCollection('PTVC Lists') ############################################################################## @@ -144,22 +147,34 @@ class PTVC(NamedList): def __init__(self, name, records): "Constructor" - self.list = [] - NamedList.__init__(self, name, self.list) + NamedList.__init__(self, name, []) expected_offset = None # Make a PTVCRecord object for each list in 'records' for record in records: - ptvc_rec = PTVCRecord(record) + offset = record[0] + length = record[1] + field = record[2] + + # Check if an endianness override is given + try: + endianness = record[3] + + # If no endianness was given in the record, then + # use the field's default endianness. + except IndexError: + endianness = field.Endianness() + + ptvc_rec = PTVCRecord(field, length, endianness) if expected_offset == None: - expected_offset = ptvc_rec.Offset() + expected_offset = offset elif expected_offset == -1: pass - elif expected_offset != ptvc_rec.Offset(): + elif expected_offset != offset: sys.stderr.write("Expected offset in %s to be %d\n" % (name, expected_offset)) sys.exit(1) @@ -180,33 +195,47 @@ class PTVC(NamedList): self.list.append(ptvc_rec) -class PTVCRecord: - def __init__(self, record): - "Constructor" - self.offset = record[0] - self.length = record[1] - self.field = record[2] + def __str__(self): + x = "static const ptvc_record %s[] = {\n" % (self.Name()) + for ptvc_rec in self.list: + x = x + "\t%s,\n" % (ptvc_rec) + x = x + "\t{ NULL, 0, 0, NULL }\n" + x = x + "};\n" + return x - # Small sanity check - field_length = self.field.Length() -# if type(field_length) != type(self.length): -# sys.stderr.write("Length types do not match") -# sys.exit(1) +class PTVCBitfield(PTVC): + def __init__(self, name, vars): + NamedList.__init__(self, name, []) -# if type(field_length) == type(0) and field_length > 0: -# if field_length != self.length: -# sys.stderr.write("Length %d does not match field length %d for field %s\n" % (self.length, field_length, self.field.Abbreviation())) -# sys.exit(1) + for var in vars: + ptvc_rec = PTVCRecord(var, var.Length(), var.Endianness()) + self.list.append(ptvc_rec) - # Check if an endianness override is given - try: - self.endianness = record[3] + def ETTName(self): + return "ett_%s" % (self.Name(),) + def __str__(self): + ett_name = self.ETTName() + x = "static gint %s;\n" % (ett_name,) - # If no endianness was given in the record, then - # use the field's default endianness. - except IndexError: - self.endianness = self.field.Endianness() + x = x + "static const ptvc_record ptvc_%s[] = {\n" % (self.Name()) + for ptvc_rec in self.list: + x = x + "\t%s,\n" % (ptvc_rec) + x = x + "\t{ NULL, 0, 0, NULL }\n" + x = x + "};\n" + + x = x + "static const sub_ptvc_record %s = {\n" % (self.Name(),) + x = x + "\t&%s,\n" % (ett_name,) + x = x + "\tptvc_%s,\n" % (self.Name(),) + x = x + "};\n" + return x + +class PTVCRecord: + def __init__(self, field, length, endianness): + "Constructor" + self.field = field + self.length = length + self.endianness = endianness def __cmp__(self, other): "Comparison operator" @@ -222,13 +251,14 @@ class PTVCRecord: else: return 0 - def __repr__(self): + def __str__(self): "String representation" endianness = 'FALSE' if self.endianness == LE: endianness = 'TRUE' - length = -1 + # Default the length to this value + length = "PTVC_VARIABLE_LENGTH" if type(self.length) == type(0): length = self.length @@ -237,13 +267,12 @@ class PTVCRecord: if var_length > 0: length = var_length - if length > -1: - return "{ &%s, %d, %s }" % (self.field.HFName(), - length, endianness) - else: - length = "PTVC_VARIABLE_LENGTH" - return "{ &%s, %s, %s }" % (self.field.HFName(), - length, endianness) + sub_ptvc_name = self.field.PTVCName() + if sub_ptvc_name != "NULL": + sub_ptvc_name = "&%s" % (sub_ptvc_name,) + + return "{ &%s, %s, %s, %s }" % (self.field.HFName(), + length, endianness, sub_ptvc_name) def Offset(self): return self.offset @@ -254,7 +283,6 @@ class PTVCRecord: def Field(self): return self.field - ############################################################################## class NCP: @@ -398,11 +426,19 @@ class NCP: var = record[2] variables[var] = 1 + sub_vars = var.SubVariables() + for sv in sub_vars: + variables[sv] = 1 + if self.reply_records: for record in self.reply_records: var = record[2] variables[var] = 1 + sub_vars = var.SubVariables() + for sv in sub_vars: + variables[sv] = 1 + return variables.keys() @@ -503,6 +539,12 @@ class Type: def Endianness(self): return self.endianness + def SubVariables(self): + return [] + + def PTVCName(self): + return "NULL" + class byte(Type): type = "byte" ftype = "FT_UINT8" @@ -513,9 +555,14 @@ class byte(Type): class uint8(Type): type = "uint8" ftype = "FT_UINT8" + bytes = 1 def __init__(self, abbrev, descr): Type.__init__(self, abbrev, descr, 1) +class boolean8(uint8): + type = "boolean8" + ftype = "FT_BOOLEAN" + class uint16(Type): type = "uint16" ftype = "FT_UINT16" @@ -609,6 +656,62 @@ class bytes(Type): def __init__(self, abbrev, descr, bytes): Type.__init__(self, abbrev, descr, bytes, NA) + +class bitfield(Type): + type = "bitfield" + disp = 'BASE_HEX' + + def __init__(self, vars): + var_hash = {} + for var in vars: + var_hash[var.bitmask] = var + + bitmasks = var_hash.keys() + bitmasks.sort() + bitmasks.reverse() + + ordered_vars = [] + for bitmask in bitmasks: + var = var_hash[bitmask] + ordered_vars.append(var) + + self.vars = ordered_vars + self.sub_ptvc = PTVCBitfield(self.PTVCName(), self.vars) + + def SubVariables(self): + return self.vars + + def SubVariablesPTVC(self): + return self.sub_ptvc + + def PTVCName(self): + return "ncp_%s_bitfield" % (self.abbrev,) + +class bitfield8(bitfield, uint8): + type = "bitfield8" + ftype = "FT_UINT8" + + def __init__(self, abbrev, descr, vars): + uint8.__init__(self, abbrev, descr) + bitfield.__init__(self, vars) + +class bf_uint(Type): + type = "bf_uint" + disp = 'BASE_HEX' + + def __init__(self, bitmask, abbrev, descr): + self.bitmask = bitmask + self.abbrev = abbrev + self.descr = descr + + def Mask(self): + return self.bitmask + +class bf_boolean8(bf_uint, boolean8): + type = "bf_boolean8" + ftype = "FT_BOOLEAN" + disp = "8" + #class data(Type): # type = "data" # ftype = "FT_BYTES" @@ -1136,48 +1239,11 @@ static int hf_ncp_connection_status = -1; # Print the value_string's for var in variables_used_hash.keys(): - if var.type == "val_string8" or var.type == "val_string16": + if isinstance(var, val_string): print "" print `var` - print """ -void -proto_register_ncp2222(void) -{ - - static hf_register_info hf[] = { - { &hf_ncp_func, - { "Function", "ncp.func", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, - - { &hf_ncp_length, - { "Packet Length", "ncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, - - { &hf_ncp_subfunc, - { "SubFunction", "ncp.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, - - { &hf_ncp_completion_code, - { "Completion Code", "ncp.completion_code", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, - - { &hf_ncp_connection_status, - { "Connection Status", "ncp.connection_status", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, - """ - - # Print the registration code for the hf variables - for var in variables_used_hash.keys(): - print "\t{ &%s," % (var.HFName()) - print "\t{ \"%s\", \"%s\", %s, %s, %s, 0x%x, \"\", HFILL }},\n" % \ - (var.Description(), var.DFilter(), - var.EtherealFType(), var.Display(), var.ValuesName(), - var.Mask()) - - print """\t}; - - proto_register_field_array(proto_ncp, hf, array_length(hf)); - } - """ - - # Determine which error codes are not used errors_not_used = {} # Copy the keys from the error list... @@ -1233,16 +1299,21 @@ proto_register_ncp2222(void) print "#define NCP_GROUP_%s\t%d" % (name, groups_used_hash[group]) print "\n" - # Print PTVC's + # Print PTVC's for bitfields + ett_list = [] + print "/* PTVC records for bit-fields. */" + for var in variables_used_hash.keys(): + if isinstance(var, bitfield): + sub_vars_ptvc = var.SubVariablesPTVC() + print "/* %s */" % (sub_vars_ptvc.Name()) + print sub_vars_ptvc + ett_list.append(sub_vars_ptvc.ETTName()) + + # Print PTVC's not already printed for bitfields print "/* PTVC records. These are re-used to save space. */" for ptvc in ptvc_lists.Members(): if not ptvc.Null() and not ptvc.Empty(): - print "static const ptvc_record %s[] = {" % (ptvc.Name()) - records = ptvc.Records() - for ptvc_rec in records: - print "\t%s," % (ptvc_rec) - print "\t{ NULL, 0, 0 }" - print "};\n" + print ptvc # Print error_equivalency tables print "/* Error-Equivalency Tables. These are re-used to save space. */" @@ -1320,7 +1391,7 @@ proto_register_ncp2222(void) print "};\n" - print "/* ncp funs that have no length parameter */" + print "/* ncp funcs that have no length parameter */" print "static const guint8 ncp_func_has_no_length_parameter[] = {" funcs = funcs_without_length.keys() funcs.sort() @@ -1328,8 +1399,57 @@ proto_register_ncp2222(void) print "\t0x%02x," % (func,) print "\t0" print "};\n" - + # proto_register_ncp2222() + print """ +void +proto_register_ncp2222(void) +{ + + static hf_register_info hf[] = { + { &hf_ncp_func, + { "Function", "ncp.func", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + + { &hf_ncp_length, + { "Packet Length", "ncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + + { &hf_ncp_subfunc, + { "SubFunction", "ncp.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + + { &hf_ncp_completion_code, + { "Completion Code", "ncp.completion_code", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, + + { &hf_ncp_connection_status, + { "Connection Status", "ncp.connection_status", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, + """ + + # Print the registration code for the hf variables + for var in variables_used_hash.keys(): + print "\t{ &%s," % (var.HFName()) + print "\t{ \"%s\", \"%s\", %s, %s, %s, 0x%x, \"\", HFILL }},\n" % \ + (var.Description(), var.DFilter(), + var.EtherealFType(), var.Display(), var.ValuesName(), + var.Mask()) + + print """ + }; + + static gint *ett[] = { + """ + + for ett in ett_list: + print "\t\t&%s," % (ett,) + + print """ + }; + + proto_register_field_array(proto_ncp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + """ + + + print "" print '#include "packet-ncp2222.inc"' @@ -1340,7 +1460,6 @@ def main(): packets = UniqueCollection('NCP Packet Descriptions') compcode_lists = UniqueCollection('Completion Code Lists') - ptvc_lists = UniqueCollection('PTVC Lists') define_errors() define_groups() diff --git a/packet-ncp-int.h b/packet-ncp-int.h index 57262d0734..4a4ba14a99 100644 --- a/packet-ncp-int.h +++ b/packet-ncp-int.h @@ -2,7 +2,7 @@ * Structures and functions for NetWare Core Protocol. * Gilbert Ramirez <gram@alumni.rice.edu> * - * $Id: packet-ncp-int.h,v 1.5 2002/01/05 04:12:14 gram Exp $ + * $Id: packet-ncp-int.h,v 1.6 2002/01/10 04:44:34 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -27,11 +27,20 @@ #ifndef __PACKET_NCP_INT_H__ #define __PACKET_NCP_INT_H__ -typedef struct { - int *hf_ptr; - gint length; - gboolean endianness; -} ptvc_record; +typedef struct _ptvc_record ptvc_record; +typedef struct _sub_ptvc_record sub_ptvc_record; + +struct _ptvc_record { + int *hf_ptr; + gint length; + gboolean endianness; + const sub_ptvc_record *sub_ptvc_rec; +}; + +struct _sub_ptvc_record { + gint *ett; + const ptvc_record *ptvc_rec; +}; typedef struct { guint8 error_in_packet; diff --git a/packet-ncp2222.inc b/packet-ncp2222.inc index e1cb842ec2..57a1834846 100644 --- a/packet-ncp2222.inc +++ b/packet-ncp2222.inc @@ -7,7 +7,7 @@ * * Gilbert Ramirez <gram@alumni.rice.edu> * - * $Id: packet-ncp2222.inc,v 1.7 2002/01/05 04:12:14 gram Exp $ + * $Id: packet-ncp2222.inc,v 1.8 2002/01/10 04:44:34 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -82,13 +82,59 @@ ncp_record_find(guint8 func, guint8 subfunc) return NULL; } -/* Run through the table of ptv_record's and add info to the tree */ +/* Add a value for a ptvc_record, and process the sub-ptvc_record + * that it points to. */ +static void +process_sub_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec) +{ + proto_item *item; + proto_tree *sub_tree; + const ptvc_record *sub_rec; + int current_offset; + gint ett; + ptvcursor_t *sub_ptvc; + + /* Save the current offset */ + current_offset = ptvcursor_current_offset(ptvc); + + /* Add the item */ + item = ptvcursor_add(ptvc, *rec->hf_ptr, rec->length, + rec->endianness); + + ett = *rec->sub_ptvc_rec->ett; + + /* Make a new protocol sub-tree */ + sub_tree = proto_item_add_subtree(item, ett); + + /* Make a new ptvcursor */ + sub_ptvc = ptvcursor_new(sub_tree, ptvcursor_tvbuff(ptvc), + current_offset); + + /* Use it */ + sub_rec = rec->sub_ptvc_rec->ptvc_rec; + while(sub_rec->hf_ptr != NULL) { + g_assert(!sub_rec->sub_ptvc_rec); + ptvcursor_add_no_advance(sub_ptvc, *sub_rec->hf_ptr, + sub_rec->length, sub_rec->endianness); + sub_rec++; + } + + /* Free it. */ + ptvcursor_free(sub_ptvc); +} + +/* Run through the table of ptvc_record's and add info to the tree */ static void process_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec) { while(rec->hf_ptr != NULL) { - ptvcursor_add(ptvc, *rec->hf_ptr, rec->length, + if (rec->sub_ptvc_rec) { + process_sub_ptvc_record(ptvc, rec); + } + else { + ptvcursor_add(ptvc, *rec->hf_ptr, rec->length, rec->endianness); + } rec++; } } diff --git a/ptvcursor.c b/ptvcursor.c index 6159e6085c..bce7f80dd3 100644 --- a/ptvcursor.c +++ b/ptvcursor.c @@ -3,7 +3,7 @@ * Proto Tree TVBuff cursor * Gilbert Ramirez <gram@alumni.rice.edu> * - * $Id: ptvcursor.c,v 1.4 2001/11/13 23:55:30 gram Exp $ + * $Id: ptvcursor.c,v 1.5 2002/01/10 04:44:34 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -56,10 +56,22 @@ ptvcursor_add(ptvcursor_t *ptvc, int hf, gint length, gboolean endianness) { proto_item *item; + item = ptvcursor_add_no_advance(ptvc, hf, length, endianness); + ptvc->offset += proto_item_get_len(item); + return item; +} + +/* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment + * offset, and returns proto_item* */ +proto_item* +ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length, + gboolean endianness) +{ + proto_item *item; + item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset, length, endianness); - ptvc->offset += proto_item_get_len(item); return item; } @@ -69,3 +81,16 @@ ptvcursor_free(ptvcursor_t *ptvc) { g_free(ptvc); } +/* Returns tvbuff. */ +tvbuff_t* +ptvcursor_tvbuff(ptvcursor_t* ptvc) +{ + return ptvc->tvb; +} + +/* Returns current offset. */ +gint +ptvcursor_current_offset(ptvcursor_t* ptvc) +{ + return ptvc->offset; +} diff --git a/ptvcursor.h b/ptvcursor.h index 0926ff8f06..366796954d 100644 --- a/ptvcursor.h +++ b/ptvcursor.h @@ -3,7 +3,7 @@ * Proto Tree TVBuff cursor * Gilbert Ramirez <gram@alumni.rice.edu> * - * $Id: ptvcursor.h,v 1.3 2001/11/13 23:55:30 gram Exp $ + * $Id: ptvcursor.h,v 1.4 2002/01/10 04:44:34 gram Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -48,8 +48,22 @@ ptvcursor_new(proto_tree*, tvbuff_t*, gint); proto_item* ptvcursor_add(ptvcursor_t*, int hf, gint length, gboolean endianness); + +/* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment + * offset, and returns proto_item* */ +proto_item* +ptvcursor_add_no_advance(ptvcursor_t*, int hf, gint length, gboolean endianness); + /* Frees memory for ptvcursor_t, but nothing deeper than that. */ void ptvcursor_free(ptvcursor_t*); +/* Returns tvbuff. */ +tvbuff_t* +ptvcursor_tvbuff(ptvcursor_t*); + +/* Returns current offset. */ +gint +ptvcursor_current_offset(ptvcursor_t*); + #endif /* __PTVCURSOR_H__ */ |