1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SMB_NETBIOS_H_
27 #define	_SMB_NETBIOS_H_
28 
29 #include <stdio.h>
30 #include <synch.h>
31 #include <pthread.h>
32 #include <strings.h>
33 #include <netinet/in.h>
34 
35 #include <smbsrv/libsmbns.h>
36 
37 #include <smbsrv/smbinfo.h>
38 #include <smbsrv/netbios.h>
39 
40 #define	QUEUE_INSERT_TAIL(q, e) \
41 	((e)->back) = (void *)((q)->back);	\
42 	((e)->forw) = (void *)(q);		\
43 	((q)->back->forw) = (void *)(e);	\
44 	((q)->back) = (void *)(e);
45 
46 #define	QUEUE_CLIP(e) \
47 	(e)->forw->back = (e)->back;	\
48 	(e)->back->forw = (e)->forw;	\
49 	(e)->forw = 0;			\
50 	(e)->back = 0;
51 
52 typedef enum {
53 	NETBIOS_EVENT_START = 0,
54 	NETBIOS_EVENT_STOP,
55 	NETBIOS_EVENT_RESET,
56 	NETBIOS_EVENT_NS_START,
57 	NETBIOS_EVENT_NS_STOP,
58 	NETBIOS_EVENT_DGM_START,
59 	NETBIOS_EVENT_DGM_STOP,
60 	NETBIOS_EVENT_BROWSER_START,
61 	NETBIOS_EVENT_BROWSER_STOP,
62 	NETBIOS_EVENT_TIMER_START,
63 	NETBIOS_EVENT_TIMER_STOP,
64 	NETBIOS_EVENT_ERROR,
65 	NETBIOS_EVENT_DUMP
66 } netbios_event_t;
67 
68 typedef enum {
69 	NETBIOS_STATE_INIT = 0,
70 	NETBIOS_STATE_RUNNING,
71 	NETBIOS_STATE_CLOSING,
72 	NETBIOS_STATE_ERROR
73 } netbios_state_t;
74 
75 typedef struct {
76 	pthread_t	s_tid;
77 	boolean_t	s_up;
78 } netbios_svc_t;
79 
80 typedef struct {
81 	mutex_t		nbs_mtx;
82 	cond_t		nbs_cv;
83 	netbios_svc_t	nbs_ns;
84 	netbios_svc_t	nbs_dgm;
85 	netbios_svc_t	nbs_browser;
86 	netbios_svc_t	nbs_timer;
87 	netbios_state_t	nbs_state;
88 	uint32_t	nbs_errors;
89 	char		*nbs_last_event;
90 } netbios_service_t;
91 
92 extern char smb_node_type;
93 
94 #define	SMB_NODETYPE_B	'B'
95 #define	SMB_NODETYPE_P	'P'
96 #define	SMB_NODETYPE_M	'M'
97 #define	SMB_NODETYPE_H	'H'
98 
99 /*
100  * NAME service definitions
101  */
102 #define	ADDR_FLAG_INVALID		0x0000
103 #define	ADDR_FLAG_VALID		0x0001
104 
105 typedef struct addr_entry {
106 	struct addr_entry	*forw;
107 	struct addr_entry	*back;
108 	uint32_t		attributes;
109 	uint32_t		conflict_timer;
110 	uint32_t		refresh_ttl;
111 	uint32_t		ttl;
112 	struct sockaddr_in	sin;
113 	int			sinlen;
114 	uint32_t		flags;
115 } addr_entry_t;
116 
117 /*
118  *   The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
119  *   of NODE_NAME records.  Each NODE_NAME entry represents an active
120  *   name in the same NetBIOS scope as the requesting name in the
121  *   local name table of the responder.  RR_NAME is the requesting
122  *   name.
123  *
124  *   NODE_NAME Entry:
125  *
126  *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
127  *    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
128  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129  *   |                                                               |
130  *   +---                                                         ---+
131  *   |                                                               |
132  *   +---                    NETBIOS FORMAT NAME                  ---+
133  *   |                                                               |
134  *   +---                                                         ---+
135  *   |                                                               |
136  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137  *   |         NAME_FLAGS            |
138  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139  *
140  *   The NAME_FLAGS field:
141  *
142  *                                             1   1   1   1   1   1
143  *     0   1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
144  *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
145  *   | G |  ONT  |DRG|CNF|ACT|PRM|          RESERVED                 |
146  *   +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
147  *
148  *   The NAME_FLAGS field is defined as:
149  *
150  *   Symbol     Bit(s)   Description:
151  *
152  *   RESERVED     7-15   Reserved for future use.  Must be zero (0).
153  *   PRM             6   Permanent Name Flag.  If one (1) then entry
154  *                       is for the permanent node name.  Flag is zero
155  *                       (0) for all other names.
156  *   ACT             5   Active Name Flag.  All entries have this flag
157  *                       set to one (1).
158  *   CNF             4   Conflict Flag.  If one (1) then name on this
159  *                       node is in conflict.
160  *   DRG             3   Deregister Flag.  If one (1) then this name
161  *                       is in the process of being deleted.
162  *   ONT           1,2   Owner Node Type:
163  *                          00 = B node
164  *                          01 = P node
165  *                          10 = M node
166  *                          11 = Reserved for future use
167  *   G               0   Group Name Flag.
168  *                       name.
169  *                       If zero (0) then it is a UNIQUE NetBIOS name.
170  */
171 
172 typedef struct name_entry {
173 	struct name_entry	*forw;
174 	struct name_entry	*back;
175 	unsigned char		name[NETBIOS_NAME_SZ];
176 	unsigned char		scope[NETBIOS_DOMAIN_NAME_MAX];
177 	unsigned short		attributes;
178 	struct addr_entry	addr_list;
179 	mutex_t			mtx;
180 } name_entry_t;
181 
182 struct name_question {
183 	struct name_entry	*name;
184 	unsigned		question_type;
185 	unsigned		question_class;
186 };
187 
188 struct resource_record {
189 	/*
190 	 * These two flags and address are contained within RDATA
191 	 * when rr_type==0x0020 (NB - NetBIOS general Name Service)
192 	 * and rr_class==0x01 (IN - Internet Class).
193 	 */
194 
195 	struct name_entry *name;
196 	unsigned short rr_type;
197 	unsigned short rr_class;
198 	uint32_t ttl;
199 	unsigned short rdlength;
200 	unsigned char *rdata;
201 };
202 
203 struct name_packet {
204 	unsigned short		name_trn_id;
205 	unsigned short		info;
206 
207 	unsigned		qdcount;	/* question entries */
208 	unsigned		ancount;	/* answer recs */
209 	unsigned		nscount;	/* authority recs */
210 	unsigned		arcount;	/* additional recs */
211 
212 	struct name_question	*question;
213 	struct resource_record	*answer;
214 	struct resource_record	*authority;
215 	struct resource_record	*additional;
216 
217 	unsigned char			block_data[4];	/* begining of space */
218 };
219 
220 #define	NAME_OPCODE_R		0x8000	/* RESPONSE flag: 1 bit */
221 #define	NAME_OPCODE_OPCODE_MASK	0x7800	/* OPCODE Field: 4 bits */
222 #define	NAME_OPCODE_QUERY	0x0000
223 #define	NAME_OPCODE_REGISTRATION	0x2800
224 #define	NAME_OPCODE_RELEASE	0x3000
225 #define	NAME_OPCODE_WACK	0x3800
226 #define	NAME_OPCODE_REFRESH	0x4000
227 #define	NAME_OPCODE_MULTIHOME	0x7800
228 #define	NAME_NM_FLAGS_AA	0x0400	/* Authoritative Answer:1 bit */
229 #define	NAME_NM_FLAGS_TC	0x0200	/* Truncation:		1 bit */
230 #define	NAME_NM_FLAGS_RD	0x0100	/* Recursion desired:	1 bit */
231 #define	NAME_NM_FLAGS_RA	0x0080	/* Recursion available:	1 bit */
232 #define	NAME_NM_FLAGS_x2	0x0040	/* reserved, mbz:	1 bit */
233 #define	NAME_NM_FLAGS_x1	0x0020	/* reserved, mbz:	1 bit */
234 #define	NAME_NM_FLAGS_B		0x0010	/* Broadcast:		1 bit */
235 #define	NAME_RCODE_MASK		0x000f	/* RCODE Field:		4 bits */
236 #define	RCODE_FMT_ERR		0x0001
237 #define	RCODE_SRV_ERR		0x0002
238 #define	RCODE_NAM_ERR		0x0003
239 #define	RCODE_IMP_ERR		0x0004
240 #define	RCODE_RFS_ERR		0x0005
241 #define	RCODE_ACT_ERR		0x0006
242 #define	RCODE_CFT_ERR		0x0007
243 
244 #define	NM_FLAGS_UNICAST		0
245 #define	NM_FLAGS_BROADCAST		NAME_NM_FLAGS_B
246 
247 #define	PACKET_TYPE(x)	((x) & (NAME_OPCODE_R | NAME_OPCODE_OPCODE_MASK | \
248 			NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD))
249 
250 #define	RCODE(x)		((x) & NAME_RCODE_MASK)
251 #define	POSITIVE_RESPONSE(x)	(RCODE(x) == 0)
252 #define	NEGATIVE_RESPONSE(x)	(RCODE(x) != 0)
253 
254 #define	END_NODE_CHALLENGE_REGISTRATION_REQUEST				\
255 	    (NAME_OPCODE_REGISTRATION | NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD)
256 #define	END_NODE_CHALLENGE_NAME_REGISTRATION_RESPONSE			\
257 	    (NAME_OPCODE_R | END_NODE_CHALLENGE_REGISTRATION_REQUEST)
258 
259 #define	NAME_QUERY_REQUEST						\
260 	    (NAME_OPCODE_QUERY | NAME_NM_FLAGS_RD)
261 #define	NAME_QUERY_RESPONSE						\
262 	    (NAME_OPCODE_R | NAME_QUERY_REQUEST |			\
263 	    NAME_NM_FLAGS_AA | NAME_NM_FLAGS_RD)
264 
265 #define	NODE_STATUS_REQUEST						\
266 	    (NAME_OPCODE_QUERY)
267 #define	NODE_STATUS_RESPONSE						\
268 	    (NAME_OPCODE_R | NODE_STATUS_REQUEST | NAME_NM_FLAGS_AA)
269 
270 #define	REDIRECT_NAME_QUERY_RESPONSE					\
271 	    (NAME_OPCODE_R | NAME_QUERY_REQUEST | NAME_NM_FLAGS_RD)
272 
273 #define	NAME_REFRESH_REQUEST						\
274 	    (NAME_OPCODE_REFRESH)
275 #define	NAME_REGISTRATION_REQUEST					\
276 	    (NAME_OPCODE_REGISTRATION | NAME_NM_FLAGS_RD)
277 #define	NAME_MULTIHOME_REGISTRATION_REQUEST				\
278 	    (NAME_OPCODE_MULTIHOME | NAME_NM_FLAGS_RD)
279 #define	NAME_REGISTRATION_RESPONSE					\
280 	    (NAME_OPCODE_R | NAME_REGISTRATION_REQUEST | NAME_NM_FLAGS_AA)
281 
282 #define	NAME_RELEASE_REQUEST						\
283 	    (NAME_OPCODE_RELEASE)
284 #define	NAME_RELEASE_RESPONSE						\
285 	    (NAME_OPCODE_R | NAME_RELEASE_REQUEST | NAME_NM_FLAGS_AA)
286 
287 #define	WACK_RESPONSE						\
288 	    (NAME_OPCODE_R | NAME_OPCODE_WACK | NAME_NM_FLAGS_AA)
289 
290 #define	NAME_QUESTION_TYPE_NB		0x0020
291 #define	NAME_QUESTION_TYPE_NBSTAT	0x0021
292 #define	NAME_QUESTION_CLASS_IN		0x0001
293 
294 
295 #define	NAME_RR_TYPE_A			0x0001	/* IP Address */
296 #define	NAME_RR_TYPE_NS			0x0002	/* Name Server */
297 #define	NAME_RR_TYPE_NULL		0x000A	/* NULL */
298 #define	NAME_RR_TYPE_NB			0x0020	/* NetBIOS Name Service */
299 #define	NAME_RR_TYPE_NBSTAT		0x0021	/* NetBIOS Node Status */
300 
301 #define	NAME_RR_CLASS_IN		0x0001	/* NetBIOS Node Status */
302 
303 #define	NAME_NB_FLAGS_ONT_MASK		(3<<13)
304 #define	NAME_NB_FLAGS_ONT_B		(0<<13) /* B-node (broadcast) */
305 #define	NAME_NB_FLAGS_ONT_P		(1<<13)	/* P-node (point-to-point) */
306 #define	NAME_NB_FLAGS_ONT_M		(2<<13)	/* M-node (multicast) */
307 #define	NAME_NB_FLAGS_ONT_resv		(3<<13)
308 #define	NAME_NB_FLAGS_G			(1<<15)	/* Group Name */
309 
310 #define	UNICAST				0
311 #define	BROADCAST			1
312 #define	POINTCAST			2
313 
314 #define	NAME_ATTR_UNIQUE		0x0000
315 #define	NAME_ATTR_GROUP			0x8000
316 #define	NAME_ATTR_OWNER_NODE_TYPE	0x6000
317 #define	  NAME_ATTR_OWNER_TYPE_BNODE	  0x0000
318 #define	  NAME_ATTR_OWNER_TYPE_PNODE	  0x2000
319 #define	  NAME_ATTR_OWNER_TYPE_MNODE	  0x4000
320 #define	  NAME_ATTR_OWNER_TYPE_HNODE	  0x6000
321 #define	NAME_ATTR_DEREGISTER		0x1000
322 #define	NAME_ATTR_CONFLICT		0x0800
323 #define	NAME_ATTR_ACTIVE_NAME		0x0400
324 #define	NAME_ATTR_PERMANENT		0x0200
325 #define	NAME_ATTR_RESERVED		0x01FF
326 #define	NAME_ATTR_LOCAL			0x0001
327 
328 #define	NODE_TYPE(x)		((x) & NAME_ATTR_OWNER_NODE_TYPE))
329 #define	IS_BNODE(x)		(NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_BNODE)
330 #define	IS_PNODE(x)		(NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_PNODE)
331 #define	IS_MNODE(x)		(NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_MNODE)
332 #define	IS_HNODE(x)		(NODE_TYPE(x) == NAME_ATTR_OWNER_TYPE_HNODE)
333 
334 #define	IS_UNIQUE(x)		(((x) & NAME_ATTR_GROUP) == 0)
335 #define	IS_GROUP(x)		(((x) & NAME_ATTR_GROUP) != 0)
336 #define	IS_PERMANENT(x)		(((x) & NAME_ATTR_PERMANENT) != 0)
337 #define	IS_CONFLICTING(x)	(((x) & NAME_ATTR_CONFLICT) != 0)
338 #define	IS_ACTIVE(x)		(((x) & NAME_ATTR_ACTIVE) != 0)
339 #define	IS_DEGREGISTERED(x)	(((x) & NAME_ATTR_ACTIVE) != 0)
340 
341 #define	IS_LOCAL(x)		(((x) & NAME_ATTR_LOCAL) != 0)
342 #define	IS_PUBLIC(x)		(((x) & NAME_ATTR_LOCAL) == 0)
343 #define	PUBLIC_BITS(x)		((x) & ~NAME_ATTR_RESERVED)
344 
345 #define	SAME_SCOPE(scope, e)	(strcmp((scope), ((e)->scope)) == 0)
346 
347 /*
348  *   STATISTICS Field of the NODE STATUS RESPONSE:
349  *
350  *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
351  *    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
352  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353  *   |               UNIT_ID (Unique unit ID)                        |
354  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
355  *   |       UNIT_ID,continued       |    JUMPERS    |  TEST_RESULT  |
356  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357  *   |       VERSION_NUMBER          |      PERIOD_OF_STATISTICS     |
358  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
359  *   |       NUMBER_OF_CRCs          |     NUMBER_ALIGNMENT_ERRORS   |
360  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361  *   |       NUMBER_OF_COLLISIONS    |        NUMBER_SEND_ABORTS     |
362  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363  *   |                       NUMBER_GOOD_SENDS                       |
364  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365  *   |                      NUMBER_GOOD_RECEIVES                     |
366  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367  *   |       NUMBER_RETRANSMITS      | NUMBER_NO_RESOURCE_CONDITIONS |
368  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369  *   |  NUMBER_FREE_COMMAND_BLOCKS   |  TOTAL_NUMBER_COMMAND_BLOCKS  |
370  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
371  *   |MAX_TOTAL_NUMBER_COMMAND_BLOCKS|    NUMBER_PENDING_SESSIONS    |
372  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
373  *   |  MAX_NUMBER_PENDING_SESSIONS  |  MAX_TOTAL_SESSIONS_POSSIBLE  |
374  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
375  *   |   SESSION_DATA_PACKET_SIZE    |
376  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
377  */
378 
379 typedef struct {
380 	unsigned char	unit_id[6];
381 	unsigned char	jumpers;
382 	unsigned char	test_result;
383 	unsigned short	version_number;
384 	unsigned short	statistical_period;
385 	unsigned short	crc_errors;
386 	unsigned short	alignment_errors;
387 	unsigned short	collisions;
388 	unsigned short	send_aborts;
389 	unsigned int	good_sends;
390 	unsigned int	good_receives;
391 	unsigned short	retransmits;
392 	unsigned short	no_resource_conditions;
393 	unsigned short	free_command_blocks;
394 	unsigned short	total_command_blocks;
395 	unsigned short	max_total_command_blocks;
396 	unsigned short	pending_sessions;
397 	unsigned short	max_pending_sessions;
398 	unsigned short	total_possible_sessions;
399 	unsigned short	session_data_packet_size;
400 } node_status_response;
401 
402 /*
403  * 4.4.1.  NetBIOS DATAGRAM HEADER
404  *
405  *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
406  *     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
407  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408  *    |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
409  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410  *    |                           SOURCE_IP                           |
411  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412  *    |          SOURCE_PORT          |          DGM_LENGTH           |
413  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414  *    |         PACKET_OFFSET         |
415  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416  */
417 typedef struct {
418 	unsigned char	msg_type;
419 	unsigned char	flags;
420 	unsigned short	dgm_id;
421 	uint32_t	source_ip;
422 	unsigned short	source_port;
423 	unsigned short	dgm_length;
424 	unsigned short	packet_offset;
425 } datagram_header;
426 
427 /*
428  *    MSG_TYPE values (in hexidecimal):
429  *
430  *            10 -  DIRECT_UNIQUE DATAGRAM
431  *            11 -  DIRECT_GROUP DATAGRAM
432  *            12 -  BROADCAST DATAGRAM
433  *            13 -  DATAGRAM ERROR
434  *            14 -  DATAGRAM QUERY REQUEST
435  *            15 -  DATAGRAM POSITIVE QUERY RESPONSE
436  *            16 -  DATAGRAM NEGATIVE QUERY RESPONSE
437  */
438 #define	DATAGRAM_TYPE_DIRECT_UNIQUE	0x10
439 #define	DATAGRAM_TYPE_DIRECT_GROUP	0x11
440 #define	DATAGRAM_TYPE_BROADCAST		0x12
441 #define	DATAGRAM_TYPE_ERROR_DATAGRAM	0x13
442 #define	DATAGRAM_TYPE_QUERY_REQUEST	0x14
443 #define	DATAGRAM_TYPE_POSITIVE_RESPONSE	0x15
444 #define	DATAGRAM_TYPE_NEGATIVE_RESPONSE	0x16
445 
446 
447 /*
448  *    Bit definitions of the FLAGS field:
449  *
450  *      0   1   2   3   4   5   6   7
451  *    +---+---+---+---+---+---+---+---+
452  *    | 0 | 0 | 0 | 0 |  SNT  | F | M |
453  *    +---+---+---+---+---+---+---+---+
454  *
455  *    Symbol     Bit(s)   Description
456  *
457  *    M               7   MORE flag, If set then more NetBIOS datagram
458  *                        fragments follow.
459  *
460  *    F               6   FIRST packet flag,  If set then this is first
461  *                        (and possibly only) fragment of NetBIOS
462  *                        datagram
463  *
464  *    SNT           4,5   Source End-Node type:
465  *                           00 = B node
466  *                           01 = P node
467  *                           10 = M node
468  *                           11 = H node
469  *    RESERVED      0-3   Reserved, must be zero (0)
470  */
471 #define	DATAGRAM_FLAGS_MORE	0x01
472 #define	DATAGRAM_FLAGS_FIRST	0x02
473 #define	DATAGRAM_FLAGS_SRC_TYPE	0x0c
474 #define	DATAGRAM_FLAGS_B_NODE	  0x00
475 #define	DATAGRAM_FLAGS_P_NODE	  0x04
476 #define	DATAGRAM_FLAGS_M_NODE	  0x08
477 #define	DATAGRAM_FLAGS_H_NODE	  0x0C
478 #define	DATAGRAM_FLAGS_NBDD	  0x0c
479 #define	DATAGRAM_FLAGS_RESERVED	0xf0
480 
481 /*
482  * 4.4.2.  DIRECT_UNIQUE, DIRECT_GROUP, & BROADCAST DATAGRAM
483  *
484  *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
485  *     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
486  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487  *    |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
488  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
489  *    |                           SOURCE_IP                           |
490  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
491  *    |          SOURCE_PORT          |          DGM_LENGTH           |
492  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
493  *    |         PACKET_OFFSET         |                               |
494  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
495  *    |                                                               |
496  *    /                          SOURCE_NAME                          /
497  *    /                                                               /
498  *    |                                                               |
499  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
500  *    |                                                               |
501  *    /                       DESTINATION_NAME                        /
502  *    /                                                               /
503  *    |                                                               |
504  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
505  *    |                                                               |
506  *    /                           USER_DATA                           /
507  *    /                                                               /
508  *    |                                                               |
509  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
510  */
511 typedef struct {
512 	datagram_header	header;
513 	unsigned char	*source_name;
514 	unsigned char	*destination_name;
515 	unsigned char	*user_data;
516 } datagram_packet;
517 
518 
519 /*
520  *    4.4.3.  DATAGRAM ERROR PACKET
521  *
522  *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
523  *     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
524  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525  *    |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
526  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
527  *    |                           SOURCE_IP                           |
528  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
529  *    |          SOURCE_PORT          |  ERROR_CODE   |
530  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
531  *
532  *    ERROR_CODE values (in hexidecimal):
533  *
534  *            82 -  DESTINATION NAME NOT PRESENT
535  *            83 -  INVALID SOURCE NAME FORMAT
536  *            84 -  INVALID DESTINATION NAME FORMAT
537  */
538 
539 typedef struct {
540 	unsigned char	msg_type;
541 	unsigned char	flags;
542 	unsigned short	dgm_id;
543 	uint32_t	source_ip;
544 	unsigned short	source_port;
545 	unsigned char	error;
546 } datagram_error_packet;
547 
548 /*
549  * 4.4.4.  DATAGRAM QUERY REQUEST
550  *
551  *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
552  *     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
553  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554  *    |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
555  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
556  *    |                           SOURCE_IP                           |
557  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
558  *    |          SOURCE_PORT          |                               |
559  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
560  *    |                                                               |
561  *    /                       DESTINATION_NAME                        /
562  *    /                                                               /
563  *    |                                                               |
564  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
565  *
566  * 4.4.5.  DATAGRAM POSITIVE AND NEGATIVE QUERY RESPONSE
567  *
568  *                         1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
569  *     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
570  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571  *    |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
572  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573  *    |                           SOURCE_IP                           |
574  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575  *    |          SOURCE_PORT          |                               |
576  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
577  *    |                                                               |
578  *    /                       DESTINATION_NAME                        /
579  *    /                                                               /
580  *    |                                                               |
581  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
582  */
583 
584 typedef struct datagram_query_packet {
585 	unsigned char	msg_type;
586 	unsigned char	flags;
587 	unsigned short	dgm_id;
588 	uint32_t	source_ip;
589 	unsigned short	source_port;
590 	unsigned char	destination_name[MAX_NAME_LENGTH];
591 } datagram_query_packet;
592 
593 
594 typedef struct datagram {
595 	struct datagram		*forw;
596 	struct datagram		*back;
597 	struct addr_entry	inaddr;
598 	int			discard_timer;
599 	unsigned char		packet_type;
600 	unsigned char		flags;
601 	unsigned short		datagram_id;
602 	struct name_entry	src;
603 	struct name_entry	dest;
604 	unsigned short		offset;
605 	unsigned short		data_length;
606 	unsigned char		*data;
607 	unsigned int		rawbytes;
608 	unsigned char		rawbuf[MAX_DATAGRAM_LENGTH];
609 } datagram;
610 
611 typedef struct datagram_queue {
612 	struct datagram		*forw;
613 	struct datagram		*back;
614 } datagram_queue;
615 
616 typedef struct name_queue {
617 	struct name_entry head;
618 	mutex_t mtx;
619 } name_queue_t;
620 
621 typedef struct nbcache_iter {
622 	HT_ITERATOR		nbc_hti;
623 	struct name_entry	*nbc_entry;
624 } nbcache_iter_t;
625 
626 #define	NETBIOS_EMPTY_NAME (unsigned char *)""
627 
628 #define	NETBIOS_NAME_IS_STAR(name) \
629 	(bcmp(name, "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NETBIOS_NAME_SZ) == 0)
630 
631 
632 /*
633  * NetBIOS service state machine interface
634  */
635 void smb_netbios_event(netbios_event_t);
636 void smb_netbios_wait(netbios_event_t);
637 void smb_netbios_sleep(time_t);
638 boolean_t smb_netbios_running(void);
639 boolean_t smb_netbios_error(void);
640 
641 /*
642  * Name Cache Functions
643  */
644 int  smb_netbios_cache_init(void);
645 void smb_netbios_cache_fini(void);
646 void smb_netbios_cache_dump(FILE *fp);
647 int smb_netbios_cache_count(void);
648 void smb_netbios_cache_clean(void);
649 void smb_netbios_cache_reset_ttl(void);
650 void smb_netbios_cache_delete_locals(name_queue_t *);
651 void smb_netbios_cache_refresh(name_queue_t *);
652 
653 int smb_netbios_cache_insert(struct name_entry *name);
654 int smb_netbios_cache_insert_list(struct name_entry *name);
655 void smb_netbios_cache_delete(struct name_entry *name);
656 int smb_netbios_cache_delete_addr(struct name_entry *name);
657 struct name_entry *smb_netbios_cache_lookup(struct name_entry *name);
658 struct name_entry *smb_netbios_cache_lookup_addr(struct name_entry *name);
659 void smb_netbios_cache_update_entry(struct name_entry *, struct name_entry *);
660 void smb_netbios_cache_unlock_entry(struct name_entry *);
661 unsigned char *smb_netbios_cache_status(unsigned char *, int, unsigned char *);
662 int smb_netbios_cache_getfirst(nbcache_iter_t *);
663 int smb_netbios_cache_getnext(nbcache_iter_t *);
664 
665 void smb_netbios_name_dump(FILE *fp, struct name_entry *entry);
666 void smb_netbios_name_logf(struct name_entry *entry);
667 void smb_netbios_name_freeaddrs(struct name_entry *entry);
668 struct name_entry *smb_netbios_name_dup(struct name_entry *, int);
669 
670 /* Name service functions */
671 void *smb_netbios_name_service(void *);
672 void smb_init_name_struct(unsigned char *, char, unsigned char *, uint32_t,
673     unsigned short, uint32_t, uint32_t, struct name_entry *);
674 
675 struct name_entry *smb_name_find_name(struct name_entry *name);
676 int smb_name_add_name(struct name_entry *name);
677 int smb_name_delete_name(struct name_entry *name);
678 void smb_name_unlock_name(struct name_entry *name);
679 
680 void smb_netbios_name_config(void);
681 void smb_netbios_name_unconfig(void);
682 void smb_netbios_name_tick(void);
683 
684 int smb_first_level_name_encode(struct name_entry *, unsigned char *, int);
685 int smb_first_level_name_decode(unsigned char *, struct name_entry *);
686 void smb_encode_netbios_name(unsigned char *, char, unsigned char *,
687     struct name_entry *);
688 
689 /* Datagram service functions */
690 void *smb_netbios_datagram_service(void *);
691 int smb_netbios_datagram_send(struct name_entry *,
692     struct name_entry *, unsigned char *, int);
693 void smb_netbios_datagram_tick(void);
694 
695 /* browser functions */
696 void *smb_browser_dispatch(void *arg);
697 void *smb_browser_service(void *);
698 int smb_browser_load_transact_header(unsigned char *, int, int, int, char *);
699 
700 /* Netlogon function */
701 void smb_netlogon_receive(struct datagram *, char *, unsigned char *, int);
702 void smb_netlogon_request(struct name_entry *, char *);
703 
704 #endif /* _SMB_NETBIOS_H_ */
705