xref: /titanic_52/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c (revision a0aa776e20803c84edd153d9cb584fd67163aef3)
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 /*
27  * Description:
28  *
29  *	Contains base code for netbios datagram service.
30  *
31  * Relavent sections from RFC1002:
32  *
33  *  5.3.  NetBIOS DATAGRAM SERVICE PROTOCOLS
34  *
35  *   The following are GLOBAL variables and should be NetBIOS user
36  *   configurable:
37  *
38  *   - SCOPE_ID: the non-leaf section of the domain name preceded by a
39  *     '.'  which represents the domain of the NetBIOS scope for the
40  *     NetBIOS name.  The following protocol description only supports
41  *     single scope operation.
42  *
43  *   - MAX_DATAGRAM_LENGTH: the maximum length of an IP datagram.  The
44  *     minimal maximum length defined in for IP is 576 bytes.  This
45  *     value is used when determining whether to fragment a NetBIOS
46  *     datagram.  Implementations are expected to be capable of
47  *     receiving unfragmented NetBIOS datagrams up to their maximum
48  *     size.
49  *
50  *   - BROADCAST_ADDRESS: the IP address B-nodes use to send datagrams
51  *     with group name destinations and broadcast datagrams.  The
52  *     default is the IP broadcast address for a single IP network.
53  *
54  *
55  *   The following are Defined Constants for the NetBIOS Datagram
56  *   Service:
57  *
58  *   - IPPORT_NETBIOS_DGM: the globally well-known UDP port allocated
59  *     where the NetBIOS Datagram Service receives UDP packets.  See
60  *     section 6, "Defined Constants", for its value.
61  */
62 
63 /*
64  *
65  *  6.  DEFINED CONSTANTS AND VARIABLES
66  *
67  *   GENERAL:
68  *
69  *      SCOPE_ID                   The name of the NetBIOS scope.
70  *
71  *                                 This is expressed as a character
72  *                                 string meeting the requirements of
73  *                                 the domain name system and without
74  *                                 a leading or trailing "dot".
75  *
76  *                                 An implementation may elect to make
77  *                                 this a single global value for the
78  *                                 node or allow it to be specified
79  *                                 with each separate NetBIOS name
80  *                                 (thus permitting cross-scope
81  *                                 references.)
82  *
83  *      BROADCAST_ADDRESS          An IP address composed of the
84  *                                 node network and subnetwork
85  *                                 numbers with all remaining bits set
86  *                                 to one.
87  *
88  *                                 I.e. "Specific subnet" broadcast
89  *                                 addressing according to section 2.3
90  *                                 of RFC 950.
91  *
92  *      BCAST_REQ_RETRY_TIMEOUT    250 milliseconds.
93  *                                 An adaptive timer may be used.
94  *
95  *      BCAST_REQ_RETRY_COUNT      3
96  *
97  *      UCAST_REQ_RETRY_TIMEOUT    5 seconds
98  *                                 An adaptive timer may be used.
99  *
100  *      UCAST_REQ_RETRY_COUNT      3
101  *
102  *      MAX_DATAGRAM_LENGTH        576 bytes (default)
103  *
104  *   DATAGRAM SERVICE:
105  *
106  *      IPPORT_NETBIOS_DGM          138 (decimal)
107  *
108  *      FRAGMENT_TO                2 seconds (default)
109  */
110 
111 #include <errno.h>
112 #include <stdlib.h>
113 #include <unistd.h>
114 #include <string.h>
115 #include <strings.h>
116 #include <syslog.h>
117 #include <synch.h>
118 #include <sys/socket.h>
119 #include <arpa/inet.h>
120 
121 #include <smbns_netbios.h>
122 
123 #include <smbsrv/libsmbns.h>
124 
125 static int datagram_sock = -1;
126 static short datagram_id = 1;
127 static struct datagram_queue smb_datagram_queue;
128 static mutex_t smb_dgq_mtx;
129 
130 static void smb_netbios_datagram_error(unsigned char *buf);
131 
132 /*
133  * Function:  smb_netbios_datagram_tick(void)
134  *
135  * Description:
136  *
137  *	Called once a second to handle time to live timeouts in
138  *	datagram assembly queue.
139  *
140  * Inputs:
141  *
142  * Returns:
143  *	void	-> Nothing at all...
144  */
145 
146 void
147 smb_netbios_datagram_tick(void)
148 {
149 	struct datagram *entry;
150 	struct datagram *next;
151 
152 	(void) mutex_lock(&smb_dgq_mtx);
153 
154 	for (entry = smb_datagram_queue.forw;
155 	    entry != (struct datagram *)((uintptr_t)&smb_datagram_queue);
156 	    entry = next) {
157 		next = entry->forw;
158 		if (--entry->discard_timer == 0) {
159 			/* Toss it */
160 			QUEUE_CLIP(entry);
161 			free(entry);
162 		}
163 	}
164 	(void) mutex_unlock(&smb_dgq_mtx);
165 }
166 
167 void
168 smb_netbios_datagram_fini()
169 {
170 	struct datagram *entry;
171 
172 	(void) mutex_lock(&smb_dgq_mtx);
173 	while ((entry = smb_datagram_queue.forw) !=
174 	    (struct datagram *)((uintptr_t)&smb_datagram_queue)) {
175 		QUEUE_CLIP(entry);
176 		free(entry);
177 	}
178 	(void) mutex_unlock(&smb_dgq_mtx);
179 }
180 
181 /*
182  * Function: int smb_netbios_send_Bnode_datagram(unsigned char *data,
183  *		struct name_entry *source, struct name_entry *destination,
184  *		uint32_t broadcast)
185  *
186  * Description from rfc1002:
187  *
188  *  5.3.1.  B NODE TRANSMISSION OF NetBIOS DATAGRAMS
189  *
190  *   PROCEDURE send_datagram(data, source, destination, broadcast)
191  *
192  *   (*
193  *    * user initiated processing on B node
194  *    *)
195  *
196  *   BEGIN
197  *        group = FALSE;
198  *
199  *        do name discovery on destination name, returns name type and
200  *             IP address;
201  *
202  *        IF name type is group name THEN
203  *        BEGIN
204  *             group = TRUE;
205  *        END
206  *
207  *        (*
208  *         * build datagram service UDP packet;
209  *         *)
210  *        convert source and destination NetBIOS names into
211  *             half-ASCII, biased encoded name;
212  *        SOURCE_NAME = cat(source, SCOPE_ID);
213  *        SOURCE_IP = this nodes IP address;
214  *        SOURCE_PORT =  IPPORT_NETBIOS_DGM;
215  *
216  *        IF NetBIOS broadcast THEN
217  *        BEGIN
218  *             DESTINATION_NAME = cat("*", SCOPE_ID)
219  *        END
220  *        ELSE
221  *        BEGIN
222  *             DESTINATION_NAME = cat(destination, SCOPE_ID)
223  *        END
224  *
225  *        MSG_TYPE = select_one_from_set
226  *             {BROADCAST, DIRECT_UNIQUE, DIRECT_GROUP}
227  *        DGM_ID = next transaction id for Datagrams;
228  *        DGM_LENGTH = length of data + length of second level encoded
229  *             source and destination names;
230  *
231  *        IF (length of the NetBIOS Datagram, including UDP and
232  *            IP headers, > MAX_DATAGRAM_LENGTH) THEN
233  *        BEGIN
234  *             (*
235  *              * fragment NetBIOS datagram into 2 UDP packets
236  *              *)
237  *             Put names into 1st UDP packet and any data that fits
238  *                  after names;
239  *             Set MORE and FIRST bits in 1st UDP packets FLAGS;
240  *             OFFSET in 1st UDP = 0;
241  *
242  *             Replicate NetBIOS Datagram header from 1st UDP packet
243  *                  into 2nd UDP packet;
244  *             Put rest of data in 2nd UDP packet;
245  *             Clear MORE and FIRST bits in 2nd UDP packets FLAGS;
246  *             OFFSET in 2nd UDP = DGM_LENGTH - number of name and
247  *                  data bytes in 1st UDP;
248  *        END
249  *        BEGIN
250  *             (*
251  *              * Only need one UDP packet
252  *              *)
253  *             USER_DATA = data;
254  *             Clear MORE bit and set FIRST bit in FLAGS;
255  *             OFFSET = 0;
256  *        END
257  *
258  *        IF (group == TRUE) OR (NetBIOS broadcast) THEN
259  *        BEGIN
260  *             send UDP packet(s) to BROADCAST_ADDRESS;
261  *        END
262  *        ELSE
263  *        BEGIN
264  *             send UDP packet(s) to IP address returned by name
265  *                discovery;
266  *        END
267  *   END (* procedure *)
268  *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
269  *    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
270  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271  *   |   MSG_TYPE    |     FLAGS     |           DGM_ID              |
272  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273  *   |                           SOURCE_IP                           |
274  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
275  *   |          SOURCE_PORT          |          DGM_LENGTH           |
276  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277  *   |         PACKET_OFFSET         |
278  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279  *
280  *   MSG_TYPE values (in hexidecimal):
281  *
282  *           10 -  DIRECT_UNIQUE DATAGRAM
283  *           11 -  DIRECT_GROUP DATAGRAM
284  *           12 -  BROADCAST DATAGRAM
285  *           13 -  DATAGRAM ERROR
286  *           14 -  DATAGRAM QUERY REQUEST
287  *           15 -  DATAGRAM POSITIVE QUERY RESPONSE
288  *           16 -  DATAGRAM NEGATIVE QUERY RESPONSE
289  *
290  *   Bit definitions of the FLAGS field:
291  *
292  *     0   1   2   3   4   5   6   7
293  *   +---+---+---+---+---+---+---+---+
294  *   | 0 | 0 | 0 | 0 |  SNT  | F | M |
295  *   +---+---+---+---+---+---+---+---+
296  *
297  *   Symbol     Bit(s)   Description
298  *
299  *   M               7   MORE flag, If set then more NetBIOS datagram
300  *                       fragments follow.
301  *
302  *   F               6   FIRST packet flag,  If set then this is first
303  *                       (and possibly only) fragment of NetBIOS
304  *                       datagram
305  *
306  *   SNT           4,5   Source End-Node type:
307  *                          00 = B node
308  *                          01 = P node
309  *                          10 = M node
310  *                          11 = NBDD
311  *   RESERVED      0-3   Reserved, must be zero (0)
312  *      (But MS sets bit 3 in this field)
313  *
314  */
315 
316 int
317 smb_netbios_datagram_send(struct name_entry *src, struct name_entry *dest,
318     unsigned char *data, int length)
319 {
320 	smb_inaddr_t ipaddr;
321 	size_t count, srclen, destlen, sinlen;
322 	addr_entry_t *addr;
323 	struct sockaddr_in sin;
324 	char *buffer;
325 	char ha_source[NETBIOS_DOMAIN_NAME_MAX];
326 	char ha_dest[NETBIOS_DOMAIN_NAME_MAX];
327 
328 	(void) smb_first_level_name_encode(src, (unsigned char *)ha_source,
329 	    sizeof (ha_source));
330 	srclen = strlen(ha_source) + 1;
331 
332 	(void) smb_first_level_name_encode(dest, (unsigned char *)ha_dest,
333 	    sizeof (ha_dest));
334 	destlen = strlen(ha_dest) + 1;
335 
336 	/* give some extra room */
337 	if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) {
338 		syslog(LOG_ERR, "nbt datagram: send: %m");
339 		return (-1);
340 	}
341 
342 	buffer[0] = DATAGRAM_TYPE_DIRECT_UNIQUE;
343 	switch (smb_node_type) {
344 	case 'B':
345 		buffer[1] = DATAGRAM_FLAGS_B_NODE | DATAGRAM_FLAGS_FIRST;
346 		break;
347 	case 'P':
348 		buffer[1] = DATAGRAM_FLAGS_P_NODE | DATAGRAM_FLAGS_FIRST;
349 		break;
350 	case 'M':
351 		buffer[1] = DATAGRAM_FLAGS_M_NODE | DATAGRAM_FLAGS_FIRST;
352 		break;
353 	case 'H':
354 	default:
355 		buffer[1] = DATAGRAM_FLAGS_H_NODE | DATAGRAM_FLAGS_FIRST;
356 		break;
357 	}
358 
359 	datagram_id++;
360 	BE_OUT16(&buffer[2], datagram_id);
361 	(void) memcpy(&buffer[4], &src->addr_list.sin.sin_addr.s_addr,
362 	    sizeof (uint32_t));
363 	(void) memcpy(&buffer[8], &src->addr_list.sin.sin_port,
364 	    sizeof (uint16_t));
365 	BE_OUT16(&buffer[10], length + srclen + destlen);
366 	BE_OUT16(&buffer[12], 0);
367 
368 	bcopy(ha_source, &buffer[14], srclen);
369 	bcopy(ha_dest, &buffer[14 + srclen], destlen);
370 	bcopy(data, &buffer[14 + srclen + destlen], length);
371 	count = &buffer[14 + srclen + destlen + length] - buffer;
372 
373 	bzero(&sin, sizeof (sin));
374 	sin.sin_family = AF_INET;
375 	sinlen = sizeof (sin);
376 	addr = &dest->addr_list;
377 	do {
378 		ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
379 		ipaddr.a_family = AF_INET;
380 		/* Don't send anything to myself... */
381 		if (smb_nic_is_local(&ipaddr))
382 			goto next;
383 
384 		sin.sin_addr.s_addr = ipaddr.a_ipv4;
385 		sin.sin_port = addr->sin.sin_port;
386 		(void) sendto(datagram_sock, buffer, count, 0,
387 		    (struct sockaddr *)&sin, sinlen);
388 
389 next:		addr = addr->forw;
390 	} while (addr != &dest->addr_list);
391 	free(buffer);
392 	return (0);
393 }
394 
395 
396 int
397 smb_netbios_datagram_send_to_net(struct name_entry *src,
398     struct name_entry *dest, char *data, int length)
399 {
400 	smb_inaddr_t ipaddr;
401 	size_t count, srclen, destlen, sinlen;
402 	addr_entry_t *addr;
403 	struct sockaddr_in sin;
404 	char *buffer;
405 	char ha_source[NETBIOS_DOMAIN_NAME_MAX];
406 	char ha_dest[NETBIOS_DOMAIN_NAME_MAX];
407 
408 	(void) smb_first_level_name_encode(src, (unsigned char *)ha_source,
409 	    sizeof (ha_source));
410 	srclen = strlen(ha_source) + 1;
411 
412 	(void) smb_first_level_name_encode(dest, (unsigned char *)ha_dest,
413 	    sizeof (ha_dest));
414 	destlen = strlen(ha_dest) + 1;
415 
416 	/* give some extra room */
417 	if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) {
418 		syslog(LOG_ERR, "nbt datagram: send_to_net: %m");
419 		return (-1);
420 	}
421 
422 	buffer[0] = DATAGRAM_TYPE_DIRECT_UNIQUE;
423 	switch (smb_node_type) {
424 	case 'B':
425 		buffer[1] = DATAGRAM_FLAGS_B_NODE | DATAGRAM_FLAGS_FIRST;
426 		break;
427 	case 'P':
428 		buffer[1] = DATAGRAM_FLAGS_P_NODE | DATAGRAM_FLAGS_FIRST;
429 		break;
430 	case 'M':
431 		buffer[1] = DATAGRAM_FLAGS_M_NODE | DATAGRAM_FLAGS_FIRST;
432 		break;
433 	case 'H':
434 	default:
435 		buffer[1] = DATAGRAM_FLAGS_H_NODE | DATAGRAM_FLAGS_FIRST;
436 		break;
437 	}
438 
439 	datagram_id++;
440 	BE_OUT16(&buffer[2], datagram_id);
441 	(void) memcpy(&buffer[4], &src->addr_list.sin.sin_addr.s_addr,
442 	    sizeof (uint32_t));
443 	(void) memcpy(&buffer[8], &src->addr_list.sin.sin_port,
444 	    sizeof (uint16_t));
445 	BE_OUT16(&buffer[10], length + srclen + destlen);
446 	BE_OUT16(&buffer[12], 0);
447 
448 	bcopy(ha_source, &buffer[14], srclen);
449 	bcopy(ha_dest, &buffer[14 + srclen], destlen);
450 	bcopy(data, &buffer[14 + srclen + destlen], length);
451 	count = &buffer[14 + srclen + destlen + length] - buffer;
452 
453 	bzero(&sin, sizeof (sin));
454 	sin.sin_family = AF_INET;
455 	sinlen = sizeof (sin);
456 	addr = &dest->addr_list;
457 	do {
458 		ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
459 		ipaddr.a_family = AF_INET;
460 		if (smb_nic_is_local(&ipaddr))
461 			goto next;
462 
463 		sin.sin_addr.s_addr = ipaddr.a_ipv4;
464 		sin.sin_port = addr->sin.sin_port;
465 		(void) sendto(datagram_sock, buffer, count, 0,
466 		    (struct sockaddr *)&sin, sinlen);
467 
468 next:		addr = addr->forw;
469 	} while (addr != &dest->addr_list);
470 	free(buffer);
471 	return (0);
472 }
473 
474 
475 int
476 smb_datagram_decode(struct datagram *datagram, int bytes)
477 {
478 	unsigned char *ha_src;
479 	unsigned char *ha_dest;
480 	unsigned char *data;
481 
482 	if (bytes == DATAGRAM_ERR_HEADER_LENGTH) {
483 		if (datagram->rawbuf[0] == DATAGRAM_TYPE_ERROR_DATAGRAM)
484 			smb_netbios_datagram_error(datagram->rawbuf);
485 		return (-1);
486 
487 	}
488 
489 	if (bytes >= DATAGRAM_HEADER_LENGTH) {
490 		ha_src = &datagram->rawbuf[DATAGRAM_HEADER_LENGTH];
491 		ha_dest = ha_src + strlen((char *)ha_src) + 1;
492 		data = ha_dest + strlen((char *)ha_dest) + 1;
493 
494 		bzero(&datagram->src, sizeof (struct name_entry));
495 		bzero(&datagram->dest, sizeof (struct name_entry));
496 
497 		datagram->rawbytes = bytes;
498 		datagram->packet_type = datagram->rawbuf[0];
499 		datagram->flags = datagram->rawbuf[1];
500 		datagram->datagram_id = BE_IN16(&datagram->rawbuf[2]);
501 
502 		datagram->src.addr_list.sinlen = sizeof (struct sockaddr_in);
503 		(void) memcpy(&datagram->src.addr_list.sin.sin_addr.s_addr,
504 		    &datagram->rawbuf[4], sizeof (uint32_t));
505 		(void) memcpy(&datagram->src.addr_list.sin.sin_port,
506 		    &datagram->rawbuf[8], sizeof (uint16_t));
507 		datagram->src.addr_list.forw = datagram->src.addr_list.back =
508 		    &datagram->src.addr_list;
509 
510 		datagram->data = data;
511 		datagram->data_length = BE_IN16(&datagram->rawbuf[10]);
512 		datagram->offset = BE_IN16(&datagram->rawbuf[12]);
513 
514 		if (smb_first_level_name_decode(ha_src, &datagram->src) < 0) {
515 			smb_tracef("NbtDatagram[%s]: invalid calling name",
516 			    inet_ntoa(datagram->src.addr_list.sin.sin_addr));
517 			smb_tracef("Calling name: <%02X>%32.32s",
518 			    ha_src[0], &ha_src[1]);
519 		}
520 
521 		datagram->dest.addr_list.forw = datagram->dest.addr_list.back =
522 		    &datagram->dest.addr_list;
523 
524 		if (smb_first_level_name_decode(ha_dest, &datagram->dest) < 0) {
525 			smb_tracef("NbtDatagram[%s]: invalid called name",
526 			    inet_ntoa(datagram->src.addr_list.sin.sin_addr));
527 			smb_tracef("Called name: <%02X>%32.32s", ha_dest[0],
528 			    &ha_dest[1]);
529 		}
530 
531 		return (0);
532 	}
533 
534 	/* ignore other malformed datagram packets */
535 	return (-1);
536 }
537 
538 /*
539  * 4.4.3. Datagram Error Packet
540  */
541 static void
542 smb_netbios_datagram_error(unsigned char *buf)
543 {
544 	int error;
545 	int datagram_id;
546 
547 	if (buf[0] != DATAGRAM_TYPE_ERROR_DATAGRAM)
548 		return;
549 
550 	datagram_id = BE_IN16(&buf[2]);
551 	error = buf[DATAGRAM_ERR_HEADER_LENGTH - 1];
552 	switch (error) {
553 	case DATAGRAM_INVALID_SOURCE_NAME_FORMAT:
554 		smb_tracef("NbtDatagramError[%d]: invalid source name format",
555 		    datagram_id);
556 		break;
557 
558 	case DATAGRAM_INVALID_DESTINATION_NAME_FORMAT:
559 		smb_tracef("NbtDatagramError[%d]: invalid destination name "
560 		    "format", datagram_id);
561 		break;
562 
563 	case DATAGRAM_DESTINATION_NAME_NOT_PRESENT:
564 	default:
565 		break;
566 	}
567 }
568 
569 
570 /*
571  * Function: int smb_netbios_process_BPM_datagram(unsigned char *packet,
572  *		addr_entry_t *addr)
573  *
574  * Description from rfc1002:
575  *
576  *  5.3.3.  RECEPTION OF NetBIOS DATAGRAMS BY ALL NODES
577  *
578  *   The following algorithm discards out of order NetBIOS Datagram
579  *   fragments.  An implementation which reassembles out of order
580  *   NetBIOS Datagram fragments conforms to this specification.  The
581  *   fragment discard timer is initialized to the value FRAGMENT_TIMEOUT.
582  *   This value should be user configurable.  The default value is
583  *   given in Section 6, "Defined Constants and Variables".
584  *
585  *   PROCEDURE datagram_packet(packet)
586  *
587  *   (*
588  *    * processing initiated by datagram packet reception
589  *    * on B, P and M nodes
590  *    *)
591  *   BEGIN
592  *        (*
593  *         * if this node is a P node, ignore
594  *         * broadcast packets.
595  *         *)
596  *
597  *        IF this is a P node AND incoming packet is
598  *             a broadcast packet THEN
599  *        BEGIN
600  *             discard packet;
601  *        END
602  *
603  *        CASE packet type OF
604  *
605  *           DATAGRAM SERVICE:
606  *           BEGIN
607  *             IF FIRST bit in FLAGS is set THEN
608  *             BEGIN
609  *                  IF MORE bit in FLAGS is set THEN
610  *                  BEGIN
611  *                       Save 1st UDP packet of the Datagram;
612  *                       Set this Datagrams fragment discard
613  *                         timer to FRAGMENT_TIMEOUT;
614  *                       return;
615  *                  END
616  *                  ELSE
617  *                       Datagram is composed of a single
618  *                         UDP packet;
619  *             END
620  *             ELSE
621  *             BEGIN
622  *                  (* Have the second fragment of a Datagram *)
623  *
624  *                  Search for 1st fragment by source IP address
625  *                     and DGM_ID;
626  *                  IF found 1st fragment THEN
627  *                       Process both UDP packets;
628  *                  ELSE
629  *                  BEGIN
630  *                       discard 2nd fragment UDP packet;
631  *                       return;
632  *                  END
633  *             END
634  *
635  *             IF DESTINATION_NAME is '*' THEN
636  *             BEGIN
637  *                  (* NetBIOS broadcast *)
638  *
639  *                  deliver USER_DATA from UDP packet(s) to all
640  *                       outstanding receive broadcast
641  *                       datagram requests;
642  *                  return;
643  *             END
644  *             ELSE
645  *             BEGIN (* non-broadcast *)
646  *                  (* Datagram for Unique or Group Name *)
647  *
648  *                  IF DESTINATION_NAME is not present in the
649  *                     local name table THEN
650  *                  BEGIN
651  *                       (* destination not present *)
652  *                       build DATAGRAM ERROR packet, clear
653  *                            FIRST and MORE bit, put in
654  *                            this nodes IP and PORT, set
655  *                            ERROR_CODE;
656  *                       send DATAGRAM ERROR packet to
657  *                            source IP address and port
658  *                            of UDP;
659  *                       discard UDP packet(s);
660  *                       return;
661  *                  END
662  *                  ELSE
663  *                  BEGIN (* good *)
664  *                       (*
665  *                        * Replicate received NetBIOS datagram for
666  *                        * each recipient
667  *                        *)
668  *                       FOR EACH pending NetBIOS users receive
669  *                            datagram operation
670  *                       BEGIN
671  *                            IF source name of operation
672  *                               matches destination name
673  *                               of packet THEN
674  *                            BEGIN
675  *                               deliver USER_DATA from UDP
676  *                                 packet(s);
677  *                            END
678  *                       END (* for each *)
679  *                       return;
680  *                  END (* good *)
681  *             END (* non-broadcast *)
682  *            END (* datagram service *)
683  *
684  *           DATAGRAM ERROR:
685  *           BEGIN
686  *                (*
687  *                 * name service returned incorrect information
688  *                 *)
689  *
690  *                inform local name service that incorrect
691  *                  information was provided;
692  *
693  *                IF this is a P or M node THEN
694  *                BEGIN
695  *                     (*
696  *                      * tell NetBIOS Name Server that it may
697  *                      * have given incorrect information
698  *                      *)
699  *
700  *                     send NAME RELEASE REQUEST with name
701  *                       and incorrect IP address to NetBIOS
702  *                       Name Server;
703  *                END
704  *           END (* datagram error *)
705  *
706  *        END (* case *)
707  *   END
708  */
709 
710 static struct datagram *
711 smb_netbios_datagram_getq(struct datagram *datagram)
712 {
713 	struct datagram *prev = 0;
714 
715 	(void) mutex_lock(&smb_dgq_mtx);
716 	for (prev = smb_datagram_queue.forw;
717 	    prev != (struct datagram *)((uintptr_t)&smb_datagram_queue);
718 	    prev = prev->forw) {
719 		if (prev->src.addr_list.sin.sin_addr.s_addr ==
720 		    datagram->src.addr_list.sin.sin_addr.s_addr) {
721 			/* Something waiting */
722 			QUEUE_CLIP(prev);
723 			(void) mutex_unlock(&smb_dgq_mtx);
724 			bcopy(datagram->data, &prev->data[prev->data_length],
725 			    datagram->data_length);
726 			prev->data_length += datagram->data_length;
727 			free(datagram);
728 			return (prev);
729 		}
730 	}
731 	(void) mutex_unlock(&smb_dgq_mtx);
732 
733 	return (0);
734 }
735 
736 static void
737 smb_netbios_BPM_datagram(struct datagram *datagram)
738 {
739 	struct name_entry *entry = 0;
740 	struct datagram *qpacket = 0;
741 	pthread_t browser_dispatch;
742 
743 	switch (datagram->packet_type) {
744 	case DATAGRAM_TYPE_BROADCAST :
745 		if (smb_node_type == 'P') {
746 			/*
747 			 * if this node is a P node, ignore
748 			 * broadcast packets.
749 			 */
750 			break;
751 		}
752 		/* FALLTHROUGH */
753 
754 	case DATAGRAM_TYPE_DIRECT_UNIQUE :
755 	case DATAGRAM_TYPE_DIRECT_GROUP :
756 		if ((datagram->flags & DATAGRAM_FLAGS_FIRST) != 0) {
757 			if (datagram->flags & DATAGRAM_FLAGS_MORE) {
758 				/* Save 1st UDP packet of the Datagram */
759 				datagram->discard_timer = FRAGMENT_TIMEOUT;
760 				(void) mutex_lock(&smb_dgq_mtx);
761 				QUEUE_INSERT_TAIL(&smb_datagram_queue, datagram)
762 				(void) mutex_unlock(&smb_dgq_mtx);
763 				return;
764 			}
765 			/* process datagram */
766 		} else {
767 			qpacket = smb_netbios_datagram_getq(datagram);
768 			if (qpacket) {
769 				datagram = qpacket;
770 				goto process_datagram;
771 			}
772 			break;
773 		}
774 
775 process_datagram:
776 		entry = 0;
777 		if ((strcmp((char *)datagram->dest.name, "*") == 0) ||
778 		    ((entry =
779 		    smb_netbios_cache_lookup(&datagram->dest)) != 0)) {
780 			if (entry) {
781 				int is_local = IS_LOCAL(entry->attributes);
782 				smb_netbios_cache_unlock_entry(entry);
783 
784 				if (is_local) {
785 					(void) pthread_create(&browser_dispatch,
786 					    0, smb_browser_dispatch,
787 					    (void *)datagram);
788 					(void) pthread_detach(browser_dispatch);
789 					return;
790 				}
791 			}
792 
793 			datagram->rawbuf[0] = DATAGRAM_TYPE_ERROR_DATAGRAM;
794 			datagram->rawbuf[1] &= DATAGRAM_FLAGS_SRC_TYPE;
795 
796 			(void) memcpy(&datagram->rawbuf[4],
797 			    &datagram->src.addr_list.sin.sin_addr.s_addr,
798 			    sizeof (uint32_t));
799 			BE_OUT16(&datagram->rawbuf[8], IPPORT_NETBIOS_DGM);
800 
801 			(void) sendto(datagram_sock, datagram->rawbuf,
802 			    datagram->rawbytes, 0,
803 			    (struct sockaddr *)&datagram->src.addr_list.sin,
804 			    datagram->src.addr_list.sinlen);
805 		}
806 		break;
807 
808 	case DATAGRAM_TYPE_ERROR_DATAGRAM :
809 		break;
810 	}
811 	free(datagram);
812 }
813 
814 /*
815  * NetBIOS Datagram Service (port 138)
816  */
817 /*ARGSUSED*/
818 void *
819 smb_netbios_datagram_service(void *arg)
820 {
821 	struct sockaddr_in 	sin;
822 	struct datagram 	*datagram;
823 	int			bytes, flag = 1;
824 	smb_inaddr_t 		ipaddr;
825 
826 	(void) mutex_lock(&smb_dgq_mtx);
827 	bzero(&smb_datagram_queue, sizeof (smb_datagram_queue));
828 	smb_datagram_queue.forw = smb_datagram_queue.back =
829 	    (struct datagram *)((uintptr_t)&smb_datagram_queue);
830 	(void) mutex_unlock(&smb_dgq_mtx);
831 
832 	if ((datagram_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
833 		syslog(LOG_ERR, "nbt datagram: socket failed: %m");
834 		smb_netbios_event(NETBIOS_EVENT_ERROR);
835 		return (NULL);
836 	}
837 
838 	flag = 1;
839 	(void) setsockopt(datagram_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
840 	    sizeof (flag));
841 
842 	bzero(&sin, sizeof (sin));
843 	sin.sin_family = AF_INET;
844 	sin.sin_port = htons(IPPORT_NETBIOS_DGM);
845 	if (bind(datagram_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
846 		syslog(LOG_ERR, "nbt datagram: bind(%d) failed: %m",
847 		    IPPORT_NETBIOS_DGM);
848 		(void) close(datagram_sock);
849 		smb_netbios_event(NETBIOS_EVENT_ERROR);
850 		return (NULL);
851 	}
852 
853 	flag = 1;
854 	(void) setsockopt(datagram_sock, SOL_SOCKET, SO_BROADCAST, &flag,
855 	    sizeof (flag));
856 
857 	smb_netbios_event(NETBIOS_EVENT_DGM_START);
858 
859 	while (smb_netbios_running()) {
860 		if ((datagram = malloc(sizeof (struct datagram))) == NULL) {
861 			/* Sleep for 10 seconds and try again */
862 			smb_netbios_sleep(10);
863 			continue;
864 		}
865 
866 ignore:		bzero(&datagram->inaddr, sizeof (addr_entry_t));
867 		datagram->inaddr.sinlen = sizeof (datagram->inaddr.sin);
868 		datagram->inaddr.forw = datagram->inaddr.back =
869 		    &datagram->inaddr;
870 
871 		if ((bytes = recvfrom(datagram_sock, datagram->rawbuf,
872 		    MAX_DATAGRAM_LENGTH, 0,
873 		    (struct sockaddr *)&datagram->inaddr.sin,
874 		    &datagram->inaddr.sinlen)) < 0) {
875 			syslog(LOG_ERR, "nbt datagram: recvfrom failed: %m");
876 			smb_netbios_event(NETBIOS_EVENT_ERROR);
877 			break;
878 		}
879 
880 		/* Ignore any incoming packets from myself... */
881 		ipaddr.a_ipv4 = datagram->inaddr.sin.sin_addr.s_addr;
882 		ipaddr.a_family = AF_INET;
883 		if (smb_nic_is_local(&ipaddr)) {
884 			goto ignore;
885 		}
886 
887 		if (smb_datagram_decode(datagram, bytes) < 0)
888 			goto ignore;
889 
890 	/*
891 	 * This code was doing the wrong thing with responses from a
892 	 * Windows2000 PDC because both DATAGRAM_FLAGS_H_NODE and
893 	 * DATAGRAM_FLAGS_NBDD are defined to be the same value (see
894 	 * netbios.h). Since the Windows2000 PDC wants to be an H-Node,
895 	 * we need to handle all messages via smb_netbios_BPM_datagram.
896 	 *
897 	 *	if ((datagram->flags & DATAGRAM_FLAGS_SRC_TYPE) ==
898 	 *	    DATAGRAM_FLAGS_NBDD)
899 	 *		smb_netbios_NBDD_datagram(datagram);
900 	 *	else
901 	 *		smb_netbios_BPM_datagram(datagram);
902 	 */
903 
904 		smb_netbios_BPM_datagram(datagram);
905 	}
906 
907 	smb_netbios_event(NETBIOS_EVENT_DGM_STOP);
908 	(void) smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP);
909 
910 	(void) close(datagram_sock);
911 	smb_netbios_datagram_fini();
912 	return (NULL);
913 }
914 
915 static char
916 /* LINTED - E_STATIC_UNUSED */
917 nb_fmt_flags(unsigned char flags)
918 {
919 	switch (flags & DATAGRAM_FLAGS_SRC_TYPE) {
920 	case DATAGRAM_FLAGS_B_NODE:	return ('B');
921 	case DATAGRAM_FLAGS_P_NODE:	return ('P');
922 	case DATAGRAM_FLAGS_M_NODE:	return ('M');
923 	case DATAGRAM_FLAGS_H_NODE:	return ('H');
924 	default:	return ('?');
925 	}
926 }
927