#include "idl_types.h"

/*
   IDL structures for NBT operations

   NBT is not traditionally encoded using IDL/NDR. This is a bit of an
   experiment, and I may well switch us back to a more traditional
   encoding if it doesn't work out
*/

import "misc.idl", "security.idl";
[
	helper("../librpc/ndr/ndr_nbt.h"),
	helpstring("NBT messages"),
	uuid("6def41b6-86e4-4c32-997c-ed33af7bcd8e")
]
interface nbt
{
	const int NBT_NAME_SERVICE_PORT  = 137;
	const int NBT_DGRAM_SERVICE_PORT = 138;

	typedef [bitmap16bit] bitmap {
		NBT_RCODE                   = 0x000F,
		NBT_FLAG_BROADCAST          = 0x0010,
		NBT_FLAG_RECURSION_AVAIL    = 0x0080,
		NBT_FLAG_RECURSION_DESIRED  = 0x0100,
		NBT_FLAG_TRUNCATION         = 0x0200,
		NBT_FLAG_AUTHORITATIVE      = 0x0400,
		NBT_OPCODE                  = 0x7800,
		NBT_FLAG_REPLY              = 0x8000
	} nbt_operation;

	/* the opcodes are in the operation field, masked with
	   NBT_OPCODE */
	typedef enum {
		NBT_OPCODE_QUERY          =  (0x0<<11),
		NBT_OPCODE_REGISTER       =  (0x5<<11),
		NBT_OPCODE_RELEASE        =  (0x6<<11),
		NBT_OPCODE_WACK           =  (0x7<<11),
		NBT_OPCODE_REFRESH        =  (0x8<<11),
		NBT_OPCODE_REFRESH2       =  (0x9<<11),
		NBT_OPCODE_MULTI_HOME_REG =  (0xf<<11)
	} nbt_opcode;

	/* rcode values */
	typedef enum {
		NBT_RCODE_OK  = 0x0,
		NBT_RCODE_FMT = 0x1,
		NBT_RCODE_SVR = 0x2,
		NBT_RCODE_NAM = 0x3,
		NBT_RCODE_IMP = 0x4,
		NBT_RCODE_RFS = 0x5,
		NBT_RCODE_ACT = 0x6,
		NBT_RCODE_CFT = 0x7
	} nbt_rcode;

	/* we support any 8bit name type, but by defining the common
	   ones here we get better debug displays */
	typedef [enum8bit] enum {
		NBT_NAME_CLIENT   = 0x00,
		NBT_NAME_MS       = 0x01,
		NBT_NAME_USER     = 0x03,
		NBT_NAME_SERVER   = 0x20,
		NBT_NAME_PDC      = 0x1B,
		NBT_NAME_LOGON    = 0x1C,
		NBT_NAME_MASTER   = 0x1D,
		NBT_NAME_BROWSER  = 0x1E
	} nbt_name_type;

	/* the ndr parser for nbt_name is separately defined in
	   nbtname.c (along with the parsers for nbt_string) */
	typedef [public,nopull,nopush] struct {
		string        name;
		string        scope;
		nbt_name_type type;
	} nbt_name;

	typedef [public,enum16bit] enum {
		NBT_QCLASS_IP = 0x01
	} nbt_qclass;

	typedef [public,enum16bit] enum {
		NBT_QTYPE_ADDRESS     = 0x0001,
		NBT_QTYPE_NAMESERVICE = 0x0002,
		NBT_QTYPE_NULL        = 0x000A,
		NBT_QTYPE_NETBIOS     = 0x0020,
		NBT_QTYPE_STATUS      = 0x0021
	} nbt_qtype;

	typedef struct {
		nbt_name   name;
		nbt_qtype  question_type;
		nbt_qclass question_class;
	} nbt_name_question;

	/* these are the possible values of the NBT_NM_OWNER_TYPE
	   field */
	typedef enum {
		NBT_NODE_B = 0x0000,
		NBT_NODE_P = 0x2000,
		NBT_NODE_M = 0x4000,
		NBT_NODE_H = 0x6000
	} nbt_node_type;

	typedef [bitmap16bit] bitmap {
		NBT_NM_PERMANENT        = 0x0200,
		NBT_NM_ACTIVE           = 0x0400,
		NBT_NM_CONFLICT         = 0x0800,
		NBT_NM_DEREGISTER       = 0x1000,
		NBT_NM_OWNER_TYPE       = 0x6000,
		NBT_NM_GROUP            = 0x8000
	} nb_flags;

	typedef struct {
		nb_flags nb_flags;
		ipv4address ipaddr;
	} nbt_rdata_address;

	typedef struct {
		uint16 length;
		nbt_rdata_address addresses[length/6];
	} nbt_rdata_netbios;

	typedef struct {
		uint8 unit_id[6];
		uint8 jumpers;
		uint8 test_result;
		uint16 version_number;
		uint16 period_of_statistics;
		uint16 number_of_crcs;
		uint16 number_alignment_errors;
		uint16 number_of_collisions;
		uint16 number_send_aborts;
		uint32 number_good_sends;
		uint32 number_good_receives;
		uint16 number_retransmits;
		uint16 number_no_resource_conditions;
		uint16 number_free_command_blocks;
		uint16 total_number_command_blocks;
		uint16 max_total_number_command_blocks;
		uint16 number_pending_sessions;
		uint16 max_number_pending_sessions;
		uint16 max_total_sessions_possible;
		uint16 session_data_packet_size;
	} nbt_statistics;

	typedef struct {
		[charset(DOS)] uint8 name[15];
		nbt_name_type type;
		nb_flags  nb_flags;
	} nbt_status_name;

	typedef struct {
		[value(num_names * 18 + 47)] uint16 length;
		uint8 num_names;
		nbt_status_name names[num_names];
		nbt_statistics  statistics;
	} nbt_rdata_status;

	typedef struct {
		uint16 length;
		uint8  data[length];
	} nbt_rdata_data;

	typedef [nodiscriminant,public] union {
		[case(NBT_QTYPE_NETBIOS)] nbt_rdata_netbios netbios;
		[case(NBT_QTYPE_STATUS)]  nbt_rdata_status status;
		[default]                 nbt_rdata_data   data;
	} nbt_rdata;

/*
 * this macro works around the problem
 * that we need to use nbt_rdata_data
 * together with NBT_QTYPE_NETBIOS
 * for WACK replies
 */
	typedef [flag(LIBNDR_PRINT_ARRAY_HEX),nopush] struct {
		nbt_name   name;
		nbt_qtype  rr_type;
		nbt_qclass rr_class;
		uint32     ttl;
		[switch_is(rr_type)] nbt_rdata rdata;
	} nbt_res_rec;

	typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct {
		uint16            name_trn_id;
		nbt_operation     operation;
		uint16            qdcount;
		uint16            ancount;
		uint16            nscount;
		uint16            arcount;
		nbt_name_question questions[qdcount];
		nbt_res_rec       answers[ancount];
		nbt_res_rec       nsrecs[nscount];
		nbt_res_rec       additional[arcount];
		[flag(NDR_REMAINING)] DATA_BLOB padding;
	} nbt_name_packet;


	/*
	  NBT DGRAM packets (UDP/138)
	*/

	typedef [enum8bit] enum {
		DGRAM_DIRECT_UNIQUE  = 0x10,
		DGRAM_DIRECT_GROUP   = 0x11,
		DGRAM_BCAST          = 0x12,
		DGRAM_ERROR          = 0x13,
		DGRAM_QUERY          = 0x14,
		DGRAM_QUERY_POSITIVE = 0x15,
		DGRAM_QUERY_NEGATIVE = 0x16
	} dgram_msg_type;

	typedef [bitmap8bit] bitmap {
		DGRAM_FLAG_MORE         = 0x01,
		DGRAM_FLAG_FIRST        = 0x02,
		DGRAM_FLAG_NODE_TYPE    = 0x0C
	} dgram_flags;

	typedef [enum8bit] enum {
		DGRAM_NODE_B    = 0x00,
		DGRAM_NODE_P    = 0x04,
		DGRAM_NODE_M    = 0x08,
		DGRAM_NODE_NBDD = 0x0C
	} dgram_node_type;

	/* a dgram_message is the main dgram body in general use */

	/* the most common datagram type is a SMB_TRANSACTION
	   operation, where a SMB packet is used in the data section
	   of a dgram_message to hold a trans request, which in turn
	   holds a small command structure. It's a very strange beast
	   indeed. To make the code cleaner we define a basic SMB
	   packet in IDL here. This is not a general purpose SMB
	   packet, and won't be used in the core SMB client/server
	   code, but it does make working with these types of dgrams
	   easier */

	const string NBT_MAILSLOT_NETLOGON = "\\MAILSLOT\\NET\\NETLOGON";
	const string NBT_MAILSLOT_NTLOGON  = "\\MAILSLOT\\NET\\NTLOGON";
	const string NBT_MAILSLOT_GETDC    = "\\MAILSLOT\\NET\\GETDC";
	const string NBT_MAILSLOT_BROWSE   = "\\MAILSLOT\\BROWSE";

	typedef [enum8bit] enum {
		SMB_TRANSACTION = 0x25
	} smb_command;

	typedef struct {
		[range(17,17),value(17)] uint8 wct;
		uint16                      total_param_count;
		uint16                      total_data_count;
		uint16                      max_param_count;
		uint16                      max_data_count;
		uint8                       max_setup_count;
		uint8                       pad;
		uint16                      trans_flags;
		uint32                      timeout;
		uint16                      reserved;
		uint16                      param_count;
		uint16                      param_offset;
		uint16                      data_count;
		uint16                      data_offset;
		[range(3,3),value(3)] uint8 setup_count;
		uint8                       pad2;
		uint16                      opcode;
		uint16                      priority;
		uint16                      _class;
		[value(strlen(mailslot_name)+1+data.length)]
		      uint16                byte_count;
		astring                     mailslot_name;
		[flag(NDR_REMAINING)]       DATA_BLOB data;
	} smb_trans_body;

	typedef [nodiscriminant] union {
		[case(SMB_TRANSACTION)] smb_trans_body trans;
	} smb_body;


	typedef [flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN|NDR_PAHEX),public] struct {
		smb_command                smb_command;
		uint8                      err_class;
		uint8                      pad;
		uint16                     err_code;
		uint8                      flags;
		uint16                     flags2;
		uint16                     pid_high;
		uint8                      signature[8];
		uint16                     reserved;
		uint16                     tid;
		uint16                     pid;
		uint16                     vuid;
		uint16                     mid;
		[switch_is(smb_command)]   smb_body body;
	} dgram_smb_packet;

	const uint32 DGRAM_SMB = 0xff534d42; /* 0xffSMB */

	typedef [nodiscriminant] union {
		[case(DGRAM_SMB)] dgram_smb_packet smb;
	} dgram_message_body;

	typedef struct {
		uint16          length;
		uint16          offset;
		nbt_name        source_name;
		nbt_name        dest_name;
		uint32		dgram_body_type;
		[switch_is(dgram_body_type)] dgram_message_body body;
	} dgram_message;

	typedef [enum8bit] enum {
		DGRAM_ERROR_NAME_NOT_PRESENT = 0x82,
		DGRAM_ERROR_INVALID_SOURCE   = 0x83,
		DGRAM_ERROR_INVALID_DEST     = 0x84
	} dgram_err_code;

	typedef [nodiscriminant] union {
		[case(DGRAM_DIRECT_UNIQUE)]   dgram_message  msg;
		[case(DGRAM_DIRECT_GROUP)]    dgram_message  msg;
		[case(DGRAM_BCAST)]           dgram_message  msg;
		[case(DGRAM_ERROR)]           dgram_err_code error;
		[case(DGRAM_QUERY)]           nbt_name       dest_name;
		[case(DGRAM_QUERY_POSITIVE)]  nbt_name       dest_name;
		[case(DGRAM_QUERY_NEGATIVE)]  nbt_name       dest_name;
	} dgram_data;

	typedef [flag(NDR_NOALIGN|NDR_BIG_ENDIAN|NDR_PAHEX),public] struct {
		dgram_msg_type msg_type;
		dgram_flags    flags;
		uint16         dgram_id;
		ipv4address    src_addr;
		uint16         src_port;
		[switch_is(msg_type)] dgram_data data;
	} nbt_dgram_packet;


	/******************************************
	 * \MAILSLOT\NET\NETLOGON mailslot requests
	 * and
	 * \MAILSLOT\NET\NTLOGON mailslot requests
	 */

	typedef [public,gensize] struct {
		uint32			sockaddr_family;
		[flag(NDR_BIG_ENDIAN)]	ipv4address pdc_ip;
		[flag(NDR_REMAINING)]	DATA_BLOB remaining;
	} nbt_sockaddr;

	typedef [bitmap32bit,public] bitmap {
		NBT_SERVER_PDC				= 0x00000001,
		NBT_SERVER_GC				= 0x00000004,
		NBT_SERVER_LDAP				= 0x00000008,
		NBT_SERVER_DS				= 0x00000010,
		NBT_SERVER_KDC				= 0x00000020,
		NBT_SERVER_TIMESERV			= 0x00000040,
		NBT_SERVER_CLOSEST			= 0x00000080,
		NBT_SERVER_WRITABLE			= 0x00000100,
		NBT_SERVER_GOOD_TIMESERV		= 0x00000200,
		NBT_SERVER_NDNC				= 0x00000400,
		NBT_SERVER_SELECT_SECRET_DOMAIN_6	= 0x00000800,
		NBT_SERVER_FULL_SECRET_DOMAIN_6		= 0x00001000,
		NBT_SERVER_ADS_WEB_SERVICE		= 0x00002000,
		NBT_SERVER_DS_8				= 0x00004000,
		NBT_SERVER_HAS_DNS_NAME			= 0x20000000,
		NBT_SERVER_IS_DEFAULT_NC		= 0x40000000,
		NBT_SERVER_FOREST_ROOT			= 0x80000000
	} nbt_server_type;

	typedef [bitmap32bit,public] bitmap {
		NETLOGON_NT_VERSION_1			= 0x00000001,
		NETLOGON_NT_VERSION_5			= 0x00000002,
		NETLOGON_NT_VERSION_5EX			= 0x00000004,
		NETLOGON_NT_VERSION_5EX_WITH_IP		= 0x00000008,
		NETLOGON_NT_VERSION_WITH_CLOSEST_SITE	= 0x00000010,
		NETLOGON_NT_VERSION_AVOID_NT4EMUL	= 0x01000000,
		NETLOGON_NT_VERSION_PDC			= 0x10000000,
		NETLOGON_NT_VERSION_IP			= 0x20000000,
		NETLOGON_NT_VERSION_LOCAL		= 0x40000000,
		NETLOGON_NT_VERSION_GC			= 0x80000000
	} netlogon_nt_version_flags;

	typedef [enum16bit,public] enum {
		LOGON_REQUEST			  = 0,
		LOGON_RESPONSE2			  = 6,
		LOGON_PRIMARY_QUERY               = 7,	/* Was also NETLOGON_QUERY_FOR_PDC */
		NETLOGON_ANNOUNCE_UAS             = 10,
		NETLOGON_RESPONSE_FROM_PDC        = 12,
		LOGON_SAM_LOGON_REQUEST           = 18, /* Was also NETLOGON_QUERY_FOR_PDC2, NTLOGON_SAM_LOGON */
		LOGON_SAM_LOGON_RESPONSE          = 19, /* Was also NTLOGON_SAM_LOGON_REPLY */
		LOGON_SAM_LOGON_PAUSE_RESPONSE    = 20,
		LOGON_SAM_LOGON_USER_UNKNOWN      = 21, /* Was also NTLOGON_SAM_LOGON_REPLY15 */
		LOGON_SAM_LOGON_RESPONSE_EX       = 23,  /* was NETLOGON_RESPONSE_FROM_PDC2     */
		LOGON_SAM_LOGON_PAUSE_RESPONSE_EX = 24,
		LOGON_SAM_LOGON_USER_UNKNOWN_EX   = 25 /* was NETLOGON_RESPONSE_FROM_PDC_USER */
	} netlogon_command;

	/* query to dc hand marshaled, as it has 'optional'
	 * parts */
	typedef [nopull,nopush] struct {
		uint16               request_count;
		nstring              computer_name;
		nstring              user_name;
		astring              mailslot_name;
		uint32               acct_control;
		/* samr_AcctFlags       acct_control; */
		[value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size;
		/* The manual alignment is required because this
		 * structure is marked flag(NDR_NOALIGN) via the
		 * nbt_netlogon_packet below.
		 *
		 * However, both MUST only be present if sid_size > 0
		 */
		[flag(NDR_ALIGN4)]   DATA_BLOB _pad;
		[subcontext(0),subcontext_size(sid_size)] dom_sid0 sid;
		netlogon_nt_version_flags               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} NETLOGON_SAM_LOGON_REQUEST;

	typedef struct {
		astring              computer_name;
		astring              user_name;
		astring              mailslot_name;
		uint8                request_count;
		uint16               lmnt_token;
		uint16               lm20_token;
	} NETLOGON_LOGON_REQUEST;

	typedef [flag(NDR_NOALIGN),public] struct {
		netlogon_command command;
		nstring              pdc_name;
		nstring              user_name;
		nstring              domain_name;
		netlogon_nt_version_flags               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} NETLOGON_SAM_LOGON_RESPONSE_NT40;

	typedef [flag(NDR_NOALIGN),public] struct {
		netlogon_command command;
		nstring              pdc_name;
		nstring              user_name;
		nstring              domain_name;
		GUID                 domain_uuid;
		GUID                 zero_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		ipv4address          pdc_ip;
		nbt_server_type      server_type;
		netlogon_nt_version_flags    nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} NETLOGON_SAM_LOGON_RESPONSE;

	/* response from pdc hand marshaled (we have an additional
	 * function that uses this structure), as it has 'optional'
	 * parts */
	typedef [flag(NDR_NOALIGN),public] struct {
		netlogon_command command;
		uint16               sbz; /* From the docs */
		nbt_server_type      server_type;
		GUID                 domain_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		nbt_string           domain_name;
		nbt_string           pdc_name;
		nbt_string           user_name;
		nbt_string           server_site;
		nbt_string           client_site;

		/* Optional on NETLOGON_NT_VERSION_5EX_WITH_IP */
		[value(ndr_size_nbt_sockaddr(&sockaddr, ndr->flags))] uint8 sockaddr_size;
		[subcontext(0),subcontext_size(sockaddr_size)] nbt_sockaddr sockaddr;

		/* Optional on NETLOGON_NT_VERSION_WITH_CLOSEST_SITE */
		nbt_string           next_closest_site;

		netlogon_nt_version_flags               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} NETLOGON_SAM_LOGON_RESPONSE_EX;

	typedef [nopush,nopull] union {
		[case(NETLOGON_NT_VERSION_1)] NETLOGON_SAM_LOGON_RESPONSE_NT40 nt4;
		[case(NETLOGON_NT_VERSION_5)] NETLOGON_SAM_LOGON_RESPONSE nt5;
		[case(NETLOGON_NT_VERSION_5EX)] NETLOGON_SAM_LOGON_RESPONSE_EX nt5_ex;
	} netlogon_samlogon_response_union;

	typedef [nopush,nopull] struct {
		uint32 ntver;
		[switch_is(ntver)] netlogon_samlogon_response_union data;
	} netlogon_samlogon_response;

	void decode_netlogon_samlogon_response_packet(
		[in] netlogon_samlogon_response packet
		);

	/* query for pdc request */
	typedef struct {
		astring              computer_name;
		astring              mailslot_name;
		[flag(NDR_ALIGN2)]   DATA_BLOB _pad;
		nstring              unicode_name;
		netlogon_nt_version_flags               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_netlogon_query_for_pdc;

	/* response from pdc */
	typedef [public] struct {
		netlogon_command command;
		astring pdc_name;
		[flag(NDR_ALIGN2)]   DATA_BLOB _pad;
		nstring              unicode_pdc_name;
		nstring              domain_name;
		netlogon_nt_version_flags               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_netlogon_response_from_pdc;

	typedef [flag(NDR_NOALIGN),public] struct {
		netlogon_command command;
		astring pdc_name;
		uint16 lm20_token;
	} nbt_netlogon_response2;

	/* used to announce SAM changes - MS-NRPC 2.2.1.5.1 */
	typedef struct {
		netr_SamDatabaseID   db_index;
		hyper                serial;
		NTTIME               timestamp;
	} nbt_db_change_info;

	typedef struct {
		uint32           serial_lo;
		time_t           timestamp;
		uint32           pulse;
		uint32           random;
		astring          pdc_name;
		astring          domain;
		[flag(NDR_ALIGN2)] DATA_BLOB _pad;
		nstring          unicode_pdc_name;
		nstring          unicode_domain;
		uint32           db_count;
		nbt_db_change_info    dbchange[db_count];
		[value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size;
		[subcontext(0),subcontext_size(sid_size)] dom_sid0 sid;
		uint32           message_format_version;
		uint32           message_token;
	} NETLOGON_DB_CHANGE;

	typedef [nodiscriminant] union {
		[case(LOGON_REQUEST)]  NETLOGON_LOGON_REQUEST logon0;
		[case(LOGON_SAM_LOGON_REQUEST)]       NETLOGON_SAM_LOGON_REQUEST logon;
		[case(LOGON_PRIMARY_QUERY)] nbt_netlogon_query_for_pdc pdc;
		[case(NETLOGON_ANNOUNCE_UAS)] NETLOGON_DB_CHANGE uas;
	} nbt_netlogon_request;

#if 0 
	/* These responses are all handled manually, as they cannot be encoded in IDL fully
	   
	   See push_nbt_netlogon_response()
	*/
		[case(NETLOGON_RESPONSE_FROM_PDC)] nbt_netlogon_response_from_pdc response;
		[case(NETLOGON_RESPONSE_FROM_PDC_USER)] nbt_netlogon_response_from_pdc2 response2;

		[case(LOGON_SAM_LOGON_PAUSE_RESPONSE)] NETLOGON_SAM_LOGON_RESPONSE reply;
		[case(LOGON_SAM_LOGON_RESPONSE)] NETLOGON_SAM_LOGON_RESPONSE reply;
		[case(LOGON_SAM_LOGON_USER_UNKNOWN)] NETLOGON_SAM_LOGON_RESPONSE reply;
		[case(LOGON_SAM_LOGON_RESPONSE_EX)] NETLOGON_SAM_LOGON_RESPONSE_EX reply_ex;
		[case(LOGON_SAM_LOGON_PAUSE_RESPONSE_EX)] NETLOGON_SAM_LOGON_RESPONSE_EX reply_ex;
		[case(LOGON_SAM_LOGON_USER_UNKNOWN_EX)] NETLOGON_SAM_LOGON_RESPONSE_EX reply_ex;
#endif

	typedef [flag(NDR_NOALIGN),public] struct {
		netlogon_command command;
		[switch_is(command)] nbt_netlogon_request req;
	} nbt_netlogon_packet;

	void decode_nbt_netlogon_packet(
		[in] nbt_netlogon_packet packet
		);

	/********************************************************/
	/* \MAILSLOT\BROWSE mailslot requests			*/
	/* for details see http://ubiqx.org/cifs/Browsing.html  */
	/********************************************************/
	typedef bitmap svcctl_ServerType svcctl_ServerType;

	typedef [enum8bit] enum {
		HostAnnouncement 	= 1,
		AnnouncementRequest	= 2,
		Election		= 8,
		GetBackupListReq	= 9,
		GetBackupListResp	= 10,
		BecomeBackup		= 11,
		DomainAnnouncement	= 12,
		MasterAnnouncement	= 13,
		ResetBrowserState	= 14,
		LocalMasterAnnouncement	= 15
	} nbt_browse_opcode;

	typedef struct {
		uint8 UpdateCount;
		uint32 Periodicity;
		[charset(DOS)] uint8 ServerName[16];
		uint8 OSMajor;
		uint8 OSMinor;
		svcctl_ServerType ServerType;
		uint8 BroMajorVer;
		uint8 BroMinorVer;
		uint16 Signature;
		astring Comment;
	} nbt_browse_host_announcement;

	typedef struct {
		uint8 Unused;
		astring ResponseName;
	} nbt_browse_announcement_request;

	typedef struct {
		uint8 Version;
		uint32 Criteria;
		uint32 UpTime; /* In milliseconds */
		uint32 Reserved; /* Must be zero */
		astring ServerName;
	} nbt_browse_election_request;

	typedef struct {
		uint8 ReqCount;
		uint32 Token;
	} nbt_browse_backup_list_request;

	typedef struct {
		uint8 BackupCount;
		uint32 Token;
		nbt_name BackupServerList[BackupCount];/* TODO: this is wrong */
	} nbt_browse_backup_list_response;

	typedef struct {
		astring BrowserName;
	} nbt_browse_become_backup;

	typedef struct {
		uint8 UpdateCount;
		uint32 Periodicity;
		[charset(DOS)] uint8 ServerName[16];
		uint8 OSMajor;
		uint8 OSMinor;
		svcctl_ServerType ServerType;
		uint32 MysteriousField;
		astring Comment;
	} nbt_browse_domain_announcement;

	typedef struct {
		astring ServerName;
	} nbt_browse_master_announcement;

	typedef struct {
		uint8 Command;
	} nbt_browse_reset_state;

	typedef struct {
		uint8 UpdateCount;
		uint32 Periodicity;
		[charset(DOS)] uint8 ServerName[16];
		uint8 OSMajor;
		uint8 OSMinor;
		svcctl_ServerType ServerType;
		uint8 BroMajorVer;
		uint8 BroMinorVer;
		uint16 Signature;
		astring Comment;
	} nbt_browse_local_master_announcement;

	typedef [nodiscriminant] union {
		[case(HostAnnouncement)] nbt_browse_host_announcement host_annoucement;
		[case(AnnouncementRequest)] nbt_browse_announcement_request announcement_request;
		[case(Election)] nbt_browse_election_request election_request;
		[case(GetBackupListReq)] nbt_browse_backup_list_request backup_list_request;
		[case(GetBackupListResp)] nbt_browse_backup_list_response backup_list_response;
		[case(BecomeBackup)] nbt_browse_become_backup become_backup;
		[case(DomainAnnouncement)] nbt_browse_domain_announcement domain_announcement;
		[case(MasterAnnouncement)] nbt_browse_master_announcement master_announcement;
		[case(ResetBrowserState)] nbt_browse_reset_state reset_browser_state;
		[case(LocalMasterAnnouncement)] nbt_browse_local_master_announcement local_master_announcement;
	} nbt_browse_payload;

	typedef [public,flag(NDR_NOALIGN)] struct {
		nbt_browse_opcode opcode;
		[switch_is(opcode)] nbt_browse_payload payload;
	} nbt_browse_packet;
}
