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
smb_netbios_datagram_tick(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
smb_netbios_datagram_fini()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
smb_netbios_datagram_send(struct name_entry * src,struct name_entry * dest,unsigned char * data,int length)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
smb_netbios_datagram_send_to_net(struct name_entry * src,struct name_entry * dest,char * data,int length)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
smb_datagram_decode(struct datagram * datagram,int bytes)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
smb_netbios_datagram_error(unsigned char * buf)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 *
smb_netbios_datagram_getq(struct datagram * 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
smb_netbios_BPM_datagram(struct datagram * datagram)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 *
smb_netbios_datagram_service(void * arg)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 */
nb_fmt_flags(unsigned char flags)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