summaryrefslogtreecommitdiff
path: root/source4/librpc/idl/nbt.idl
blob: aa8836088258342a45240273f6c9189bf5166043 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
#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", "svcctl.idl";
[
helper("libcli/nbt/libnbt.h")
]
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_AUTHORITIVE        = 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 [enum16bit] enum {
		NBT_QCLASS_IP = 0x01
	} nbt_qclass;

	typedef [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] 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 arround the problem
 * that we need to use nbt_rdata_data
 * together with NBT_QTYPE_NETBIOS
 * for WACK replies
 */
#define NBT_RES_REC_LEVEL(rr_type, rdata) (\
	(((rr_type) == NBT_QTYPE_NETBIOS) && \
	talloc_check_name(ndr, "struct ndr_push") && \
	((rdata).data.length == 2)) \
	? 0 : rr_type)

	typedef [flag(LIBNDR_PRINT_ARRAY_HEX)] struct {
		nbt_name   name;
		nbt_qtype  rr_type;
		nbt_qclass rr_class;
		uint32     ttl;
		[switch_is(NBT_RES_REC_LEVEL(rr_type, rdata))] 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 */
	typedef enum {
		NETLOGON_QUERY_FOR_PDC           = 0x7,	
		NETLOGON_ANNOUNCE_UAS            = 0xa,
		NETLOGON_RESPONSE_FROM_PDC       = 0xc,
		NETLOGON_QUERY_FOR_PDC2          = 0x12,
		NETLOGON_RESPONSE_FROM_PDC2      = 0x17,
		NETLOGON_RESPONSE_FROM_PDC_USER  = 0x19
	} nbt_netlogon_command;

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

	/* query for pdc request - new style */
	typedef struct {
		uint16               request_count;
		nstring              computer_name;
		nstring              user_name;
		astring              mailslot_name;
		uint32               unknown[2];
		uint32               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_netlogon_query_for_pdc2;

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

	typedef [bitmap32bit] 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_type;

	/* response from pdc - type2 */
	typedef struct {
		[flag(NDR_ALIGN4)]   DATA_BLOB _pad;
		nbt_server_type      server_type;
		GUID                 domain_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		nbt_string           domain;
		nbt_string           pdc_name;
		nbt_string           user_name;
		nbt_string           server_site;
		nbt_string           client_site;
		uint8                unknown;
		uint32               unknown2;
		[flag(NDR_BIG_ENDIAN)] 
	          ipv4address          pdc_ip;
		uint32               unknown3[2];
		uint32               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_netlogon_response_from_pdc2;

	typedef enum netr_SamDatabaseID netr_SamDatabaseID;

	/* announce change to UAS or SAM */
	typedef struct {
		netr_SamDatabaseID   db_index;
		hyper                serial;
		NTTIME               timestamp;
	} nbt_db_change;

	/* used to announce SAM changes */
	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    dbchange[db_count];
		[value(ndr_size_dom_sid(&sid, ndr->flags))] uint32 sid_size;
		[flag(NDR_ALIGN4)] DATA_BLOB _pad2;
		dom_sid          sid;
		uint32           nt_version;
		uint16           lmnt_token;
		uint16           lm20_token;
	} nbt_netlogon_announce_uas;

	typedef [nodiscriminant] union {
		[case(NETLOGON_QUERY_FOR_PDC)] nbt_netlogon_query_for_pdc pdc;
		[case(NETLOGON_QUERY_FOR_PDC2)] nbt_netlogon_query_for_pdc2 pdc2;
		[case(NETLOGON_ANNOUNCE_UAS)] nbt_netlogon_announce_uas uas;
		[case(NETLOGON_RESPONSE_FROM_PDC)] nbt_netlogon_response_from_pdc response;
		[case(NETLOGON_RESPONSE_FROM_PDC2)] nbt_netlogon_response_from_pdc2 response2;
		[case(NETLOGON_RESPONSE_FROM_PDC_USER)] nbt_netlogon_response_from_pdc2 response2;
	} nbt_netlogon_request;

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

	/*******************************************/
	/* CLDAP netlogon response                 */

	/* note that these structures are very similar to, but not
	   quite identical to, the netlogon structures above */

	typedef struct {
		uint16               type;
		nstring              pdc_name;
		nstring              user_name;
		nstring              domain_name;
		[value(1)] uint32    nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;		
	} nbt_cldap_netlogon_1;

	typedef struct {
		uint16               type;
		nstring              pdc_name;
		nstring              user_name;
		nstring              domain_name;
		GUID                 domain_uuid;
		GUID                 unknown_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		ipv4address          pdc_ip;
		nbt_server_type      server_type;
		[value(3)] uint32    nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;		
	} nbt_cldap_netlogon_3;

	typedef struct {
		uint32               type;
		nbt_server_type      server_type;
		GUID                 domain_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		nbt_string           domain;
		nbt_string           pdc_name;
		nbt_string           user_name;
		nbt_string           server_site;
		nbt_string           client_site;
		[value(5)] uint32    nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_cldap_netlogon_5;

	typedef struct {
		uint32               type;
		nbt_server_type      server_type;
		GUID                 domain_uuid;
		nbt_string           forest;
		nbt_string           dns_domain;
		nbt_string           pdc_dns_name;
		nbt_string           domain;
		nbt_string           pdc_name;
		nbt_string           user_name;
		nbt_string           server_site;
		nbt_string           client_site;
		uint8                unknown;
		uint32               unknown2;
		[flag(NDR_BIG_ENDIAN)] 
	          ipv4address          pdc_ip;
		uint32               unknown3[2];
		[value(13)] uint32   nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_cldap_netlogon_13;

	typedef [flag(NDR_NOALIGN),public,nodiscriminant] union {
		[case(0)]  nbt_cldap_netlogon_1 logon1;
		[case(1)]  nbt_cldap_netlogon_1 logon1;
		[case(2)]  nbt_cldap_netlogon_3 logon3;
		[case(3)]  nbt_cldap_netlogon_3 logon3;
		[case(4)]  nbt_cldap_netlogon_5 logon5;
		[case(5)]  nbt_cldap_netlogon_5 logon5;
		[case(6)]  nbt_cldap_netlogon_5 logon5;
		[case(7)]  nbt_cldap_netlogon_5 logon5;
		[default]  nbt_cldap_netlogon_13 logon13;
	} nbt_cldap_netlogon;

	/*******************************************/
	/* \MAILSLOT\NET\NTLOGON mailslot requests */
	typedef enum {
		NTLOGON_SAM_LOGON         = 0x12,
		NTLOGON_SAM_LOGON_REPLY   = 0x13,
		NTLOGON_SAM_LOGON_REPLY15 = 0x15
	} nbt_ntlogon_command;

	typedef struct {
		uint16               request_count;
		nstring              computer_name;
		nstring              user_name;
		astring              mailslot_name;
		uint32               acct_control;
		[value(ndr_size_dom_sid(&sid, ndr->flags))] uint32 sid_size;
		[flag(NDR_ALIGN4)]   DATA_BLOB _pad;
		dom_sid              sid;
		uint32               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_ntlogon_sam_logon;

	typedef struct {
		nstring              server;
		nstring              user_name;
		nstring              domain;
		uint32               nt_version;
		uint16               lmnt_token;
		uint16               lm20_token;
	} nbt_ntlogon_sam_logon_reply;

	typedef [nodiscriminant] union {
		[case(NTLOGON_SAM_LOGON)]       nbt_ntlogon_sam_logon logon;
		[case(NTLOGON_SAM_LOGON_REPLY)] nbt_ntlogon_sam_logon_reply reply;
		[case(NTLOGON_SAM_LOGON_REPLY15)] nbt_ntlogon_sam_logon_reply reply;
	} nbt_ntlogon_request;

	typedef [flag(NDR_NOALIGN),public] struct {
		nbt_ntlogon_command command;
		[switch_is(command)] nbt_ntlogon_request req;
	} nbt_ntlogon_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;
}