1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00
samba-mirror/librpc/idl/nbt.idl
Joseph Sutton edad945339 librpc/nbt: Avoid reading invalid member of union
WACK packets use the ‘data’ member of the ‘nbt_rdata’ union, but they
claim to be a different type — NBT_QTYPE_NETBIOS — than would normally
be used with that union member. This means that if rr_type is equal to
NBT_QTYPE_NETBIOS, ndr_push_nbt_res_rec() has to guess which type the
structure really is by examining the data member. However, if the
structure is actually of a different type, that union member will not be
valid and accessing it will invoke undefined behaviour.

To fix this, eliminate all the guesswork and introduce a new type,
NBT_QTYPE_WACK, which can never appear on the wire, and which indicates
that although the ‘data’ union member should be used, the wire type is
actually NBT_QTYPE_NETBIOS.

This means that as far as NDR is concerned, the ‘netbios’ member of the
‘nbt_rdata’ union will consistently be used for all NBT_QTYPE_NETBIOS
structures; we shall no longer access the wrong member of the union.

Credit to OSS-Fuzz.

REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38480

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15019

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>

Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org>
Autobuild-Date(master): Fri Jul  7 01:14:06 UTC 2023 on atb-devel-224
2023-07-07 01:14:06 +00:00

690 lines
21 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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,nopush] enum {
NBT_QTYPE_ADDRESS = 0x0001,
NBT_QTYPE_NAMESERVICE = 0x0002,
NBT_QTYPE_NULL = 0x000A,
NBT_QTYPE_NETBIOS = 0x0020,
NBT_QTYPE_STATUS = 0x0021,
/*
* Indicates that this is a WACK packet. As long as the size of
* int is larger than 16 bits, this value cannot appear on the
* wire. Well encode it instead as NBT_QTYPE_NETBIOS.
*/
NBT_QTYPE_WACK = -1
} 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;
typedef [flag(LIBNDR_PRINT_ARRAY_HEX)] 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, /* 2008 / RODC */
NBT_SERVER_FULL_SECRET_DOMAIN_6 = 0x00001000, /* 2008 */
NBT_SERVER_ADS_WEB_SERVICE = 0x00002000,
NBT_SERVER_DS_8 = 0x00004000, /* 2012 */
NBT_SERVER_DS_9 = 0x00008000, /* 2012R2 */
NBT_SERVER_DS_10 = 0x00010000, /* 2016 */
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;
/* 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;
/********************************************************/
/* \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;
}