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
701
702
703
704
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SMB_NETBIOS_H_
#define _SMB_NETBIOS_H_
#include <stdio.h>
#include <synch.h>
#include <pthread.h>
#include <strings.h>
#include <netinet/in.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/netbios.h>
#define QUEUE_INSERT_TAIL(q, e) \
((e)->back) = (void *)((q)->back); \
((e)->forw) = (void *)(q); \
((q)->back->forw) = (void *)(e); \
((q)->back) = (void *)(e);
#define QUEUE_CLIP(e) \
(e)->forw->back = (e)->back; \
(e)->back->forw = (e)->forw; \
(e)->forw = 0; \
(e)->back = 0;
typedef enum {
NETBIOS_EVENT_START = 0,
NETBIOS_EVENT_STOP,
NETBIOS_EVENT_RESET,
NETBIOS_EVENT_NS_START,
NETBIOS_EVENT_NS_STOP,
NETBIOS_EVENT_DGM_START,
NETBIOS_EVENT_DGM_STOP,
NETBIOS_EVENT_BROWSER_START,
NETBIOS_EVENT_BROWSER_STOP,
NETBIOS_EVENT_TIMER_START,
NETBIOS_EVENT_TIMER_STOP,
NETBIOS_EVENT_ERROR,
NETBIOS_EVENT_DUMP
} netbios_event_t;
typedef enum {
NETBIOS_STATE_INIT = 0,
NETBIOS_STATE_RUNNING,
NETBIOS_STATE_CLOSING,
NETBIOS_STATE_ERROR
} netbios_state_t;
typedef struct {
pthread_t s_tid;
boolean_t s_up;
} netbios_svc_t;
typedef struct {
mutex_t nbs_mtx;
cond_t nbs_cv;
netbios_svc_t nbs_ns;
netbios_svc_t nbs_dgm;
netbios_svc_t nbs_browser;
netbios_svc_t nbs_timer;
netbios_state_t nbs_state;
uint32_t nbs_errors;
char *nbs_last_event;
} netbios_service_t;
extern char smb_node_type;
#define SMB_NODETYPE_B 'B'
#define SMB_NODETYPE_P 'P'
#define SMB_NODETYPE_M 'M'
#define SMB_NODETYPE_H 'H'
/*
* NAME service definitions
*/
#define ADDR_FLAG_INVALID 0x0000
#define ADDR_FLAG_VALID 0x0001
typedef struct addr_entry {
struct addr_entry *forw;
struct addr_entry *back;
uint32_t attributes;
uint32_t conflict_timer;
uint32_t refresh_ttl;
uint32_t ttl;
struct sockaddr_in sin;
int sinlen;
uint32_t flags;
} addr_entry_t;
/*
* The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
* of NODE_NAME records. Each NODE_NAME entry represents an active
* name in the same NetBIOS scope as the requesting name in the
* local name table of the responder. RR_NAME is the requesting
* name.
*
* NODE_NAME Entry:
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +--- ---+
* | |
* +--- NETBIOS FORMAT NAME ---+
* | |
* +--- ---+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* The NAME_FLAGS field:
*
* 1 1 1 1 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | G | ONT |DRG|CNF|ACT|PRM| RESERVED |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* The NAME_FLAGS field is defined as:
*
* Symbol Bit(s) Description:
*
* RESERVED 7-15 Reserved for future use. Must be zero (0).
* PRM 6 Permanent Name Flag. If one (1) then entry
* is for the permanent node name. Flag is zero
* (0) for all other names.
* ACT 5 Active Name Flag. All entries have this flag
* set to one (1).
* CNF 4 Conflict Flag. If one (1) then name on this
* node is in conflict.
* DRG 3 Deregister Flag. If one (1) then this name
* is in the process of being deleted.
* ONT 1,2 Owner Node Type:
* 00 = B node
* 01 = P node
* 10 = M node
* 11 = Reserved for future use
* G 0 Group Name Flag.
* name.
* If zero (0) then it is a UNIQUE NetBIOS name.
*/
typedef struct name_entry {
struct name_entry *forw;
struct name_entry *back;
unsigned char name[NETBIOS_NAME_SZ];
unsigned char scope[NETBIOS_DOMAIN_NAME_MAX];
unsigned short attributes;
struct addr_entry addr_list;
mutex_t mtx;
} name_entry_t;
struct name_question {
struct name_entry *name;
unsigned question_type;
unsigned question_class;
};
struct resource_record {
/*
* These two flags and address are contained within RDATA
* when rr_type==0x0020 (NB - NetBIOS general Name Service)
* and rr_class==0x01 (IN - Internet Class).
*/
struct name_entry *name;
unsigned short rr_type;
unsigned short rr_class;
uint32_t ttl;
unsigned short rdlength;
unsigned char *rdata;
};
struct name_packet {
unsigned short name_trn_id;
unsigned short info;
unsigned qdcount; /* question entries */
unsigned ancount; /* answer recs */
unsigned nscount; /* authority recs */
unsigned arcount; /* additional recs */
struct name_question *question;
struct resource_record *answer;
struct resource_record *authority;
struct resource_record *additional;
unsigned char block_data[4]; /* begining of space */
};
#define NAME_OPCODE_R 0x8000 /* RESPONSE flag: 1 bit */
#define NAME_OPCODE_OPCODE_MASK 0x7800 /* OPCODE Field: 4 bits */
#define NAME_OPCODE_QUERY 0x0000
#define NAME_OPCODE_REGISTRATION 0x2800
#define NAME_OPCODE_RELEASE 0x3000
#define NAME_OPCODE_WACK 0x3800
#define NAME_OPCODE_REFRESH 0x4000
#define NAME_OPCODE_MULTIHOME 0x7800
#define NAME_NM_FLAGS_AA 0x0400 /* Authoritative Answer:1 bit */
#define NAME_NM_FLAGS_TC 0x0200 /* Truncation: 1 bit */
#define NAME_NM_FLAGS_RD 0x0100 /* Recursion desired: 1 bit */
#define NAME_NM_FLAGS_RA 0x0080 /* Recursion available: 1 bit */
#define NAME_NM_FLAGS_x2 0x0040 /* reserved, mbz: 1 bit */
#define NAME_NM_FLAGS_x1 0x0020 /* reserved, mbz: 1 bit */
#define NAME_NM_FLAGS_B 0x0010 /* Broadcast: 1 bit */
#define NAME_RCODE_MASK 0x000f /* RCODE Field: 4 bits */
#define RCODE_FMT_ERR 0x0001
#define RCODE_SRV_ERR 0x0002
#define RCODE_NAM_ERR 0x0003
#define RCODE_IMP_ERR 0x0004
#define RCODE_RFS_ERR 0x0005
#define RCODE_ACT_ERR 0x0006
#define RCODE_CFT_ERR 0x0007
#define NM_FLAGS_UNICAST 0
#define NM_FLAGS_BROADCAST NAME_NM_FLAGS_B
#define PACKET_TYPE(x) ((x) & (NAME_OPCODE_R | NAME_OPCODE_OPCODE_MASK | \
NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD))
#define RCODE(x) ((x) & NAME_RCODE_MASK)
#define POSITIVE_RESPONSE(x) (RCODE(x) == 0)
#define NEGATIVE_RESPONSE(x) (RCODE(x) != 0)
#define END_NODE_CHALLENGE_REGISTRATION_REQUEST \
(NAME_OPCODE_REGISTRATION | NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD)
#define END_NODE_CHALLENGE_NAME_REGISTRATION_RESPONSE \
(NAME_OPCODE_R | END_NODE_CHALLENGE_REGISTRATION_REQUEST)
#define NAME_QUERY_REQUEST \
(NAME_OPCODE_QUERY | NAME_NM_FLAGS_RD)
#define NAME_QUERY_RESPONSE \
(NAME_OPCODE_R | NAME_QUERY_REQUEST | \
NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD)
#define NODE_STATUS_REQUEST \
(NAME_OPCODE_QUERY)
#define NODE_STATUS_RESPONSE \
(NAME_OPCODE_R | NODE_STATUS_REQUEST | NAME_NM_FLAGS_AA)
#define REDIRECT_NAME_QUERY_RESPONSE \
(NAME_OPCODE_R | NAME_QUERY_REQUEST | NAME_NM_FLAGS_RD)
#define NAME_REFRESH_REQUEST \
(NAME_OPCODE_REFRESH)
#define NAME_REGISTRATION_REQUEST \
(NAME_OPCODE_REGISTRATION | NAME_NM_FLAGS_RD)
#define NAME_MULTIHOME_REGISTRATION_REQUEST \
(NAME_OPCODE_MULTIHOME | NAME_NM_FLAGS_RD)
#define NAME_REGISTRATION_RESPONSE \
(NAME_OPCODE_R | NAME_REGISTRATION_REQUEST | NAME_NM_FLAGS_AA)
#define NAME_RELEASE_REQUEST \
(NAME_OPCODE_RELEASE)
#define NAME_RELEASE_RESPONSE \
(NAME_OPCODE_R | NAME_RELEASE_REQUEST | NAME_NM_FLAGS_AA)
#define WACK_RESPONSE \
(NAME_OPCODE_R | NAME_OPCODE_WACK | NAME_NM_FLAGS_AA)
#define NAME_QUESTION_TYPE_NB 0x0020
#define NAME_QUESTION_TYPE_NBSTAT 0x0021
#define NAME_QUESTION_CLASS_IN 0x0001
#define NAME_RR_TYPE_A 0x0001 /* IP Address */
#define NAME_RR_TYPE_NS 0x0002 /* Name Server */
#define NAME_RR_TYPE_NULL 0x000A /* NULL */
#define NAME_RR_TYPE_NB 0x0020 /* NetBIOS Name Service */
#define NAME_RR_TYPE_NBSTAT 0x0021 /* NetBIOS Node Status */
#define NAME_RR_CLASS_IN 0x0001 /* NetBIOS Node Status */
#define NAME_NB_FLAGS_ONT_MASK (3<<13)
#define NAME_NB_FLAGS_ONT_B (0<<13) /* B-node (broadcast) */
#define NAME_NB_FLAGS_ONT_P (1<<13) /* P-node (point-to-point) */
#define NAME_NB_FLAGS_ONT_M (2<<13) /* M-node (multicast) */
#define NAME_NB_FLAGS_ONT_resv (3<<13)
#define NAME_NB_FLAGS_G (1<<15) /* Group Name */
#define UNICAST 0
#define BROADCAST 1
#define POINTCAST 2
#define NAME_ATTR_UNIQUE 0x0000
#define NAME_ATTR_GROUP 0x8000
#define NAME_ATTR_OWNER_NODE_TYPE 0x6000
#define NAME_ATTR_OWNER_TYPE_BNODE 0x0000
#define NAME_ATTR_OWNER_TYPE_PNODE 0x2000
#define NAME_ATTR_OWNER_TYPE_MNODE 0x4000
#define NAME_ATTR_OWNER_TYPE_HNODE 0x6000
#define NAME_ATTR_DEREGISTER 0x1000
#define NAME_ATTR_CONFLICT 0x0800
#define NAME_ATTR_ACTIVE_NAME 0x0400
#define NAME_ATTR_PERMANENT 0x0200
#define NAME_ATTR_RESERVED 0x01FF
#define NAME_ATTR_LOCAL 0x0001
#define NODE_TYPE(x) ((x) & NAME_ATTR_OWNER_NODE_TYPE))
#define IS_BNODE(x) (NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_BNODE)
#define IS_PNODE(x) (NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_PNODE)
#define IS_MNODE(x) (NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_MNODE)
#define IS_HNODE(x) (NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_HNODE)
#define IS_UNIQUE(x) (((x) & NAME_ATTR_GROUP) == 0)
#define IS_GROUP(x) (((x) & NAME_ATTR_GROUP) != 0)
#define IS_PERMANENT(x) (((x) & NAME_ATTR_PERMANENT) != 0)
#define IS_CONFLICTING(x) (((x) & NAME_ATTR_CONFLICT) != 0)
#define IS_ACTIVE(x) (((x) & NAME_ATTR_ACTIVE) != 0)
#define IS_DEGREGISTERED(x) (((x) & NAME_ATTR_ACTIVE) != 0)
#define IS_LOCAL(x) (((x) & NAME_ATTR_LOCAL) != 0)
#define IS_PUBLIC(x) (((x) & NAME_ATTR_LOCAL) == 0)
#define PUBLIC_BITS(x) ((x) & ~NAME_ATTR_RESERVED)
#define SAME_SCOPE(scope, e) (strcmp((scope), ((e)->scope)) == 0)
/*
* STATISTICS Field of the NODE STATUS RESPONSE:
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | UNIT_ID (Unique unit ID) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | UNIT_ID,continued | JUMPERS | TEST_RESULT |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VERSION_NUMBER | PERIOD_OF_STATISTICS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_OF_CRCs | NUMBER_ALIGNMENT_ERRORS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_OF_COLLISIONS | NUMBER_SEND_ABORTS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_GOOD_SENDS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_GOOD_RECEIVES |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_RETRANSMITS | NUMBER_NO_RESOURCE_CONDITIONS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_FREE_COMMAND_BLOCKS | TOTAL_NUMBER_COMMAND_BLOCKS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |MAX_TOTAL_NUMBER_COMMAND_BLOCKS| NUMBER_PENDING_SESSIONS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MAX_NUMBER_PENDING_SESSIONS | MAX_TOTAL_SESSIONS_POSSIBLE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SESSION_DATA_PACKET_SIZE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct {
unsigned char unit_id[6];
unsigned char jumpers;
unsigned char test_result;
unsigned short version_number;
unsigned short statistical_period;
unsigned short crc_errors;
unsigned short alignment_errors;
unsigned short collisions;
unsigned short send_aborts;
unsigned int good_sends;
unsigned int good_receives;
unsigned short retransmits;
unsigned short no_resource_conditions;
unsigned short free_command_blocks;
unsigned short total_command_blocks;
unsigned short max_total_command_blocks;
unsigned short pending_sessions;
unsigned short max_pending_sessions;
unsigned short total_possible_sessions;
unsigned short session_data_packet_size;
} node_status_response;
/*
* 4.4.1. NetBIOS DATAGRAM HEADER
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MSG_TYPE | FLAGS | DGM_ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_IP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_PORT | DGM_LENGTH |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PACKET_OFFSET |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct {
unsigned char msg_type;
unsigned char flags;
unsigned short dgm_id;
uint32_t source_ip;
unsigned short source_port;
unsigned short dgm_length;
unsigned short packet_offset;
} datagram_header;
/*
* MSG_TYPE values (in hexidecimal):
*
* 10 - DIRECT_UNIQUE DATAGRAM
* 11 - DIRECT_GROUP DATAGRAM
* 12 - BROADCAST DATAGRAM
* 13 - DATAGRAM ERROR
* 14 - DATAGRAM QUERY REQUEST
* 15 - DATAGRAM POSITIVE QUERY RESPONSE
* 16 - DATAGRAM NEGATIVE QUERY RESPONSE
*/
#define DATAGRAM_TYPE_DIRECT_UNIQUE 0x10
#define DATAGRAM_TYPE_DIRECT_GROUP 0x11
#define DATAGRAM_TYPE_BROADCAST 0x12
#define DATAGRAM_TYPE_ERROR_DATAGRAM 0x13
#define DATAGRAM_TYPE_QUERY_REQUEST 0x14
#define DATAGRAM_TYPE_POSITIVE_RESPONSE 0x15
#define DATAGRAM_TYPE_NEGATIVE_RESPONSE 0x16
/*
* Bit definitions of the FLAGS field:
*
* 0 1 2 3 4 5 6 7
* +---+---+---+---+---+---+---+---+
* | 0 | 0 | 0 | 0 | SNT | F | M |
* +---+---+---+---+---+---+---+---+
*
* Symbol Bit(s) Description
*
* M 7 MORE flag, If set then more NetBIOS datagram
* fragments follow.
*
* F 6 FIRST packet flag, If set then this is first
* (and possibly only) fragment of NetBIOS
* datagram
*
* SNT 4,5 Source End-Node type:
* 00 = B node
* 01 = P node
* 10 = M node
* 11 = H node
* RESERVED 0-3 Reserved, must be zero (0)
*/
#define DATAGRAM_FLAGS_MORE 0x01
#define DATAGRAM_FLAGS_FIRST 0x02
#define DATAGRAM_FLAGS_SRC_TYPE 0x0c
#define DATAGRAM_FLAGS_B_NODE 0x00
#define DATAGRAM_FLAGS_P_NODE 0x04
#define DATAGRAM_FLAGS_M_NODE 0x08
#define DATAGRAM_FLAGS_H_NODE 0x0C
#define DATAGRAM_FLAGS_NBDD 0x0c
#define DATAGRAM_FLAGS_RESERVED 0xf0
/*
* 4.4.2. DIRECT_UNIQUE, DIRECT_GROUP, & BROADCAST DATAGRAM
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MSG_TYPE | FLAGS | DGM_ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_IP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_PORT | DGM_LENGTH |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PACKET_OFFSET | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | |
* / SOURCE_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / DESTINATION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / USER_DATA /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct {
datagram_header header;
unsigned char *source_name;
unsigned char *destination_name;
unsigned char *user_data;
} datagram_packet;
/*
* 4.4.3. DATAGRAM ERROR PACKET
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MSG_TYPE | FLAGS | DGM_ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_IP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_PORT | ERROR_CODE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* ERROR_CODE values (in hexidecimal):
*
* 82 - DESTINATION NAME NOT PRESENT
* 83 - INVALID SOURCE NAME FORMAT
* 84 - INVALID DESTINATION NAME FORMAT
*/
typedef struct {
unsigned char msg_type;
unsigned char flags;
unsigned short dgm_id;
uint32_t source_ip;
unsigned short source_port;
unsigned char error;
} datagram_error_packet;
/*
* 4.4.4. DATAGRAM QUERY REQUEST
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MSG_TYPE | FLAGS | DGM_ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_IP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_PORT | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | |
* / DESTINATION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* 4.4.5. DATAGRAM POSITIVE AND NEGATIVE QUERY RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MSG_TYPE | FLAGS | DGM_ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_IP |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SOURCE_PORT | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | |
* / DESTINATION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct datagram_query_packet {
unsigned char msg_type;
unsigned char flags;
unsigned short dgm_id;
uint32_t source_ip;
unsigned short source_port;
unsigned char destination_name[MAX_NAME_LENGTH];
} datagram_query_packet;
typedef struct datagram {
struct datagram *forw;
struct datagram *back;
struct addr_entry inaddr;
int discard_timer;
unsigned char packet_type;
unsigned char flags;
unsigned short datagram_id;
struct name_entry src;
struct name_entry dest;
unsigned short offset;
unsigned short data_length;
unsigned char *data;
unsigned int rawbytes;
unsigned char rawbuf[MAX_DATAGRAM_LENGTH];
} datagram;
typedef struct datagram_queue {
struct datagram *forw;
struct datagram *back;
} datagram_queue;
typedef struct name_queue {
struct name_entry head;
mutex_t mtx;
} name_queue_t;
typedef struct nbcache_iter {
HT_ITERATOR nbc_hti;
struct name_entry *nbc_entry;
} nbcache_iter_t;
#define NETBIOS_EMPTY_NAME (unsigned char *)""
#define NETBIOS_NAME_IS_STAR(name) \
(bcmp(name, "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NETBIOS_NAME_SZ) == 0)
/*
* NetBIOS service state machine interface
*/
void smb_netbios_event(netbios_event_t);
void smb_netbios_wait(netbios_event_t);
void smb_netbios_sleep(time_t);
boolean_t smb_netbios_running(void);
boolean_t smb_netbios_error(void);
/*
* Name Cache Functions
*/
int smb_netbios_cache_init(void);
void smb_netbios_cache_fini(void);
void smb_netbios_cache_dump(FILE *fp);
int smb_netbios_cache_count(void);
void smb_netbios_cache_clean(void);
void smb_netbios_cache_reset_ttl(void);
void smb_netbios_cache_delete_locals(name_queue_t *);
void smb_netbios_cache_refresh(name_queue_t *);
int smb_netbios_cache_insert(struct name_entry *name);
int smb_netbios_cache_insert_list(struct name_entry *name);
void smb_netbios_cache_delete(struct name_entry *name);
int smb_netbios_cache_delete_addr(struct name_entry *name);
struct name_entry *smb_netbios_cache_lookup(struct name_entry *name);
struct name_entry *smb_netbios_cache_lookup_addr(struct name_entry *name);
void smb_netbios_cache_update_entry(struct name_entry *, struct name_entry *);
void smb_netbios_cache_unlock_entry(struct name_entry *);
unsigned char *smb_netbios_cache_status(unsigned char *, int, unsigned char *);
int smb_netbios_cache_getfirst(nbcache_iter_t *);
int smb_netbios_cache_getnext(nbcache_iter_t *);
void smb_netbios_name_dump(FILE *fp, struct name_entry *entry);
void smb_netbios_name_logf(struct name_entry *entry);
void smb_netbios_name_freeaddrs(struct name_entry *entry);
struct name_entry *smb_netbios_name_dup(struct name_entry *, int);
/* Name service functions */
void *smb_netbios_name_service(void *);
void smb_init_name_struct(unsigned char *, char, unsigned char *, uint32_t,
unsigned short, uint32_t, uint32_t, struct name_entry *);
struct name_entry *smb_name_find_name(struct name_entry *name);
int smb_name_add_name(struct name_entry *name);
int smb_name_delete_name(struct name_entry *name);
void smb_name_unlock_name(struct name_entry *name);
void smb_netbios_name_config(void);
void smb_netbios_name_unconfig(void);
void smb_netbios_name_tick(void);
int smb_first_level_name_encode(struct name_entry *, unsigned char *, int);
int smb_first_level_name_decode(unsigned char *, struct name_entry *);
void smb_encode_netbios_name(unsigned char *, char, unsigned char *,
struct name_entry *);
/* Datagram service functions */
void *smb_netbios_datagram_service(void *);
int smb_netbios_datagram_send(struct name_entry *,
struct name_entry *, unsigned char *, int);
void smb_netbios_datagram_tick(void);
/* browser functions */
void *smb_browser_dispatch(void *arg);
void *smb_browser_service(void *);
int smb_browser_load_transact_header(unsigned char *, int, int, int, char *);
/* Netlogon function */
void smb_netlogon_receive(struct datagram *, char *, unsigned char *, int);
void smb_netlogon_request(struct name_entry *, char *);
#endif /* _SMB_NETBIOS_H_ */
|