summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/dcerpc
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/dcerpc')
-rw-r--r--epan/dissectors/dcerpc/CMakeLists.txt70
-rw-r--r--epan/dissectors/dcerpc/budb/budb.cnf4
-rw-r--r--epan/dissectors/dcerpc/budb/budb.idl695
-rw-r--r--epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.c72
-rw-r--r--epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.h20
-rw-r--r--epan/dissectors/dcerpc/butc/butc.cnf6
-rw-r--r--epan/dissectors/dcerpc/butc/butc.idl487
-rw-r--r--epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.c71
-rw-r--r--epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.h19
-rw-r--r--epan/dissectors/dcerpc/idl2wrs.c3521
10 files changed, 4965 insertions, 0 deletions
diff --git a/epan/dissectors/dcerpc/CMakeLists.txt b/epan/dissectors/dcerpc/CMakeLists.txt
new file mode 100644
index 00000000..5f98ac18
--- /dev/null
+++ b/epan/dissectors/dcerpc/CMakeLists.txt
@@ -0,0 +1,70 @@
+# CMakeLists.txt
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 1998 Gerald Combs
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+
+set(PIDL_DISSECTOR_NAMES
+ budb
+ butc
+)
+
+foreach(PROTOCOL_NAME IN LISTS PIDL_DISSECTOR_NAMES)
+ # Use a stamp file instead of OUTPUT to packet-dcerpc-X.c to
+ # avoid removing the .c file on clean.
+ add_custom_command(
+ OUTPUT packet-dcerpc-${PROTOCOL_NAME}-stamp
+ COMMAND
+ idl2wrs ${PROTOCOL_NAME}
+ COMMAND
+ "${CMAKE_COMMAND}" -E copy_if_different
+ packet-dcerpc-${PROTOCOL_NAME}.c
+ "${CMAKE_CURRENT_SOURCE_DIR}/../packet-dcerpc-${PROTOCOL_NAME}.c"
+ COMMAND
+ "${CMAKE_COMMAND}" -E copy_if_different
+ packet-dcerpc-${PROTOCOL_NAME}.h
+ "${CMAKE_CURRENT_SOURCE_DIR}/../packet-dcerpc-${PROTOCOL_NAME}.h"
+ COMMAND
+ "${CMAKE_COMMAND}" -E touch
+ "${CMAKE_CURRENT_BINARY_DIR}/packet-dcerpc-${PROTOCOL_NAME}-stamp"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${PROTOCOL_NAME}"
+ DEPENDS
+ "${CMAKE_SOURCE_DIR}/tools/pidl/pidl"
+ ${PROTOCOL_NAME}/${PROTOCOL_NAME}.idl
+ ${PROTOCOL_NAME}/${PROTOCOL_NAME}.cnf
+ ${PROTOCOL_NAME}/packet-dcerpc-${PROTOCOL_NAME}-template.h
+ ${PROTOCOL_NAME}/packet-dcerpc-${PROTOCOL_NAME}-template.c
+ VERBATIM
+ )
+ add_custom_target(generate_dissector-dcerpc-${PROTOCOL_NAME}
+ DEPENDS packet-dcerpc-${PROTOCOL_NAME}-stamp
+ )
+ set_target_properties(generate_dissector-dcerpc-${PROTOCOL_NAME}
+ PROPERTIES FOLDER "Generated Dissectors/PIDL"
+ )
+ list(APPEND PIDL_DISSECTOR_TARGETS
+ generate_dissector-dcerpc-${PROTOCOL_NAME}
+ )
+endforeach()
+
+# TODO should probably just merge this into pidl-dissectors
+add_custom_target(idl2wrs-dissectors ALL DEPENDS ${PIDL_DISSECTOR_TARGETS})
+set_target_properties(idl2wrs-dissectors
+ PROPERTIES FOLDER "Generated Dissectors/PIDL"
+)
+
+#
+# Editor modelines - https://www.wireshark.org/tools/modelines.html
+#
+# Local variables:
+# c-basic-offset: 4
+# tab-width: 4
+# indent-tabs-mode: t
+# End:
+#
+# vi: set shiftwidth=4 tabstop=4 noexpandtab:
+# :indentSize=4:tabSize=4:noTabs=false:
+#
diff --git a/epan/dissectors/dcerpc/budb/budb.cnf b/epan/dissectors/dcerpc/budb/budb.cnf
new file mode 100644
index 00000000..c99e8f47
--- /dev/null
+++ b/epan/dissectors/dcerpc/budb/budb.cnf
@@ -0,0 +1,4 @@
+#
+#
+TYPE budbNameString_t budb_dissect_NameString_t FT_STRING BASE_NONE 0 NULL 4
+# \ No newline at end of file
diff --git a/epan/dissectors/dcerpc/budb/budb.idl b/epan/dissectors/dcerpc/budb/budb.idl
new file mode 100644
index 00000000..40e46778
--- /dev/null
+++ b/epan/dissectors/dcerpc/budb/budb.idl
@@ -0,0 +1,695 @@
+/* this idl is from the LGPL irelease of dce/dfs from the open group.
+ it has been significantly modified to pass through idl2wrs
+ original copyright follows:
+ */
+/*
+ * @OSF_COPYRIGHT@
+ * COPYRIGHT NOTICE
+ * Copyright (c) 1990, 1996 Open Software Foundation, Inc.
+ * ALL RIGHTS RESERVED (DCE). See the file named COPYRIGHT.DCE for
+ * the full copyright text.
+ */
+/*
+ * HISTORY
+ * $Log: budb.idl,v $
+ * Revision 1.1.13.1 1996/10/02 16:59:37 damon
+ * Newest DFS from Transarc
+ * [1996/10/01 18:04:09 damon]
+ *
+ * $EndLog$
+ */
+/* Copyright (C) 1996, 1990 Transarc Corporation - All rights reserved */
+
+/* $Header: /u0/rcs_trees/dce/rcs/file/bakserver/budb.idl,v 1.1.13.1 1996/10/02 16:59:37 damon Exp $ */
+
+[
+uuid("eb814e2a-0099-11ca-8678-02608c2ea96e"),
+version(4.0),
+/*provider_version(2)*/
+pointer_default(ptr)
+] interface budb /* The backup database interface */
+{
+
+/*import "dcedfs/common_data.idl";*/
+
+
+/*
+ * Constants for bakserver data structures
+ */
+const long BU_MAXNAMELEN = 128; /* names of objects: volumes */
+const long BU_MAXTAPELEN = 256; /* names of objects: tapes */
+const long BU_MAXHOSTLEN = 128; /* names of server machines */
+const long BU_MAXTOKENLEN = 16; /* identifiers */
+const long BU_MAXUNAMELEN = 256; /* length of user name */
+const long BU_MAXCELLLEN = 256; /* length of a cell name */
+const long BU_MAXINAMELEN = 128; /* length of user name */
+const long BU_MAXPATHLEN = 256; /* length of schedule path name */
+const long BU_MAXGENNAMELEN = 512; /* length of generic name */
+const long BU_MAXVOLCOUNT = 64; /* max volumes in volume array */
+
+/* first some constants */
+const long BUDB_MAJORVERSION = 1; /* version number of this interface */
+const long BUDB_PROVIDER_VERSION = 2; /* provider version of this interface */
+
+/* types of text blocks */
+const long TB_DUMPSCHEDULE = 0;
+const long TB_VOLUMESET = 1;
+const long TB_TAPEHOSTS = 2;
+
+/* TB_NUM must be <= TB_MAX */
+const long TB_NUM = 3; /* no. of block types */
+const long TB_MAX = 6; /* unused items are spares */
+
+/* dump flag bit definitions */
+const long BUDB_DUMP_INCOMPLETE = 1<<0; /* some vols omitted due to errors */
+const long BUDB_DUMP_TAPEERROR = 1<<1; /* tape error during dump */
+const long BUDB_DUMP_INPROGRESS = 1<<2;
+const long BUDB_DUMP_ABORTED = 1<<3; /* aborted: prob. dump unavailable */
+
+/* tape flag bit definitions */
+const long BUDB_TAPE_TAPEERROR = 1<<0;
+const long BUDB_TAPE_DELETED = 1<<1;
+const long BUDB_TAPE_BEINGWRITTEN = 1<<2;/* writing in progress */
+const long BUDB_TAPE_ABORTED = 1<<3;/* aborted: tape probably garbaged */
+const long BUDB_TAPE_STAGED = 1<<4;/* not yet on permanent media */
+const long BUDB_TAPE_WRITTEN = 1<<5;/* tape writing finished: all OK */
+
+/* volume flag bit definitions */
+const long BUDB_VOL_TAPEERROR = 1<<0;/* tape problem during dump */
+const long BUDB_VOL_FILEERROR = 1<<1;/* voldump aborted during dump */
+const long BUDB_VOL_BEINGWRITTEN = 1<<2;
+const long BUDB_VOL_FIRSTFRAG = 1<<3;/* same as low bits of tape position */
+const long BUDB_VOL_LASTFRAG = 1<<4;
+const long BUDB_VOL_ABORTED = 1<<5;/* aborted: vol probably undumped */
+
+const long BUDB_OP_NAMES = 0x7;
+const long BUDB_OP_STARTS = 0x7<<3;
+const long BUDB_OP_ENDS = 0x7<<6;
+const long BUDB_OP_TIMES = 0x3<<9;
+const long BUDB_OP_MISC = 0xff<<16;
+
+/* The flag bits specify which entries are being requested. They are search
+ operations that use name, start, and end to select a subset of entries to be
+ returned. Not all combinations are meaning full or supported. */
+/* defining the meaning of "name" */
+const long BUDB_OP_DUMPNAME = 1<<0;
+const long BUDB_OP_VOLUMENAME = 2<<0;
+const long BUDB_OP_TAPENAME = 3<<0;
+
+/* "start" is a time value */
+const long BUDB_OP_STARTTIME = 1<<3;
+/* "end" delimits a range of times */
+const long BUDB_OP_RANGE = 1<<6;
+/* "end" specifies number of earlier entries */
+const long BUDB_OP_NPREVIOUS = 2<<6;
+/* "end" specifies number of later entries */
+const long BUDB_OP_NFOLLOWING = 3<<6;
+/* start is dump id (name may be null), return all entries */
+const long BUDB_OP_DUMPID = 2<<3;
+/* defining the which type of time values */
+const long BUDB_OP_CLONETIME = 1<<9; /* use clone time */
+const long BUDB_OP_DUMPTIME = 2<<9; /* use dump time (create?) */
+const long BUDB_OP_INCTIME = 3<<9; /* use inc time */
+
+/* Miscellaneous bits: */
+/* for volumes: return only first fragment */
+const long BUDB_OP_FIRSTFRAG = 1<<16;
+/* maximum number of elements returnable by these functions */
+const long BUDB_MAX_RETURN_LIST = 1000;
+const long BUDB_MAX_CHAR_LIST = 1024;
+
+/* maximum number of volumes accepted by these functions */
+const long BUDB_MAX_VOL_COUNT = 64;
+
+const long BUDB_TEXT_COMPLETE = 1;
+/* structure type values for database dump and restore operations */
+/* XXX -- these names need a better prefix */
+const long SD_DBHEADER = 1;
+const long SD_DUMP = 2;
+const long SD_TAPE = 3;
+const long SD_VOLUME = 4;
+const long SD_TEXT_DUMPSCHEDULE = 5;
+const long SD_TEXT_VOLUMESET = 6;
+const long SD_TEXT_TAPEHOSTS = 7;
+const long SD_END = 8;
+
+/*
+ * Now, the bakserver data structure type definitions
+ */
+
+/*
+ * A generic string type for backup
+ */
+
+typedef struct { /* identifies a principal identity */
+ budbNameString_t name;
+ budbNameString_t instance;
+ budbNameString_t cell;
+ budbNameString_t spare;
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_principal;
+
+typedef struct { /* describes a tape sequence */
+ int32 id; /* id of tapeSet, assigned by budb */
+ budbNameString_t tapeServer;
+ budbNameString_t format;
+ /* Sequence numbers are assumed to be relatively small and relatively
+ * densely packed in 0<=seq<maxTapes. */
+ int32 maxTapes; /* maximum number of tapes in seq. */
+ int32 a; int32 b; /* linear transforms for tape */
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_tapeSet;
+
+typedef struct { /* describes a dump */
+ uint32 id; /* identifier of this dump */
+ uint32 parent; /* parent dump */
+ int32 level; /* level in multi-level incremental */
+ int32 flags; /* various bits described below */
+ budbNameString_t volumeSetName;
+ budbNameString_t dumpPath;
+ budbNameString_t name;
+ time_t created; /* creation date of dump */
+ time_t incTime; /* time for incrementals, 0 => full */
+ int32 nVolumes; /* number of vol fragments in dump */
+ budb_tapeSet tapes; /* tapes containing dump */
+ budb_principal dumper; /* name of person running doing dump */
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_dumpEntry;
+
+typedef struct { /* describes a tape */
+ budbNameString_t name;
+ uint32 flags; /* various bits described below */
+ time_t written; /* date tape was last written */
+ time_t expires; /* expiration date */
+ uint32 nMBytes; /* number of Mbytes on tape */
+ uint32 nBytes; /* Megabyte remainder */
+ int32 nFiles; /* number of files on tape */
+ int32 nVolumes; /* number of vol fragments on tape */
+ int32 seq; /* sequence in tape set */
+ int32 tapeid; /* unique tape id */
+ int32 useCount; /* # of times used */
+ int32 mediaType; /* what kind of tape */
+ uint32 dump; /* dump on tape (set) */
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_tapeEntry;
+
+typedef struct { /* describes a fragment of a volume */
+
+ /* volume information */
+ budbNameString_t name;
+ uint32 flags; /* various bits described below */
+ udlong id; /* volume uid */
+ budbNameString_t server;
+ int32 partition; /* partition on server */
+ int32 nFrags; /* number fragments in whole volume */
+ /* per fragment */
+ int32 position; /* position on tape */
+ time_t clone; /* time volume was cloned for dump */
+ time_t incTime; /* NOT USED */
+ int32 startByte; /* first byte of volume in this frag */
+ int32 nBytes; /* number of bytes in this frag */
+ int32 seq; /* sequence of frag in volume */
+ /* additional location info */
+ uint32 dump; /* dump volume is part of */
+ budbNameString_t tape;
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_volumeEntry;
+
+/* To facilitate returning large large amounts of data some of these procedures
+ expect to receive a pointer to an array of structures. The majorVersion
+ number implicitly specifies the size of each array element. The progress
+ parameter is set to the number of elements actually returned. Since the
+ caller may have limited buffer space, provisions are made to get the data in
+ a series of calls. The index parameter specifies starting point of a
+ continued operation: for the first call it will be zero, a negative number
+ will produce an error. If more elements are available on a subsequent call
+ nextIndex is set to the index of the next element. Otherwise nextIndex is
+ set to a negative number. */
+
+typedef struct {
+ uint32 budb_volumeList_len;
+ [size_is(budb_volumeList_len),ptr] budb_volumeEntry budb_volumeList_val[*];
+} budb_volumeList;
+
+typedef struct {
+ uint32 budb_dumpList_len;
+ [size_is(budb_dumpList_len),ptr] budb_dumpEntry budb_dumpList_val[*];
+} budb_dumpList;
+
+typedef struct {
+ uint32 budb_tapeList_len;
+ [size_is(budb_tapeList_len),ptr] budb_tapeEntry budb_tapeList_val[*];
+} budb_tapeList;
+
+typedef struct {
+ uint32 charListT_len;
+ [length_is(charListT_len)] uint8 charListT_val[1024];
+} charListT;
+
+/* database header - minimal version that is dumped. Allows values of important
+ * state variables to be saved/restored.
+ */
+/* XXX -- this name needs a budb_ prefix */
+typedef struct {
+ int32 dbversion; /* database version */
+ int32 created; /* creation time */
+ budbNameString_t cell;
+ uint32 lastDumpId; /* last dump id generated */
+ uint32 lastInstanceId; /* last lock instance */
+ uint32 lastTapeId; /* last tape id */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} DbHeader;
+
+/* The structure is a version of budb_volumeEntry with the layout of the volume
+ * id hyper explicitly specified. */
+
+typedef struct { /* describes a volume in a database dump */
+ /* volume information */
+ budbNameString_t name;
+ uint32 flags; /* various bits described below */
+ udlong id;
+ budbNameString_t server;
+ int32 partition; /* partition on server */
+ int32 nFrags; /* number fragments in whole volume */
+ /* per fragment */
+ int32 position; /* position on tape */
+ time_t clone; /* time volume was cloned for dump */
+ time_t incTime; /* NOT USED */
+ int32 startByte; /* first byte of volume in this frag */
+ int32 nBytes; /* number of bytes in this frag */
+ int32 seq; /* sequence of frag in volume */
+ /* additional location info */
+ uint32 dump; /* dump volume is part of */
+ budbNameString_t tape;
+ uint32 spare1; /* nominal spares */
+ uint32 spare2; /* nominal spares */
+ uint32 spare3; /* nominal spares */
+ uint32 spare4; /* nominal spares */
+} budb_dbVolume;
+
+/* Header prefix for each structure in the byte stream returned by BUDB_DumpDB.
+ * The type field identifies the structure that follows --
+ * SD_DBHEADER -- DbHeader
+ * SD_DUMP -- budb_dumpEntry
+ * SD_TAPE -- budb_tapeEntry
+ * SD_VOLUME -- budb_dbVolume_t
+ * SD_TEXT_DUMPSCHEDULE -- ???
+ * SD_TEXT_VOLUMESET -- ???
+ * SD_TEXT_TAPEHOSTS -- ???
+ * SD_END -- end of database */
+
+/* XXX -- this name needs a budb_ prefix */
+typedef struct {
+ int32 type; /* structure type */
+ int32 structversion; /* version of following structure */
+ int32 size; /* bytes in following structure */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} structDumpHeader;
+
+/*
+ * Bakserver interface procedure declarations
+ */
+/* This adds a volume to particular dump and tape. It is called after the
+ volume has been written to tape and allows the database to attach the volume
+ information to the structures for its containing dump and tape. The
+ description of the volume must be specified on input, including the vldb
+ information, incTime, and a description of the volume's fragmention. */
+/*
+ * provider_version(1)
+ */
+WERROR AddVolume
+(
+ [ref, in] budb_volumeEntry *vol
+);
+
+/* This creates a new dump. On input the dumpEntry specifies the containing
+ tape set, the dump name, the incTime, and the identity of the dumper. On
+ output the dump's id is set. */
+
+/*
+ * provider_version(1)
+ */
+WERROR CreateDump
+(
+ [ref, in, out] budb_dumpEntry *dump
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR DeleteDump
+(
+ [in] uint32 id
+);
+
+/* This is called, probably infrequently, to remove a tape from the database.
+ The assumption is that sometimes tapes are retired or lost and this routine
+ facilitates cleaning up the database. */
+
+/*
+ * provider_version(1)
+ */
+WERROR DeleteTape
+(
+ [ref, in] budb_tapeEntry *tape
+); /* tape info */
+
+/*
+ * provider_version(1)
+ */
+WERROR DeleteVDP
+(
+ [in] budbNameString_t *dsname, /* dump name */
+ [in] budbNameString_t *dumpPath, /* dump node path name */
+ [in] int32 curDumpId /* current dump Id for exclusion */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR FindClone
+(
+ [in] int32 dumpID, /* id of dump to start with */
+ [in] budbNameString_t *volName, /* clone time required for volName */
+ [ref, out] uint32 *clonetime, /* returned clone time */
+ [ref, out] uint32 *cloneSpare
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR FindDump
+(
+ [in] budbNameString_t *volName, /* name of volume to look for */
+ [in] uint32 beforeDate, /* must be before this date */
+ [in] uint32 dateSpare,
+ [ref, out] budb_dumpEntry *deptr /* returned dump information */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR FindLatestDump
+(
+ [in] budbNameString_t *vsname, /* name of volumeset to look for */
+ [in] budbNameString_t *dname, /* name of dump to look for */
+ [ref, out] budb_dumpEntry *dumpentry
+);
+
+/* This notifies the database that the dump is finished. Some status bits can
+ be specified on input. */
+
+/*
+ * provider_version(1)
+ */
+WERROR FinishDump
+(
+ [ref, in, out] budb_dumpEntry *dump
+);
+
+/* This is called when writing to the tape has been completed. The tapeEntry
+ includes some status bits on input, such as whether any tape errors were
+ encountered. Volumes and dumps on the tape are marked as safe if the status
+ was good. */
+
+/*
+ * provider_version(1)
+ */
+WERROR FinishTape
+(
+ [ref, in] budb_tapeEntry *tape
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetDumps
+(
+ [in] int32 majorVersion, /* version of interface structures */
+ [in] int32 flags, /* search & select controls */
+ [in] budbNameString_t *name, /* s&s parameters */
+ [in] int32 start,
+ [in] int32 end,
+ [in] int32 index, /* start index of returned entries */
+ [ref, out] int32 *nextIndex, /* output index for next call */
+ [ref, out] int32 *dbUpdate, /* time of last db change */
+ [out] budb_dumpList **dumps /* structure list */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetTapes
+(
+ [in] int32 majorVersion, /* version of interface structures */
+ [in] int32 flags, /* search & select controls */
+ [in] budbNameString_t *name, /* s&s parameters */
+ [in] int32 start,
+ [in] int32 end, /* reserved: MBZ */
+ [in] int32 index, /* start index of returned entries */
+ [ref, out] int32 *nextIndex, /* output index for next call */
+ [ref, out] int32 *dbUpdate, /* time of last db change */
+ [out] budb_tapeList **tapes /* structure list */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetVolumes
+(
+ [in] int32 majorVersion, /* version of interface structures */
+ [in] int32 flags, /* search & select controls */
+ [in] budbNameString_t *name, /* - parameters for search */
+ [in] int32 start, /* - usage depends which BUDP_OP_* */
+ [in] int32 end, /* - bits are set */
+ [in] int32 index, /* start index of returned entries */
+ [ref, out] int32 *nextIndex, /* output index for next call */
+ [ref, out] int32 *dbUpdate, /* time of last db change */
+ [out] budb_volumeList **volumes /* structure list */
+);
+
+/* Called when a tape is about to be used. It deletes from the database the
+ previous contents of the tape, if any, and marks it as "being written". The
+ tapeEntry identifies the tape name and dump on input. The updated entry is
+ returned on output. */
+
+/*
+ * provider_version(1)
+ */
+WERROR UseTape
+(
+ [ref, in] budb_tapeEntry *tape, /* tape info */
+ [ref, out] int32 *new /* set if tape is new */
+);
+
+/* text file management calls - alphabetic */
+
+/*
+ * provider_version(1)
+ */
+WERROR GetText
+(
+ [in] int32 lockHandle,
+ [in] int32 textType, /* which type of text */
+ [in] int32 maxLength,
+ [in] int32 offset,
+ [ref, out] int32 *nextOffset,
+ [ref, out] charListT *charListPtr
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetTextVersion
+(
+ [in] int32 textType,
+ [ref, out] int32 *tversion
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR SaveText
+(
+ [in] int32 lockHandle, /* which type of text */
+ [in] int32 textType, /* which type of text */
+ [in] int32 offset, /* offset into text block */
+ [in] int32 flags,
+ [ref, in] charListT *charListPtr
+);
+
+/* Lock management interface routines */
+
+/*
+ * provider_version(1)
+ */
+WERROR FreeAllLocks
+(
+ [in] uint32 instanceId /* identifies user */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR FreeLock
+(
+ [in] uint32 lockHandle /* identifies lock */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetInstanceId
+(
+ [ref, out] uint32 *instanceId /* instance of a user */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR GetLock
+(
+ [in] uint32 instanceId, /* instance of user */
+ [in] int32 lockName, /* which lock */
+ [in] int32 expiration, /* # secs after which lock
+ released */
+ [ref, out] uint32 *lockHandle /* returned lock handle */
+);
+
+/* database dump and reconstruction */
+
+/*
+ * provider_version(1)
+ */
+WERROR DbVerify
+(
+ [ref, out] int32 *status, /* 0=ok, 1=inconsistent */
+ [ref, out] int32 *orphans, /* orphan block count */
+ [ref, out] int32 *host /* host where checks done */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR DumpDB
+(
+ [in] int32 maxLength, /* max transfer size */
+ [ref, out] int32 *flags, /* status flags */
+ [ref, out] charListT *charListPtr /* byte stream out */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR RestoreDbHeader
+(
+ [ref, in] DbHeader *header /* restore database header */
+);
+
+/* Debug and test interface routines
+ *
+ * These routines provide a low level interface that can be used to test out
+ * the backup database.
+ */
+
+/*
+ * provider_version(1)
+ */
+WERROR T_GetVersion
+(
+ [ref, out] int32 *majorVersion
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR T_DumpHashTable
+(
+ [in] int32 type,
+ [in] budbNameString_t *filename
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR T_DumpDatabase
+(
+ [in] budbNameString_t *filename
+);
+
+/*
+ * provider_version(1)
+ */
+
+
+typedef struct {
+
+ uuid_t interface_uuid; /* i/f UUID of the supported i/f */
+ uint16 vers_major; /* i/f major version number */
+ uint16 vers_minor; /* i/f minor version number */
+ uint32 vers_provider; /* provider_version number */
+
+ uint32 spare0; /* some long spares */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+ uint32 spare5;
+ uint32 spare6;
+ uint32 spare7;
+ uint32 spare8;
+ uint32 spare9;
+
+ uint8 spareText[50]; /* spare text */
+
+} dfs_interfaceDescription;
+
+typedef struct {
+
+ uint32 dfs_interfaceList_len;
+ [length_is(dfs_interfaceList_len)] dfs_interfaceDescription dfs_interfaceList_val;
+
+} dfs_interfaceList;
+
+
+WERROR GetServerInterfaces
+(
+ [ref, in, out] dfs_interfaceList *serverInterfacesP
+);
+
+/*
+ * Same as AddVolume, except takes array of volumes instead of
+ * single volume
+ */
+
+/*
+ * provider_version(2)
+ */
+
+WERROR AddVolumes
+(
+ [in] uint32 cnt,
+ [in, size_is(cnt)] budb_volumeEntry vol[]
+);
+}
diff --git a/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.c b/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.c
new file mode 100644
index 00000000..88cd3b21
--- /dev/null
+++ b/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.c
@@ -0,0 +1,72 @@
+/* DO NOT EDIT
+ * This dissector is autogenerated
+ */
+
+/* packet-dcerpc-budb.c
+ * Routines for BUDB packet disassembly
+ * ronnie sahlberg 2005
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-windows-common.h"
+#include "packet-dcerpc-budb.h"
+
+void proto_register_budb(void);
+void proto_reg_handoff_budb(void);
+
+static int proto_budb = -1;
+ETH_HF
+
+ETH_ETT
+
+static int
+budb_dissect_NameString_t(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)
+{
+ offset=dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep, 1, hf_index, FALSE, NULL);
+ return offset;
+}
+
+ETH_CODE
+
+void
+proto_register_budb(void)
+{
+ static hf_register_info hf[] = {
+
+ETH_HFARR
+ };
+
+ static gint *ett[] = {
+ETH_ETTARR
+ };
+
+ proto_budb = proto_register_protocol(
+ "DCE/DFS BUDB",
+ "BUDB", "budb");
+ proto_register_field_array(proto_budb, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+static dcerpc_sub_dissector function_dissectors[] = {
+ETH_FT
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_reg_handoff_budb(void)
+{
+ETH_HANDOFF
+}
diff --git a/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.h b/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.h
new file mode 100644
index 00000000..4359a8d3
--- /dev/null
+++ b/epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.h
@@ -0,0 +1,20 @@
+/* DO NOT EDIT
+ * This dissector is autogenerated
+ * ronnie sahlberg 2005
+ */
+/* packet-dcerpc-budb.h
+ * Routines for BUDB packet disassembly
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef __PACKET_DCERPC_BUDB_H
+#define __PACKET_DCERPC_BUDB_H
+
+ETH_HDR
+
+#endif /* packet-dcerpc-budb.h */
diff --git a/epan/dissectors/dcerpc/butc/butc.cnf b/epan/dissectors/dcerpc/butc/butc.cnf
new file mode 100644
index 00000000..5c67a396
--- /dev/null
+++ b/epan/dissectors/dcerpc/butc/butc.cnf
@@ -0,0 +1,6 @@
+#
+#
+TYPE butcNameString_t butc_dissect_NameString_t FT_STRING BASE_NONE 0 NULL 4
+#
+UNION_TAG_SIZE tc_statusInfoSwitch 4
+#
diff --git a/epan/dissectors/dcerpc/butc/butc.idl b/epan/dissectors/dcerpc/butc/butc.idl
new file mode 100644
index 00000000..dfdb28f5
--- /dev/null
+++ b/epan/dissectors/dcerpc/butc/butc.idl
@@ -0,0 +1,487 @@
+/* This idl file originally came from the DCE project but has been
+ significantly refactored to pass through the idl2wrs idl-lite
+ compiler.
+
+ DCE has been released as LGPL, hats off to TheOpenGroup
+
+
+ The original copyright of the IDL file follos below:
+*/
+
+/*
+ * @OSF_COPYRIGHT@
+ * COPYRIGHT NOTICE
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994 Open Software Foundation, Inc.
+ * ALL RIGHTS RESERVED (DCE). See the file named COPYRIGHT.DCE for
+ * the full copyright text.
+ */
+/*
+ * HISTORY
+ * $Log: butc.idl,v $
+ * Revision 1.1.41.1 1996/10/02 17:05:24 damon
+ * Newest DFS from Transarc
+ * [1996/10/01 18:05:16 damon]
+ *
+ * Revision 1.1.35.2 1994/06/09 13:52:46 annie
+ * fixed copyright in src/file
+ * [1994/06/08 21:26:40 annie]
+ *
+ * Revision 1.1.35.1 1994/02/04 20:06:46 devsrc
+ * Merged from 1.0.3a to 1.1
+ * [1994/02/04 15:06:52 devsrc]
+ *
+ * Revision 1.1.33.1 1993/12/07 17:13:22 jaffe
+ * 1.0.3a update from Transarc
+ * [1993/12/03 12:59:50 jaffe]
+ *
+ * Revision 1.1.2.5 1993/01/18 20:47:57 cjd
+ * embedded copyright notice
+ * [1993/01/18 17:33:13 cjd]
+ *
+ * Revision 1.1.2.4 1993/01/13 15:53:56 shl
+ * Transarc delta: cfe-ot6054-genl-and-i18n-spares 1.1
+ * Selected comments:
+ * Add spares to several RPC structures, with two goals:
+ * - general future usage
+ * - allow for at least some internationalization designs
+ * The only tricky part of this work is that the on-the-wire representation for
+ * directory contents is expanded.
+ * Transarc delta: vijay-ot6381-correct-handling-of-device-queue-lock 1.4
+ * Selected comments:
+ *
+ * The aim of this delta is to get bak restore to succeed. The problems in restore
+ * were some spurious thread exceptions and assertions that made bak dump core.
+ * Upon investigation it turned out that there were some locking problems in
+ * backup and butc. The delta cleans up locking in backup and butc.
+ * The delta is not ready for export. Much more needs to be done to get all the
+ * locking issues right. This is just a checkpoint.
+ * Second set of changes to get locking issues in order. This time the changes
+ * are mostly in bakserver. The changes introduced are
+ * 1. Establish a global lock so that two RPCs do not interfere with each other.
+ * This was introduced because there are some global data structures in
+ * backup that might get affected. These global structures now have
+ * individual locks to serialize changes. The global lock in temporary, and
+ * will go away once we have serialized all accesses to all global data
+ * structures.
+ * 2. Disable cancels in bakserver RPCs. Care is taken to not disable cancels in
+ * operations that can be cancelled. There is some more work that needs to be
+ * done in this area.
+ * 3. Accesses to the database are controlled by memoryDB.lock. The accesses are
+ * by means of dbread and dbwrite. The hash tables too are protected by this
+ * mechanism.
+ * 4. Changes to the backup database dump code to simplify the dump operation. In
+ * particular, the Unix pipe mechanism is used to synchronize reader and
+ * writer without need for condition variables.
+ * 5. Get rid of any pthread_mutex and pthread_cond operations. Use afslk and
+ * afsos routines instead.
+ * 6. Continue the work described by the previous revision of the delta in bak
+ * and butc. This should be it for changes in bak and butc.
+ * Fix compilation problems on the RIOS.
+ * This is hopefully the final revision of this delta. The fixes here are
+ * 1. Changes to the bakserver and butc RPC interfaces.
+ * The RPCs that handle variable size arrays now use conformant arrays.
+ * This avoids allocating lots of memory on the client thread stack which
+ * was the cause of the exceptions in restoreft. The server allocates
+ * memory which is freed by the server stub on the way out. The client thread
+ * frees the memory allocated by the client stub.
+ * 2. get database dump and restore to handle status correctly.
+ * 3. Get the locking hierarchy right in bakserver, bak and butc.
+ * 4. Other minor nits.
+ * There is still a problem with scantape -dbadd that has to be addressed. With
+ * this delta, all backup commands should work when used in a straightforward
+ * manner. Some error cases are still not handled properly though. Subsequent
+ * deltas would fix those.
+ * Transarc delta: vijay-ot6604-butc-add-spares 1.1
+ * Selected comments:
+ *
+ * Add spares to butc structures wherever necessary.
+ * [1993/01/12 18:39:46 shl]
+ *
+ * Revision 1.1.2.3 1992/11/24 15:42:03 bolinger
+ * Change include file install directory from .../afs to .../dcedfs.
+ * [1992/11/22 16:10:10 bolinger]
+ *
+ * Revision 1.1.2.2 1992/08/31 18:37:26 jaffe
+ * Transarc delta: cfe-ot4029-portable-rpc-data-types 1.2
+ * Selected comments:
+ * If ``long'' could possibly mean ``64 bits'' any time soon, we need to keep
+ * our RPC interfaces from breaking.
+ * More of the same. Forgot a couple of .idl files, and needed to change
+ * a couple of procedure signatures to match.
+ * forgot this one too
+ * [1992/08/28 20:59:01 jaffe]
+ *
+ * Revision 1.1 1992/01/19 02:57:17 devrcs
+ * Initial revision
+ *
+ * $EndLog$
+ */
+
+
+/* changed to the following types:
+ time_t 4 bytes, aligned at 4 bytes holding a unix time_t
+ uint32 4 byte unsigned integer
+ int32 4 byte signed integer
+
+ renamed error_status_t WERROR a 32bit integer ststus code
+ removed handle_t it has no wire encoding
+
+ rewrote the unions so that idl2wrs can parse them
+
+ changed all varying strings to the type butcNameString_t which is
+ implemented in the template
+
+ changed the structs so they are compatible with idl2wrs
+
+ afshyper is called udlong in idl2wrs 8 bytes, aligned at 4 bytes
+
+ added afsnetaddr definition
+
+*/
+[
+uuid("1d193c08-000b-11ca-ba1d-02608c2ea96e"),
+version(4.0),
+/*provider_version(1)*/
+pointer_default(ptr) /* All pointers are by default Full pointers */
+] interface butc
+{
+
+const long TC_DEFAULT_STACK_SIZE = 153600; /* stack size for tc threads */
+const long TC_MAXGENNAMELEN = 512; /* length of generic name */
+const long TC_MAXDUMPPATH = 256; /* dump path names*/
+const long TC_MAXNAMELEN = 128; /* name length */
+const long TC_MAXFORMATLEN = 100; /*size of the format statement */
+const long TC_MAXHOSTLEN = 128; /*for server/machine names */
+const long TC_MAXTAPELEN = 256; /*max tape name allowed */
+const long TC_STAT_DONE = 1; /* all done */
+const long TC_STAT_OPRWAIT = 2; /* waiting for user interaction */
+const long TC_STAT_DUMP = 4; /* true if dump, false if restore */
+const long TC_STAT_ABORTED = 8; /* the operation was aborted */
+const long TC_STAT_ERROR = 16; /* error ocuured in the operation */
+const long TSK_STAT_FIRST = 0x1; /* get id of first task */
+const long TSK_STAT_END = 0x2; /* no more tasks */
+const long TSK_STAT_NOTFOUND= 0x4; /* couldn't find task id requested */
+
+const long TCOP_NONE = 0;
+const long TCOP_READLABEL = 1;
+const long TCOP_LABELTAPE = 2;
+const long TCOP_DUMP = 3;
+const long TCOP_RESTORE = 4;
+const long TCOP_SCANTAPE = 5;
+const long TCOP_SAVEDB = 6;
+const long TCOP_RESTOREDB = 7;
+const long TCOP_STATUS = 8;
+const long TCOP_SPARE = 9;
+
+
+/* restore flags */
+typedef [bitmap32bit] bitmap {
+ TC_RESTORE_CREATE = 0x00000001, /* create new volume; fail if there */
+ TC_RESTORE_INCR = 0x00000002 /* incremental, must already exist */
+} butc_Restore_flags;
+
+
+/*typedef [string] byte butcNameString_t[TC_MAXGENNAMELEN];*/
+
+typedef struct {
+ uint16 type;
+ uint8 data[14];
+} afsNetAddr;
+
+typedef struct {
+ udlong vid; /* volume to dump */
+ butcNameString_t name; /* name of volume whose clone is to
+ be dumped*/
+ int32 partition; /* partition at which to find the volume */
+ time_t date; /* date from which to do the dump */
+ time_t cloneDate; /* clone date of the volume */
+ afsNetAddr hostAddr; /* file server for this volume */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tc_dumpDesc;
+
+typedef struct {
+ int32 frag; /* fragment number, 1..n */
+ butcNameString_t tapeName; /*name of tape frag is on*/
+ int32 position; /*start position of frag on tape */
+ udlong origVid; /* original volume id */
+ udlong vid; /* 0 means allocate new volid */
+ int32 partition; /* where to restore the volume */
+ butc_Restore_flags flags; /* flags */
+ afsNetAddr hostAddr; /* file server to restore volume to */
+ uint32 realDumpId; /* dump id associated with this tape */
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+ butcNameString_t oldName; /* volume whose clone is to
+ be dumped */
+ butcNameString_t newName; /* new name suffix */
+} tc_restoreDesc;
+
+/*describes the current status of a dump */
+typedef struct {
+ int32 dumpID; /* dump id we're returning */
+ int32 bytesDumped; /* bytes dumped so far */
+ udlong volumeBeingDumped; /* guess ?*/
+ int32 numVolErrs; /* # of volumes that had errors */
+ int32 flags; /* true if the dump is done */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tc_dumpStat;
+
+/*identifier for a tape */
+typedef struct {
+ uint32 size; /* size of tape in bytes */
+ uint32 size_ext;
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+ uint32 nameLen; /* length of tape name */
+ butcNameString_t name;
+} tc_tapeLabel;
+
+
+typedef struct { /* describes a tape sequence */
+ int32 id; /* unique id of tapeSet,
+ assigned by budb */
+ butcNameString_t tapeServer; /* name of server where
+ this tape is */
+ butcNameString_t format; /* using printf to make
+ tape name */
+ int32 maxTapes; /* maximum number of tapes in seq. */
+ int32 a; int32 b; /* linear transforms for tape */
+ int32 expDate; /* expiration date */
+ int32 expType; /* absolute or relative expiration */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tc_tapeSet;
+
+/* identifies the tape coordinator interface */
+typedef struct {
+ int32 tcVersion; /* for the interface & this struct */
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tc_tcInfo;
+
+typedef struct {
+ uint32 tc_restoreArray_len; /* count of restore descriptors */
+ [size_is(tc_restoreArray_len),ptr] tc_restoreDesc tc_restoreArray_val[*];
+} tc_restoreArray;
+
+typedef struct {
+ uint32 tc_dumpArray_len; /* count of dump descriptors */
+ [size_is(tc_dumpArray_len),ptr] tc_dumpDesc tc_dumpArray[*];
+} tc_dumpArray;
+
+/* interface structure */
+typedef struct {
+ butcNameString_t dumpPath; /* full dump path */
+ butcNameString_t volumeSetName; /* volume set name */
+ butcNameString_t dumpName; /* volset.dump */
+ tc_tapeSet tapeSet;
+ int32 parentDumpId;
+ int32 dumpLevel;
+ uint32 spare1;
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tc_dumpInterface;
+
+/* The status structure returns information about the task running in butc.
+ It contains a union that returns the info about the particular operation
+ currently running in butc.
+*/
+typedef struct {
+ uint32 nKBytes; /* bytes xferred */
+ butcNameString_t volumeName; /* current volume (if any) */
+ int32 volsFailed; /* # operation failures */
+ uint32 spare1;
+} tc_statusInfoSwitchVol;
+typedef struct {
+ tc_tapeLabel tapeLabel;
+ uint32 spare1;
+} tc_statusInfoSwitchLabel;
+
+/* 32bit tag */
+typedef union {
+ [case(TCOP_NONE)] uint32 none;
+ [case(TCOP_DUMP)] tc_statusInfoSwitchVol vol;
+ [case(TCOP_RESTORE)] tc_statusInfoSwitchVol vol;
+ [case(TCOP_LABELTAPE)] tc_statusInfoSwitchLabel label;
+ [case(TCOP_READLABEL)] tc_statusInfoSwitchLabel label;
+ [case(TCOP_SCANTAPE)] uint32 spare1;
+ [case(TCOP_STATUS)] uint32 spare2;
+ [case(TCOP_SAVEDB)] uint32 spare3;
+ [case(TCOP_RESTOREDB)] uint32 spare4;
+ [case(TCOP_SPARE)] uint32 spare5;
+} tc_statusInfoSwitch;
+
+typedef struct {
+ /* general info */
+ butcNameString_t taskName; /* task name */
+ uint32 flags; /* as above */
+ time_t lastPolled; /* last successful poll */
+
+ /* op specific info */
+ tc_statusInfoSwitch info;
+ uint32 taskId;
+
+
+ /* nominal spares */
+ uint32 spare2;
+ uint32 spare3;
+ uint32 spare4;
+} tciStatusS;
+
+/*
+ * Procedure Definitions
+ */
+
+/* Start a dump, given a dump set name, a tape set name and the volumes to
+ * dump.
+ */
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_PerformDump
+(
+ [ref, in] tc_dumpInterface *tcdiPtr,
+ [ref, in] tc_dumpArray *dumps,
+ [ref, out] int32 *dumpID
+);
+
+/* Start a restore, given a dump set name, a tape set name and the volumes to
+ * dump.
+ */
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_PerformRestore
+(
+ [in] butcNameString_t *dumpSetName,
+ [ref, in] tc_restoreArray *restores,
+ [ref, out] int32 *dumpID
+);
+
+/* abort a dump */
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_AbortDump
+(
+ [in] int32 dumpID
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_LabelTape
+(
+ [ref, in] tc_tapeLabel *label,
+ [ref, out] uint32 *taskId
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_ReadLabel
+(
+ [ref, out] uint32 *taskId /* unused */
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_ScanDumps
+(
+ [in] int32 addDbFlag,
+ [ref, out] uint32 *taskId
+);
+
+/* For returning information about the butc interface.
+ * Currently this is just the version number
+ */
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_TCInfo
+(
+ [ref, out] tc_tcInfo *tciptr
+);
+
+/* for database dump/restores */
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_SaveDb
+(
+ [ref, out] uint32 *taskId
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_RestoreDb
+(
+ [ref, out] uint32 *taskId
+);
+
+/* new status management */
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_EndStatus
+(
+ [in] uint32 taskId
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_GetStatus
+(
+ [in] uint32 taskId,
+ [ref, out] tciStatusS *statusPtr
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_RequestAbort
+(
+ [in] uint32 taskId
+);
+
+/*
+ * provider_version(1)
+ */
+WERROR BUTC_ScanStatus
+(
+ [ref, in, out] uint32 *taskId,
+ [ref, out] tciStatusS *statusPtr,
+ [ref, in, out] uint32 *flags
+);
+
+
+/*
+ * provider_version(1)
+ */
+
+WERROR BUTC_GetServerInterfaces
+(
+/* [ref, in, out] dfs_interfaceList *serverInterfacesP*/
+);
+
+}
diff --git a/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.c b/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.c
new file mode 100644
index 00000000..5d012d36
--- /dev/null
+++ b/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.c
@@ -0,0 +1,71 @@
+/* DO NOT EDIT
+ * This dissector is autogenerated
+ */
+
+/* packet-dcerpc-butc.c
+ * Routines for BUTC packet disassembly
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-windows-common.h"
+#include "packet-dcerpc-butc.h"
+
+void proto_register_butc(void);
+void proto_reg_handoff_butc(void);
+
+static int proto_butc = -1;
+ETH_HF
+
+ETH_ETT
+
+static int
+butc_dissect_NameString_t(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)
+{
+ offset=dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep, 1, hf_index, FALSE, NULL);
+ return offset;
+}
+
+ETH_CODE
+
+void
+proto_register_butc(void)
+{
+ static hf_register_info hf[] = {
+
+ETH_HFARR
+ };
+
+ static gint *ett[] = {
+ETH_ETTARR
+ };
+
+ proto_butc = proto_register_protocol(
+ "DCE/RPC BUTC",
+ "BUTC", "butc");
+ proto_register_field_array(proto_butc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+static dcerpc_sub_dissector function_dissectors[] = {
+ETH_FT
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_reg_handoff_butc(void)
+{
+ETH_HANDOFF
+}
diff --git a/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.h b/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.h
new file mode 100644
index 00000000..16832841
--- /dev/null
+++ b/epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.h
@@ -0,0 +1,19 @@
+/* DO NOT EDIT
+ * This dissector is autogenerated
+ */
+/* packet-dcerpc-butc.h
+ * Routines for BUTC packet disassembly
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef __PACKET_DCERPC_BUTC_H
+#define __PACKET_DCERPC_BUTC_H
+
+ETH_HDR
+
+#endif /* packet-dcerpc-butc.h */
diff --git a/epan/dissectors/dcerpc/idl2wrs.c b/epan/dissectors/dcerpc/idl2wrs.c
new file mode 100644
index 00000000..054a62d1
--- /dev/null
+++ b/epan/dissectors/dcerpc/idl2wrs.c
@@ -0,0 +1,3521 @@
+/* idl2wrs.c
+ * DCE RPC IDL to Wireshark dissector compiler
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+TODO
+ check that every cnf defined type,hffield,rename,... has been referenced
+ at least once and if not, abort with an error
+
+ need to distinguish between NTTIME (absolute time) and relative time
+
+ prune_xxx should only act inside of '[' ']'
+
+ add support for bool8,16,32,64 with tfs strings
+
+ add the remaining array type (uvarray)
+
+ add code to verify that union tag length is correct
+*/
+/* List of built in types :
+ WERROR A 32 bit integer holding a DCE/NT status code.
+
+ uint8 A 8 bit integer
+ int8
+
+ uint16 A 16 bit integer
+ int16
+
+ uint32 A 32 bit integer
+ int32
+
+ uint64 A 64 bit integer
+
+ udlong A 64 bit integer aligned on 4 byte boundary
+ dlong
+
+ time_t A 32 bit integer holding a unix style time_t
+
+ NTTIME_hyper A 64 bit integer representing a NTTIME
+ NTTIME_1sec
+
+ unistr A conformant and varying unicode string
+
+ ascstr A conformant and varying ascii string
+
+
+ SID A SID structure.
+
+ uuid_t A 16 byte FT_GUID blob.
+ GUID
+
+
+ policy_handle
+ bool8
+ uuid_t
+ policy_handle
+ NTTIME
+*/
+
+/* All field dissectors that call a normal type
+ (i.e. not a pointer, not an array)
+ has a local variable guint param declared which is passed on to the
+ type dissector.
+ The default value is 0 but the PARAM_VALUE conformance tag can be used to
+ change it.
+ This is only meaningful if the called type dissector actually does anything
+ with this parameter.
+*/
+
+#define _GNU_SOURCE
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <wsutil/strtoi.h>
+
+#undef IDL2WRS_DEBUG
+
+#define DISSECTORNAME_MAXLEN 256
+
+#define BASE_BUFFER_SIZE 256
+
+static FILE *tfh, *eth_code, *eth_hdr, *eth_hf, *eth_hfarr, *eth_ett, *eth_ettarr, *eth_ft, *eth_handoff;
+static char *uuid=NULL;
+static char *version=NULL;
+static const char *pointer_default=NULL;
+static char *ifname=NULL;
+static char hf_status[BASE_BUFFER_SIZE];
+static int lineno,linepos;
+static char line[4 * BASE_BUFFER_SIZE];
+
+static void FPRINTF(FILE *fh, const char *format, ...)
+{
+ va_list args;
+
+#ifdef IDL2WRS_DEBUG
+ va_start(args, format);
+ vfprintf (stderr, format, args);
+ va_end(args);
+#endif
+ if (fh) {
+ va_start(args, format);
+ vfprintf (fh, format, args);
+ va_end(args);
+ }
+}
+
+typedef struct _pointer_item_t {
+ struct _pointer_item_t *next;
+ const char *type;
+} pointer_item_t;
+
+#define BI_CASE 0x00000001
+#define BI_CASE_DEFAULT 0x00000002
+#define BI_IN 0x00000004
+#define BI_OUT 0x00000008
+#define BI_SIZE_IS 0x00000010
+#define BI_LENGTH_IS 0x00000020
+#define BI_POINTER 0x00000040
+#define BI_BITMAP8 0x00000100
+#define BI_BITMAP32 0x00000200
+#define BI_SWITCH_TYPE 0x00000400
+typedef struct _bracket_item_t {
+ unsigned int flags;
+ const char *case_name;
+ pointer_item_t *pointer_list;
+ int union_tag_size;
+} bracket_item_t;
+
+typedef struct _no_emit_item_t {
+ struct _no_emit_item_t *next;
+ char *name;
+} no_emit_item_t;
+static no_emit_item_t *no_emit_list=NULL;
+
+typedef struct _hf_rename_item_t {
+ struct _hf_rename_item_t *next;
+ int refcount; /* number of times this rename has been referenced */
+ char *old_name;
+ char *new_name;
+} hf_rename_item_t;
+static hf_rename_item_t *hf_rename_list=NULL;
+
+typedef struct _enum_list_t {
+ struct _enum_list_t *next;
+ char *name;
+ int val;
+} enum_list_t;
+
+typedef struct _token_item_t {
+ struct _token_item_t *next;
+ char *str;
+} token_item_t;
+static token_item_t *token_list=NULL;
+static token_item_t *last_token_item=NULL;
+
+typedef struct _type_item_t {
+ struct _type_item_t *next;
+ char *name;
+ char *dissector;
+ char *ft_type;
+ char *base_type;
+ char *mask;
+ char *vals;
+ int alignment;
+} type_item_t;
+static type_item_t *type_list=NULL;
+
+typedef struct _union_tag_size_item_t {
+ struct _union_tag_size_item_t *next;
+ char *name;
+ int size;
+} union_tag_size_item_t;
+static union_tag_size_item_t *union_tag_size_list=NULL;
+
+typedef struct _hf_field_item_t {
+ struct _hf_field_item_t *next;
+ char *name;
+ char *ft_type;
+} hf_field_item_t;
+static hf_field_item_t *hf_field_list=NULL;
+
+typedef struct _dissector_param_value_t {
+ struct _dissector_param_value_t *next;
+ char *name;
+ char *value;
+} dissector_param_value_t;
+static dissector_param_value_t *dissector_param_list=NULL;
+
+static type_item_t *find_type(char *name);
+static int Exit(int code);
+
+static void
+register_dissector_param_value(const char *name, const char *value)
+{
+ dissector_param_value_t *dpv;
+ dpv=g_new0(dissector_param_value_t, 1);
+ if (!dpv) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ dpv->next=dissector_param_list;
+ dissector_param_list=dpv;
+ dpv->name=g_strdup(name);
+ dpv->value=g_strdup(value);
+}
+
+static const char *
+find_dissector_param_value(char *name)
+{
+ dissector_param_value_t *dpv;
+ for(dpv=dissector_param_list;dpv;dpv=dpv->next){
+ if(!g_strcmp0(name,dpv->name)){
+ return dpv->value;
+ }
+ }
+ return "0";
+}
+
+static pointer_item_t *
+prepend_pointer_list(pointer_item_t *ptrs, int num_pointers)
+{
+ pointer_item_t *pi;
+
+ pi=ptrs;
+ while(pi){
+ if(num_pointers)num_pointers--;
+ pi=pi->next;
+ }
+ if(!pi)pi=ptrs;
+ while(num_pointers--){
+ pi=g_new0(pointer_item_t, 1);
+ if (!pi) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ pi->next=ptrs;
+ pi->type=pointer_default;
+ ptrs=pi;
+ }
+ ptrs=pi;
+
+ return ptrs;
+}
+
+static const char *
+ptr_to_define(const char *pointer_type)
+{
+ if(!g_strcmp0(pointer_type, "unique")){
+ return "NDR_POINTER_UNIQUE";
+ } else if(!g_strcmp0(pointer_type, "ref")){
+ return "NDR_POINTER_REF";
+ } else if(!g_strcmp0(pointer_type, "ptr")){
+ return "NDR_POINTER_PTR";
+ }
+
+ FPRINTF(stderr, "prt_to_define, weirdo pointer :%s\n", pointer_type);
+ exit(10);
+}
+
+static int
+get_union_tag_size(char *name)
+{
+ union_tag_size_item_t *utsi;
+ for(utsi=union_tag_size_list;utsi;utsi=utsi->next){
+ if(!g_strcmp0(name, utsi->name)){
+ return utsi->size;
+ }
+ }
+ FPRINTF(stderr, "ERROR: size of tag for union:%s is not known\n", name);
+ FPRINTF(stderr, " use the UNION_TAG_SIZE directive to specify it in teh conformance file\n");
+ exit(10);
+}
+
+
+/* this function will add an entry to the hf_rename list */
+static void
+register_hf_rename(const char *old_name, const char *new_name)
+{
+ hf_rename_item_t *new_item;
+ new_item=g_new0(hf_rename_item_t, 1);
+ if (!new_item) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ new_item->next=hf_rename_list;
+ hf_rename_list=new_item;
+ new_item->refcount=0;
+ new_item->old_name=g_strdup(old_name);
+ new_item->new_name=g_strdup(new_name);
+}
+
+/* this function checks that all hf_rename fields have actually been referenced
+ if not out conformance file is stale
+*/
+static void
+check_hf_rename_refcount(void)
+{
+ hf_rename_item_t *hri;
+
+ /* don't generate code for renamed hf fields just return the new name*/
+ for(hri=hf_rename_list;hri;hri=hri->next){
+ if(!hri->refcount){
+ FPRINTF(stderr, "ERROR: the hf_rename field:%s was never referenced. it is likely the conformance file is stale\n", hri->old_name);
+ exit(10);
+ }
+ }
+}
+
+static hf_field_item_t *
+find_hf_field(char *name)
+{
+ hf_field_item_t *hfi;
+
+ for(hfi=hf_field_list;hfi;hfi=hfi->next){
+ if(!g_strcmp0(hfi->name, name)){
+ break;
+ }
+ }
+ if (!hfi) {
+ FPRINTF(stderr, "find_hf_field: unknown hf_field:%s\n",name);
+ Exit(10);
+ }
+
+ return hfi;
+}
+
+
+/* this function will create the code required for a hf field.
+ it MIGHT rename the field so a user MUST use the name returned
+ from this function.
+ for fields that are to be renamed no code is generated
+*/
+static const char *
+register_hf_field(const char *hf_name, const char *title, const char *filter_name, const char *ft_type, const char *base_type, const char *valsstring, const char *mask, const char *blurb)
+{
+ hf_field_item_t *hfi;
+ hf_rename_item_t *hri;
+
+ /* don't generate code for renamed hf fields just return the new name*/
+ for(hri=hf_rename_list;hri;hri=hri->next){
+ if(!strncmp(hf_name, hri->old_name, strlen(hf_name))){
+ hfi=find_hf_field(hri->new_name);
+ if(g_strcmp0(ft_type, hfi->ft_type)){
+ FPRINTF(stderr, "register_hf_field: hf_fields %s and %s have different types %s %s\n",hf_name,hfi->name,ft_type,hfi->ft_type);
+ Exit(10);
+ }
+ hri->refcount++;
+ return hri->new_name;
+ }
+ }
+
+ hfi=g_new0(hf_field_item_t, 1);
+ if (!hfi) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ hfi->next=hf_field_list;
+ hf_field_list=hfi;
+ hfi->name=g_strdup(hf_name);
+ hfi->ft_type=g_strdup(ft_type);
+
+ FPRINTF(eth_hf, "static int %s = -1;\n", hf_name);
+ FPRINTF(eth_hfarr, " { &%s,\n", hf_name);
+ FPRINTF(eth_hfarr, " { \"%s\", \"%s\", %s, %s,\n", title, filter_name, ft_type, base_type);
+ FPRINTF(eth_hfarr, " %s, %s,\n", valsstring, mask);
+ if (strlen(blurb) > 0)
+ FPRINTF(eth_hfarr, " \"%s\", HFILL }},\n", blurb);
+ else
+ FPRINTF(eth_hfarr, " NULL, HFILL }},\n");
+ FPRINTF(eth_hfarr, "\n");
+
+ return hf_name;
+}
+
+/* this function will parse the no emit list and decide whether code should
+ be generated for this dissector or if we should only register the type.
+*/
+static int
+check_if_to_emit(char *name)
+{
+ no_emit_item_t *nel;
+
+ for(nel=no_emit_list;nel;nel=nel->next){
+ if(!g_strcmp0(name, nel->name)){
+ FPRINTF(NULL, "SKIPPED emitting of %s\n",name);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#if 0
+static void
+prune_keywords(char *name)
+{
+ token_item_t *ti;
+
+ for(ti=token_list;ti;ti=ti->next){
+ if(!ti->next){
+ break;
+ }
+ if(!g_strcmp0(ti->next->str, name)){
+ if(!g_strcmp0(ti->next->next->str, ",")){
+ ti->next=ti->next->next->next;
+ } else {
+ ti->next=ti->next->next;
+ }
+ }
+ }
+}
+#endif
+
+static void
+rename_tokens(const char *old_name, const char *new_name)
+{
+ token_item_t *ti;
+
+ for(ti=token_list;ti;ti=ti->next){
+ if(!g_strcmp0(ti->str, old_name)){
+ ti->str=g_strdup(new_name);
+ }
+ }
+}
+
+static void
+prune_keyword_parameters(const char *name)
+{
+ token_item_t *ti, *tmpti;
+
+ for(ti=token_list;ti;ti=ti->next){
+ if(!g_strcmp0(ti->str, name)){
+ if(!g_strcmp0(ti->next->str, "(")){
+ tmpti=ti;
+ while(1){
+ if(!g_strcmp0(tmpti->str, ")")){
+ ti->next=tmpti->next;
+ break;
+ }
+ tmpti=tmpti->next;
+ }
+ }
+ }
+ }
+}
+
+/* this function will parse a bracket item
+ [ ... ]
+ it will return the token of the next item following the ']'
+*/
+static token_item_t *
+parsebrackets(token_item_t *ti, bracket_item_t **bracket){
+ bracket_item_t *br;
+ type_item_t *type_item;
+
+ if(g_strcmp0(ti->str, "[")){
+ FPRINTF(stderr, "ERROR: parsebrackets first token is not '['\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ br=g_new0(bracket_item_t, 1);
+ if (!br) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ *bracket=br;
+ br->flags=0;
+ br->case_name=NULL;
+ br->pointer_list=NULL;
+
+ while(ti){
+ if( !g_strcmp0(ti->str, "{")
+ ||!g_strcmp0(ti->str, "}")){
+ FPRINTF(stderr, "ERROR: parsebrackets '{' '}' inside bracket item\n");
+ Exit(10);
+ }
+
+ if(!g_strcmp0(ti->str, "[")){
+ FPRINTF(stderr, "ERROR: parsebrackets '[' inside bracket item\n");
+ Exit(10);
+ }
+
+ /* finished */
+ if(!g_strcmp0(ti->str, "]")){
+ /* check for [ ... ] [ ...] */
+ ti=ti->next;
+
+ if(!g_strcmp0(ti->str, "[")){
+ ti=ti->next;
+ continue;
+ }
+ return ti;
+ }
+
+ /* just ignore all ',' */
+ if(!g_strcmp0(ti->str, ",")){
+ ti=ti->next;
+ continue;
+ }
+
+ /* case '(' tag ')' */
+ if(!g_strcmp0(ti->str, "case")){
+ br->flags|=BI_CASE;
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "(")){
+ FPRINTF(stderr, "ERROR: parsebrackets case not followed by '('\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* name */
+ br->case_name=ti->str;
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, ")")){
+ FPRINTF(stderr, "ERROR: parsebrackets case does not end with ')'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+ continue;
+ }
+
+ /* default */
+ if(!g_strcmp0(ti->str, "default")){
+ br->flags|=BI_CASE;
+ br->flags|=BI_CASE_DEFAULT;
+ br->case_name="default";
+ ti=ti->next;
+ continue;
+ }
+
+
+ /* in */
+ if(!g_strcmp0(ti->str, "in")){
+ br->flags|=BI_IN;
+ ti=ti->next;
+ continue;
+ }
+
+ /* out */
+ if(!g_strcmp0(ti->str, "out")){
+ br->flags|=BI_OUT;
+ ti=ti->next;
+ continue;
+ }
+
+ /* public : we don't care about this one */
+ if(!g_strcmp0(ti->str, "public")){
+ ti=ti->next;
+ continue;
+ }
+
+ /* gensize : we don't care about this one */
+ if(!g_strcmp0(ti->str, "gensize")){
+ ti=ti->next;
+ continue;
+ }
+
+ /* switch_is */
+ if(!g_strcmp0(ti->str, "switch_is")){
+ FPRINTF(stderr, "WARNING: parsebrackets can not handle switch_is properly yet so we can not verify the tag size\n");
+ while(ti){
+ if(!g_strcmp0(ti->str, ")")){
+ ti=ti->next;
+ break;
+ }
+ ti=ti->next;
+ }
+ continue;
+ }
+
+ /* switch_is */
+ if(!g_strcmp0(ti->str, "subcontext")){
+ while(ti){
+ if(!g_strcmp0(ti->str, ")")){
+ ti=ti->next;
+ break;
+ }
+ ti=ti->next;
+ }
+ continue;
+ }
+
+ /* value we don't care about this one so just skip it */
+ if(!g_strcmp0(ti->str, "value")){
+ int level;
+ ti=ti->next;
+ if( g_strcmp0(ti->str, "(") ){
+ FPRINTF(stderr, "WARNING: parsebrackets value was not followed by '('\n");
+ Exit(10);
+ }
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "(")){
+ ti=ti->next;
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, ")")){
+ ti=ti->next;
+ level--;
+ if(level){
+ continue;
+ }
+ break;
+ }
+ ti=ti->next;
+ }
+ continue;
+ }
+
+ /* range we don't care about this one so just skip it */
+ if(!g_strcmp0(ti->str, "range")){
+ int level;
+ ti=ti->next;
+ if( g_strcmp0(ti->str, "(") ){
+ FPRINTF(stderr, "WARNING: parsebrackets range was not followed by '('\n");
+ Exit(10);
+ }
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "(")){
+ ti=ti->next;
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, ")")){
+ ti=ti->next;
+ level--;
+ if(level){
+ continue;
+ }
+ break;
+ }
+ ti=ti->next;
+ }
+ continue;
+ }
+
+ /* flag we don't care about this one so just skip it */
+ if(!g_strcmp0(ti->str, "flag")){
+ int level;
+ ti=ti->next;
+ if( g_strcmp0(ti->str, "(") ){
+ FPRINTF(stderr, "WARNING: parsebrackets flag was not followed by '('\n");
+ Exit(10);
+ }
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "(")){
+ ti=ti->next;
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, ")")){
+ ti=ti->next;
+ level--;
+ if(level){
+ continue;
+ }
+ break;
+ }
+ ti=ti->next;
+ }
+ continue;
+ }
+
+ /* switch_type */
+ if(!g_strcmp0(ti->str, "switch_type")){
+ br->flags|=BI_SWITCH_TYPE;
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "(")){
+ FPRINTF(stderr, "WARNING: parsebrackets switch_type was not followed by '('\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ type_item=find_type(ti->str);
+ if(!type_item){
+ FPRINTF(stderr, "ERROR : parsebrackets switch_type unknown type %s\n",ti->str);
+ Exit(10);
+ }
+ br->union_tag_size=type_item->alignment;
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, ")")){
+ FPRINTF(stderr, "WARNING: parsebrackets switch_type did not end with ')'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ continue;
+ }
+
+ /* size_is */
+ if(!g_strcmp0(ti->str, "size_is")){
+ br->flags|=BI_SIZE_IS;
+ ti=ti->next;
+ continue;
+ }
+
+ /* length_is */
+ if(!g_strcmp0(ti->str, "length_is")){
+ br->flags|=BI_LENGTH_IS;
+ ti=ti->next;
+ continue;
+ }
+
+ /* bitmap8bit */
+ if(!g_strcmp0(ti->str, "bitmap8bit")){
+ br->flags|=BI_BITMAP8;
+ ti=ti->next;
+ continue;
+ }
+
+ /* bitmap32bit */
+ if(!g_strcmp0(ti->str, "bitmap32bit")){
+ br->flags|=BI_BITMAP32;
+ ti=ti->next;
+ continue;
+ }
+
+ /* ref, unique or ptr */
+ if(!g_strcmp0(ti->str, "ref")
+ || !g_strcmp0(ti->str, "unique")
+ || !g_strcmp0(ti->str, "ptr")){
+ pointer_item_t *newpi;
+
+ br->flags|=BI_POINTER;
+ newpi=g_new0(pointer_item_t, 1);
+ if (!newpi) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ newpi->next=NULL;
+ newpi->type=ti->str;
+ newpi->next=br->pointer_list;
+ br->pointer_list=newpi;
+ ti=ti->next;
+ continue;
+ }
+
+ FPRINTF(stderr, "ERROR: parsebrackets should not be reached unknown tag:%s\n", ti->str);
+ Exit(10);
+ }
+
+ return NULL;
+}
+
+/* this function will register a new type learnt from the IDL file
+*/
+static type_item_t *
+register_new_type(const char *name, const char *dissectorname, const char *ft_type, const char *base_type, const char *mask, const char *valsstring, int alignment){
+ type_item_t *new_type;
+
+ FPRINTF(NULL,"XXX new type:%s dissector:%s Type:%s Base:%s Mask:%s Vals:%s alignment:%d\n", name, dissectorname, ft_type, base_type, mask, valsstring, alignment);
+
+ new_type=g_new0(type_item_t, 1);
+ if (!new_type) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ new_type->next=type_list;
+ new_type->name=g_strdup(name);
+ new_type->dissector=g_strdup(dissectorname);
+ new_type->ft_type=g_strdup(ft_type);
+ new_type->base_type=g_strdup(base_type);
+ new_type->mask=g_strdup(mask);
+ new_type->vals=g_strdup(valsstring);
+ new_type->alignment=alignment;
+ type_list=new_type;
+
+ return new_type;
+}
+
+
+/* this function will print the remaining content of the token list
+*/
+static void printtokenlist(int count)
+{
+ token_item_t *ti;
+ FPRINTF(stderr, "TOKENLIST:\n");
+ for(ti=token_list;ti&&count;count--,ti=ti->next){
+ FPRINTF(stderr, "Token \"%s\"\n",ti->str);
+ }
+ if(!count){
+ FPRINTF(stderr, " ...\n");
+ }
+}
+
+
+/* this function will parse the header and pick up the fields
+ * we are interested in.
+ * the header is supposed to start at the very first token and look like
+ * [ <fields> ] inteface <ifname> {
+ *
+ * we are interested in the fields:
+ * uuid
+ * version
+ * pointer_default
+ *
+ * this function will also g_remove the header from the token list
+ */
+static void parseheader(void)
+{
+ char filter_name[BASE_BUFFER_SIZE];
+ token_item_t *ti;
+ int level=0;
+ int major, minor;
+
+ ti=token_list;
+ if(!ti){
+ FPRINTF(stderr, "ERROR: no tokens\n");
+ Exit(10);
+ }
+
+ /* first token must be '[' */
+ if( g_strcmp0(ti->str, "[") ){
+ FPRINTF(stderr, "ERROR: first token is not '['\n");
+ Exit(10);
+ }
+
+ for(ti=token_list;ti;ti=ti->next){
+ if( !g_strcmp0(ti->str, "[")){
+ level++;
+ continue;
+ }
+ if( !g_strcmp0(ti->str, "]")){
+ level--;
+ if(!level){
+ token_list=ti->next;
+ break;
+ }
+ }
+ if(level==1){
+ if( !g_strcmp0(ti->str, "uuid")){
+ uuid=ti->next->next->str;
+ FPRINTF(NULL,"UUID:%s\n",uuid);
+ }
+ if( !g_strcmp0(ti->str, "version")){
+ version=ti->next->next->str;
+ FPRINTF(NULL,"VERSION:%s\n",version);
+ }
+ if( !g_strcmp0(ti->str, "pointer_default")){
+ if(!g_strcmp0(ti->next->next->str, "unique")){
+ pointer_default="unique";
+ } else if(!g_strcmp0(ti->next->next->str, "ptr")){
+ pointer_default="ptr";
+ } else {
+ FPRINTF(stderr, "ERROR: unknown pointer type\n");
+ Exit(10);
+ }
+ FPRINTF(NULL,"POINTER_DEFAULT:%s\n",pointer_default);
+ }
+ }
+ }
+ if(!token_list){
+ FPRINTF(stderr, "ERROR: ran out of tokens inside header\n");
+ Exit(10);
+ }
+ /* interface */
+ if(g_strcmp0(token_list->str, "interface")){
+ FPRINTF(stderr, "ERROR: interface not found\n");
+ Exit(10);
+ }
+ token_list=token_list->next;
+ if (!token_list){
+ FPRINTF(stderr, "ERROR: ran out of tokens\n");
+ Exit(10);
+ }
+ /* interface name */
+ ifname=token_list->str;
+ token_list=token_list->next;
+ FPRINTF(NULL,"Interface:%s\n",ifname);
+
+ /* opnum */
+ snprintf(hf_status, BASE_BUFFER_SIZE, "hf_%s_opnum", ifname);
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.opnum", ifname);
+ register_hf_field(hf_status, "Operation", filter_name, "FT_UINT16", "BASE_DEC", "NULL", "0", "");
+
+ /* status */
+ snprintf(hf_status, BASE_BUFFER_SIZE, "hf_%s_rc", ifname);
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.rc", ifname);
+ register_hf_field(hf_status, "Return code", filter_name, "FT_UINT32", "BASE_HEX", "VALS(NT_errors)", "0", "");
+
+ FPRINTF(eth_ett, "static gint ett_%s = -1;\n", ifname);
+ FPRINTF(eth_ettarr, " &ett_%s,\n", ifname);
+
+ /* the body must start with { */
+ if(g_strcmp0(token_list->str, "{")){
+ FPRINTF(stderr, "ERROR: body does not start with '{'\n");
+ Exit(10);
+ }
+
+ /* skip the initial '{' */
+ token_list=token_list->next;
+
+ if(!uuid){
+ FPRINTF(stderr, "ERROR: no uuid found\n");
+ Exit(10);
+ }
+ FPRINTF(eth_code,"static e_guid_t uuid_dcerpc_%s = {\n", ifname);
+ FPRINTF(eth_code," 0x%c%c%c%c%c%c%c%c, 0x%c%c%c%c, 0x%c%c%c%c,\n",uuid[1],uuid[2],uuid[3],uuid[4],uuid[5],uuid[6],uuid[7],uuid[8],uuid[10],uuid[11],uuid[12],uuid[13],uuid[15],uuid[16],uuid[17],uuid[18]);
+ FPRINTF(eth_code," { 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c, 0x%c%c}\n",uuid[20],uuid[21],uuid[22],uuid[23],uuid[25],uuid[26],uuid[27],uuid[28],uuid[29],uuid[30],uuid[31],uuid[32],uuid[33],uuid[34],uuid[35],uuid[36]);
+ FPRINTF(eth_code,"};\n");
+ FPRINTF(eth_code,"\n");
+
+ sscanf(version, "%d.%d", &major, &minor);
+ FPRINTF(eth_code,"static guint16 ver_%s = %d;\n", ifname, major);
+ FPRINTF(eth_code,"\n");
+
+ FPRINTF(eth_handoff, " dcerpc_init_uuid(proto_%s, ett_%s,\n", ifname, ifname);
+ FPRINTF(eth_handoff, " &uuid_dcerpc_%s, ver_%s,\n", ifname, ifname);
+ FPRINTF(eth_handoff, " function_dissectors, hf_%s_opnum);\n", ifname);
+}
+
+
+
+/* this helper function is called by the tokenizer and will just append the
+ current token to the linked list
+*/
+static void pushtoken(char *token)
+{
+ token_item_t *new_token_item;
+ new_token_item=g_new0(token_item_t, 1);
+ if (!new_token_item) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ new_token_item->next=NULL;
+ new_token_item->str=token;
+ if(!token_list){
+ token_list=new_token_item;
+ } else {
+ last_token_item->next=new_token_item;
+ }
+ last_token_item=new_token_item;
+}
+
+/* this function reads the idl file and translates it into tokens.
+ the tokens are stored in a linked list token_list of type token_item_t
+*/
+static void tokenize(FILE *fh)
+{
+ int ch;
+ int fullinecomment=0;
+ int normalcomment=0;
+ int insidequote=0;
+ char qs[4 * BASE_BUFFER_SIZE];
+ int qspos=0;
+ int insidetoken=0;
+ char token[4 * BASE_BUFFER_SIZE];
+ int tokenpos=0;
+
+ while(!feof(fh)){
+ ch=fgetc(fh);
+
+ /* full line comment */
+ if(fullinecomment){
+ if( (ch=='\n')||(ch=='\r') ){
+ fullinecomment=0;
+ linepos=0;
+ }
+ continue;
+ }
+ if( (ch=='#')&&(linepos==0) ){
+ fullinecomment=1;
+ continue;
+ }
+
+ /* normal comment */
+ if(normalcomment==0){
+ if(ch=='/'){
+ int nextch;
+ nextch=fgetc(fh);
+ if(nextch=='*'){
+ normalcomment=1;
+ continue;
+ }
+ ungetc(nextch, fh);
+ }
+ } else {
+ if(ch=='*'){
+ int nextch;
+ nextch=fgetc(fh);
+ if(nextch=='/'){
+ normalcomment=0;
+ continue;
+ }
+ ungetc(nextch, fh);
+ }
+ continue;
+ }
+
+ /* quoted string */
+ if(insidequote){
+ if(ch=='"'){
+ insidequote=0;
+ qs[qspos++]='"';
+ qs[qspos]=0;
+ pushtoken(g_strdup(qs));
+ continue;
+ } else {
+ qs[qspos++]=(char)ch;
+ continue;
+ }
+ } else {
+ if(ch=='"'){
+ insidequote=1;
+ qs[0]='"';
+ qspos=1;
+ continue;
+ }
+ }
+
+
+ switch(ch){
+ case '\n':
+ case '\r':
+ if(insidetoken){
+ insidetoken=0;
+ token[tokenpos]=0;
+ pushtoken(g_strdup(token));
+ }
+ line[linepos]=0;
+
+ linepos=0;
+ lineno++;
+ break;
+ case '\t':
+ case ' ':
+ if(insidetoken){
+ insidetoken=0;
+ token[tokenpos]=0;
+ pushtoken(g_strdup(token));
+ }
+ break;
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+ case ',':
+ case ';':
+ case '*':
+ case '=':
+ if(insidetoken){
+ insidetoken=0;
+ token[tokenpos]=0;
+ pushtoken(g_strdup(token));
+ }
+ token[0]=(char)ch;
+ token[1]=0;
+ pushtoken(g_strdup(token));
+ break;
+ default:
+ if(!insidetoken){
+ tokenpos=0;
+ }
+ insidetoken=1;
+ token[tokenpos++]=(char)ch;
+ line[linepos++]=(char)ch;
+ break;
+ }
+
+ }
+}
+
+
+static type_item_t *
+find_type(char *name)
+{
+ type_item_t *tmptype;
+ for(tmptype=type_list;tmptype;tmptype=tmptype->next){
+ if(!g_strcmp0(tmptype->name, name)){
+ break;
+ }
+ }
+ /* autogenerate built in types */
+ if(!tmptype){
+ char dissectorname[DISSECTORNAME_MAXLEN];
+ if(!g_strcmp0(name,"uint16")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("uint16", dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", 2);
+ } else if(!g_strcmp0(name,"int16")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("int16", dissectorname, "FT_INT16", "BASE_DEC", "0", "NULL", 2);
+ } else if(!g_strcmp0(name,"uint32")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("uint32", dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", 4);
+ } else if( (!g_strcmp0(name,"int32"))
+ || (!g_strcmp0(name,"long")) ){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ if (!g_strcmp0(name,"int32"))
+ tmptype=register_new_type("int32", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4);
+ else
+ tmptype=register_new_type("long", dissectorname, "FT_INT32", "BASE_DEC", "0", "NULL", 4);
+ } else if( (!g_strcmp0(name,"uint8")) ){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("uint8", dissectorname, "FT_UINT8", "BASE_DEC", "0", "NULL", 1);
+ } else if( (!g_strcmp0(name,"int8"))
+ || (!g_strcmp0(name, "char")) ){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ if (!g_strcmp0(name,"int8"))
+ tmptype=register_new_type("int8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+ else
+ tmptype=register_new_type("char", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+ } else if(!g_strcmp0(name,"bool8")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("bool8", dissectorname, "FT_INT8", "BASE_DEC", "0", "NULL", 1);
+ } else if(!g_strcmp0(name,"unistr")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, 2, hf_index, FALSE, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("unistr", dissectorname, "FT_STRING", "BASE_NONE", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"ascstr")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, 1, hf_index, FALSE, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("ascstr", dissectorname, "FT_STRING", "BASE_NONE", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"GUID")
+ ||!g_strcmp0(name,"uuid_t")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uuid_t(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type(name, dissectorname, "FT_GUID", "BASE_NONE", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"policy_handle")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static e_ctx_hnd policy_hnd;\n");
+ FPRINTF(eth_code, "static proto_item *hnd_item;\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, di, drep,\n");
+ FPRINTF(eth_code, " hf_index, &policy_hnd, &hnd_item,\n");
+ FPRINTF(eth_code, " param&0x01, param&0x02);\n");
+
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("policy_handle", dissectorname, "FT_BYTES", "BASE_NONE", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"NTTIME")){
+ /* 8 bytes, aligned to 4 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, hf_index);\n");
+
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("NTTIME", dissectorname, "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"NTTIME_hyper")){
+ /* 8 bytes, aligned to 8 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n");
+ FPRINTF(eth_code, " offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, hf_index);\n");
+
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("NTTIME_hyper", dissectorname, "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"NTTIME_1sec")){
+ /* 8 bytes, aligned to 8 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n");
+ FPRINTF(eth_code, " offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, hf_index);\n");
+
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("NTTIME_1sec", dissectorname, "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"udlong")){
+ /* 8 bytes, aligned to 4 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("udlong", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"dlong")){
+ /* 8 bytes, aligned to 4 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_duint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("dlong", dissectorname, "FT_INT64", "BASE_DEC", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"uint64")){
+ /* 8 bytes, aligned to 8 bytes */
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " \n");
+ FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint64(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("uint64", dissectorname, "FT_UINT64", "BASE_DEC", "0", "NULL", 8);
+ } else if(!g_strcmp0(name,"time_t")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " \n");
+ FPRINTF(eth_code, " offset=dissect_ndr_time_t(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("time_t", dissectorname, "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"SID")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_nt_SID_with_options(tvb, offset, pinfo, tree, di, drep, param, hf_index);\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("SID", dissectorname, "FT_STRING", "BASE_NONE", "0", "NULL", 4);
+ } else if(!g_strcmp0(name,"WERROR")){
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, name);
+ FPRINTF(NULL,"\nAutogenerating built-in type:%s\n------------\n",name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " \n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ tmptype=register_new_type("WERROR", dissectorname, "FT_UINT32", "BASE_DEC", "0", "VALS(NT_errors)", 4);
+ }
+ }
+
+ return tmptype;
+}
+
+
+/* this function will skip past an entire declare ... ; statement */
+static void skipdeclare(void)
+{
+ token_item_t *ti;
+
+ /* first must be the keyword const */
+ ti=token_list;
+ if(strncmp(ti->str, "declare", 7)){
+ FPRINTF(stderr, "ERROR: skipdeclare first token is not 'declare'\n");
+ Exit(10);
+ }
+ while(ti->str[0] != ';'){
+ ti=ti->next;
+ }
+ ti=ti->next;
+
+ token_list=ti;
+}
+
+/* this function will parse a
+ const
+ and generate the appropriate code
+ const must be followed by a suitable keyword [uint16|uint32|...]
+ the const will later be g_removed from the token list
+ the function assumes that the const is the first object in the token_list
+*/
+static void parseconst(void)
+{
+ token_item_t *ti;
+ char *name, *value;
+
+ /* first must be the keyword const */
+ ti=token_list;
+ if(strncmp(ti->str, "const", 5)){
+ FPRINTF(stderr, "ERROR: const first token is not 'const'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* just skip second token */
+ ti=ti->next;
+
+ /* third is a variable and not a type */
+ if(find_type(ti->str)){
+ FPRINTF(stderr, "ERROR: const, not a variable name:%s\n", ti->str);
+ Exit(10);
+ }
+ name=ti->str;
+ ti=ti->next;
+
+ /* fourth is '=' */
+ if(ti->str[0] != '='){
+ FPRINTF(stderr, "ERROR: const fourth token is not '='\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* fifth is the value */
+ value=ti->str;
+ ti=ti->next;
+
+ /* sixth is ';' */
+ if(ti->str[0] != ';'){
+ FPRINTF(stderr, "ERROR: const sixth token is not ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ FPRINTF(NULL,"\nCONST:%s\n-------\n",name);
+
+ FPRINTF(eth_hdr, "#define %s %s\n", name, value);
+
+ FPRINTF(NULL,"\n----------\nEND CONST:%s\n",name);
+
+ token_list=ti;
+}
+
+/* this function will parse a
+ typedef struct {
+ construct and generate the appropriate code.
+ the typedef will be g_removed from the token_list once it has been processed
+ the function assumes that the typedef is the first object in the token_list
+ the function will be called twice, once with pass=0 and once with pass=1
+ which controls whether subdissectors are to be generated or whether the
+ struct dissector itself is to be generated
+*/
+static void parsetypedefstruct(int pass)
+{
+ token_item_t *ti, *tmpti;
+ char *struct_name;
+ char dissectorname[DISSECTORNAME_MAXLEN];
+ char tmpstr[BASE_BUFFER_SIZE], *ptmpstr;
+ int level, num_pointers;
+ static int alignment;
+ type_item_t *type_item;
+ char hf_index[BASE_BUFFER_SIZE];
+ bracket_item_t *bi=NULL;
+ pointer_item_t *pi;
+ const char *pointer_type;
+ char *field_name;
+ guint32 fixed_array_size;
+ int is_array_of_pointers;
+ int empty_struct = 0;
+
+ ti=token_list;
+ if(g_strcmp0(ti->str, "typedef")){
+ FPRINTF(stderr, "ERROR: typedefstruct first token is not 'typedef'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ }
+ /* check that we know how to handle the bracket thing */
+ if(bi){
+ if(bi->flags){
+ FPRINTF(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ }
+
+ if(g_strcmp0(ti->str, "struct")){
+ FPRINTF(stderr, "ERROR: typedefstruct second token is not 'struct'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "{")){
+ FPRINTF(stderr, "ERROR: typedefstruct third token is not '{'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* Check if the struct is empty (search if there is no end bracket) */
+ if(g_strcmp0(ti->str, "}") == 0){
+ empty_struct = 1;
+ }
+
+ /* search forward until the '}' so we can find the name of the struct */
+ for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){
+ if(!g_strcmp0(tmpti->str, "{")){
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(tmpti->str, "}")){
+ if(!level){
+ break;
+ }
+ level--;
+ continue;
+ }
+ }
+ if(!tmpti || !tmpti->next){
+ FPRINTF(stderr, "ERROR: typedefstruct missing matching '}'\n");
+ Exit(10);
+ }
+
+ struct_name=tmpti->next->str;
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, struct_name);
+
+ FPRINTF(NULL,"\nSTRUCT:%s pass:%d\n-------\n",struct_name,pass);
+
+ if(!check_if_to_emit(dissectorname)){
+ FPRINTF(NULL,"NOEMIT Skipping this struct dissector.\n");
+ ti=tmpti;
+ goto typedef_struct_finished;
+ }
+
+ /* this is pass 0 so reset alignment to zero and update as items are
+ processed. we need alignment when pass 1 is run.
+ set alignment initially to 1 so we don't fail for empty structs
+ */
+ if(pass==0){
+ alignment=1;
+ }
+ /* pass 1 generate header for the struct dissector */
+ if(pass==1){
+ FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, struct_name);
+ FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, struct_name);
+ FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *parent_tree, dcerpc_info *di _U_, guint8 *drep _U_, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " proto_item *item=NULL;\n");
+ if(!empty_struct){
+ FPRINTF(eth_code, " proto_tree *tree=NULL;\n");
+ }
+ FPRINTF(eth_code, " int old_offset;\n");
+ FPRINTF(eth_code, "\n");
+ switch(alignment){
+ case 1:
+ break;
+ case 2:
+ FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ case 8:
+ FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, " old_offset=offset;\n");
+ FPRINTF(eth_code, " if(parent_tree){\n");
+ FPRINTF(eth_code, " item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, -1, ENC_NA);\n");
+ if(!empty_struct){
+ FPRINTF(eth_code, " tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, struct_name);
+ }
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ }
+
+ /* scan the struct and create all subdissectors */
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "{")){
+ level++;
+ ti=ti->next;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, "}")){
+ if(!level){
+ break;
+ }
+ level--;
+ ti=ti->next;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ continue;
+ }
+
+ /* check that we know how to handle the bracket thing */
+ if(bi){
+ if(bi->flags&(~(BI_SIZE_IS|BI_LENGTH_IS|BI_POINTER))){
+ FPRINTF(stderr, "ERROR: typedefstruct unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ }
+
+ /* handle the type, verify that we KNOW this type */
+ type_item=find_type(ti->str);
+ if(!type_item){
+ FPRINTF(stderr, "ERROR : typedefstruct unknown type %s\n",ti->str);
+ Exit(10);
+ }
+ ti=ti->next;
+ /* count the levels of pointers */
+ for(num_pointers=0;!g_strcmp0(ti->str, "*");ti=ti->next){
+ num_pointers++;
+ /* poitners are aligned at 4 byte boundaries */
+ if(alignment<4){
+ alignment=4;
+ }
+ }
+ /* now that we know how many real pointers there were we must
+ prepend default pointers to the list so it has the right
+ length.
+ */
+ pi=prepend_pointer_list(bi?bi->pointer_list:NULL, num_pointers);
+ /* keep track of alignment */
+ if(alignment<type_item->alignment){
+ alignment=type_item->alignment;
+ }
+
+ field_name=ti->str;
+ ti=ti->next;
+
+ /* see if it is a fixed array */
+ fixed_array_size=0;
+ is_array_of_pointers=0;
+ if(!g_strcmp0(ti->str, "[")){
+ char fss[BASE_BUFFER_SIZE];
+
+ /* this might be a fixed array */
+ ti=ti->next;
+
+ if (!ws_strtou32(ti->str, NULL, &fixed_array_size)) {
+ FPRINTF(stderr, "ERROR: invalid integer: %s\n", ti->str);
+ Exit(10);
+ }
+ snprintf(fss, BASE_BUFFER_SIZE, "%d", fixed_array_size);
+
+ if(!g_strcmp0("]", ti->str)){
+ /* this is just a normal [] array */
+ fixed_array_size=0;
+ } else if(!g_strcmp0("*", ti->str)){
+ pi=prepend_pointer_list(pi, num_pointers+1);
+ fixed_array_size=0;
+ is_array_of_pointers=1;
+ ti=ti->next;
+ } else if(g_strcmp0(fss, ti->str)){
+ FPRINTF(stderr, "ERROR: typedefstruct (%s) fixed array size looks different to calculated one %s!=%s\n", struct_name, fss, ti->str);
+ ti=ti->next;
+ Exit(10);
+ } else {
+ ti=ti->next;
+ }
+
+ if(g_strcmp0(ti->str, "]")){
+ FPRINTF(stderr, "ERROR: typedefstruct fixed array does not end with ']' it ended with %s\n",ti->str);
+ Exit(10);
+ }
+ ti=ti->next;
+ }
+
+ snprintf(hf_index, BASE_BUFFER_SIZE, "hf_%s_%s_%s", ifname, struct_name, field_name);
+ /* pass 0 generate subdissectors */
+ if(pass==0){
+ char filter_name[BASE_BUFFER_SIZE];
+ const char *hf;
+
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_%s_%s", ifname, struct_name, field_name);
+ ptmpstr=g_strdup(tmpstr);
+
+ if(check_if_to_emit(tmpstr)){
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.%s.%s", ifname, struct_name, field_name);
+ hf=register_hf_field(hf_index, field_name, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", ptmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep, %s, param);\n", type_item->dissector, hf);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+
+ if(is_array_of_pointers){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_embedded_pointer(tvb, offset, pinfo, tree, di, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+
+ ptmpstr=g_strdup(tmpstr);
+ } else if(fixed_array_size){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "fixedarray_%s", ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " int count=%d;\n",fixed_array_size);
+ FPRINTF(eth_code, " while(count--){\n");
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep);\n", ptmpstr);
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+ ptmpstr=g_strdup(tmpstr);
+ }
+
+ /* handle switch_is */
+ if(bi){
+ switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+ case 0:
+ break;
+ case BI_SIZE_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucarray_%s", ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, di, drep, %s);\n", ptmpstr);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "uvarray_%s", ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_uvarray(tvb, offset, pinfo, tree, di, drep, %s);\n", ptmpstr);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_SIZE_IS|BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucvarray_%s", ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, di, drep, %s);\n", ptmpstr);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n");
+ Exit(10);
+ }
+ }
+
+ /* handle pointers */
+ while(num_pointers--){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ if(check_if_to_emit(tmpstr)){
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_embedded_pointer(tvb, offset, pinfo, tree, di, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), field_name);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ } else {
+ FPRINTF(NULL,"NOEMIT Skipping this struct item :%s\n",tmpstr);
+ }
+
+ ptmpstr=g_strdup(tmpstr);
+ }
+ }
+
+ if(pass==1){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_%s_%s", ifname, struct_name, field_name);
+ ptmpstr=g_strdup(tmpstr);
+
+ /* handle fixedsizearrays */
+ if(is_array_of_pointers){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ } else if(fixed_array_size){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "fixedarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ }
+
+ /* handle switch_is */
+ if(bi){
+ switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+ case 0:
+ break;
+ case BI_SIZE_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "uvarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_SIZE_IS|BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucvarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefstruct can not handle this combination of sizeis/lengthis\n");
+ Exit(10);
+ }
+ }
+
+ /* handle pointers */
+ while(num_pointers--){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ }
+
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep);\n", ptmpstr);
+ FPRINTF(eth_code, "\n");
+ }
+
+ if(g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: field does not en with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+ bi=NULL; /* clear bi before we start on the next field */
+ }
+
+ if(pass==1){
+ FPRINTF(eth_code, " proto_item_set_len(item, offset-old_offset);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ register_new_type(struct_name, dissectorname, "FT_NONE", "BASE_NONE", "0", "NULL", alignment);
+ }
+
+
+typedef_struct_finished:
+ FPRINTF(NULL,"\nEND STRUCT:%s pass:%d\n-------\n",struct_name,pass);
+
+ /* only advance token_list for pass==1
+ ti now points to the '}' token
+ */
+ if(pass==1){
+ if(!ti || g_strcmp0(ti->str,"}")){
+ FPRINTF(stderr, "ERROR: struct does not end with '}'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* just skip the name */
+ ti=ti->next;
+
+ if(!ti || g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: struct does not end with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ token_list=ti;
+ }
+}
+
+/* this function will parse a
+ typedef bitmap {
+ construct and generate the appropriate code.
+ the typedef will be g_removed from the token_list once it has been processed
+ the function assumes that the typedef is the first object in the token_list
+ the function will be called twice, once with pass=0 and once with pass=1
+ which controls whether subdissectors are to be generated or whether the
+ bitmap dissector itself is to be generated
+
+ bitmaps are by default 32 bits
+*/
+static void parsetypedefbitmap(int pass)
+{
+ token_item_t *ti, *tmpti;
+ char *bitmap_name;
+ char dissectorname[BASE_BUFFER_SIZE], hf_bitname[BASE_BUFFER_SIZE];
+ int alignment;
+ unsigned int val;
+ char *name, *value;
+ bracket_item_t *bi=NULL;
+
+ ti=token_list;
+ if(g_strcmp0(ti->str, "typedef")){
+ FPRINTF(stderr, "ERROR: typedefbitmap first token is not 'typedef'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ alignment=4; /* default size is 32 bits */
+
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ }
+ /* check that we know how to handle the bracket thing */
+ if(bi){
+ if(bi->flags&(~(BI_BITMAP32|BI_BITMAP8))){
+ FPRINTF(stderr, "ERROR: typedefbitmap unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ if(bi->flags&BI_BITMAP32){
+ alignment=4;
+ }
+ if(bi->flags&BI_BITMAP8){
+ alignment=1;
+ }
+ }
+
+
+ if(g_strcmp0(ti->str, "bitmap")){
+ FPRINTF(stderr, "ERROR: typedefbitmap second token is not 'bitmap'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "{")){
+ FPRINTF(stderr, "ERROR: typedefbitmap third token is not '{'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* search forward until the '}' so we can find the name of the bitmap */
+ for(tmpti=ti;tmpti;tmpti=tmpti->next){
+ if(!g_strcmp0(tmpti->str, "{")){
+ FPRINTF(stderr, "ERROR: typedefbitmap '{' encountered inside bitmap\n");
+ Exit(10);
+ }
+ if(!g_strcmp0(tmpti->str, "}")){
+ break;
+ }
+ }
+ if (!tmpti || !tmpti->next){
+ FPRINTF(stderr, "ERROR: typedefbitmap missing matching '}'\n");
+ Exit(10);
+ }
+ bitmap_name=tmpti->next->str;
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, bitmap_name);
+
+ FPRINTF(NULL,"\nBITMAP:%s pass:%d\n-------\n",bitmap_name,pass);
+
+ /* pass 1 generate header for the struct dissector */
+ if(pass==1){
+ FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, bitmap_name);
+ FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, bitmap_name);
+ FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " proto_item *item=NULL;\n");
+ FPRINTF(eth_code, " proto_tree *tree=NULL;\n");
+ switch(alignment){
+ case 1:
+ FPRINTF(eth_code, " guint8 flags;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " guint32 flags;\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " if(parent_tree){\n");
+ FPRINTF(eth_code, " item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, %d, ENC_LITTLE_ENDIAN);\n", alignment);
+ FPRINTF(eth_code, " tree=proto_item_add_subtree(item, ett_%s_%s);\n", ifname, bitmap_name);
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ switch(alignment){
+ case 1:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint8(tvb, offset, pinfo, NULL, di, drep, -1, &flags);\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, di, drep, -1, &flags);\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, "\n");
+ }
+
+ /* scan the struct and create call for all bits */
+ while(ti){
+ if(!g_strcmp0(ti->str, "}")){
+ break;
+ }
+ if(!g_strcmp0(ti->str, "[")){
+ FPRINTF(stderr, "ERROR: typedefbitmap can not handle '[' yet\n");
+ Exit(10);
+ }
+
+ name=ti->str;
+ ti=ti->next;
+ snprintf(hf_bitname, BASE_BUFFER_SIZE, "hf_%s_%s_%s", ifname, bitmap_name, name);
+
+ if(g_strcmp0(ti->str, "=")){
+ FPRINTF(stderr, "ERROR: typedefbitmap i expected a '=' here\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ value=ti->str;
+ ti=ti->next;
+ val=0;
+ if(!strncmp(value, "0x", 2)){
+ sscanf(value, "0x%x", &val);
+ } else {
+ FPRINTF(stderr, "ERROR: typedefbitmap can only handle hexadecimal constants\n");
+ Exit(10);
+ }
+
+ if( val&(val-1) ){
+ FPRINTF(stderr, "ERROR: typedefbitmap can only handle single bit fields\n");
+ Exit(10);
+ }
+
+ if(pass==0){
+ char filter_name[BASE_BUFFER_SIZE], base_name[BASE_BUFFER_SIZE], tfs_name[BASE_BUFFER_SIZE];
+
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.%s.%s", ifname, bitmap_name, name);
+ snprintf(base_name, BASE_BUFFER_SIZE, "%d", alignment*8);
+ snprintf(tfs_name, BASE_BUFFER_SIZE, "TFS(&%s_tfs)", name);
+ register_hf_field(hf_bitname, name, filter_name, "FT_BOOLEAN", base_name, tfs_name, value, "");
+
+ FPRINTF(eth_code, "static const true_false_string %s_tfs = {\n",name);
+ FPRINTF(eth_code, " \"%s is SET\",\n", name);
+ FPRINTF(eth_code, " \"%s is NOT set\"\n", name);
+ FPRINTF(eth_code, "};\n");
+ FPRINTF(eth_code, "\n");
+ }
+
+ if(pass==1){
+ FPRINTF(eth_code, " proto_tree_add_boolean(tree, %s, tvb, offset-%d, %d, flags);\n", hf_bitname, alignment, alignment);
+ FPRINTF(eth_code, " if(flags&%s){\n", value);
+ FPRINTF(eth_code, " proto_item_append_text(item, \" %s\");\n", name);
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, " flags&=(~%s);\n", value);
+ FPRINTF(eth_code, "\n");
+ }
+
+ if(!g_strcmp0(ti->str, ",")){
+ ti=ti->next;
+ continue;
+ }
+ }
+
+ if(pass==1){
+ FPRINTF(eth_code, " if(flags){\n");
+ FPRINTF(eth_code, " proto_item_append_text(item, \"UNKNOWN-FLAGS\");\n");
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ switch(alignment){
+ case 1:
+ register_new_type(bitmap_name, dissectorname, "FT_UINT8", "BASE_HEX", "0", "NULL", alignment);
+ break;
+ case 4:
+ register_new_type(bitmap_name, dissectorname, "FT_UINT32", "BASE_HEX", "0", "NULL", alignment);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefbitmap can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ }
+
+ FPRINTF(NULL,"\nEND BITMAP:%s pass:%d\n-------\n",bitmap_name,pass);
+
+ /* only advance token_list for pass==1
+ ti now points to the '}' token
+ */
+ if(pass==1){
+ if(!ti || g_strcmp0(ti->str,"}")){
+ FPRINTF(stderr, "ERROR: bitmap does not end with '}'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* just skip the name */
+ ti=ti->next;
+
+ if(!ti || g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: bitmap does not end with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ token_list=ti;
+ }
+}
+
+/* a case tag might be a negative number, i.e. contain a '-' sign which
+ is not valid inside a symbol name in c.
+*/
+static const char *
+case2str(const char *str)
+{
+ char *newstr;
+ if(str[0]!='-'){
+ return str;
+ }
+ newstr=g_strdup(str);
+ newstr[0]='m';
+ return newstr;
+}
+
+/* this function will parse a
+ typedef union {
+ construct and generate the appropriate code.
+ the typedef will be g_removed from the token_list once it has been processed
+ the function assumes that the typedef is the first object in the token_list
+ the function will be called twice, once with pass=0 and once with pass=1
+ which controls whether subdissectors are to be generated or whether the
+ union dissector itself is to be generated
+*/
+static void parsetypedefunion(int pass)
+{
+ char *union_name;
+ token_item_t *ti, *tmpti;
+ char dissectorname[BASE_BUFFER_SIZE];
+ bracket_item_t *bi=NULL;
+ char tmpstr[BASE_BUFFER_SIZE], *ptmpstr;
+ int level, num_pointers;
+ static int alignment;
+ type_item_t *type_item;
+ char hf_index[BASE_BUFFER_SIZE];
+ int tag_alignment, item_alignment;
+
+ ti=token_list;
+ if(g_strcmp0(ti->str, "typedef")){
+ FPRINTF(stderr, "ERROR: typedefunion first token is not 'typedef'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ }
+ /* check that we know how to handle the bracket thing */
+ if(bi){
+ if(bi->flags&(~(BI_SWITCH_TYPE))){
+ FPRINTF(stderr, "ERROR: typedefunion unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ }
+
+ if(g_strcmp0(ti->str, "union")){
+ FPRINTF(stderr, "ERROR: typedefunion second token is not 'union'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "{")){
+ FPRINTF(stderr, "ERROR: typedefunion third token is not '{'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* search forward until the '}' so we can find the name of the union */
+ for(tmpti=ti,level=0;tmpti;tmpti=tmpti->next){
+ if(!g_strcmp0(tmpti->str, "{")){
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(tmpti->str, "}")){
+ if(!level){
+ break;
+ }
+ level--;
+ continue;
+ }
+ }
+
+ if (!tmpti || !tmpti->next){
+ FPRINTF(stderr, "ERROR: typedefunion missing matching '}'\n");
+ Exit(10);
+ }
+ union_name=tmpti->next->str;
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_union_%s", ifname, union_name);
+
+ FPRINTF(NULL,"\nUNION:%s pass:%d\n-------\n",union_name,pass);
+
+ if(bi && bi->flags&BI_SWITCH_TYPE){
+ tag_alignment=bi->union_tag_size;
+ } else {
+ tag_alignment=get_union_tag_size(union_name);
+ }
+
+ /* this is pass 0 so reset alignment to the minimum possible value
+ and update as items are processed.
+ we need alignment when pass 1 is run
+ */
+ if(pass==0){
+ alignment=tag_alignment;
+ }
+
+ /* pass 1 generate header for the struct dissector */
+ if(pass==1){
+ FPRINTF(eth_ett, "static gint ett_%s_%s = -1;\n", ifname, union_name);
+ FPRINTF(eth_ettarr, " &ett_%s_%s,\n", ifname, union_name);
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " proto_item *item=NULL;\n");
+ FPRINTF(eth_code, " proto_tree *tree=NULL;\n");
+ FPRINTF(eth_code, " int old_offset;\n");
+ /* we do alignment on the tag itself here so that
+ we skip any alignment padding prior to where the tag
+ itself starts, this makes the byterange in the hexpane
+ for the union expansion start with the first byte of the tag
+ */
+ switch(tag_alignment){
+ case 1:
+ break;
+ case 2:
+ FPRINTF(eth_code, " guint16 level;\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " guint32 level = 0;\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n");
+ FPRINTF(eth_code, "\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefunion 1 can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, " old_offset=offset;\n");
+ FPRINTF(eth_code, " if(parent_tree){\n");
+ FPRINTF(eth_code, " tree=proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_%s_%s, &item, \"%s\");\n", ifname, union_name, union_name);
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ switch(tag_alignment){
+ case 1:
+ break;
+ case 2:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree,\n");
+ FPRINTF(eth_code, " di, drep, hf_index, &level);\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree,\n");
+ FPRINTF(eth_code, " di, drep, hf_index, &level);\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefunion 2 can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " switch(level){\n");
+ }
+
+ /* scan the struct and create all subdissectors */
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "{")){
+ ti=ti->next;
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, "}")){
+ if(!level){
+ break;
+ }
+ ti=ti->next;
+ level--;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ continue;
+ }
+
+ if(!bi){
+ FPRINTF(stderr, "ERROR : typedefunion no brackets found for case\n");
+ Exit(10);
+ }
+ /* make sure we catch when we havent implemented everything
+ yet.
+ we currently only know about CASE and CASE_DEFAULT flags
+ */
+ if(bi->flags&(~(BI_CASE|BI_CASE_DEFAULT|BI_POINTER))){
+ FPRINTF(stderr, "ERROR: typedefunion unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ if(!(bi->flags&BI_CASE)){
+ FPRINTF(stderr, "ERROR : typedefunion no case found in brackets\n");
+ Exit(10);
+ }
+#ifdef g_removeD
+ /* only empty default cases for now */
+ if(bi->flags&BI_CASE_DEFAULT){
+ if(g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: default tag is not empty\n");
+ Exit(10);
+ }
+ ti=ti->next;
+ continue;
+ }
+#endif
+
+ /* just skip all and any 'empty' arms */
+ if(!g_strcmp0(ti->str, ";")){
+ ti=ti->next;
+ continue;
+ }
+
+ /* handle the type, verify that we KNOW this type */
+ type_item=find_type(ti->str);
+ if(!type_item){
+ FPRINTF(stderr, "ERROR : typedefunion unknown type %s\n",ti->str);
+ Exit(10);
+ }
+ ti=ti->next;
+ /* count the levels of pointers */
+ for(num_pointers=0;!g_strcmp0(ti->str, "*");ti=ti->next){
+ num_pointers++;
+ }
+
+ /* keep track of alignment */
+ if(num_pointers){
+ item_alignment=4;
+ } else {
+ item_alignment=type_item->alignment;
+ }
+ if(alignment<item_alignment){
+ alignment=item_alignment;
+ }
+
+ snprintf(hf_index, BASE_BUFFER_SIZE, "hf_%s_%s_%s_%s", ifname, union_name, case2str(bi->case_name), ti->str);
+ /* pass 0 generate subdissectors */
+ if(pass==0){
+ char filter_name[BASE_BUFFER_SIZE];
+ const char *hf;
+
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_union_%s_%s_%s", ifname, union_name, case2str(bi->case_name), ti->str);
+ ptmpstr=g_strdup(tmpstr);
+
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.%s.%s", ifname, union_name, ti->str);
+ hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", ptmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep, %s, param);\n", type_item->dissector, hf);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+
+ /* handle pointers */
+ while(num_pointers--){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", ptmpstr, "unique");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_embedded_pointer(tvb, offset, pinfo, tree, di, drep, %s, NDR_POINTER_UNIQUE, \"%s\", -1);\n", ptmpstr, ti->str);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+
+ ptmpstr=g_strdup(tmpstr);
+
+ }
+ }
+
+ if(pass==1){
+ /* handle pointers */
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_union_%s_%s_%s", ifname, union_name, case2str(bi->case_name), ti->str);
+ ptmpstr=g_strdup(tmpstr);
+ while(num_pointers--){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", ptmpstr, "unique");
+ ptmpstr=g_strdup(tmpstr);
+ }
+
+ if(bi->flags&BI_CASE_DEFAULT){
+ FPRINTF(eth_code, " default:\n");
+ } else {
+ FPRINTF(eth_code, " case %s:\n",bi->case_name);
+ }
+ /* each arm itself is aligned independently */
+ switch(item_alignment){
+ case 1:
+ break;
+ case 2:
+ FPRINTF(eth_code, " ALIGN_TO_2_BYTES;\n");
+ break;
+ case 4:
+ FPRINTF(eth_code, " ALIGN_TO_4_BYTES;\n");
+ break;
+ case 8:
+ FPRINTF(eth_code, " ALIGN_TO_8_BYTES;\n");
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefunion 3 can not handle alignment:%d\n",item_alignment);
+ Exit(10);
+ }
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep);\n", ptmpstr);
+ FPRINTF(eth_code, " break;\n");
+ FPRINTF(eth_code, "\n");
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: field does not end with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+ }
+
+ if(pass==1){
+ FPRINTF(eth_code, " }\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " proto_item_set_len(item, offset-old_offset);\n");
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ switch(tag_alignment){
+ case 2:
+ register_new_type(union_name, dissectorname, "FT_UINT16", "BASE_DEC", "0", "NULL", alignment);
+ break;
+ case 4:
+ register_new_type(union_name, dissectorname, "FT_UINT32", "BASE_DEC", "0", "NULL", alignment);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedefunion 4 can not handle alignment:%d\n",alignment);
+ Exit(10);
+ }
+ }
+
+ FPRINTF(NULL,"\nEND UNION:%s pass:%d\n-------\n",union_name,pass);
+
+ /* only advance token_list for pass==1
+ ti now points to the '}' token
+ */
+ if(pass==1){
+ if(!ti || g_strcmp0(ti->str,"}")){
+ FPRINTF(stderr, "ERROR: union does not end with '}'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* just skip the name */
+ ti=ti->next;
+
+ if(!ti || g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: union does not end with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ token_list=ti;
+ }
+}
+
+
+/* this function will parse a
+ WERROR function (
+ construct and generate the appropriate code.
+ the function will be g_removed from the token_list once it has been processed
+ the function assumes that the function is the first object in the token_list
+ the function will be called three times with
+ pass=0 generate subdissectors and entries for the function table
+ pass=1 generate code for the REQUEST
+ pass=2 generate code for the REPLY
+*/
+static void parsefunction(int pass)
+{
+ char *function_name;
+ static int funcno=0;
+ token_item_t *ti;
+ bracket_item_t *bi=NULL;
+ pointer_item_t *pi;
+ const char *pointer_type;
+
+ char tmpstr[BASE_BUFFER_SIZE], *ptmpstr;
+ int level, num_pointers;
+ type_item_t *type_item;
+ char hf_index[BASE_BUFFER_SIZE];
+
+ ti=token_list;
+ if(g_strcmp0(ti->str, "WERROR")){
+ FPRINTF(stderr, "ERROR: function first token is not 'WERROR'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ function_name=ti->str;
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "(")){
+ FPRINTF(stderr, "ERROR: function third token is not '('\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ FPRINTF(NULL,"\nFUNCTION:%s pass:%d\n-------\n",function_name,pass);
+
+ if(pass==0){
+ FPRINTF(eth_ft, " { %d, \"%s\",\n",funcno,function_name);
+ FPRINTF(eth_ft, " %s_dissect_%s_request,\n", ifname, function_name);
+ FPRINTF(eth_ft, " %s_dissect_%s_response },\n", ifname, function_name);
+ funcno++;
+ }
+
+ /* pass 1,2 generate header for the function dissector */
+ if((pass==1)||(pass==2)){
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s_dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_)\n", ifname, function_name, (pass==1)?"request":"response");
+ FPRINTF(eth_code, "{\n");
+ }
+
+ /* scan the struct and create all subdissectors */
+ level=0;
+ while(ti){
+ if(!g_strcmp0(ti->str, "(")){
+ ti=ti->next;
+ level++;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, ")")){
+ if(!level){
+ break;
+ }
+ ti=ti->next;
+ level--;
+ continue;
+ }
+ if(!g_strcmp0(ti->str, "[")){
+ ti=parsebrackets(ti, &bi);
+ continue;
+ }
+
+ if(!bi){
+ FPRINTF(stderr, "ERROR : function no brackets found for case\n");
+ Exit(10);
+ }
+
+ /* make sure we catch when we havent implemented everything
+ yet.
+ we currently only know about IN and OUT flags
+ */
+ if(bi->flags&(~(BI_IN|BI_OUT|BI_POINTER|BI_SIZE_IS|BI_LENGTH_IS))){
+ FPRINTF(stderr, "ERROR: function unknown bracket flags encountered : 0x%08x\n",bi->flags);
+ Exit(10);
+ }
+ if(!(bi->flags&(BI_IN|BI_OUT))){
+ FPRINTF(stderr, "ERROR : function parameter is neither in nor out\n");
+ Exit(10);
+ }
+
+ /* handle the type, verify that we KNOW this type */
+ type_item=find_type(ti->str);
+ if(!type_item){
+ FPRINTF(stderr, "ERROR : function unknown type %s\n",ti->str);
+ Exit(10);
+ }
+ ti=ti->next;
+ /* count the levels of pointers */
+ for(num_pointers=0;!g_strcmp0(ti->str, "*");ti=ti->next){
+ num_pointers++;
+ }
+
+ /* now that we know how many real poitner there were we must
+ prepend default pointers to the list so it has the right
+ length.
+ */
+ pi=prepend_pointer_list(bi->pointer_list, num_pointers);
+
+ snprintf(hf_index, BASE_BUFFER_SIZE, "hf_%s_%s_%s", ifname, function_name, ti->str);
+ /* pass 0 generate subdissectors */
+ if(pass==0){
+ char filter_name[BASE_BUFFER_SIZE];
+ const char *hf;
+
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_%s_%s", ifname, function_name, ti->str);
+ ptmpstr=g_strdup(tmpstr);
+
+ snprintf(filter_name, BASE_BUFFER_SIZE, "%s.%s.%s", ifname, function_name, ti->str);
+ hf=register_hf_field(hf_index, ti->str, filter_name, type_item->ft_type, type_item->base_type, type_item->vals, type_item->mask, "");
+
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", ptmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " guint32 param=%s;\n",find_dissector_param_value(ptmpstr));
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep, %s, param);\n", type_item->dissector, hf);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+
+
+ /* handle switch_is */
+ if(bi){
+ switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+ case 0:
+ break;
+ case BI_SIZE_IS|BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucvarray_%s", ptmpstr);
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_ucvarray(tvb, offset, pinfo, tree, di, drep, %s);\n", ptmpstr);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_SIZE_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucarray_%s", ptmpstr);
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_ucarray(tvb, offset, pinfo, tree, di, drep, %s);\n", ptmpstr);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n");
+ Exit(10);
+ }
+ }
+
+ /* handle pointers */
+ while(num_pointers--){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ FPRINTF(eth_code, "static int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)\n", tmpstr);
+ FPRINTF(eth_code, "{\n");
+ FPRINTF(eth_code, " offset=dissect_ndr_toplevel_pointer(tvb, offset, pinfo, tree, di, drep, %s, %s, \"%s\", -1);\n", ptmpstr, ptr_to_define(pointer_type), ti->str);
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+
+ ptmpstr=g_strdup(tmpstr);
+
+ }
+ }
+
+ if((pass==1)||(pass==2)){
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_dissect_%s_%s", ifname, function_name, ti->str);
+ ptmpstr=g_strdup(tmpstr);
+
+ if(bi){
+ switch(bi->flags&(BI_SIZE_IS|BI_LENGTH_IS)){
+ case 0:
+ break;
+ case BI_SIZE_IS|BI_LENGTH_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucvarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ case BI_SIZE_IS:
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "ucarray_%s", ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ break;
+ default:
+ FPRINTF(stderr, "ERROR: typedeffunction can not handle this combination of sizeis/lengthis\n");
+ Exit(10);
+ }
+ }
+
+ /* handle pointers */
+ while(num_pointers--){
+ pointer_type=pi->type;
+ pi=pi->next;
+ snprintf(tmpstr, BASE_BUFFER_SIZE, "%s_%s", pointer_type, ptmpstr);
+ ptmpstr=g_strdup(tmpstr);
+ }
+
+ if((pass==1)&&(bi->flags&BI_IN)){
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep);\n", ptmpstr);
+ FPRINTF(eth_code, " offset=dissect_deferred_pointers(pinfo, tvb, offset, di, drep);\n");
+ FPRINTF(eth_code, "\n");
+ }
+ if((pass==2)&&(bi->flags&BI_OUT)){
+ FPRINTF(eth_code, " offset=%s(tvb, offset, pinfo, tree, di, drep);\n", ptmpstr);
+ FPRINTF(eth_code, " offset=dissect_deferred_pointers(pinfo, tvb, offset, di, drep);\n");
+ FPRINTF(eth_code, "\n");
+ }
+ }
+ ti=ti->next;
+
+
+ if(!g_strcmp0(ti->str,",")){
+ ti=ti->next;
+ continue;
+ }
+ }
+
+ if((pass==1)||(pass==2)){
+ if(pass==2){
+ FPRINTF(eth_code, " offset=dissect_ntstatus(tvb, offset, pinfo, tree, di, drep, %s, NULL);\n", hf_status);
+ FPRINTF(eth_code, "\n");
+ }
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ }
+
+ FPRINTF(NULL,"\nEND FUNCTION:%s pass:%d\n-------\n",function_name,pass);
+
+ /* only advance token_list for pass==2
+ ti now points to the ')' token
+ */
+ if(pass==2){
+ if(!ti || g_strcmp0(ti->str,")")){
+ FPRINTF(stderr, "ERROR: function does not end with ')'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(!ti || g_strcmp0(ti->str,";")){
+ FPRINTF(stderr, "ERROR: function does not end with ';'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ token_list=ti;
+ }
+}
+
+
+/* this function will parse a
+ typedef enum {
+ or a
+ typedef [ v1_enum ] enum {
+ construct and generate the appropriate code.
+ the typedef will be g_removed from the token_list once it has been processed
+ the function assumes that the typedef is the first object in the token_list
+*/
+static void parsetypedefenum(void)
+{
+ token_item_t *ti;
+ enum_list_t *enum_list, *el, *lastel;
+ char *p;
+ long val;
+ int eval, enumsize;
+ char dissectorname[BASE_BUFFER_SIZE], valsstring[BASE_BUFFER_SIZE], hfvalsstring[BASE_BUFFER_SIZE];
+
+ enumsize=16;
+
+ ti=token_list;
+ if(g_strcmp0(ti->str, "typedef")){
+ FPRINTF(stderr, "ERROR: typedefenum first token is not 'typedef'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* this could be a [ v1_enum ] */
+ if(!g_strcmp0(ti->str, "[")){
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "v1_enum")){
+ FPRINTF(stderr, "ERROR: typedefenum not 'v1_enum' inside brackets\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "]")){
+ FPRINTF(stderr, "ERROR: typedefenum 'v1_enum' is not followed by ']'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ enumsize=32;
+ }
+
+
+ if(g_strcmp0(ti->str, "enum")){
+ FPRINTF(stderr, "ERROR: typedefenum second token is not 'enum'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ if(g_strcmp0(ti->str, "{")){
+ FPRINTF(stderr, "ERROR: typedefenum third token is not '{'\n");
+ Exit(10);
+ }
+ ti=ti->next;
+
+ /* now parse all values until we find the "}" */
+ eval=0;
+ enum_list=NULL;
+ lastel=NULL;
+ while(1){
+ /* check for '}' */
+ if(!g_strcmp0(ti->str,"}")){
+ ti=ti->next;
+ break;
+ }
+
+ /* handle 4 types of entries:
+ * 1, CONST = value,
+ * 2, CONST,
+ * 3, CONST = value}
+ * 4, CONST}
+ */
+ el=g_new0(enum_list_t, 1);
+ if (!el) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ el->next=NULL;
+ if(!enum_list){
+ enum_list=el;
+ } else {
+ lastel->next=el;
+ }
+ lastel=el;
+
+ /* grab CONST */
+ el->name=ti->str;
+ ti=ti->next;
+
+ /* grab separator */
+ if(!g_strcmp0(ti->str,"=")){
+ ti=ti->next;
+ /* grab value */
+ val=strtol(ti->str,&p,0);
+ if (p==ti->str||*p) {
+ FPRINTF(stderr, "ERROR: typedefenum value is not a number\n");
+ Exit(10);
+ }
+ el->val=(int)val;
+ ti=ti->next;
+ } else {
+ el->val=eval;
+ }
+ eval=el->val+1;
+
+ /* check for ',' */
+ if(!g_strcmp0(ti->str,",")){
+ ti=ti->next;
+ continue;
+ }
+
+ /* check for '}' */
+ if(!g_strcmp0(ti->str,"}")){
+ ti=ti->next;
+ break;
+ }
+
+ FPRINTF(stderr,"ERROR: typedefenum should not be reached\n");
+ Exit(10);
+ }
+
+ /* verify that it ends with a ';' */
+ if(g_strcmp0(ti->next->str,";")){
+ FPRINTF(stderr,"ERROR enum terminator is not ';'\n");
+ Exit(10);
+ }
+
+ snprintf(valsstring, BASE_BUFFER_SIZE, "%s_%s_vals", ifname, ti->str);
+ snprintf(dissectorname, DISSECTORNAME_MAXLEN, "%s_dissect_%s", ifname, ti->str);
+
+ FPRINTF(NULL,"\nENUM:%s\n-------\n",ti->str);
+
+ FPRINTF(eth_hdr, "\n");
+ for(el=enum_list;el;el=el->next){
+ FPRINTF(eth_hdr, "#define %s %d\n", el->name, el->val);
+ }
+
+ FPRINTF(eth_hdr, "\n");
+ FPRINTF(eth_hdr, "extern const value_string %s[];\n", valsstring);
+ FPRINTF(eth_hdr, "int %s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param);\n", dissectorname);
+
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "const value_string %s[] = {\n", valsstring);
+
+ for(el=enum_list;el;el=el->next){
+ FPRINTF(eth_code, " { %d , \"%s\" },\n", el->val, el->name);
+ }
+ FPRINTF(eth_code, " { 0 , NULL }\n");
+ FPRINTF(eth_code, "};\n");
+
+ FPRINTF(eth_code, "\n");
+ FPRINTF(eth_code, "int\n");
+ FPRINTF(eth_code, "%s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hf_index, guint32 param _U_)\n", dissectorname);
+ FPRINTF(eth_code, "{\n");
+ switch(enumsize){
+ case 16:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint16(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ break;
+ case 32:
+ FPRINTF(eth_code, " offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf_index, NULL);\n");
+ break;
+ default:
+ FPRINTF(stderr,"ERROR enum unknown size\n");
+ Exit(10);
+ }
+
+ FPRINTF(eth_code, " return offset;\n");
+ FPRINTF(eth_code, "}\n");
+ FPRINTF(eth_code, "\n");
+
+
+ snprintf(hfvalsstring, BASE_BUFFER_SIZE, "VALS(%s)", valsstring);
+ switch(enumsize){
+ case 16:
+ register_new_type(ti->str, dissectorname, "FT_INT16", "BASE_DEC", "0", hfvalsstring, 2);
+ break;
+ case 32:
+ register_new_type(ti->str, dissectorname, "FT_INT32", "BASE_DEC", "0", hfvalsstring, 4);
+ break;
+ default:
+ FPRINTF(stderr,"ERROR enum unknown size\n");
+ Exit(10);
+ }
+
+ FPRINTF(NULL,"\n----------\nEND ENUM:%s\n",ti->str);
+
+ /* skip past the name and the ';' */
+ token_list=ti->next->next;
+}
+
+typedef struct _trimmed_prefixes_t {
+ struct _trimmed_prefixes_t *next;
+ char *name;
+} trimmed_prefixes_t;
+static trimmed_prefixes_t *prefixes_to_trim=NULL;
+
+static void preparetrimprefix(char *prefix_name)
+{
+ trimmed_prefixes_t *new_prefix;
+ new_prefix=g_new0(trimmed_prefixes_t, 1);
+ if (!new_prefix) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ new_prefix->next=prefixes_to_trim;
+ prefixes_to_trim=new_prefix;
+ new_prefix->name=g_strdup(prefix_name);
+}
+
+static void
+trimprefix(void)
+{
+ token_item_t *ti;
+ trimmed_prefixes_t *pfx;
+ size_t len;
+
+ for(pfx=prefixes_to_trim;pfx;pfx=pfx->next){
+ len=strlen(pfx->name);
+ for(ti=token_list;ti;ti=ti->next){
+ if(!strncmp(ti->str, pfx->name, len)){
+ ti->str+=len;
+ }
+ }
+ }
+}
+
+static int Exit(int code)
+{
+ FPRINTF(stderr, "The tokens remaining when aborting:\n");
+ printtokenlist(10);
+
+ exit(code);
+}
+
+static void usage(void)
+{
+ FPRINTF(stderr, "Usage: idl2wrs <interface>\n");
+}
+
+static void
+mergefile(const char *name, FILE *outfile)
+{
+ FILE *infile;
+
+ FPRINTF(outfile, "\n\n/* INCLUDED FILE : %s */\n", name);
+ infile=g_fopen(name, "r");
+ while(!feof(infile)){
+ int ch;
+ ch=fgetc(infile);
+ if(ch!=-1){
+ fputc(ch, outfile);
+ }
+ }
+ fclose(infile);
+ FPRINTF(outfile, "/* END OF INCLUDED FILE : %s */\n\n\n", name);
+}
+
+
+
+static char *
+str_read_string(char *str, char **name)
+{
+ char tmpstr[BASE_BUFFER_SIZE], *strptr;
+ int skip_blanks;
+ int quoted_string;
+
+ strptr=tmpstr;
+ skip_blanks=1;
+ quoted_string=0;
+ while(1){
+ if(!*str){
+ *strptr=0;
+ *name=g_strdup(tmpstr);
+ return str;
+ }
+ if(skip_blanks){
+ if( (*str==' ') || (*str=='\t') ){
+ str++;
+ continue;
+ }
+ if( *str=='"' ){
+ str++;
+ quoted_string=1;
+ }
+ skip_blanks=0;
+ continue;
+ }
+ if( (*str==' ') || (*str=='\t') ){
+ if(quoted_string){
+ *strptr++ = *str++;
+ continue;
+ }
+ *strptr=0;
+ *name=g_strdup(tmpstr);
+ return str;
+ }
+ if( (*str=='"') || (*str=='\n') ){
+ *strptr=0;
+ *name=g_strdup(tmpstr);
+ return ++str;
+ }
+ *strptr++ = *str++;
+ }
+ return NULL;
+}
+
+static void
+readcnffile(FILE *fh)
+{
+ char cnfline[4 * BASE_BUFFER_SIZE];
+
+ FPRINTF(NULL, "Reading conformance file\n=======================\n");
+ while(!feof(fh)){
+ cnfline[0]=0;
+ if(!fgets(cnfline, 4 * BASE_BUFFER_SIZE, fh) || !cnfline[0]){
+ continue;
+ }
+ if(cnfline[0]=='#'){
+ /* ignore all comments */
+ } else if(!strncmp(cnfline, "NOEMIT", 6)){
+ no_emit_item_t *nei;
+ char *str, *name;
+
+ str=cnfline+6;
+ str_read_string(str, &name);
+ nei=g_new0(no_emit_item_t, 1);
+ if (!nei) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ nei->next=no_emit_list;
+ no_emit_list=nei;
+ nei->name=name;
+ FPRINTF(NULL, "NOEMIT : %s\n", nei->name);
+ } else if(!strncmp(cnfline, "TYPE", 4)){
+ char *name, *dissectorname, *ft_type, *base_type;
+ char *mask, *valsstring, *al;
+ char *str;
+ int alignment;
+
+ str=cnfline+4;
+ str=str_read_string(str, &name);
+ str=str_read_string(str, &dissectorname);
+ str=str_read_string(str, &ft_type);
+ str=str_read_string(str, &base_type);
+ str=str_read_string(str, &mask);
+ str=str_read_string(str, &valsstring);
+ str_read_string(str, &al);
+ if (ws_strtoi32(al, NULL, &alignment)) {
+ FPRINTF(NULL, "TYPE : X%s,%sX\n", name, dissectorname);
+ register_new_type(name, dissectorname, ft_type, base_type, mask, valsstring, alignment);
+ }
+ } else if(!strncmp(cnfline, "PARAM_VALUE", 11)){
+ char *dissectorname, *value;
+ char *str;
+
+ str=cnfline+11;
+ str=str_read_string(str, &dissectorname);
+ str_read_string(str, &value);
+
+ FPRINTF(NULL, "PARAM_VALUE : %s=%s\n", dissectorname,value);
+ register_dissector_param_value(dissectorname, value);
+ } else if(!strncmp(cnfline, "HF_FIELD", 8)){
+ char *hf_index, *title, *filter_name, *ft_type;
+ char *base_type, *valsstring, *mask, *blurb;
+ char *str;
+
+ str=cnfline+8;
+ str=str_read_string(str, &hf_index);
+ str=str_read_string(str, &title);
+ str=str_read_string(str, &filter_name);
+ str=str_read_string(str, &ft_type);
+ str=str_read_string(str, &base_type);
+ str=str_read_string(str, &valsstring);
+ str=str_read_string(str, &mask);
+ str_read_string(str, &blurb);
+ FPRINTF(NULL, "HF_FIELD: %s \"%s\"\n", hf_index, title);
+ register_hf_field(hf_index, title, filter_name, ft_type, base_type, valsstring, mask, blurb);
+ } else if(!strncmp(cnfline, "HF_RENAME", 9)){
+ char *old_name, *new_name;
+ char *str;
+
+ str=cnfline+9;
+ str=str_read_string(str, &old_name);
+ str_read_string(str, &new_name);
+ FPRINTF(NULL, "HF_RENAME: %s -> %s\n", old_name, new_name);
+ register_hf_rename(old_name, new_name);
+ } else if(!strncmp(cnfline, "UNION_TAG_SIZE", 14)){
+ char *union_name, *union_tag;
+ gint32 union_tag_size;
+ union_tag_size_item_t *utsi;
+ char *str;
+
+ str=cnfline+14;
+ str=str_read_string(str, &union_name);
+ str_read_string(str, &union_tag);
+ if (!ws_strtoi32(union_tag, NULL, &union_tag_size)) {
+ FPRINTF(NULL, "UNION_TAG_SIZE: invalid string: %s\n", union_tag);
+ exit(10);
+ }
+ FPRINTF(NULL, "UNION_TAG_SIZE: %s == %d\n", union_name, union_tag_size);
+ utsi=g_new0(union_tag_size_item_t, 1);
+ if (!utsi) {
+ FPRINTF(stderr, "Can't allocate memory. Exit.\n");
+ exit(10);
+ }
+ utsi->next=union_tag_size_list;
+ union_tag_size_list=utsi;
+ utsi->name=g_strdup(union_name);
+ utsi->size=union_tag_size;
+ } else if(!strncmp(cnfline, "STRIP_PREFIX", 12)){
+ char *prefix_name;
+ char *str;
+
+ str=cnfline+12;
+ str_read_string(str, &prefix_name);
+ FPRINTF(NULL, "STRIP_PREFIX: %s\n", prefix_name);
+ preparetrimprefix(prefix_name);
+ } else {
+ FPRINTF(stderr, "ERROR: could not parse cnf directive:%s\n",cnfline);
+ exit(10);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char idlfile[BASE_BUFFER_SIZE];
+ char tmplfile[BASE_BUFFER_SIZE];
+ char prefix_str[BASE_BUFFER_SIZE];
+ bracket_item_t *bi;
+ FILE *fh;
+
+ if(argc!=2){
+ usage();
+ exit(0);
+ }
+
+ eth_code=g_fopen("ETH_CODE", "w");
+ eth_hdr=g_fopen("ETH_HDR", "w");
+ eth_hfarr=g_fopen("ETH_HFARR", "w");
+ eth_hf=g_fopen("ETH_HF", "w");
+ eth_ettarr=g_fopen("ETH_ETTARR", "w");
+ eth_ett=g_fopen("ETH_ETT", "w");
+ eth_ft=g_fopen("ETH_FT", "w");
+ eth_handoff=g_fopen("ETH_HANDOFF", "w");
+
+ snprintf(idlfile, BASE_BUFFER_SIZE, "%s.cnf", argv[1]);
+ fh=g_fopen(idlfile,"r");
+ if(fh){
+ readcnffile(fh);
+ fclose(fh);
+ }
+
+ snprintf(idlfile, BASE_BUFFER_SIZE, "%s.idl", argv[1]);
+ fh=g_fopen(idlfile,"r");
+ if(!fh){
+ FPRINTF(stderr, "ERROR: could not open idl-file:%s\n", idlfile);
+ Exit(0);
+ }
+
+ lineno=0;
+ linepos=0;
+ tokenize(fh);
+ prune_keyword_parameters("size_is");
+ prune_keyword_parameters("length_is");
+ rename_tokens("NTSTATUS", "WERROR");
+ rename_tokens("unistr_noterm", "unistr");
+ rename_tokens("ascstr_noterm", "ascstr");
+ rename_tokens("hyper", "uint64");
+ FPRINTF(NULL,"\n\nParsing header:\n================\n");
+ parseheader();
+
+ /* some idl files prepend a lot of symbols with <ifname>_
+ search through the tokenlist and g_remove all such
+ prefixes
+ */
+ snprintf(prefix_str, BASE_BUFFER_SIZE, "%s_", ifname);
+ preparetrimprefix(prefix_str);
+ trimprefix();
+
+ /* this is the main loop, each iteration it tries to identify what
+ kind of construct is the first entry in the token_list and call
+ the appropriate handler
+ */
+ while(1) {
+ /* just skip any [ ] that starts a new construct */
+ if( !g_strcmp0(token_list->str, "[") ){
+ token_list=parsebrackets(token_list, &bi);
+ continue;
+ }
+
+ /* typedef enum { */
+ if( !g_strcmp0(token_list->str,"typedef")
+ &&!g_strcmp0(token_list->next->str,"enum") ){
+ parsetypedefenum();
+ continue;
+ }
+
+ /* typedef [ v1_enum ] enum { */
+ if( !g_strcmp0(token_list->str,"typedef")
+ &&!g_strcmp0(token_list->next->str,"[")
+ &&!g_strcmp0(token_list->next->next->str,"v1_enum")
+ &&!g_strcmp0(token_list->next->next->next->str,"]")
+ &&!g_strcmp0(token_list->next->next->next->next->str,"enum") ){
+ parsetypedefenum();
+ continue;
+ }
+
+ /* const */
+ if( !g_strcmp0(token_list->str,"const") ){
+ parseconst();
+ continue;
+ }
+
+ /* typedef struct { */
+ if( !g_strcmp0(token_list->str,"typedef") ){
+ token_item_t *tmpti;
+
+ tmpti=token_list->next;
+ if( !g_strcmp0(tmpti->str, "[") ){
+ tmpti=parsebrackets(tmpti, &bi);
+ /* do some sanity checks here of bi->flags */
+ }
+ if( !g_strcmp0(tmpti->str, "struct") ){
+ parsetypedefstruct(0);
+ parsetypedefstruct(1);
+ continue;
+ }
+ }
+
+ /* typedef union { */
+ if( !g_strcmp0(token_list->str,"typedef") ){
+ token_item_t *tmpti;
+
+ tmpti=token_list->next;
+ if( !g_strcmp0(tmpti->str, "[") ){
+ tmpti=parsebrackets(tmpti, &bi);
+ /* do some sanity checks here of bi->flags */
+ }
+ if( !g_strcmp0(tmpti->str, "union") ){
+ parsetypedefunion(0);
+ parsetypedefunion(1);
+ continue;
+ }
+ }
+
+ /* typedef bitmap { */
+ if( !g_strcmp0(token_list->str,"typedef") ){
+ token_item_t *tmpti;
+
+ tmpti=token_list->next;
+ if( !g_strcmp0(tmpti->str, "[") ){
+ tmpti=parsebrackets(tmpti, &bi);
+ /* do some sanity checks here of bi->flags */
+ }
+ if( !g_strcmp0(tmpti->str, "bitmap") ){
+ parsetypedefbitmap(0);
+ parsetypedefbitmap(1);
+ continue;
+ }
+ }
+
+ /* functions: WERROR function '(' */
+ if( !g_strcmp0(token_list->str,"WERROR")
+ &&!g_strcmp0(token_list->next->next->str,"(") ){
+ parsefunction(0);
+ parsefunction(1);
+ parsefunction(2);
+ continue;
+ }
+
+ /* declare ... ; */
+ if( !g_strcmp0(token_list->str,"declare") ){
+ skipdeclare();
+ continue;
+ }
+
+
+ break;
+ };
+
+
+ fclose(eth_code);
+ fclose(eth_hdr);
+ fclose(eth_hf);
+ fclose(eth_hfarr);
+ fclose(eth_ett);
+ fclose(eth_ettarr);
+ fclose(eth_ft);
+ fclose(eth_handoff);
+
+ /* unless the token_list now only contains a single token : '}'
+ we have failed to compile the idl file properly
+ */
+ if( g_strcmp0(token_list->str, "}") || token_list->next){
+ FPRINTF(stderr, "ERROR: we did not process all tokens. Compiler is incomplete.\n===========================================\n");
+ printtokenlist(10);
+ exit(10);
+ }
+
+ check_hf_rename_refcount();
+
+ /* merge code and template into dissector */
+ snprintf(line, 4 * BASE_BUFFER_SIZE, "packet-dcerpc-%s.c", ifname);
+ fh=g_fopen(line, "w");
+ snprintf(tmplfile, BASE_BUFFER_SIZE, "packet-dcerpc-%s-template.c", argv[1]);
+ tfh=g_fopen(tmplfile, "r");
+ if(!tfh){
+ FPRINTF(stderr, "ERROR: could not find %s\n", tmplfile);
+ exit(10);
+ }
+ while(!feof(tfh)){
+ line[0]=0;
+ if(!fgets(line, 4 * BASE_BUFFER_SIZE, tfh) || !line[0]){
+ continue;
+ }
+ if(!strncmp(line, "ETH_CODE", 8)){
+ mergefile("ETH_CODE",fh);
+ } else if(!strncmp(line, "ETH_HDR", 7)){
+ mergefile("ETH_HDR",fh);
+ } else if(!strncmp(line, "ETH_HFARR", 9)){
+ mergefile("ETH_HFARR",fh);
+ } else if(!strncmp(line, "ETH_HF", 6)){
+ mergefile("ETH_HF",fh);
+ } else if(!strncmp(line, "ETH_ETTARR", 10)){
+ mergefile("ETH_ETTARR",fh);
+ } else if(!strncmp(line, "ETH_ETT", 7)){
+ mergefile("ETH_ETT",fh);
+ } else if(!strncmp(line, "ETH_FT", 6)){
+ mergefile("ETH_FT",fh);
+ } else if(!strncmp(line, "ETH_HANDOFF", 11)){
+ mergefile("ETH_HANDOFF",fh);
+ } else {
+ fputs(line, fh);
+ }
+ }
+ fclose(fh);
+ fclose(tfh);
+
+ snprintf(line, 4 * BASE_BUFFER_SIZE, "packet-dcerpc-%s.h", ifname);
+ fh=g_fopen(line, "w");
+ snprintf(tmplfile, BASE_BUFFER_SIZE, "packet-dcerpc-%s-template.h", argv[1]);
+ tfh=g_fopen(tmplfile, "r");
+ if(!tfh){
+ FPRINTF(stderr, "ERROR: could not find %s\n", tmplfile);
+ exit(10);
+ }
+ while(!feof(tfh)){
+ line[0]=0;
+ if(!fgets(line, 4 * BASE_BUFFER_SIZE, tfh) || !line[0]){
+ continue;
+ }
+ if(!strncmp(line, "ETH_CODE", 8)){
+ mergefile("ETH_CODE",fh);
+ } else if(!strncmp(line, "ETH_HDR", 7)){
+ mergefile("ETH_HDR",fh);
+ } else if(!strncmp(line, "ETH_HFARR", 9)){
+ mergefile("ETH_HFARR",fh);
+ } else if(!strncmp(line, "ETH_HF", 6)){
+ mergefile("ETH_HF",fh);
+ } else if(!strncmp(line, "ETH_ETTARR", 10)){
+ mergefile("ETH_ETTARR",fh);
+ } else if(!strncmp(line, "ETH_ETT", 7)){
+ mergefile("ETH_ETT",fh);
+ } else if(!strncmp(line, "ETH_FT", 6)){
+ mergefile("ETH_FT",fh);
+ } else if(!strncmp(line, "ETH_HANDOFF", 11)){
+ mergefile("ETH_HANDOFF",fh);
+ } else {
+ fputs(line, fh);
+ }
+ }
+
+ g_print("%s was successfully compiled\n", ifname);
+
+ fclose(fh);
+ fclose(tfh);
+
+ if (g_remove("ETH_CODE") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_HDR") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_HFARR") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_HF") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_ETTARR") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_ETT") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_FT") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+ if (g_remove("ETH_HANDOFF") == -1) {
+ FPRINTF(stderr, "Can't remove ETH_CODE");
+ }
+
+
+ return 0;
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */