diff options
Diffstat (limited to 'epan/dissectors/dcerpc')
-rw-r--r-- | epan/dissectors/dcerpc/CMakeLists.txt | 70 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/budb/budb.cnf | 4 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/budb/budb.idl | 695 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.c | 72 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/budb/packet-dcerpc-budb-template.h | 20 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/butc/butc.cnf | 6 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/butc/butc.idl | 487 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.c | 71 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/butc/packet-dcerpc-butc-template.h | 19 | ||||
-rw-r--r-- | epan/dissectors/dcerpc/idl2wrs.c | 3521 |
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: + */ |