8821 smbsrv: error: variable 'dnptrs' set but not used
[unleashed.git] / usr / src / lib / smbsrv / libsmbns / common / smbns_netbios_name.c
blob024fda6e863d59fae4d86d6abf4ba44b596eb790
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
28 * NetBIOS name resolution node types.
30 * A B-node (broadcast node) uses broadcasts for name registration
31 * and resolution. Routers typically do not forward broadcasts and
32 * only computers on the local subnet will respond.
34 * A P-node (peer-to-peer node) uses a NetBIOS name server (WINS)
35 * to resolve NetBIOS names, which allows it to work across routers.
36 * In order to function in a P-node environment, all computers must
37 * be configured to use the NetBIOS name server because P-nodes do
38 * not broadcast on the network.
40 * A mixed node (M-node) behaves as a B-node by default. If it cannot
41 * resolve the name via broadcast then it tries a NetBIOS name server
42 * lookup (P-node).
44 * A hybrid node (H-node) behaves as a P-node by default. If it cannot
45 * resolve the name using a NetBIOS name server then it resorts to
46 * broadcasts (B-node).
48 * NetBIOS Name Service Protocols
50 * A REQUEST packet is always sent to the well known UDP port 137.
51 * The destination address is normally either the IP broadcast address or
52 * the address of the NAME - the address of the NAME server it set up at
53 * initialization time. In rare cases, a request packet will be sent to
54 * an end node, e.g. a NAME QUERY REQUEST sent to "challenge" a node.
56 * A RESPONSE packet is always sent to the source UDP port and source IP
57 * address of the request packet.
59 * A DEMAND packet must always be sent to the well known UDP port 137.
60 * There is no restriction on the target IP address.
62 * A transaction ID is a value composed from the requestor's IP address and
63 * a unique 16 bit value generated by the originator of the transaction.
66 #include <unistd.h>
67 #include <syslog.h>
68 #include <stdlib.h>
69 #include <synch.h>
70 #include <errno.h>
71 #include <netdb.h>
72 #include <sys/socket.h>
73 #include <sys/sockio.h>
74 #include <arpa/inet.h>
75 #include <net/if_arp.h>
77 #include <smbsrv/libsmbns.h>
78 #include <smbns_netbios.h>
81 * RFC 1002 4.2.1.1. HEADER
83 #define QUESTION_TYPE_NETBIOS_GENERAL 0x20
84 #define QUESTION_TYPE_NETBIOS_STATUS 0x21
86 #define QUESTION_CLASS_INTERNET 0x0001
89 * RFC 1002 4.2.1.3. RESOURCE RECORD
91 #define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001
92 #define RR_TYPE_NAME_SERVER_RESOURCE 0x0002
93 #define RR_TYPE_NULL_RESOURCE 0x000A
94 #define RR_TYPE_NETBIOS_RESOURCE 0x0020
95 #define RR_TYPE_NETBIOS_STATUS 0x0021
99 * RESOURCE RECORD RR_CLASS field definitions
101 #define RR_CLASS_INTERNET_CLASS 0x0001
104 * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of NB.
106 #define RR_FLAGS_NB_ONT_MASK 0x6000
107 #define RR_FLAGS_NB_ONT_B_NODE 0x0000
108 #define RR_FLAGS_NB_ONT_P_NODE 0x2000
109 #define RR_FLAGS_NB_ONT_M_NODE 0x4000
110 #define RR_FLAGS_NB_ONT_RESERVED 0x6000
111 #define RR_FLAGS_NB_GROUP_NAME 0x8000
113 #define NAME_FLAGS_PERMANENT_NAME 0x0200
114 #define NAME_FLAGS_ACTIVE_NAME 0x0400
115 #define NAME_FLAGS_CONFLICT 0x0800
116 #define NAME_FLAGS_DEREGISTER 0x1000
117 #define NAME_FLAGS_ONT_MASK 0x6000
118 #define NAME_FLAGS_ONT_B_NODE 0x0000
119 #define NAME_FLAGS_ONT_P_NODE 0x2000
120 #define NAME_FLAGS_ONT_M_NODE 0x4000
121 #define NAME_FLAGS_ONT_RESERVED 0x6000
122 #define NAME_FLAGS_GROUP_NAME 0x8000
124 #define MAX_NETBIOS_REPLY_DATA_SIZE 500
126 #define NAME_HEADER_SIZE 12
128 typedef struct nbt_name_reply {
129 struct nbt_name_reply *forw;
130 struct nbt_name_reply *back;
131 struct name_packet *packet;
132 addr_entry_t *addr;
133 uint16_t name_trn_id;
134 boolean_t reply_ready;
135 } nbt_name_reply_t;
137 static nbt_name_reply_t reply_queue;
138 static mutex_t rq_mtx;
139 static cond_t rq_cv;
141 static mutex_t nbt_name_config_mtx;
143 static name_queue_t delete_queue;
144 static name_queue_t refresh_queue;
146 static int name_sock = 0;
148 static int bcast_num = 0;
149 static int nbns_num = 0;
150 static addr_entry_t smb_bcast_list[SMB_PI_MAX_NETWORKS];
151 static addr_entry_t smb_nbns[SMB_PI_MAX_WINS];
153 static int smb_netbios_process_response(uint16_t, addr_entry_t *,
154 struct name_packet *, uint32_t);
156 static int smb_send_name_service_packet(addr_entry_t *addr,
157 struct name_packet *packet);
160 * Allocate a transaction id.
162 static uint16_t
163 smb_netbios_name_trn_id(void)
165 static uint16_t trn_id;
166 static mutex_t trn_id_mtx;
168 (void) mutex_lock(&trn_id_mtx);
170 do {
171 ++trn_id;
172 } while (trn_id == 0 || trn_id == (uint16_t)-1);
174 (void) mutex_unlock(&trn_id_mtx);
175 return (trn_id);
178 static int
179 smb_end_node_challenge(nbt_name_reply_t *reply_info)
181 int rc;
182 uint32_t retry;
183 uint16_t tid;
184 struct resource_record *answer;
185 struct name_question question;
186 addr_entry_t *addr;
187 struct name_entry *destination;
188 struct name_packet packet;
189 struct timespec st;
192 * The response packet has in it the address of the presumed owner
193 * of the name. Challenge that owner. If owner either does not
194 * respond or indicates that they no longer own the name, claim the
195 * name. Otherwise, the name cannot be claimed.
198 if ((answer = reply_info->packet->answer) == 0)
199 return (-1);
201 destination = answer->name;
202 question.name = answer->name;
204 packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST;
205 packet.qdcount = 1; /* question entries */
206 packet.question = &question;
207 packet.ancount = 0; /* answer recs */
208 packet.answer = NULL;
209 packet.nscount = 0; /* authority recs */
210 packet.authority = NULL;
211 packet.arcount = 0; /* additional recs */
212 packet.additional = NULL;
214 addr = &destination->addr_list;
215 for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) {
216 tid = smb_netbios_name_trn_id();
217 packet.name_trn_id = tid;
218 if (smb_send_name_service_packet(addr, &packet) >= 0) {
219 if ((rc = smb_netbios_process_response(tid, addr,
220 &packet, UCAST_REQ_RETRY_TIMEOUT)) != 0)
221 return (rc);
223 st.tv_sec = 0;
224 st.tv_nsec = (UCAST_REQ_RETRY_TIMEOUT * 1000000);
225 (void) nanosleep(&st, 0);
227 /* No reply */
228 return (0);
231 static nbt_name_reply_t *
232 smb_name_get_reply(uint16_t tid, uint32_t timeout)
234 uint16_t info;
235 struct resource_record *answer;
236 nbt_name_reply_t *reply;
237 uint32_t wait_time, to_save; /* in millisecond */
238 struct timeval wt;
239 timestruc_t to;
241 to_save = timeout;
242 reply = malloc(sizeof (nbt_name_reply_t));
243 if (reply != NULL) {
244 reply->reply_ready = B_FALSE;
245 reply->name_trn_id = tid;
246 (void) mutex_lock(&rq_mtx);
247 QUEUE_INSERT_TAIL(&reply_queue, reply);
248 (void) mutex_unlock(&rq_mtx);
250 for (;;) {
251 (void) gettimeofday(&wt, 0);
252 wait_time = wt.tv_usec / 1000;
254 to.tv_sec = 0;
255 to.tv_nsec = timeout * 1000000;
256 (void) mutex_lock(&rq_mtx);
257 (void) cond_reltimedwait(&rq_cv, &rq_mtx, &to);
258 (void) mutex_unlock(&rq_mtx);
260 if (reply->reply_ready) {
261 info = reply->packet->info;
262 if (PACKET_TYPE(info) == WACK_RESPONSE) {
263 answer = reply->packet->answer;
264 wait_time = (answer) ?
265 TO_MILLISECONDS(answer->ttl) :
266 DEFAULT_TTL;
267 free(reply->addr);
268 free(reply->packet);
269 timeout = to_save + wait_time;
270 reply->reply_ready = B_FALSE;
271 reply->name_trn_id = tid;
272 (void) mutex_lock(&rq_mtx);
273 QUEUE_INSERT_TAIL(&reply_queue, reply);
274 (void) mutex_unlock(&rq_mtx);
275 continue;
277 return (reply);
279 (void) gettimeofday(&wt, 0);
280 wait_time = (wt.tv_usec / 1000) - wait_time;
281 if (wait_time >= timeout) {
282 (void) mutex_lock(&rq_mtx);
283 QUEUE_CLIP(reply);
284 (void) mutex_unlock(&rq_mtx);
285 free(reply);
286 break;
288 timeout -= wait_time;
292 return (0);
295 static void
296 smb_reply_ready(struct name_packet *packet, addr_entry_t *addr)
298 nbt_name_reply_t *reply;
299 struct resource_record *answer;
301 (void) mutex_lock(&rq_mtx);
302 for (reply = reply_queue.forw; reply != &reply_queue;
303 reply = reply->forw) {
304 if (reply->name_trn_id == packet->name_trn_id) {
305 QUEUE_CLIP(reply);
307 reply->addr = addr;
308 reply->packet = packet;
309 reply->reply_ready = B_TRUE;
310 (void) cond_signal(&rq_cv);
311 (void) mutex_unlock(&rq_mtx);
312 return;
315 (void) mutex_unlock(&rq_mtx);
317 /* Presumably nobody is waiting any more... */
318 free(addr);
320 answer = packet->answer;
321 if (answer)
322 smb_netbios_name_freeaddrs(answer->name);
323 free(packet);
326 static int
327 smb_netbios_process_response(uint16_t tid, addr_entry_t *addr,
328 struct name_packet *packet, uint32_t timeout)
330 int rc = 0;
331 uint16_t info;
332 nbt_name_reply_t *reply;
333 struct resource_record *answer;
334 struct name_entry *name;
335 struct name_entry *entry;
336 struct name_question *question;
337 uint32_t ttl;
339 if ((reply = smb_name_get_reply(tid, timeout)) == 0) {
340 return (0); /* No reply: retry */
342 info = reply->packet->info;
343 answer = reply->packet->answer;
345 /* response */
346 switch (PACKET_TYPE(info)) {
347 case NAME_QUERY_RESPONSE:
348 if (POSITIVE_RESPONSE(info)) {
349 addr = &answer->name->addr_list;
350 do {
352 * Make sure that remote name is not
353 * flagged local
355 addr->attributes &= ~NAME_ATTR_LOCAL;
357 if (answer->ttl)
358 addr->ttl = answer->ttl;
359 else
360 addr->ttl = DEFAULT_TTL;
361 addr->refresh_ttl = TO_SECONDS(addr->ttl);
362 addr->ttl = addr->refresh_ttl;
364 addr = addr->forw;
365 } while (addr != &answer->name->addr_list);
366 smb_netbios_name_logf(answer->name);
367 (void) smb_netbios_cache_insert_list(answer->name);
368 rc = 1;
369 } else {
370 rc = -1;
372 break;
374 case NAME_REGISTRATION_RESPONSE:
375 if (NEGATIVE_RESPONSE(info)) {
376 if (RCODE(info) == RCODE_CFT_ERR) {
377 if (answer == 0) {
378 rc = -RCODE(info);
379 break;
382 name = answer->name;
383 entry = smb_netbios_cache_lookup(name);
384 if (entry) {
386 * a name in the state "conflict
387 * detected" does not "logically" exist
388 * on that node. No further session
389 * will be accepted on that name.
390 * No datagrams can be sent against
391 * that name.
392 * Such an entry will not be used for
393 * purposes of processing incoming
394 * request packets.
395 * The only valid user NetBIOS operation
396 * against such a name is DELETE NAME.
398 entry->attributes |= NAME_ATTR_CONFLICT;
399 syslog(LOG_DEBUG,
400 "nbns: name conflict: %15.15s",
401 entry->name);
402 smb_netbios_cache_unlock_entry(entry);
405 rc = -RCODE(info);
406 break;
410 * name can be added:
411 * adjust refresh timeout value,
412 * TTL, for this name
414 question = packet->question;
415 ttl = (answer && answer->ttl) ? answer->ttl : DEFAULT_TTL;
416 ttl = TO_SECONDS(ttl);
417 if ((entry = smb_netbios_cache_lookup(question->name)) != 0) {
418 addr = &entry->addr_list;
419 do {
420 if ((addr->refresh_ttl == 0) ||
421 (ttl < addr->refresh_ttl))
422 addr->refresh_ttl = addr->ttl = ttl;
423 addr = addr->forw;
424 } while (addr != &entry->addr_list);
425 smb_netbios_cache_unlock_entry(entry);
428 rc = 1;
429 break;
431 case NAME_RELEASE_RESPONSE:
432 rc = 1;
433 break;
435 case END_NODE_CHALLENGE_REGISTRATION_REQUEST:
437 * The response packet has in it the
438 * address of the presumed owner of the
439 * name. Challenge that owner. If
440 * owner either does not respond or
441 * indicates that they no longer own the
442 * name, claim the name. Otherwise,
443 * the name cannot be claimed.
445 rc = smb_end_node_challenge(reply);
446 break;
448 default:
449 rc = 0;
450 break;
453 if (answer)
454 smb_netbios_name_freeaddrs(answer->name);
455 free(reply->addr);
456 free(reply->packet);
457 free(reply);
458 return (rc); /* retry */
462 * smb_name_buf_from_packet
464 * Description:
465 * Convert a NetBIOS Name Server Packet Block (npb)
466 * into the bits and bytes destined for the wire.
467 * The "buf" is used as a heap.
469 * Inputs:
470 * char * buf -> Buffer, from the wire
471 * unsigned n_buf -> Length of 'buf'
472 * name_packet *npb -> Packet block, decode into
473 * unsigned n_npb -> Max bytes in 'npb'
475 * Returns:
476 * >0 -> Encode successful, value is length of packet in "buf"
477 * -1 -> Hard error, can not possibly encode
478 * -2 -> Need more memory in buf -- it's too small
480 static int
481 smb_name_buf_from_packet(unsigned char *buf, int n_buf,
482 struct name_packet *npb)
484 addr_entry_t *raddr;
485 unsigned char *heap = buf;
486 unsigned char *end_heap = heap + n_buf;
487 unsigned char comp_name_buf[MAX_NAME_LENGTH];
488 unsigned int tmp;
489 int i, step;
491 if (n_buf < NAME_HEADER_SIZE)
492 return (-1); /* no header, impossible */
494 BE_OUT16(heap, npb->name_trn_id);
495 heap += 2;
497 BE_OUT16(heap, npb->info);
498 heap += 2;
500 BE_OUT16(heap, npb->qdcount);
501 heap += 2;
503 BE_OUT16(heap, npb->ancount);
504 heap += 2;
506 BE_OUT16(heap, npb->nscount);
507 heap += 2;
509 BE_OUT16(heap, npb->arcount);
510 heap += 2;
512 for (i = 0; i < npb->qdcount; i++) {
513 if ((heap + 34 + 4) > end_heap)
514 return (-2);
516 (void) smb_first_level_name_encode(npb->question[i].name,
517 comp_name_buf, sizeof (comp_name_buf));
518 (void) strcpy((char *)heap, (char *)comp_name_buf);
519 heap += strlen((char *)comp_name_buf) + 1;
521 BE_OUT16(heap, npb->question[i].question_type);
522 heap += 2;
524 BE_OUT16(heap, npb->question[i].question_class);
525 heap += 2;
528 for (step = 1; step <= 3; step++) {
529 struct resource_record *nrr;
530 int n;
532 /* truly ugly, but saves code copying */
533 if (step == 1) {
534 n = npb->ancount;
535 nrr = npb->answer;
536 } else if (step == 2) {
537 n = npb->nscount;
538 nrr = npb->authority;
539 } else { /* step == 3 */
540 n = npb->arcount;
541 nrr = npb->additional;
544 for (i = 0; i < n; i++) {
545 if ((heap + 34 + 10) > end_heap)
546 return (-2);
548 (void) smb_first_level_name_encode(nrr->name,
549 comp_name_buf, sizeof (comp_name_buf));
550 (void) strcpy((char *)heap, (char *)comp_name_buf);
551 heap += strlen((char *)comp_name_buf) + 1;
553 BE_OUT16(heap, nrr[i].rr_type);
554 heap += 2;
556 BE_OUT16(heap, nrr[i].rr_class);
557 heap += 2;
559 BE_OUT32(heap, nrr[i].ttl);
560 heap += 4;
562 BE_OUT16(heap, nrr[i].rdlength);
563 heap += 2;
565 if ((tmp = nrr[i].rdlength) > 0) {
566 if ((heap + tmp) > end_heap)
567 return (-2);
569 if (nrr[i].rr_type == NAME_RR_TYPE_NB &&
570 nrr[i].rr_class == NAME_RR_CLASS_IN &&
571 tmp >= 6 && nrr[i].rdata == 0) {
572 tmp = nrr[i].name->attributes &
573 (NAME_ATTR_GROUP |
574 NAME_ATTR_OWNER_NODE_TYPE);
575 BE_OUT16(heap, tmp);
576 heap += 2;
578 raddr = &nrr[i].name->addr_list;
579 (void) memcpy(heap,
580 &raddr->sin.sin_addr.s_addr,
581 sizeof (uint32_t));
582 heap += 4;
583 } else {
584 bcopy(nrr[i].rdata, heap, tmp);
585 heap += tmp;
590 return (heap - buf);
594 * strnchr
596 * Lookup for character 'c' in first 'n' chars of string 's'.
597 * Returns pointer to the found char, otherwise returns 0.
599 static char *
600 strnchr(const char *s, char c, int n)
602 char *ps = (char *)s;
603 char *es = (char *)s + n;
605 while (ps < es && *ps) {
606 if (*ps == c)
607 return (ps);
609 ++ps;
612 if (*ps == '\0' && c == '\0')
613 return (ps);
615 return (0);
618 static boolean_t
619 is_multihome(char *name)
621 return (smb_nic_getnum(name) > 1);
625 * smb_netbios_getname
627 * Get the Netbios name part of the given record.
628 * Does some boundary checks.
630 * Returns the name length on success, otherwise
631 * returns 0.
633 static int
634 smb_netbios_getname(char *name, char *buf, char *buf_end)
636 char *name_end;
637 int name_len;
639 if (buf >= buf_end) {
640 /* no room for a NB name */
641 return (0);
644 name_end = strnchr(buf, '\0', buf_end - buf + 1);
645 if (name_end == 0) {
646 /* not a valid NB name */
647 return (0);
650 name_len = name_end - buf + 1;
652 (void) strlcpy(name, buf, name_len);
653 return (name_len);
657 * smb_name_buf_to_packet
659 * Convert the bits and bytes that came from the wire into a NetBIOS
660 * Name Server Packet Block (npb). The "block" is used as a heap.
662 * Returns a pointer to a name packet on success. Otherwise, returns
663 * a NULL pointer.
665 static struct name_packet *
666 smb_name_buf_to_packet(char *buf, int n_buf)
668 struct name_packet *npb;
669 unsigned char *heap;
670 unsigned char *scan = (unsigned char *)buf;
671 unsigned char *scan_end = scan + n_buf;
672 char name_buf[MAX_NAME_LENGTH];
673 struct resource_record *nrr = 0;
674 int rc, i, n, nn, ns;
675 uint16_t name_trn_id, info;
676 uint16_t qdcount, ancount, nscount, arcount;
677 addr_entry_t *next;
678 int name_len;
680 if (n_buf < NAME_HEADER_SIZE) {
681 /* truncated header */
682 syslog(LOG_DEBUG, "nbns: short packet (%d bytes)", n_buf);
683 return (NULL);
686 name_trn_id = BE_IN16(scan); scan += 2;
687 info = BE_IN16(scan); scan += 2;
688 qdcount = BE_IN16(scan); scan += 2;
689 ancount = BE_IN16(scan); scan += 2;
690 nscount = BE_IN16(scan); scan += 2;
691 arcount = BE_IN16(scan); scan += 2;
693 ns = sizeof (struct name_entry);
694 n = n_buf + sizeof (struct name_packet) +
695 ((unsigned)qdcount * (sizeof (struct name_question) + ns)) +
696 ((unsigned)ancount * (sizeof (struct resource_record) + ns)) +
697 ((unsigned)nscount * (sizeof (struct resource_record) + ns)) +
698 ((unsigned)arcount * (sizeof (struct resource_record) + ns));
700 if ((npb = malloc(n)) == NULL)
701 return (NULL);
703 bzero(npb, n);
704 heap = npb->block_data;
705 npb->name_trn_id = name_trn_id;
706 npb->info = info;
707 npb->qdcount = qdcount;
708 npb->ancount = ancount;
709 npb->nscount = nscount;
710 npb->arcount = arcount;
712 /* scan is in position for question entries */
715 * Measure the space needed for the tables
717 if (qdcount > 0) {
718 /* LINTED - E_BAD_PTR_CAST_ALIGN */
719 npb->question = (struct name_question *)heap;
720 heap += qdcount * sizeof (struct name_question);
721 for (i = 0; i < qdcount; i++) {
722 /* LINTED - E_BAD_PTR_CAST_ALIGN */
723 npb->question[i].name = (struct name_entry *)heap;
724 heap += sizeof (struct name_entry);
728 /* LINTED - E_BAD_PTR_CAST_ALIGN */
729 nrr = (struct resource_record *)heap;
731 if (ancount > 0) {
732 /* LINTED - E_BAD_PTR_CAST_ALIGN */
733 npb->answer = (struct resource_record *)heap;
734 heap += ancount * sizeof (struct resource_record);
737 if (nscount > 0) {
738 /* LINTED - E_BAD_PTR_CAST_ALIGN */
739 npb->authority = (struct resource_record *)heap;
740 heap += nscount * sizeof (struct resource_record);
743 if (arcount > 0) {
744 /* LINTED - E_BAD_PTR_CAST_ALIGN */
745 npb->additional = (struct resource_record *)heap;
746 heap += arcount * sizeof (struct resource_record);
750 * Populate each resource_record's .name field.
751 * Done as a second pass so that all resource records
752 * (answer, authority, additional) are consecutive via nrr[i].
754 for (i = 0; i < (ancount + nscount + arcount); i++) {
755 /* LINTED - E_BAD_PTR_CAST_ALIGN */
756 nrr[i].name = (struct name_entry *)heap;
757 heap += sizeof (struct name_entry);
761 for (i = 0; i < npb->qdcount; i++) {
762 name_len = smb_netbios_getname(name_buf, (char *)scan,
763 (char *)scan_end);
764 if (name_len <= 0) {
765 free(npb);
766 return (NULL);
769 smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
770 npb->question[i].name);
771 rc = smb_first_level_name_decode((unsigned char *)name_buf,
772 npb->question[i].name);
773 if (rc < 0) {
774 /* Couldn't decode the question name */
775 free(npb);
776 return (NULL);
779 scan += name_len;
780 if (scan + 4 > scan_end) {
781 /* no room for Question Type(2) and Class(2) fields */
782 free(npb);
783 return (NULL);
786 npb->question[i].question_type = BE_IN16(scan); scan += 2;
787 npb->question[i].question_class = BE_IN16(scan); scan += 2;
791 * Cheat. Remaining sections are of the same resource_record
792 * format. Table space is consecutive.
795 for (i = 0; i < (ancount + nscount + arcount); i++) {
796 if (scan[0] == 0xc0) {
797 /* Namebuf is reused... */
798 rc = 2;
799 } else {
800 name_len = smb_netbios_getname(name_buf, (char *)scan,
801 (char *)scan_end);
802 if (name_len <= 0) {
803 free(npb);
804 return (NULL);
806 rc = name_len;
808 scan += rc;
810 if (scan + 10 > scan_end) {
812 * no room for RR_TYPE (2), RR_CLASS (2), TTL (4) and
813 * RDLENGTH (2) fields.
815 free(npb);
816 return (NULL);
819 smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
820 nrr[i].name);
821 if ((rc = smb_first_level_name_decode((unsigned char *)name_buf,
822 nrr[i].name)) < 0) {
823 free(npb);
824 return (NULL);
827 nrr[i].rr_type = BE_IN16(scan); scan += 2;
828 nrr[i].rr_class = BE_IN16(scan); scan += 2;
829 nrr[i].ttl = BE_IN32(scan); scan += 4;
830 nrr[i].rdlength = BE_IN16(scan); scan += 2;
832 if ((n = nrr[i].rdlength) > 0) {
833 if ((scan + n) > scan_end) {
834 /* no room for RDATA */
835 free(npb);
836 return (NULL);
838 bcopy(scan, heap, n);
840 nn = n;
841 if (nrr[i].rr_type == 0x0020 &&
842 nrr[i].rr_class == 0x01 && n >= 6) {
843 while (nn) {
844 if (nn == 6)
845 next = &nrr[i].name->addr_list;
846 else {
847 next = malloc(
848 sizeof (addr_entry_t));
849 if (next == 0) {
850 /* not enough memory */
851 free(npb);
852 return (NULL);
854 QUEUE_INSERT_TAIL(
855 &nrr[i].name->addr_list,
856 next);
858 nrr[i].name->attributes =
859 BE_IN16(scan);
860 next->sin.sin_family = AF_INET;
861 next->sinlen = sizeof (next->sin);
862 (void) memcpy(
863 &next->sin.sin_addr.s_addr,
864 scan + 2, sizeof (uint32_t));
865 next->sin.sin_port =
866 htons(IPPORT_NETBIOS_DGM);
867 nn -= 6;
868 scan += 6;
870 } else {
871 nrr[i].rdata = heap;
872 scan += n;
874 heap += n;
877 return (npb);
881 * smb_send_name_service_packet
883 * Description:
885 * Send out a name service packet to proper destination.
887 * Inputs:
888 * struct netbios_name *dest -> NETBIOS name of destination
889 * struct name_packet *packet -> Packet to send
891 * Returns:
892 * success -> >0
893 * failure -> <=0
895 static int
896 smb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet)
898 unsigned char buf[MAX_DATAGRAM_LENGTH];
899 int len;
901 if ((len = smb_name_buf_from_packet(buf, sizeof (buf), packet)) < 0) {
902 errno = EINVAL;
903 return (-1);
906 return (sendto(name_sock, buf, len, MSG_EOR,
907 (struct sockaddr *)&addr->sin, addr->sinlen));
911 * smb_netbios_send_rcv
913 * This function sends the given NetBIOS packet to the given
914 * address and get back the response. If send operation is not
915 * successful, it's repeated 'retries' times.
917 * Returns:
918 * 0 Unsuccessful send operation; no reply
919 * 1 Got reply
921 static int
922 smb_netbios_send_rcv(int bcast, addr_entry_t *destination,
923 struct name_packet *packet, uint32_t retries, uint32_t timeout)
925 uint32_t retry;
926 uint16_t tid;
927 struct timespec st;
928 int rc;
930 for (retry = 0; retry < retries; retry++) {
931 if ((destination->flags & ADDR_FLAG_VALID) == 0)
932 return (0);
934 tid = smb_netbios_name_trn_id();
935 packet->name_trn_id = tid;
936 if (smb_send_name_service_packet(destination, packet) >= 0) {
937 rc = smb_netbios_process_response(tid, destination,
938 packet, timeout);
940 if ((rc > 0) || (bcast == BROADCAST))
941 return (1);
943 if (rc != 0)
944 return (0);
947 st.tv_sec = 0;
948 st.tv_nsec = (timeout * 1000000);
949 (void) nanosleep(&st, 0);
952 return (0);
956 * RFC 1002 4.2.2. NAME REGISTRATION REQUEST
958 static int
959 smb_send_name_registration_request(int bcast, struct name_question *question,
960 struct resource_record *additional)
962 int gotreply = 0;
963 uint32_t retries;
964 uint32_t timeout;
965 addr_entry_t *destination;
966 struct name_packet packet;
967 unsigned char type;
968 int i, addr_num, rc;
970 type = question->name->name[15];
971 if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
972 syslog(LOG_DEBUG, "nbns: name registration bad type (0x%02x)",
973 type);
974 smb_netbios_name_logf(question->name);
975 question->name->attributes &= ~NAME_ATTR_LOCAL;
976 return (-1);
979 if (bcast == BROADCAST) {
980 if (bcast_num == 0)
981 return (0);
982 destination = smb_bcast_list;
983 addr_num = bcast_num;
984 retries = BCAST_REQ_RETRY_COUNT;
985 timeout = BCAST_REQ_RETRY_TIMEOUT;
986 packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_BROADCAST;
987 } else {
988 if (nbns_num == 0)
989 return (0);
990 destination = smb_nbns;
991 addr_num = nbns_num;
992 retries = UCAST_REQ_RETRY_COUNT;
993 timeout = UCAST_REQ_RETRY_TIMEOUT;
994 packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_UNICAST;
997 packet.qdcount = 1; /* question entries */
998 packet.question = question;
999 packet.ancount = 0; /* answer recs */
1000 packet.answer = NULL;
1001 packet.nscount = 0; /* authority recs */
1002 packet.authority = NULL;
1003 packet.arcount = 1; /* additional recs */
1004 packet.additional = additional;
1006 if (IS_UNIQUE(question->name->attributes) &&
1007 (is_multihome((char *)(question->name->name))))
1008 packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST;
1010 for (i = 0; i < addr_num; i++) {
1012 * Only register with the Primary WINS server,
1013 * unless we got no reply.
1015 if ((bcast == UNICAST) && gotreply)
1016 break;
1018 rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
1019 retries, timeout);
1020 if (rc == 1)
1021 gotreply = 1;
1024 return (gotreply);
1028 * RFC 1002 4.2.4. NAME REFRESH REQUEST
1030 /*ARGSUSED*/
1031 static int
1032 smb_send_name_refresh_request(int bcast, struct name_question *question,
1033 struct resource_record *additional, int force)
1035 int rc = 0;
1036 int gotreply = 0;
1037 uint32_t retries;
1038 uint32_t timeout;
1039 addr_entry_t *addr;
1040 addr_entry_t *destination;
1041 struct name_packet packet;
1042 unsigned char type;
1043 int i, addr_num, q_addrs = 0;
1045 type = question->name->name[15];
1046 if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
1047 syslog(LOG_DEBUG, "nbns: name refresh bad type (0x%02x)", type);
1048 smb_netbios_name_logf(question->name);
1049 question->name->attributes &= ~NAME_ATTR_LOCAL;
1050 return (-1);
1052 switch (bcast) {
1053 case BROADCAST :
1054 if (bcast_num == 0)
1055 return (-1);
1056 destination = smb_bcast_list;
1057 addr_num = bcast_num;
1058 retries = BCAST_REQ_RETRY_COUNT;
1059 timeout = BCAST_REQ_RETRY_TIMEOUT;
1060 packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_BROADCAST;
1061 break;
1063 case UNICAST :
1064 if (nbns_num == 0)
1065 return (-1);
1066 destination = smb_nbns;
1067 addr_num = nbns_num;
1068 retries = UCAST_REQ_RETRY_COUNT;
1069 timeout = UCAST_REQ_RETRY_TIMEOUT;
1070 packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST;
1071 break;
1073 default:
1074 destination = &question->name->addr_list;
1076 * the value of addr_num is irrelvant here, because
1077 * the code is going to do special_process so it doesn't
1078 * need the addr_num. We set a value here just to avoid
1079 * compiler warning.
1081 addr_num = 0;
1082 retries = UCAST_REQ_RETRY_COUNT;
1083 timeout = UCAST_REQ_RETRY_TIMEOUT;
1084 packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST;
1085 q_addrs = 1;
1086 break;
1089 if (IS_UNIQUE(question->name->attributes) &&
1090 (is_multihome((char *)(question->name->name))))
1091 packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST;
1093 packet.qdcount = 1; /* question entries */
1094 packet.question = question;
1095 packet.ancount = 0; /* answer recs */
1096 packet.answer = NULL;
1097 packet.nscount = 0; /* authority recs */
1098 packet.authority = NULL;
1099 packet.arcount = 1; /* additional recs */
1100 packet.additional = additional;
1102 if (q_addrs)
1103 goto special_process;
1105 for (i = 0; i < addr_num; i++) {
1106 rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
1107 retries, timeout);
1108 if (rc == 1)
1109 gotreply = 1;
1112 return (gotreply);
1114 special_process:
1115 addr = destination;
1116 do {
1117 rc = smb_netbios_send_rcv(bcast, addr, &packet,
1118 retries, timeout);
1119 if (rc == 1)
1120 gotreply = 1;
1121 addr = addr->forw;
1122 } while (addr != destination);
1124 return (gotreply);
1128 * RFC 1002 4.2.5. POSITIVE NAME REGISTRATION RESPONSE
1129 * RFC 1002 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE
1131 static int
1132 smb_send_name_registration_response(addr_entry_t *addr,
1133 struct name_packet *original_packet, uint16_t rcode)
1135 struct name_packet packet;
1136 struct resource_record answer;
1138 bzero(&packet, sizeof (struct name_packet));
1139 bzero(&answer, sizeof (struct resource_record));
1141 packet.name_trn_id = original_packet->name_trn_id;
1142 packet.info = NAME_REGISTRATION_RESPONSE | NAME_NM_FLAGS_RA |
1143 (rcode & NAME_RCODE_MASK);
1144 packet.qdcount = 0; /* question entries */
1145 packet.question = NULL;
1146 packet.ancount = 1; /* answer recs */
1147 packet.answer = &answer;
1148 packet.nscount = 0; /* authority recs */
1149 packet.authority = NULL;
1150 packet.arcount = 0; /* additional recs */
1151 packet.additional = NULL;
1153 answer.name = original_packet->question->name;
1154 answer.rr_type = NAME_QUESTION_TYPE_NB;
1155 answer.rr_class = NAME_QUESTION_CLASS_IN;
1156 answer.ttl = original_packet->additional->ttl;
1157 answer.rdlength = original_packet->additional->rdlength;
1158 answer.rdata = original_packet->additional->rdata;
1160 return (smb_send_name_service_packet(addr, &packet));
1164 * RFC 1002 4.2.9. NAME RELEASE REQUEST & DEMAND
1166 static int
1167 smb_send_name_release_request_and_demand(int bcast,
1168 struct name_question *question, struct resource_record *additional)
1170 int gotreply = 0;
1171 int i, rc;
1172 int addr_num;
1173 uint32_t retries;
1174 uint32_t timeout;
1175 addr_entry_t *destination;
1176 struct name_packet packet;
1178 if (bcast == BROADCAST) {
1179 if (bcast_num == 0)
1180 return (-1);
1181 destination = smb_bcast_list;
1182 addr_num = bcast_num;
1183 retries = 1; /* BCAST_REQ_RETRY_COUNT */
1184 timeout = 100; /* BCAST_REQ_RETRY_TIMEOUT */
1185 packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_BROADCAST;
1186 } else {
1187 if (nbns_num == 0)
1188 return (-1);
1189 destination = smb_nbns;
1190 addr_num = nbns_num;
1191 retries = 1; /* UCAST_REQ_RETRY_COUNT */
1192 timeout = 100; /* UCAST_REQ_RETRY_TIMEOUT */
1193 packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_UNICAST;
1196 packet.qdcount = 1; /* question entries */
1197 packet.question = question;
1198 packet.ancount = 0; /* answer recs */
1199 packet.answer = NULL;
1200 packet.nscount = 0; /* authority recs */
1201 packet.authority = NULL;
1202 packet.arcount = 1; /* additional recs */
1203 packet.additional = additional;
1205 for (i = 0; i < addr_num; i++) {
1206 rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
1207 retries, timeout);
1208 if (rc == 1)
1209 gotreply = 1;
1212 return (gotreply);
1216 * RFC 1002 4.2.10. POSITIVE NAME RELEASE RESPONSE
1217 * RFC 1002 4.2.11. NEGATIVE NAME RELEASE RESPONSE
1219 static int
1220 /* LINTED - E_STATIC_UNUSED */
1221 smb_send_name_release_response(addr_entry_t *addr,
1222 struct name_packet *original_packet, uint16_t rcode)
1224 struct name_packet packet;
1225 struct resource_record answer;
1227 bzero(&packet, sizeof (struct name_packet));
1228 bzero(&answer, sizeof (struct resource_record));
1230 packet.name_trn_id = original_packet->name_trn_id;
1231 packet.info = NAME_RELEASE_RESPONSE | (rcode & NAME_RCODE_MASK);
1232 packet.qdcount = 0; /* question entries */
1233 packet.question = NULL;
1234 packet.ancount = 1; /* answer recs */
1235 packet.answer = &answer;
1236 packet.nscount = 0; /* authority recs */
1237 packet.authority = NULL;
1238 packet.arcount = 0; /* additional recs */
1239 packet.additional = NULL;
1241 answer.name = original_packet->question->name;
1242 answer.rr_type = NAME_QUESTION_TYPE_NB;
1243 answer.rr_class = NAME_QUESTION_CLASS_IN;
1244 answer.ttl = original_packet->additional->ttl;
1245 answer.rdlength = original_packet->additional->rdlength;
1246 answer.rdata = original_packet->additional->rdata;
1248 return (smb_send_name_service_packet(addr, &packet));
1252 * RFC 1002 4.2.12. NAME QUERY REQUEST
1254 static int
1255 smb_send_name_query_request(int bcast, struct name_question *question)
1257 int rc = 0;
1258 uint32_t retry, retries;
1259 uint32_t timeout;
1260 uint16_t tid;
1261 addr_entry_t *destination;
1262 struct name_packet packet;
1263 int i, addr_num;
1264 struct timespec st;
1266 if (bcast == BROADCAST) {
1267 if (bcast_num == 0)
1268 return (-1);
1269 destination = smb_bcast_list;
1270 addr_num = bcast_num;
1271 retries = BCAST_REQ_RETRY_COUNT;
1272 timeout = BCAST_REQ_RETRY_TIMEOUT;
1273 packet.info = NAME_QUERY_REQUEST | NM_FLAGS_BROADCAST;
1274 } else {
1275 if (nbns_num == 0)
1276 return (-1);
1277 destination = smb_nbns;
1278 addr_num = nbns_num;
1279 retries = UCAST_REQ_RETRY_COUNT;
1280 timeout = UCAST_REQ_RETRY_TIMEOUT;
1281 packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST;
1283 packet.qdcount = 1; /* question entries */
1284 packet.question = question;
1285 packet.ancount = 0; /* answer recs */
1286 packet.answer = NULL;
1287 packet.nscount = 0; /* authority recs */
1288 packet.authority = NULL;
1289 packet.arcount = 0; /* additional recs */
1290 packet.additional = NULL;
1292 for (i = 0; i < addr_num; i++) {
1293 for (retry = 0; retry < retries; retry++) {
1294 if ((destination[i].flags & ADDR_FLAG_VALID) == 0)
1295 break;
1296 tid = smb_netbios_name_trn_id();
1297 packet.name_trn_id = tid;
1299 if (smb_send_name_service_packet(&destination[i],
1300 &packet) >= 0) {
1301 if ((rc = smb_netbios_process_response(tid,
1302 &destination[i],
1303 &packet, timeout)) != 0)
1304 break;
1306 st.tv_sec = 0;
1307 st.tv_nsec = (timeout * 1000000);
1308 (void) nanosleep(&st, 0);
1312 return (rc);
1316 * RFC 1002 4.2.13. POSITIVE NAME QUERY RESPONSE
1317 * RFC 1002 4.2.14. NEGATIVE NAME QUERY RESPONSE
1319 static int
1320 smb_send_name_query_response(addr_entry_t *addr,
1321 struct name_packet *original_packet, struct name_entry *entry,
1322 uint16_t rcode)
1324 addr_entry_t *raddr;
1325 struct name_packet packet;
1326 struct resource_record answer;
1327 uint16_t attr;
1328 unsigned char data[MAX_DATAGRAM_LENGTH];
1329 unsigned char *scan = data;
1330 uint32_t ret_addr;
1332 packet.name_trn_id = original_packet->name_trn_id;
1333 packet.info = NAME_QUERY_RESPONSE | (rcode & NAME_RCODE_MASK);
1334 packet.qdcount = 0; /* question entries */
1335 packet.question = NULL;
1336 packet.ancount = 1; /* answer recs */
1337 packet.answer = &answer;
1338 packet.nscount = 0; /* authority recs */
1339 packet.authority = NULL;
1340 packet.arcount = 0; /* additional recs */
1341 packet.additional = NULL;
1343 answer.name = entry;
1344 answer.rr_class = NAME_QUESTION_CLASS_IN;
1345 answer.ttl = entry->addr_list.ttl;
1346 answer.rdata = data;
1347 if (rcode) {
1348 answer.rr_type = NAME_RR_TYPE_NULL;
1349 answer.rdlength = 0;
1350 bzero(data, 6);
1351 } else {
1352 answer.rdlength = 0;
1353 answer.rr_type = NAME_QUESTION_TYPE_NB;
1354 raddr = &entry->addr_list;
1355 scan = data;
1356 do {
1357 attr = entry->attributes & (NAME_ATTR_GROUP |
1358 NAME_ATTR_OWNER_NODE_TYPE);
1360 BE_OUT16(scan, attr); scan += 2;
1361 ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
1362 *scan++ = ret_addr;
1363 *scan++ = ret_addr >> 8;
1364 *scan++ = ret_addr >> 16;
1365 *scan++ = ret_addr >> 24;
1367 answer.rdlength += 6;
1368 raddr = raddr->forw;
1369 } while (raddr != &entry->addr_list);
1372 return (smb_send_name_service_packet(addr, &packet));
1376 * RFC 1002 4.2.18. NODE STATUS RESPONSE
1378 static int
1379 smb_send_node_status_response(addr_entry_t *addr,
1380 struct name_packet *original_packet)
1382 uint32_t net_ipaddr;
1383 int64_t max_connections;
1384 struct arpreq arpreq;
1385 struct name_packet packet;
1386 struct resource_record answer;
1387 unsigned char *scan;
1388 unsigned char *scan_end;
1389 unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE];
1390 boolean_t scan_done = B_FALSE;
1391 smb_inaddr_t ipaddr;
1393 bzero(&packet, sizeof (struct name_packet));
1394 bzero(&answer, sizeof (struct resource_record));
1396 packet.name_trn_id = original_packet->name_trn_id;
1397 packet.info = NODE_STATUS_RESPONSE;
1398 packet.qdcount = 0; /* question entries */
1399 packet.question = NULL;
1400 packet.ancount = 1; /* answer recs */
1401 packet.answer = &answer;
1402 packet.nscount = 0; /* authority recs */
1403 packet.authority = NULL;
1404 packet.arcount = 0; /* additional recs */
1405 packet.additional = NULL;
1407 answer.name = original_packet->question->name;
1408 answer.rr_type = NAME_RR_TYPE_NBSTAT;
1409 answer.rr_class = NAME_QUESTION_CLASS_IN;
1410 answer.ttl = 0;
1411 answer.rdata = data;
1413 scan = smb_netbios_cache_status(data, MAX_NETBIOS_REPLY_DATA_SIZE,
1414 original_packet->question->name->scope);
1416 scan_end = data + MAX_NETBIOS_REPLY_DATA_SIZE;
1418 ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
1419 ipaddr.a_family = AF_INET;
1420 if (smb_nic_is_same_subnet(&ipaddr))
1421 net_ipaddr = addr->sin.sin_addr.s_addr;
1422 else
1423 net_ipaddr = 0;
1425 (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections);
1427 while (!scan_done) {
1428 if ((scan + 6) >= scan_end) {
1429 packet.info |= NAME_NM_FLAGS_TC;
1430 break;
1433 if (net_ipaddr != 0) {
1434 struct sockaddr_in *s_in;
1435 int s;
1437 s = socket(AF_INET, SOCK_DGRAM, 0);
1438 /* LINTED - E_BAD_PTR_CAST_ALIGN */
1439 s_in = (struct sockaddr_in *)&arpreq.arp_pa;
1440 s_in->sin_family = AF_INET;
1441 s_in->sin_addr.s_addr = net_ipaddr;
1442 if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) < 0) {
1443 bzero(scan, 6);
1444 } else {
1445 bcopy(&arpreq.arp_ha.sa_data, scan, 6);
1447 (void) close(s);
1448 } else {
1449 bzero(scan, 6);
1451 scan += 6;
1453 if ((scan + 26) >= scan_end) {
1454 packet.info |= NAME_NM_FLAGS_TC;
1455 break;
1457 bzero(scan, 26);
1458 scan += 26;
1460 if ((scan + 2) >= scan_end) {
1461 packet.info |= NAME_NM_FLAGS_TC;
1462 break;
1464 BE_OUT16(scan, 0); scan += 2;
1466 if ((scan + 2) >= scan_end) {
1467 packet.info |= NAME_NM_FLAGS_TC;
1468 break;
1470 BE_OUT16(scan, 0); scan += 2;
1472 if ((scan + 2) >= scan_end) {
1473 packet.info |= NAME_NM_FLAGS_TC;
1474 break;
1476 BE_OUT16(scan, 0); scan += 2;
1478 if ((scan + 2) >= scan_end) {
1479 packet.info |= NAME_NM_FLAGS_TC;
1480 break;
1482 BE_OUT16(scan, 0); scan += 2;
1484 if ((scan + 2) >= scan_end) {
1485 packet.info |= NAME_NM_FLAGS_TC;
1486 break;
1488 BE_OUT16(scan, 0); scan += 2;
1490 if ((scan + 2) >= scan_end) {
1491 packet.info |= NAME_NM_FLAGS_TC;
1492 break;
1494 BE_OUT16(scan, 0); scan += 2;
1496 if ((scan + 2) >= scan_end) {
1497 packet.info |= NAME_NM_FLAGS_TC;
1498 break;
1500 BE_OUT16(scan, 0); scan += 2;
1502 if ((scan + 2) >= scan_end) {
1503 packet.info |= NAME_NM_FLAGS_TC;
1504 break;
1506 BE_OUT16(scan, max_connections); scan += 2;
1508 if ((scan + 2) >= scan_end) {
1509 packet.info |= NAME_NM_FLAGS_TC;
1510 break;
1513 BE_OUT16(scan, 0); scan += 2;
1515 scan_done = B_TRUE;
1517 answer.rdlength = scan - data;
1518 return (smb_send_name_service_packet(addr, &packet));
1521 static int
1522 smb_name_Bnode_add_name(struct name_entry *name)
1524 struct name_question question;
1525 struct resource_record additional;
1526 unsigned char data[8];
1527 uint16_t attr;
1528 addr_entry_t *addr;
1529 int rc = 0;
1531 addr = &name->addr_list;
1533 do {
1534 /* build name service packet */
1535 question.name = name;
1537 * question.name->attributes |= NAME_NB_FLAGS_ONT_B;
1538 * This is commented because NAME_NB_FLAGS_ONT_B is 0
1540 question.question_type = NAME_QUESTION_TYPE_NB;
1541 question.question_class = NAME_QUESTION_CLASS_IN;
1543 additional.name = name;
1544 additional.rr_class = NAME_QUESTION_CLASS_IN;
1545 additional.ttl = 0;
1546 additional.rdata = data;
1547 additional.rdlength = 6;
1548 additional.rr_type = NAME_QUESTION_TYPE_NB;
1549 attr = name->attributes & (NAME_ATTR_GROUP |
1550 NAME_ATTR_OWNER_NODE_TYPE);
1552 BE_OUT16(&data[0], attr);
1553 (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
1554 sizeof (uint32_t));
1556 rc |= smb_send_name_registration_request(BROADCAST, &question,
1557 &additional);
1558 addr = addr->forw;
1560 } while (addr != &name->addr_list);
1562 return (rc);
1565 static int
1566 smb_name_Bnode_find_name(struct name_entry *name)
1568 struct name_question question;
1570 question.name = name;
1571 question.question_type = NAME_QUESTION_TYPE_NB;
1572 question.question_class = NAME_QUESTION_CLASS_IN;
1574 return (smb_send_name_query_request(BROADCAST, &question));
1577 static int
1578 smb_name_Bnode_delete_name(struct name_entry *name)
1580 struct name_question question;
1581 struct resource_record additional;
1582 addr_entry_t *raddr;
1583 unsigned char data[MAX_DATAGRAM_LENGTH];
1584 unsigned char *scan = data;
1585 uint32_t attr;
1586 uint32_t ret_addr;
1588 /* build packet */
1589 question.name = name;
1590 question.question_type = NAME_QUESTION_TYPE_NB;
1591 question.question_class = NAME_QUESTION_CLASS_IN;
1593 additional.name = name;
1594 additional.rr_class = NAME_QUESTION_CLASS_IN;
1595 additional.ttl = 0;
1596 additional.rdata = data;
1597 additional.rdlength = 0;
1598 additional.rr_type = NAME_QUESTION_TYPE_NB;
1599 raddr = &name->addr_list;
1600 scan = data;
1601 do {
1602 attr = name->attributes & (NAME_ATTR_GROUP |
1603 NAME_ATTR_OWNER_NODE_TYPE);
1605 BE_OUT16(scan, attr); scan += 2;
1606 ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
1607 *scan++ = ret_addr;
1608 *scan++ = ret_addr >> 8;
1609 *scan++ = ret_addr >> 16;
1610 *scan++ = ret_addr >> 24;
1612 additional.rdlength += 6;
1613 } while (raddr != &name->addr_list);
1615 return (smb_send_name_release_request_and_demand(BROADCAST,
1616 &question, &additional));
1619 static int
1620 smb_name_Pnode_add_name(struct name_entry *name)
1622 struct name_question question;
1623 struct resource_record additional;
1624 unsigned char data[8];
1625 uint16_t attr;
1626 addr_entry_t *addr;
1627 int rc = 0;
1629 /* build packet */
1630 addr = &name->addr_list;
1631 do {
1632 question.name = name;
1633 question.question_type = NAME_QUESTION_TYPE_NB;
1634 question.question_class = NAME_QUESTION_CLASS_IN;
1636 additional.name = name;
1637 additional.rr_class = NAME_QUESTION_CLASS_IN;
1638 additional.ttl = 0;
1639 additional.rdata = data;
1640 additional.rdlength = 6;
1641 additional.rr_type = NAME_QUESTION_TYPE_NB;
1642 attr = name->attributes &
1643 (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE);
1645 BE_OUT16(&data[0], attr);
1646 (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
1647 sizeof (uint32_t));
1649 rc |= smb_send_name_registration_request(UNICAST, &question,
1650 &additional);
1652 addr = addr->forw;
1654 } while (addr != &name->addr_list);
1656 return (rc);
1659 static int
1660 smb_name_Pnode_refresh_name(struct name_entry *name)
1662 struct name_question question;
1663 struct resource_record additional;
1664 unsigned char data[8];
1665 uint16_t attr;
1666 addr_entry_t *addr;
1667 int rc = 0;
1669 /* build packet */
1670 addr = &name->addr_list;
1671 do {
1672 question.name = name;
1673 question.question_type = NAME_QUESTION_TYPE_NB;
1674 question.question_class = NAME_QUESTION_CLASS_IN;
1676 additional.name = name;
1677 additional.rr_class = NAME_QUESTION_CLASS_IN;
1678 additional.ttl = 0;
1679 additional.rdata = data;
1680 additional.rdlength = 6;
1681 additional.rr_type = NAME_QUESTION_TYPE_NB;
1682 attr = name->attributes &
1683 (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE);
1685 BE_OUT16(&data[0], attr);
1686 (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
1687 sizeof (uint32_t));
1689 rc |= smb_send_name_refresh_request(UNICAST, &question,
1690 &additional, 1);
1692 addr = addr->forw;
1693 } while (addr != &name->addr_list);
1695 return (rc);
1698 static int
1699 smb_name_Pnode_find_name(struct name_entry *name)
1701 struct name_question question;
1704 * Host initiated processing for a P node
1706 question.name = name;
1707 question.name->attributes |= NAME_NB_FLAGS_ONT_P;
1708 question.question_type = NAME_QUESTION_TYPE_NB;
1709 question.question_class = NAME_QUESTION_CLASS_IN;
1711 return (smb_send_name_query_request(UNICAST, &question));
1714 static int
1715 smb_name_Pnode_delete_name(struct name_entry *name)
1717 struct name_question question;
1718 struct resource_record additional;
1719 addr_entry_t *raddr;
1720 unsigned char data[MAX_DATAGRAM_LENGTH];
1721 unsigned char *scan = data;
1722 uint32_t attr;
1723 uint32_t ret_addr;
1725 /* build packet */
1726 question.name = name;
1727 question.name->attributes |= NAME_NB_FLAGS_ONT_P;
1728 question.question_type = NAME_QUESTION_TYPE_NB;
1729 question.question_class = NAME_QUESTION_CLASS_IN;
1731 additional.name = name;
1732 additional.rr_class = NAME_QUESTION_CLASS_IN;
1733 additional.ttl = 0;
1734 additional.rdata = data;
1735 additional.rdlength = 0;
1736 additional.rr_type = NAME_QUESTION_TYPE_NB;
1737 raddr = &name->addr_list;
1738 do {
1739 scan = data;
1740 attr = name->attributes & (NAME_ATTR_GROUP |
1741 NAME_ATTR_OWNER_NODE_TYPE);
1743 BE_OUT16(scan, attr); scan += 2;
1744 ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
1745 *scan++ = ret_addr;
1746 *scan++ = ret_addr >> 8;
1747 *scan++ = ret_addr >> 16;
1748 *scan++ = ret_addr >> 24;
1750 additional.rdlength = 6;
1751 raddr = raddr->forw;
1752 (void) smb_send_name_release_request_and_demand(UNICAST,
1753 &question, &additional);
1754 } while (raddr != &name->addr_list);
1756 return (1);
1759 static int
1760 smb_name_Mnode_add_name(struct name_entry *name)
1762 if (smb_name_Bnode_add_name(name) > 0) {
1763 if (nbns_num == 0)
1764 return (1); /* No name server configured */
1766 return (smb_name_Pnode_add_name(name));
1768 return (-1);
1771 static int
1772 smb_name_Hnode_add_name(struct name_entry *name)
1774 if (nbns_num > 0) {
1775 if (smb_name_Pnode_add_name(name) == 1)
1776 return (1);
1779 return (smb_name_Bnode_add_name(name));
1782 static int
1783 smb_name_Mnode_find_name(struct name_entry *name)
1785 if (smb_name_Bnode_find_name(name) == 1)
1786 return (1);
1788 if (nbns_num == 0)
1789 return (1); /* No name server configured */
1791 return (smb_name_Pnode_find_name(name));
1794 static int
1795 smb_name_Hnode_find_name(struct name_entry *name)
1797 if (nbns_num > 0)
1798 if (smb_name_Pnode_find_name(name) == 1)
1799 return (1);
1801 return (smb_name_Bnode_find_name(name));
1804 static int
1805 smb_name_Mnode_delete_name(struct name_entry *name)
1807 (void) smb_name_Bnode_delete_name(name);
1809 if (nbns_num == 0)
1810 return (-1); /* No name server configured */
1812 if (smb_name_Pnode_delete_name(name) > 0)
1813 return (1);
1815 return (-1);
1818 static int
1819 smb_name_Hnode_delete_name(struct name_entry *name)
1821 if (nbns_num > 0)
1822 if (smb_name_Pnode_delete_name(name) > 0)
1823 return (1);
1825 return (smb_name_Bnode_delete_name(name));
1828 static void
1829 smb_name_process_Bnode_packet(struct name_packet *packet, addr_entry_t *addr)
1831 struct name_entry *name;
1832 struct name_entry *entry;
1833 struct name_question *question;
1834 struct resource_record *additional;
1836 question = packet->question;
1837 additional = packet->additional;
1839 switch (packet->info & NAME_OPCODE_OPCODE_MASK) {
1840 case NAME_OPCODE_REFRESH:
1841 /* Guard against malformed packets */
1842 if ((question == 0) || (additional == 0))
1843 break;
1844 if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
1845 break;
1847 name = question->name;
1848 name->addr_list.ttl = additional->ttl;
1849 name->attributes = additional->name->attributes;
1850 name->addr_list.sin = additional->name->addr_list.sin;
1851 name->addr_list.forw = name->addr_list.back = &name->addr_list;
1853 if ((entry = smb_netbios_cache_lookup_addr(name)) != 0) {
1854 smb_netbios_cache_update_entry(entry, question->name);
1855 smb_netbios_cache_unlock_entry(entry);
1857 else
1858 (void) smb_netbios_cache_insert(question->name);
1859 break;
1861 case NAME_OPCODE_QUERY:
1863 * This opcode covers both NAME_QUERY_REQUEST and
1864 * NODE_STATUS_REQUEST. They can be distinguished
1865 * based on the type of question entry.
1868 /* All query requests have to have question entry */
1869 if (question == 0)
1870 break;
1872 if (question->question_type == NAME_QUESTION_TYPE_NB) {
1873 name = question->name;
1874 if ((entry = smb_netbios_cache_lookup(name)) != 0) {
1875 (void) smb_send_name_query_response(addr,
1876 packet, entry, 0);
1877 smb_netbios_cache_unlock_entry(entry);
1880 else
1881 if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
1883 * Name of "*" may be used to force node to
1884 * divulge status for administrative purposes
1886 name = question->name;
1887 entry = 0;
1888 if (NETBIOS_NAME_IS_STAR(name->name) ||
1889 ((entry = smb_netbios_cache_lookup(name)) != 0)) {
1890 if (entry)
1891 smb_netbios_cache_unlock_entry(entry);
1893 * send only those names that are
1894 * in the same scope as the scope
1895 * field in the request packet
1897 (void) smb_send_node_status_response(addr,
1898 packet);
1901 break;
1903 default:
1904 break;
1908 static void
1909 smb_name_process_Pnode_packet(struct name_packet *packet, addr_entry_t *addr)
1911 struct name_entry *name;
1912 struct name_entry *entry;
1913 struct name_question *question;
1914 struct resource_record *additional;
1916 question = packet->question;
1917 additional = packet->additional;
1919 if (packet->info & NAME_NM_FLAGS_B) {
1921 * always ignore UDP broadcast packets
1923 return;
1926 switch (packet->info & NAME_OPCODE_OPCODE_MASK) {
1927 case NAME_OPCODE_REFRESH:
1928 /* Guard against malformed packets */
1929 if ((question == 0) || (additional == 0))
1930 break;
1931 if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
1932 break;
1934 name = question->name;
1935 name->addr_list.ttl = additional->ttl;
1936 name->attributes = additional->name->attributes;
1937 name->addr_list.sin = additional->name->addr_list.sin;
1938 name->addr_list.forw = name->addr_list.back = &name->addr_list;
1940 if ((entry = smb_netbios_cache_lookup(name)) != 0) {
1941 smb_netbios_cache_update_entry(entry, name);
1942 smb_netbios_cache_unlock_entry(entry);
1944 else
1945 (void) smb_netbios_cache_insert(name);
1947 (void) smb_send_name_registration_response(addr, packet, 0);
1948 break;
1950 case NAME_OPCODE_QUERY:
1952 * This opcode covers both NAME_QUERY_REQUEST and
1953 * NODE_STATUS_REQUEST. They can be distinguished
1954 * based on the type of question entry.
1957 /* All query requests have to have question entry */
1958 if (question == 0)
1959 break;
1961 if (question->question_type == NAME_QUESTION_TYPE_NB) {
1962 name = question->name;
1963 if ((entry = smb_netbios_cache_lookup(name)) != 0) {
1965 * send response to the IP address and port
1966 * number from which the request was received.
1968 (void) smb_send_name_query_response(addr,
1969 packet, entry, 0);
1970 smb_netbios_cache_unlock_entry(entry);
1971 } else {
1973 * send response to the requestor
1975 (void) smb_send_name_query_response(addr,
1976 packet, name, RCODE_NAM_ERR);
1979 else
1980 if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
1982 * Name of "*" may be used to force node to
1983 * divulge status for administrative purposes
1985 name = question->name;
1986 entry = 0;
1987 if (NETBIOS_NAME_IS_STAR(name->name) ||
1988 ((entry = smb_netbios_cache_lookup(name)) != 0)) {
1990 * send only those names that are
1991 * in the same scope as the scope
1992 * field in the request packet
1994 if (entry)
1995 smb_netbios_cache_unlock_entry(entry);
1996 (void) smb_send_node_status_response(addr,
1997 packet);
2000 break;
2002 default:
2003 break;
2007 static void
2008 smb_name_process_Mnode_packet(struct name_packet *packet, addr_entry_t *addr)
2010 if (packet->info & NAME_NM_FLAGS_B)
2011 smb_name_process_Bnode_packet(packet, addr);
2012 else
2013 smb_name_process_Pnode_packet(packet, addr);
2016 static void
2017 smb_name_process_Hnode_packet(struct name_packet *packet, addr_entry_t *addr)
2019 if (packet->info & NAME_NM_FLAGS_B)
2020 smb_name_process_Bnode_packet(packet, addr);
2021 else
2022 smb_name_process_Pnode_packet(packet, addr);
2027 * smb_netbios_name_tick
2029 * Called once a second to handle name server timeouts.
2031 void
2032 smb_netbios_name_tick(void)
2034 struct name_entry *name;
2035 struct name_entry *entry;
2037 (void) mutex_lock(&refresh_queue.mtx);
2038 smb_netbios_cache_refresh(&refresh_queue);
2040 while ((name = refresh_queue.head.forw) != &refresh_queue.head) {
2041 QUEUE_CLIP(name);
2042 if (IS_LOCAL(name->attributes)) {
2043 if (IS_UNIQUE(name->attributes)) {
2044 (void) smb_name_Pnode_refresh_name(name);
2046 } else {
2047 entry = smb_name_find_name(name);
2048 smb_name_unlock_name(entry);
2050 free(name);
2052 (void) mutex_unlock(&refresh_queue.mtx);
2054 smb_netbios_cache_reset_ttl();
2058 * smb_name_find_name
2060 * Lookup name cache for the given name.
2061 * If it's not in the cache it'll send a
2062 * name query request and then lookup the
2063 * cache again. Note that if a name is
2064 * returned it's locked and called MUST
2065 * unlock it by calling smb_name_unlock_name()
2067 struct name_entry *
2068 smb_name_find_name(struct name_entry *name)
2070 struct name_entry *result;
2072 if ((result = smb_netbios_cache_lookup(name)) == 0) {
2073 switch (smb_node_type) {
2074 case 'B':
2075 (void) smb_name_Bnode_find_name(name);
2076 break;
2077 case 'P':
2078 (void) smb_name_Pnode_find_name(name);
2079 break;
2080 case 'M':
2081 (void) smb_name_Mnode_find_name(name);
2082 break;
2083 case 'H':
2084 default:
2085 (void) smb_name_Hnode_find_name(name);
2086 break;
2088 return (smb_netbios_cache_lookup(name));
2091 return (result);
2094 void
2095 smb_name_unlock_name(struct name_entry *name)
2097 smb_netbios_cache_unlock_entry(name);
2101 smb_name_add_name(struct name_entry *name)
2103 int rc = 1;
2105 smb_netbios_name_logf(name);
2107 switch (smb_node_type) {
2108 case 'B':
2109 rc = smb_name_Bnode_add_name(name);
2110 break;
2111 case 'P':
2112 rc = smb_name_Pnode_add_name(name);
2113 break;
2114 case 'M':
2115 rc = smb_name_Mnode_add_name(name);
2116 break;
2117 case 'H':
2118 default:
2119 rc = smb_name_Hnode_add_name(name);
2120 break;
2123 if (rc >= 0)
2124 (void) smb_netbios_cache_insert(name);
2126 return (rc);
2130 smb_name_delete_name(struct name_entry *name)
2132 int rc;
2133 unsigned char type;
2135 type = name->name[15];
2136 if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
2137 syslog(LOG_DEBUG, "nbns: name delete bad type (0x%02x)", type);
2138 smb_netbios_name_logf(name);
2139 name->attributes &= ~NAME_ATTR_LOCAL;
2140 return (-1);
2143 smb_netbios_cache_delete(name);
2145 switch (smb_node_type) {
2146 case 'B':
2147 rc = smb_name_Bnode_delete_name(name);
2148 break;
2149 case 'P':
2150 rc = smb_name_Pnode_delete_name(name);
2151 break;
2152 case 'M':
2153 rc = smb_name_Mnode_delete_name(name);
2154 break;
2155 case 'H':
2156 default:
2157 rc = smb_name_Hnode_delete_name(name);
2158 break;
2161 if (rc > 0)
2162 return (0);
2164 return (-1);
2167 typedef struct {
2168 addr_entry_t *addr;
2169 char *buf;
2170 int length;
2171 } worker_param_t;
2174 * smb_netbios_worker
2176 * Process incoming request/response packets for Netbios
2177 * name service (on port 138).
2179 void *
2180 smb_netbios_worker(void *arg)
2182 worker_param_t *p = (worker_param_t *)arg;
2183 addr_entry_t *addr = p->addr;
2184 struct name_packet *packet;
2186 if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != NULL) {
2187 if (packet->info & NAME_OPCODE_R) {
2188 /* Reply packet */
2189 smb_reply_ready(packet, addr);
2190 free(p->buf);
2191 free(p);
2192 return (NULL);
2195 /* Request packet */
2196 switch (smb_node_type) {
2197 case 'B':
2198 smb_name_process_Bnode_packet(packet, addr);
2199 break;
2200 case 'P':
2201 smb_name_process_Pnode_packet(packet, addr);
2202 break;
2203 case 'M':
2204 smb_name_process_Mnode_packet(packet, addr);
2205 break;
2206 case 'H':
2207 default:
2208 smb_name_process_Hnode_packet(packet, addr);
2209 break;
2212 if (packet->answer)
2213 smb_netbios_name_freeaddrs(packet->answer->name);
2214 free(packet);
2215 } else {
2216 syslog(LOG_ERR, "nbns: packet decode failed");
2219 free(addr);
2220 free(p->buf);
2221 free(p);
2222 return (NULL);
2226 * Configure the node type. If a WINS server has been specified,
2227 * act like an H-node. Otherwise, behave like a B-node.
2229 static void
2230 smb_netbios_node_config(void)
2232 static smb_cfg_id_t wins[SMB_PI_MAX_WINS] = {
2233 SMB_CI_WINS_SRV1,
2234 SMB_CI_WINS_SRV2
2236 char ipstr[16];
2237 uint32_t ipaddr;
2238 int i;
2240 smb_node_type = SMB_NODETYPE_B;
2241 nbns_num = 0;
2242 bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS);
2244 for (i = 0; i < SMB_PI_MAX_WINS; ++i) {
2245 ipstr[0] = '\0';
2246 (void) smb_config_getstr(wins[i], ipstr, sizeof (ipstr));
2248 if ((ipaddr = inet_addr(ipstr)) == INADDR_NONE)
2249 continue;
2251 smb_node_type = SMB_NODETYPE_H;
2252 smb_nbns[nbns_num].flags = ADDR_FLAG_VALID;
2253 smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in);
2254 smb_nbns[nbns_num].sin.sin_family = AF_INET;
2255 smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr;
2256 smb_nbns[nbns_num].sin.sin_port = htons(IPPORT_NETBIOS_NS);
2257 nbns_num++;
2261 static void
2262 smb_netbios_name_registration(void)
2264 nbcache_iter_t nbc_iter;
2265 struct name_entry *name;
2266 int rc;
2268 rc = smb_netbios_cache_getfirst(&nbc_iter);
2269 while (rc == 0) {
2270 name = nbc_iter.nbc_entry;
2271 (void) smb_netbios_name_logf(name);
2272 if (IS_UNIQUE(name->attributes) && IS_LOCAL(name->attributes)) {
2273 switch (smb_node_type) {
2274 case SMB_NODETYPE_B:
2275 (void) smb_name_Bnode_add_name(name);
2276 break;
2277 case SMB_NODETYPE_P:
2278 (void) smb_name_Pnode_add_name(name);
2279 break;
2280 case SMB_NODETYPE_M:
2281 (void) smb_name_Mnode_add_name(name);
2282 break;
2283 case SMB_NODETYPE_H:
2284 default:
2285 (void) smb_name_Hnode_add_name(name);
2286 break;
2289 free(name);
2290 rc = smb_netbios_cache_getnext(&nbc_iter);
2295 * Note that the node configuration must be setup before calling
2296 * smb_init_name_struct().
2298 void
2299 smb_netbios_name_config(void)
2301 addr_entry_t *bcast_entry;
2302 struct name_entry name;
2303 smb_niciter_t ni;
2304 int rc;
2306 (void) mutex_lock(&nbt_name_config_mtx);
2307 smb_netbios_node_config();
2309 bcast_num = 0;
2310 bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS);
2312 rc = smb_nic_getfirst(&ni);
2313 while (rc == SMB_NIC_SUCCESS) {
2314 if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
2315 (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) {
2316 rc = smb_nic_getnext(&ni);
2317 continue;
2320 bcast_entry = &smb_bcast_list[bcast_num];
2321 bcast_entry->flags = ADDR_FLAG_VALID;
2322 bcast_entry->attributes = NAME_ATTR_LOCAL;
2323 bcast_entry->sinlen = sizeof (struct sockaddr_in);
2324 bcast_entry->sin.sin_family = AF_INET;
2325 bcast_entry->sin.sin_port = htons(IPPORT_NETBIOS_NS);
2326 bcast_entry->sin.sin_addr.s_addr = ni.ni_nic.nic_bcast;
2327 bcast_num++;
2329 smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
2330 NBT_WKSTA, 0, ni.ni_nic.nic_ip.a_ipv4,
2331 htons(IPPORT_NETBIOS_DGM),
2332 NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
2333 (void) smb_netbios_cache_insert(&name);
2335 smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
2336 NBT_SERVER, 0, ni.ni_nic.nic_ip.a_ipv4,
2337 htons(IPPORT_NETBIOS_DGM),
2338 NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
2339 (void) smb_netbios_cache_insert(&name);
2341 rc = smb_nic_getnext(&ni);
2344 smb_netbios_name_registration();
2345 (void) mutex_unlock(&nbt_name_config_mtx);
2348 void
2349 smb_netbios_name_unconfig(void)
2351 struct name_entry *name;
2353 (void) mutex_lock(&nbt_name_config_mtx);
2354 (void) mutex_lock(&delete_queue.mtx);
2355 smb_netbios_cache_delete_locals(&delete_queue);
2357 while ((name = delete_queue.head.forw) != &delete_queue.head) {
2358 QUEUE_CLIP(name);
2359 (void) smb_name_delete_name(name);
2360 free(name);
2362 (void) mutex_unlock(&delete_queue.mtx);
2363 (void) mutex_unlock(&nbt_name_config_mtx);
2366 void
2367 smb_netbios_name_reconfig(void)
2369 smb_netbios_name_unconfig();
2370 smb_netbios_name_config();
2374 * NetBIOS Name Service (port 137)
2376 /*ARGSUSED*/
2377 void *
2378 smb_netbios_name_service(void *arg)
2380 struct sockaddr_in sin;
2381 addr_entry_t *addr;
2382 int len;
2383 int flag = 1;
2384 char *buf;
2385 worker_param_t *worker_param;
2386 smb_inaddr_t ipaddr;
2389 * Initialize reply_queue
2391 bzero(&reply_queue, sizeof (reply_queue));
2392 reply_queue.forw = reply_queue.back = &reply_queue;
2394 if ((name_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
2395 syslog(LOG_ERR, "nbns: socket failed: %m");
2396 smb_netbios_event(NETBIOS_EVENT_ERROR);
2397 return (NULL);
2400 flag = 1;
2401 (void) setsockopt(name_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
2402 sizeof (flag));
2403 flag = 1;
2404 (void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag,
2405 sizeof (flag));
2407 bzero(&sin, sizeof (struct sockaddr_in));
2408 sin.sin_family = AF_INET;
2409 sin.sin_port = htons(IPPORT_NETBIOS_NS);
2410 if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
2411 syslog(LOG_ERR, "nbns: bind(%d) failed: %m",
2412 IPPORT_NETBIOS_NS);
2413 (void) close(name_sock);
2414 smb_netbios_event(NETBIOS_EVENT_ERROR);
2415 return (NULL);
2418 smb_netbios_event(NETBIOS_EVENT_NS_START);
2420 while (smb_netbios_running()) {
2421 buf = malloc(MAX_DATAGRAM_LENGTH);
2422 addr = malloc(sizeof (addr_entry_t));
2423 if ((buf == NULL) || (addr == NULL)) {
2424 /* Sleep for 10 seconds and try again */
2425 free(addr);
2426 free(buf);
2427 smb_netbios_sleep(10);
2428 continue;
2430 ignore: bzero(addr, sizeof (addr_entry_t));
2431 addr->sinlen = sizeof (addr->sin);
2432 addr->forw = addr->back = addr;
2434 if ((len = recvfrom(name_sock, buf, MAX_DATAGRAM_LENGTH,
2435 0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) {
2436 if (errno == ENOMEM || errno == ENFILE ||
2437 errno == EMFILE) {
2438 /* Sleep for 10 seconds and try again */
2439 free(buf);
2440 free(addr);
2441 smb_netbios_sleep(10);
2442 continue;
2444 syslog(LOG_ERR, "nbns: recvfrom failed: %m");
2445 free(buf);
2446 free(addr);
2447 smb_netbios_event(NETBIOS_EVENT_ERROR);
2448 goto shutdown;
2451 /* Ignore any incoming packets from myself... */
2453 ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
2454 ipaddr.a_family = AF_INET;
2455 if (smb_nic_is_local(&ipaddr))
2456 goto ignore;
2459 * Launch a netbios worker to process the received packet.
2461 worker_param = malloc(sizeof (worker_param_t));
2462 if (worker_param) {
2463 pthread_t worker;
2464 pthread_attr_t tattr;
2466 worker_param->addr = addr;
2467 worker_param->buf = buf;
2468 worker_param->length = len;
2470 (void) pthread_attr_init(&tattr);
2471 (void) pthread_attr_setdetachstate(&tattr,
2472 PTHREAD_CREATE_DETACHED);
2473 (void) pthread_create(&worker, &tattr,
2474 smb_netbios_worker, worker_param);
2475 (void) pthread_attr_destroy(&tattr);
2479 shutdown:
2480 smb_netbios_event(NETBIOS_EVENT_NS_STOP);
2481 smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP);
2483 if (!smb_netbios_error())
2484 smb_netbios_name_unconfig();
2486 (void) close(name_sock);
2487 return (NULL);