dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / smbsrv / libsmbns / common / smbns_browser.c
blob0c145da36962ad00d605cd1a63137ed78b97bee8
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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/tzfile.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <syslog.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <time.h>
34 #include <synch.h>
35 #include <netdb.h>
36 #include <sys/socket.h>
37 #include <arpa/inet.h>
39 #include <smbsrv/libsmb.h>
40 #include <smbsrv/libsmbns.h>
41 #include <smbsrv/smb.h>
42 #include <smbsrv/mailslot.h>
43 #include <smbns_browser.h>
44 #include <smbns_netbios.h>
47 * ntdomain_info
48 * Temporary. It should be removed once NBTD is integrated.
50 smb_ntdomain_t ntdomain_info;
51 mutex_t ntdomain_mtx;
52 cond_t ntdomain_cv;
54 #define SMB_SERVER_SIGNATURE 0xaa550415
56 typedef struct smb_hostinfo {
57 list_node_t hi_lnd;
58 smb_nic_t hi_nic;
59 char hi_nbname[NETBIOS_NAME_SZ];
60 name_entry_t hi_netname;
61 uint32_t hi_nextannouce;
62 int hi_reps;
63 int hi_interval;
64 uint8_t hi_updatecnt;
65 uint32_t hi_type;
66 smb_version_t hi_version;
67 } smb_hostinfo_t;
69 typedef struct smb_browserinfo {
70 list_t bi_hlist;
71 int bi_hcnt;
72 rwlock_t bi_hlist_rwl;
73 boolean_t bi_changed;
74 mutex_t bi_mtx;
75 } smb_browserinfo_t;
77 static smb_browserinfo_t smb_binfo;
79 static int smb_browser_init(void);
80 static void smb_browser_infoinit(void);
81 static void smb_browser_infoterm(void);
82 static void smb_browser_infofree(void);
85 void
86 smb_browser_reconfig(void)
88 (void) mutex_lock(&smb_binfo.bi_mtx);
89 smb_binfo.bi_changed = B_TRUE;
90 (void) mutex_unlock(&smb_binfo.bi_mtx);
94 * 3. Browser Overview
96 * Hosts involved in the browsing process can be separated into two
97 * distinct groups, browser clients and browser servers (often referred to
98 * simply as "browsers").
100 * A browser is a server which maintains information about servers -
101 * primarily the domain they are in and the services that they are running
102 * -- and about domains. Browsers may assume several different roles in
103 * their lifetimes, and dynamically switch between them.
105 * Browser clients are of two types: workstations and (non-browser)
106 * servers. In the context of browsing, workstations query browsers for the
107 * information they contain; servers supply browsers the information by
108 * registering with them. Note that, at times, browsers may themselves
109 * behave as browser clients and query other browsers.
111 * For the purposes of this specification, a domain is simply a name with
112 * which to associate a group of resources such as computers, servers and
113 * users. Domains allow a convenient means for browser clients to restrict
114 * the scope of a search when they query browser servers. Every domain has
115 * a "master" server called the Primary Domain Controller (PDC) that
116 * manages various activities within the domain.
118 * One browser for each domain on a subnet is designated the Local Master
119 * Browser for that domain. Servers in its domain on the subnet register
120 * with it, as do the Local Master Browsers for other domains on the
121 * subnet. It uses these registrations to maintain authoritative
122 * information about its domain on its subnet. If there are other subnets
123 * in the network, it also knows the name of the server running the
124 * domain's Domain Master Browser; it registers with it, and uses it to
125 * obtain information about the rest of the network (see below).
127 * Clients on a subnet query browsers designated as the Backup Browsers for
128 * the subnet (not the Master Browser). Backup Browsers maintain a copy of
129 * the information on the Local Master Browser; they get it by periodically
130 * querying the Local Master Browser for all of its information. Clients
131 * find the Backup Browsers by asking the Local Master Browser. Clients are
132 * expected to spread their queries evenly across Backup Browsers to
133 * balance the load.
135 * The Local Master Browser is dynamically elected automatically. Multiple
136 * Backup Browser Servers may exist per subnet; they are selected from
137 * among the potential browser servers by the Local Master Browser, which
138 * is configured to select enough to handle the expected query load.
140 * When there are multiple subnets, a Domain Master Browser is assigned
141 * the task of keeping the multiple subnets in synchronization. The Primary
142 * Domain Controller (PDC) always acts as the Domain Master Browser. The
143 * Domain Master Browser periodically acts as a client and queries all the
144 * Local Master Browsers for its domain, asking them for a list containing
145 * all the domains and all the servers in their domain known within their
146 * subnets; it merges all the replies into a single master list. This
147 * allows a Domain Master Browser server to act as a collection point for
148 * inter-subnet browsing information. Local Master Browsers periodically
149 * query the Domain Master Browser to retrieve the network-wide information
150 * it maintains.
152 * When a domain spans only a single subnet, there will not be any distinct
153 * Local Master Browser; this role will be handled by the Domain Master
154 * Browser. Similarly, the Domain Master Browser is always the Local Master
155 * Browser for the subnet it is on.
157 * When a browser client suspects that the Local Master Browser has failed,
158 * the client will instigate an election in which the browser servers
159 * participate, and some browser servers may change roles.
161 * Some characteristics of a good browsing mechanism include:
162 * . minimal network traffic
163 * . minimum server discovery time
164 * . minimum change discovery latency
165 * . immunity to machine failures
167 * Historically, Browser implementations had been very closely tied to
168 * NETBIOS and datagrams. The early implementations caused a lot of
169 * broadcast traffic. See Appendix D for an overview that presents how the
170 * Browser specification evolved.
172 * 4. Browsing Protocol Architecture
174 * This section first describes the how the browsing protocol is layered,
175 * then describes the roles of clients, servers, and browsers in the
176 * browsing subsystem.
178 * 4.1 Layering of Browsing Protocol Requests
180 * Most of the browser functionality is implemented using mailslots.
181 * Mailslots provide a mechanism for fast, unreliable unidirectional data
182 * transfer; they are named via ASCII "mailslot (path) name". Mailslots are
183 * implemented using the CIFS Transact SMB which is encapsulated in a
184 * NETBIOS datagram. Browser protocol requests are sent to browser specific
185 * mailslots using some browser-specific NETBIOS names. These datagrams can
186 * either be unicast or broadcast, depending on whether the NETBIOS name is
187 * a "unique name" or a "group name". Various data structures, which are
188 * detailed subsequently within this document, flow as the data portion of
189 * the Transact SMB.
191 * Here is an example of a generic browser SMB, showing how a browser
192 * request is encapsulated in a TRANSACT SMB request. Note that the PID,
193 * TID, MID, UID, and Flags are all 0 in mailslot requests.
195 * SMB: C transact, File = \MAILSLOT\BROWSE
196 * SMB: SMB Status = Error Success
197 * SMB: Error class = No Error
198 * SMB: Error code = No Error
199 * SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
200 * SMB: Tree ID (TID) = 0 (0x0)
201 * SMB: Process ID (PID) = 0 (0x0)
202 * SMB: User ID (UID) = 0 (0x0)
203 * SMB: Multiplex ID (MID) = 0 (0x0)
204 * SMB: Flags Summary = 0 (0x0)
205 * SMB: Command = C transact
206 * SMB: Word count = 17
207 * SMB: Word parameters
208 * SMB: Total parm bytes = 0
209 * SMB: Total data bytes = 33
210 * SMB: Max parm bytes = 0
211 * SMB: Max data bytes = 0
212 * SMB: Max setup words = 0
213 * SMB: Transact Flags Summary = 0 (0x0)
214 * SMB: ...............0 = Leave session intact
215 * SMB: ..............0. = Response required
216 * SMB: Transact timeout = 0 (0x0)
217 * SMB: Parameter bytes = 0 (0x0)
218 * SMB: Parameter offset = 0 (0x0)
219 * SMB: Data bytes = 33 (0x21)
220 * SMB: Data offset = 86 (0x56)
221 * SMB: Setup word count = 3
222 * SMB: Setup words
223 * SMB: Mailslot opcode = Write mailslot
224 * SMB: Transaction priority = 1
225 * SMB: Mailslot class = Unreliable (broadcast)
226 * SMB: Byte count = 50
227 * SMB: Byte parameters
228 * SMB: Path name = \MAILSLOT\BROWSE
229 * SMB: Transaction data
230 * SMB: Data: Number of data bytes remaining = 33 (0x0021)
232 * Note the SMB command is Transact, the opcode within the Transact SMB is
233 * Mailslot Write, and the browser data structure is carried as the
234 * Transact data.
235 * The Transaction data begins with an opcode, that signifies the operation
236 * and determines the size and structure of data that follows. This opcode
237 * is named as per one of the below:
239 * HostAnnouncement 1
240 * AnnouncementRequest 2
241 * RequestElection 8
242 * GetBackupListReq 9
243 * GetBackupListResp 10
244 * BecomeBackup 11
245 * DomainAnnouncment 12
246 * MasterAnnouncement 13
247 * LocalMasterAnnouncement 15
249 * Browser datagrams are often referred to as simply browser frames. The
250 * frames are in particular, referred to by the name of the opcode within
251 * the Transaction data e.g. a GetBackupListReq browser frame, a
252 * RequestElection browser frame, etc.
254 * The structures that are sent as the data portion of the Transact SMB are
255 * described in section(s) 6.2 through 6.12 in this document. These
256 * structures are tightly packed, i.e. there are no intervening pad bytes
257 * in the structure, unless they are explicitly described as being there.
258 * All quantities are sent in native Intel format and multi-byte values are
259 * transmitted least significant byte first.
261 * Besides mailslots and Transaction SMBs, the other important piece of the
262 * browser architecture is the NetServerEnum2 request. This request that
263 * allows an application to interrogate a Browser Server and obtain a
264 * complete list of resources (servers, domains, etc) known to that Browser
265 * server. Details of the NetServerEnum2 request are presented in section
266 * 6.4. Some examples of the NetServerEnum2 request being used are when a
267 * Local Master Browser sends a NetServerEnum2 request to the Domain Master
268 * Browser and vice versa. Another example is when a browser client sends a
269 * NetServerEnum2 request to a Backup Browser server.
271 * 4.3 Non-Browser Server
273 * A non-browser server is a server that has some resource(s) or service(s)
274 * it wishes to advertise as being available using the browsing protocol.
275 * Examples of non-browser servers would be an SQL server, print server,
276 * etc.
278 * A non-browser server MUST periodically send a HostAnnouncement browser
279 * frame, specifying the type of resources or services it is advertising.
280 * Details are in section 6.5.
282 * A non-browser server SHOULD announce itself relatively frequently when
283 * it first starts up in order to make its presence quickly known to the
284 * browsers and thence to potential clients. The frequency of the
285 * announcements SHOULD then be gradually stretched, so as to minimize
286 * network traffic. Typically, non-browser servers announce themselves
287 * once every minute upon start up and then gradually adjust the frequency
288 * of the announcements to once every 12 minutes.
290 * A non-browser server SHOULD send a HostAnnouncement browser frame
291 * specifying a type of 0 just prior to shutting down, to allow it to
292 * quickly be removed from the list of available servers.
294 * A non-browser server MUST receive and process AnnouncementRequest frames
295 * from the Local Master Browser, and MUST respond with a HostAnnouncement
296 * frame, after a delay chosen randomly from the interval [0,30] seconds.
297 * AnnouncementRequests typically happen when a Local Master Browser starts
298 * up with an empty list of servers for the domain, and wants to fill it
299 * quickly. The 30 second range for responses prevents the Master Browser
300 * from becoming overloaded and losing replies, as well as preventing the
301 * network from being flooded with responses.
303 * 4.4 Browser Servers
305 * The following sections describe the roles of the various types of
306 * browser servers.
308 * 4.4.1 Potential Browser Server
310 * A Potential Browser server is a browser server that is capable of being
311 * a Backup Browser server or Master Browser server, but is not currently
312 * fulfilling either of those roles.
314 * A Potential Browser MUST set type SV_TYPE_POTENTIAL_BROWSER (see section
315 * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
316 * last HostAnnouncement frame before it shuts down, it SHOULD specify a
317 * type of 0.
319 * A Potential Browser server MUST receive and process BecomeBackup frames
320 * (see section 6.9) and become a backup browser upon their receipt.
322 * A Potential Browser MUST participate in browser elections (see section
323 * 6.8).
325 * 4.4.2 Backup Browser
327 * Backup Browser servers are a subset of the Potential Browsers that have
328 * been chosen by the Master Browser on their subnet to be the Backup
329 * Browsers for the subnet.
331 * A Backup Browser MUST set type SV_TYPE_BACKUP_BROWSER (see section
332 * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
333 * last HostAnnouncement frame before it shuts down, it SHOULD specify a
334 * type of 0.
336 * A Backup Browser MUST listen for a LocalMasterAnnouncement frame (see
337 * section 6.10) from the Local Master Browser, and use it to set the name
338 * of the Master Browser it queries for the server and domain lists.
340 * A Backup Browsers MUST periodically make a NetServerEnum2 request of
341 * the Master Browser on its subnet for its domain to get a list of servers
342 * in that domain, as well as a list of domains. The period is a
343 * configuration option balancing currency of the information with network
344 * traffic costs - a typical value is 15 minutes.
346 * A Backup Browser SHOULD force an election by sending a RequestElection
347 * frame (see section 6.7) if it does not get a response to its periodic
348 * NetServeEnum2 request to the Master Browser.
350 * A Backup Browser MUST receive and process NetServerEnum2 requests from
351 * browser clients, for its own domain and others. If the request is for a
352 * list of servers in its domain, or for a list of domains, it can answer
353 * from its internal lists. If the request is for a list of servers in a
354 * domain different than the one it serves, it sends a NetServerEnum2
355 * request to the Domain Master Browser for that domain (which it can in
356 * find in its list of domains and their Domain Master Browsers).
358 * A Backup Browser MUST participate in browser elections (see section
359 * 6.8).
361 * 4.4.3 Master Browser
363 * Master Browsers are responsible for:
364 * . indicating it is a Master Browser
365 * . receiving server announcements and building a list of such servers
366 * and keeping it reasonably up-to-date.
367 * . returning lists of Backup Browsers to browser clients.
368 * . ensuring an appropriate number of Backup Browsers are available.
369 * . announcing their existence to other Master Browsers on their subnet,
370 * to the Domain Master Browser for their domain, and to all browsers in
371 * their domain on their subnet
372 * . forwarding requests for lists of servers on other domains to the
373 * Master Browser for that domain
374 * . keeping a list of domains in its subnet
375 * . synchronizing with the Domain Master Browser (if any) for its domain
376 * . participating in browser elections
377 * . ensuring that there is only one Master Browser on its subnet
379 * A Master Browser MUST set type SV_TYPE_MASTER_BROWSER (see section
380 * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
381 * last HostAnnouncement frame before it shuts down, it SHOULD specify a
382 * type of 0.
384 * A Master Browser MUST receive and process HostAnnouncement frames from
385 * servers, adding the server name and other information to its servers
386 * list; it must mark them as "local" entries. Periodically, it MUST check
387 * all local server entries to see if a server's HostAnnouncement has timed
388 * out (no HostAnnouncement received for three times the periodicity the
389 * server gave in the last received HostAnnouncement) and remove timed-out
390 * servers from its list.
392 * A Master Browser MUST receive and process DomainAnnouncement frames (see
393 * section 6.12) and maintain the domain names and their associated (Local)
394 * Master Browsers in its internal domain list until they time out; it must
395 * mark these as "local" entries. Periodically, it MUST check all local
396 * domain entries to see if a server's DomainAnnouncement has timed out (no
397 * DomainAnnouncement received for three times the periodicity the server
398 * gave in the last received DomainAnnouncement) and remove timed-out
399 * servers from its list.
401 * A Master Browser MUST receive and process GetBackupListRequest frames
402 * from clients, returning GetBackupListResponse frames containing a list
403 * of the Backup Servers for its domain.
405 * A Master Browser MUST eventually send BecomeBackup frames (see section
406 * 6.9) to one or more Potential Browser servers to increase the number of
407 * Backup Browsers if there are not enough Backup Browsers to handle the
408 * anticipated query load. Note: possible good times for checking for
409 * sufficient backup browsers are after being elected, when timing out
410 * server HostAnnouncements, and when receiving a server's HostAnnouncement
411 * for the first time.
413 * A Master Browser MUST periodically announce itself and the domain it
414 * serves to other (Local) Master Browsers on its subnet, by sending a
415 * DomainAnnouncement frame (see section 6.12) to its subnet.
417 * A Master Browser MUST send a MasterAnnouncement frame (see section 6.11)
418 * to the Domain Master Browser after it is first elected, and periodically
419 * thereafter. This informs the Domain Master Browser of the presence of
420 * all the Master Browsers.
422 * A Master Browser MUST periodically announce itself to all browsers for
423 * its domain on its subnet by sending a LocalMasterAnnouncement frame (see
424 * section 6.10).
426 * A Master Browser MUST receive and process NetServerEnum2 requests from
427 * browser clients, for its own domain and others. If the request is for a
428 * list of servers in its domain, or for a list of domains, it can answer
429 * from its internal lists. Entries in its list marked "local" MUST have
430 * the SV_TYPE_LOCAL_LIST_ONLY bit set in the returned results; it must be
431 * clear for all other entries. If the request is for a list of servers in
432 * a domain different than the one it serves, it sends a NetServerEnum2
433 * request to the Domain Master Browser for that domain (which it can in
434 * find in its list of domains and their Domain Master Browsers).
436 * Note: The list of servers that the Master Browser maintains and
437 * returns to the Backup Browsers, is limited in size to 64K of
438 * data. This will limit the number of systems that can be in a
439 * browse list in a single workgroup or domain to approximately two
440 * thousand systems.
442 * A Master Browser SHOULD request all servers to register with it by
443 * sending an AnnouncementRequest frame, if, on becoming the Master Browser
444 * by winning an election, its server list is empty. Otherwise, clients
445 * might get an incomplete list of servers until the servers' periodic
446 * registrations fill the server list.
448 * If the Master Browser on a subnet is not the Primary Domain Controller
449 * (PDC), then it is a Local Master Browser.
451 * A Local Master Browser MUST periodically synchronize with the Domain
452 * Master Browser (which is the PDC). This synchronization is performed by
453 * making a NetServerEnum2 request to the Domain Master Browser and merging
454 * the results with its list of servers and domains. An entry from the
455 * Domain Master Browser should be marked "non-local", and must not
456 * overwrite an entry with the same name marked "local". The Domain Master
457 * Browser is located as specified in Appendix B.
459 * A Master Browser MUST participate in browser elections (see section
460 * 6.8).
462 * A Master Browser MUST, if it receives a HostAnnouncement,
463 * DomainAnnouncement, or LocalMasterAnnouncement frame another system that
464 * claims to be the Master Browser for its domain, demote itself from
465 * Master Browser and force an election. This ensures that there is only
466 * ever one Master Browser in each workgroup or domain.
468 * A Master Browser SHOULD, if it loses an election, become a Backup
469 * Browser (without being told to do so by the new Master Browser). Since
470 * it has more up-to-date information in its lists than a Potential
471 * Browser, it is more efficient to have it be a Backup Browser than to
472 * promote a Potential Browser.
474 * 4.4.3.1 Preferred Master Browser
476 * A Preferred Master Browser supports exactly the same protocol elements
477 * as a Potential Browser, except as follows.
479 * A Preferred Master Browser MUST always force an election when it starts
480 * up.
482 * A Preferred Master Browser MUST participate in browser elections (see
483 * section 6.8).
485 * A Preferred Master Browser MUST set the Preferred Master bit in the
486 * RequestElection frame (see section 6.7) to bias the election in its
487 * favor.
489 * A Preferred Master Browser SHOULD, if it loses an election,
490 * automatically become a Backup Browser, without being told to do so by
491 * the Master Browser.
493 * 4.4.4 Domain Master Browser
495 * Since the Domain Master Browser always runs on the PDC, it must
496 * implement all the protocols required of a PDC in addition to the
497 * browsing protocol, and that is way beyond the scope of this
498 * specification.
500 * 5. Mailslot Protocol Specification
502 * The only transaction allowed to a mailslot is a mailslot write. Mailslot
503 * writes requests are encapsulated in TRANSACT SMBs. The following table
504 * shows the interpretation of the TRANSACT SMB parameters for a mailslot
505 * transaction:
507 * Name Value Description
508 * Command SMB_COM_TRANSACTION
509 * Name <name> STRING name of mail slot to write;
510 * must start with "\\MAILSLOT\\"
511 * SetupCount 3 Always 3 for mailslot writes
512 * Setup[0] 1 Command code == write mailslot
513 * Setup[1] Ignored
514 * Setup[2] Ignored
515 * TotalDataCount n Size of data in bytes to write to
516 * the mailslot
517 * Data[ n ] The data to write to the mailslot
522 * SMB: C transact, File = \MAILSLOT\BROWSE
523 * SMB: SMB Status = Error Success
524 * SMB: Error class = No Error
525 * SMB: Error code = No Error
526 * SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
527 * SMB: Tree ID (TID) = 0 (0x0)
528 * SMB: Process ID (PID) = 0 (0x0)
529 * SMB: User ID (UID) = 0 (0x0)
530 * SMB: Multiplex ID (MID) = 0 (0x0)
531 * SMB: Flags Summary = 0 (0x0)
532 * SMB: Command = C transact
533 * SMB: Word count = 17
534 * SMB: Word parameters
535 * SMB: Total parm bytes = 0
536 * SMB: Total data bytes = 33
537 * SMB: Max parm bytes = 0
538 * SMB: Max data bytes = 0
539 * SMB: Max setup words = 0
540 * SMB: Transact Flags Summary = 0 (0x0)
541 * SMB: ...............0 = Leave session intact
542 * SMB: ..............0. = Response required
543 * SMB: Transact timeout = 0 (0x0)
544 * SMB: Parameter bytes = 0 (0x0)
545 * SMB: Parameter offset = 0 (0x0)
546 * SMB: Data bytes = 33 (0x21)
547 * SMB: Data offset = 86 (0x56)
548 * SMB: Setup word count = 3
549 * SMB: Setup words
550 * SMB: Mailslot opcode = Write mailslot
551 * SMB: Transaction priority = 1
552 * SMB: Mailslot class = Unreliable (broadcast)
553 * SMB: Byte count = 50
554 * SMB: Byte parameters
555 * SMB: Path name = \MAILSLOT\BROWSE
556 * SMB: Transaction data
557 * SMB: Data: Number of data bytes remaining = 33 (0x0021)
559 * 5. Mailslot Protocol Specification
561 * The only transaction allowed to a mailslot is a mailslot write. Mailslot
562 * writes requests are encapsulated in TRANSACT SMBs. The following table
563 * shows the interpretation of the TRANSACT SMB parameters for a mailslot
564 * transaction:
566 * Name Value Description
567 * Command SMB_COM_TRANSACTION
568 * Name <name> STRING name of mail slot to write;
569 * must start with "\MAILSLOT\"
570 * SetupCount 3 Always 3 for mailslot writes
571 * Setup[0] 1 Command code == write mailslot
572 * Setup[1] Ignored
573 * Setup[2] Ignored
574 * TotalDataCount n Size of data in bytes to write to
575 * the mailslot
576 * Data[ n ] The data to write to the mailslot
578 * Magic 0xFF 'S' 'M' 'B'
579 * smb_com a byte, the "first" command
580 * Error a 4-byte union, ignored in a request
581 * smb_flg a one byte set of eight flags
582 * smb_flg2 a two byte set of 16 flags
583 * . twelve reserved bytes, have a role
584 * in connectionless transports (IPX, UDP?)
585 * smb_tid a 16-bit tree ID, a mount point sorta,
586 * 0xFFFF is this command does not have
587 * or require a tree context
588 * smb_pid a 16-bit process ID
589 * smb_uid a 16-bit user ID, specific to this "session"
590 * and mapped to a system (bona-fide) UID
591 * smb_mid a 16-bit multiplex ID, used to differentiate
592 * multiple simultaneous requests from the same
593 * process (pid) (ref RPC "xid")
597 smb_browser_load_transact_header(unsigned char *buffer, int maxcnt,
598 int data_count, int reply, char *mailbox)
600 smb_msgbuf_t mb;
601 int mailboxlen;
602 char *fmt;
603 int result;
604 short class = (reply == ONE_WAY_TRANSACTION) ? 2 : 0;
607 * If the mailboxlen is an even number we need to pad the
608 * header so that the data starts on a word boundary.
610 fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws";
611 mailboxlen = strlen(mailbox) + 1;
613 if ((mailboxlen & 0x01) == 0) {
614 ++mailboxlen;
615 fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws.";
618 bzero(buffer, maxcnt);
619 smb_msgbuf_init(&mb, buffer, maxcnt, 0);
621 result = smb_msgbuf_encode(&mb, fmt,
622 SMB_COM_TRANSACTION, /* Command */
623 0x18,
624 0x3,
625 17, /* Count of parameter words */
626 0, /* Total Parameter words sent */
627 data_count, /* Total Data bytes sent */
628 2, /* Max Parameters to return */
629 0, /* Max data bytes to return */
630 0, /* Max setup bytes to return */
631 reply, /* No reply */
632 0xffffffff, /* Timeout */
633 0, /* Parameter bytes sent */
634 0, /* Parameter offset */
635 data_count, /* Data bytes sent */
636 69 + mailboxlen, /* Data offset */
637 3, /* Setup word count */
638 1, /* Setup word[0] */
639 0, /* Setup word[1] */
640 class, /* Setup word[2] */
641 mailboxlen + data_count, /* Total request bytes */
642 mailbox); /* Mailbox address */
644 smb_msgbuf_term(&mb);
645 return (result);
648 static int
649 smb_browser_addr_of_subnet(struct name_entry *name, smb_hostinfo_t *hinfo,
650 struct name_entry *result)
652 uint32_t ipaddr, mask, saddr;
653 addr_entry_t *addr;
655 if (name == NULL)
656 return (-1);
658 if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS)
659 return (-1);
661 ipaddr = hinfo->hi_nic.nic_ip.a_ipv4;
662 mask = hinfo->hi_nic.nic_mask;
664 *result = *name;
665 addr = &name->addr_list;
666 do {
667 saddr = addr->sin.sin_addr.s_addr;
668 if ((saddr & mask) == (ipaddr & mask)) {
669 *result = *name;
670 result->addr_list = *addr;
671 result->addr_list.forw = result->addr_list.back =
672 &result->addr_list;
673 return (0);
675 addr = addr->forw;
676 } while (addr != &name->addr_list);
678 return (-1);
682 static int
683 smb_browser_bcast_addr_of_subnet(struct name_entry *name, uint32_t bcast,
684 struct name_entry *result)
686 if (name != NULL && name != result)
687 *result = *name;
689 result->addr_list.sin.sin_family = AF_INET;
690 result->addr_list.sinlen = sizeof (result->addr_list.sin);
691 result->addr_list.sin.sin_addr.s_addr = bcast;
692 result->addr_list.sin.sin_port = htons(IPPORT_NETBIOS_DGM);
693 result->addr_list.forw = result->addr_list.back = &result->addr_list;
694 return (0);
698 * 6.5 HostAnnouncement Browser Frame
700 * To advertise its presence, i.e. to publish itself as being available, a
701 * non-browser server sends a HostAnnouncement browser frame. If the server
702 * is a member of domain "D", this frame is sent to the NETBIOS unique name
703 * D(1d) and mailslot "\\MAILSLOT\\BROWSE". The definition of the
704 * HostAnnouncement frame is:
706 * struct {
707 * unsigned short Opcode;
708 * unsigned char UpdateCount;
709 * uint32_t Periodicity;
710 * unsigned char ServerName[];
711 * unsigned char VersionMajor;
712 * unsigned char VersionMinor;
713 * uint32_t Type;
714 * uint32_t Signature;
715 * unsigned char Comment[];
718 * where:
719 * Opcode - Identifies this structure as a browser server
720 * announcement and is defined as HostAnnouncement with a
721 * value of decimal 1.
723 * UpdateCount - must be sent as zero and ignored on receipt.
725 * Periodicity - The announcement frequency of the server (in
726 * seconds). The server will be removed from the browse list
727 * if it has not been heard from in 3X its announcement
728 * frequency. In no case will the server be removed from the
729 * browse list before the period 3X has elapsed. Actual
730 * implementations may take more than 3X to actually remove
731 * the server from the browse list.
733 * ServerName - Null terminated ASCII server name (up to 16 bytes
734 * in length).
736 * VersionMajor - The major version number of the OS the server
737 * is running. it will be returned by NetServerEnum2.
739 * VersionMinor - The minor version number of the OS the server
740 * is running. This is entirely informational and does not
741 * have any significance for the browsing protocol.
743 * Type - Specifies the type of the server. The server type bits
744 * are specified in the NetServerEnum2 section.
746 * Signature - The browser protocol minor version number in the
747 * low 8 bits, the browser protocol major version number in
748 * the next higher 8 bits and the signature 0xaa55 in the
749 * high 16 bits of this field. Thus, for this version of the
750 * browser protocol (1.15) this field has the value
751 * 0xaa55010f. This may used to isolate browser servers that
752 * are running out of revision browser software; otherwise,
753 * it is ignored.
755 * Comment - Null terminated ASCII comment for the server.
756 * Limited to 43 bytes.
758 * When a non-browser server starts up, it announces itself in the manner
759 * described once every minute. The frequency of these statements is
760 * gradually stretched to once every 12 minutes.
762 * Note: older non-browser servers in a domain "D" sent HostAnnouncement
763 * frames to the NETBIOS group name D(00). Non-Browser servers supporting
764 * version 1.15 of the browsing protocol SHOULD NOT use this NETBIOS name,
765 * but for backwards compatibility Master Browsers MAY receive and process
766 * HostAnnouncement frames on this name as described above for D(1d).
769 static void
770 smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo,
771 uint32_t next_announcement, boolean_t remove,
772 addr_entry_t *addr, char suffix)
774 smb_msgbuf_t mb;
775 int offset, announce_len, data_length;
776 struct name_entry dest_name;
777 unsigned char *buffer;
778 uint32_t type;
779 char resource_domain[SMB_PI_MAX_DOMAIN];
781 if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
782 return;
783 (void) smb_strupr(resource_domain);
785 if (addr == NULL) {
786 /* Local master Browser */
787 smb_init_name_struct((unsigned char *)resource_domain, suffix,
788 0, 0, 0, 0, 0, &dest_name);
789 if (smb_browser_bcast_addr_of_subnet(0, hinfo->hi_nic.nic_bcast,
790 &dest_name) < 0)
791 return;
792 } else {
793 smb_init_name_struct((unsigned char *)resource_domain, suffix,
794 0, 0, 0, 0, 0, &dest_name);
795 dest_name.addr_list = *addr;
796 dest_name.addr_list.forw = dest_name.addr_list.back =
797 &dest_name.addr_list;
800 /* give some extra room */
801 buffer = malloc(MAX_DATAGRAM_LENGTH * 2);
802 if (buffer == NULL) {
803 syslog(LOG_DEBUG, "smb browser: HostAnnouncement: %m");
804 return;
807 data_length = 1 + 1 + 4 + 16 + 1 + 1 + 4 + 4 +
808 strlen(hinfo->hi_nic.nic_cmnt) + 1;
810 offset = smb_browser_load_transact_header(buffer,
811 MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION,
812 MAILSLOT_BROWSE);
814 if (offset < 0) {
815 free(buffer);
816 return;
820 * A non-browser server SHOULD send a HostAnnouncement browser frame
821 * specifying a type of 0 just prior to shutting down, to allow it to
822 * quickly be removed from the list of available servers.
824 if (remove || (!smb_netbios_running()))
825 type = 0;
826 else
827 type = hinfo->hi_type;
829 smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0);
831 announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls",
832 HOST_ANNOUNCEMENT,
833 ++hinfo->hi_updatecnt,
834 next_announcement * 60000, /* Periodicity in MilliSeconds */
835 hinfo->hi_nbname,
836 (uint8_t)hinfo->hi_version.sv_major,
837 (uint8_t)hinfo->hi_version.sv_minor,
838 type,
839 SMB_SERVER_SIGNATURE,
840 hinfo->hi_nic.nic_cmnt);
842 if (announce_len > 0)
843 (void) smb_netbios_datagram_send(&hinfo->hi_netname, &dest_name,
844 buffer, offset + announce_len);
846 free(buffer);
847 smb_msgbuf_term(&mb);
850 static void
851 smb_browser_process_AnnouncementRequest(struct datagram *datagram,
852 char *mailbox)
854 smb_hostinfo_t *hinfo;
855 uint32_t next_announcement;
856 uint32_t delay = random() % 29; /* in seconds */
857 boolean_t h_found = B_FALSE;
859 if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) {
860 syslog(LOG_DEBUG, "smb browser: wrong mailbox (%s)", mailbox);
861 return;
864 smb_netbios_sleep(delay);
866 (void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
867 hinfo = list_head(&smb_binfo.bi_hlist);
868 while (hinfo) {
869 if ((hinfo->hi_nic.nic_ip.a_ipv4 &
870 hinfo->hi_nic.nic_mask) ==
871 (datagram->src.addr_list.sin.sin_addr.s_addr &
872 hinfo->hi_nic.nic_mask)) {
873 h_found = B_TRUE;
874 break;
876 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
879 if (h_found) {
880 next_announcement = hinfo->hi_nextannouce * 60 * 1000;
881 smb_browser_send_HostAnnouncement(hinfo, next_announcement,
882 B_FALSE, &datagram->src.addr_list, NBT_MB);
884 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
887 void *
888 smb_browser_dispatch(void *arg)
890 struct datagram *datagram = (struct datagram *)arg;
891 smb_msgbuf_t mb;
892 int rc;
893 unsigned char command;
894 unsigned char parameter_words;
895 unsigned short total_parameter_words;
896 unsigned short total_data_count;
897 unsigned short max_parameters_to_return;
898 unsigned short max_data_to_return;
899 unsigned char max_setup_bytes_to_return;
900 unsigned short reply;
901 unsigned short parameter_bytes_sent;
902 unsigned short parameter_offset;
903 unsigned short data_bytes_sent;
904 unsigned short data_offset;
905 unsigned char setup_word_count;
906 unsigned short setup_word_0;
907 unsigned short setup_word_1;
908 unsigned short setup_word_2;
909 unsigned short total_request_bytes;
910 char *mailbox;
911 unsigned char message_type;
912 unsigned char *data;
913 int datalen;
915 syslog(LOG_DEBUG, "smb browser: packet received");
917 smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0);
918 rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws",
919 &command, /* Command */
920 &parameter_words, /* Count of parameter words */
921 &total_parameter_words, /* Total Parameter words sent */
922 &total_data_count, /* Total Data bytes sent */
923 &max_parameters_to_return, /* Max Parameters to return */
924 &max_data_to_return, /* Max data bytes to return */
925 &max_setup_bytes_to_return, /* Max setup bytes to return */
926 &reply, /* No reply */
927 &parameter_bytes_sent, /* Parameter bytes sent */
928 &parameter_offset, /* Parameter offset */
929 &data_bytes_sent, /* Data bytes sent */
930 &data_offset, /* Data offset */
931 &setup_word_count, /* Setup word count */
932 &setup_word_0, /* Setup word[0] */
933 &setup_word_1, /* Setup word[1] */
934 &setup_word_2, /* Setup word[2] */
935 &total_request_bytes, /* Total request bytes */
936 &mailbox); /* Mailbox address */
938 if (rc < 0) {
939 syslog(LOG_ERR, "smb browser: decode error");
940 smb_msgbuf_term(&mb);
941 free(datagram);
942 return (0);
945 data = &datagram->data[data_offset];
946 datalen = datagram->data_length - data_offset;
949 * The PDC location protocol, i.e. anything on the \\NET
950 * mailslot, is handled by the smb_netlogon module.
952 if (strncasecmp("\\MAILSLOT\\NET\\", mailbox, 14) == 0) {
953 smb_netlogon_receive(datagram, mailbox, data, datalen);
954 smb_msgbuf_term(&mb);
955 free(datagram);
956 return (0);
960 * If it's not a netlogon message, assume it's a browser request.
961 * This is not the most elegant way to extract the command byte
962 * but at least we no longer use it to get the netlogon opcode.
964 message_type = datagram->data[data_offset];
966 switch (message_type) {
967 case ANNOUNCEMENT_REQUEST :
968 smb_browser_process_AnnouncementRequest(datagram, mailbox);
969 break;
971 default:
972 syslog(LOG_DEBUG, "smb browser: invalid message type(%d, %x)",
973 message_type, message_type);
974 break;
977 smb_msgbuf_term(&mb);
978 free(datagram);
979 return (0);
984 * 11.1 Registered unique names
986 * <COMPUTER>(00)
987 * This name is used by all servers and clients to receive second
988 * class mailslot messages. A system must add this name in order to
989 * receive mailslot messages. The only browser requests that should
990 * appear on this name are BecomeBackup, GetBackupListResp,
991 * MasterAnnouncement, and LocalMasterAnnouncement frames. All other
992 * datagrams (other than the expected non-browser datagrams) may be
993 * ignored and an error logged.
995 * <DOMAIN>(1d)
996 * This name is used to identify a master browser server for domain
997 * "DOMAIN" on a subnet. A master browser server adds this name as a
998 * unique NETBIOS name when it becomes master browser. If the attempt
999 * to add the name fails, the master browser server assumes that there
1000 * is another master in the domain and will fail to come up. It may
1001 * log an error if the failure occurs more than 3 times in a row (this
1002 * either indicates some form of network misconfiguration or a
1003 * software error). The only requests that should appear on this name
1004 * are GetBackupListRequest and HostAnnouncement requests. All other
1005 * datagrams on this name may be ignored (and an error logged). If
1006 * running a NETBIOS name service (NBNS, such as WINS), this name
1007 * should not be registered with the NBNS.
1009 * <DOMAIN>(1b)
1010 * This name is used to identify the Domain Master Browser for domain
1011 * "DOMAIN" (which is also the primary domain controller). It is a
1012 * unique name added only by the primary domain controller. The
1013 * primary domain controller will respond to GetBackupListRequest on
1014 * this name just as it responds to these requests on the <DOMAIN>(1d)
1015 * name.
1017 * 11.2 Registered group names
1019 * (01)(02)__MSBROWSE__(02)(01)
1020 * This name is used by Master Browsers to announce themselves to the
1021 * other Master Browsers on a subnet. It is added as a group name by
1022 * all Master Browser servers. The only broadcasts that should appear
1023 * on this name is DomainAnnouncement requests. All other datagrams
1024 * can be ignored.
1026 * <DOMAIN>(00)
1027 * This name is used by clients and servers in domain "DOMAIN" to
1028 * process server announcements. The only requests that should appear
1029 * on this name that the browser is interested in are
1030 * AnnouncementRequest and NETLOGON_QUERY (to locate the PDC) packets.
1031 * All other unidentifiable requests may be ignored (and an error
1032 * logged).
1034 * <DOMAIN>(1E)
1035 * This name is used for announcements to browsers for domain "DOMAIN"
1036 * on a subnet. This name is registered by all the browser servers in
1037 * the domain. The only requests that should appear on this name are
1038 * RequestElection and AnnouncementRequest packets. All other
1039 * datagrams may be ignored (and an error logged).
1041 * <DOMAIN>(1C)
1042 * This name is registered by Primary Domain Controllers.
1045 static void
1046 smb_browser_config(void)
1048 smb_hostinfo_t *hinfo;
1049 struct name_entry name;
1050 struct name_entry master;
1051 struct name_entry dest;
1052 struct name_entry *entry;
1053 char resource_domain[SMB_PI_MAX_DOMAIN];
1054 int rc;
1056 if (smb_browser_init() != 0)
1057 return;
1059 if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1060 return;
1061 (void) smb_strupr(resource_domain);
1063 /* domain<00> */
1064 smb_init_name_struct((unsigned char *)resource_domain, NBT_WKSTA,
1065 0, 0, 0, 0, 0, &name);
1066 entry = smb_name_find_name(&name);
1067 smb_name_unlock_name(entry);
1069 (void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
1070 hinfo = list_head(&smb_binfo.bi_hlist);
1071 while (hinfo) {
1072 smb_init_name_struct((unsigned char *)resource_domain,
1073 NBT_WKSTA, 0, hinfo->hi_nic.nic_ip.a_ipv4,
1074 htons(IPPORT_NETBIOS_DGM), NAME_ATTR_GROUP,
1075 NAME_ATTR_LOCAL, &name);
1076 (void) smb_name_add_name(&name);
1078 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1080 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1082 /* All our local master browsers */
1083 smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
1084 0, 0, 0, 0, 0, &dest);
1085 entry = smb_name_find_name(&dest);
1087 if (entry) {
1088 (void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
1089 hinfo = list_head(&smb_binfo.bi_hlist);
1090 while (hinfo) {
1091 rc = smb_browser_addr_of_subnet(entry, hinfo, &master);
1092 if (rc == 0) {
1093 syslog(LOG_DEBUG,
1094 "smb browser: master browser found at %s",
1095 inet_ntoa(master.addr_list.sin.sin_addr));
1097 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1099 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1101 smb_name_unlock_name(entry);
1104 /* Domain master browser */
1105 smb_init_name_struct((unsigned char *)resource_domain,
1106 NBT_DMB, 0, 0, 0, 0, 0, &dest);
1108 if ((entry = smb_name_find_name(&dest)) != 0) {
1109 syslog(LOG_DEBUG,
1110 "smb browser: domain master browser for %s is %s",
1111 resource_domain,
1112 inet_ntoa(entry->addr_list.sin.sin_addr));
1113 smb_name_unlock_name(entry);
1117 static int
1118 smb_browser_init(void)
1120 smb_hostinfo_t *hinfo;
1121 smb_niciter_t ni;
1122 uint32_t type;
1123 smb_version_t version;
1125 smb_config_get_version(&version);
1127 (void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
1128 smb_browser_infofree();
1130 if (smb_nic_getfirst(&ni) != SMB_NIC_SUCCESS) {
1131 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1132 return (-1);
1135 type = MY_SERVER_TYPE;
1136 if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)
1137 type |= SV_DOMAIN_MEMBER;
1139 do {
1140 if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
1141 (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS))
1142 continue;
1144 hinfo = malloc(sizeof (smb_hostinfo_t));
1145 if (hinfo == NULL) {
1146 smb_browser_infofree();
1147 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1148 return (-1);
1151 hinfo->hi_nic = ni.ni_nic;
1152 /* One Minute announcements for first five */
1153 hinfo->hi_nextannouce = 1;
1154 hinfo->hi_interval = 1;
1155 hinfo->hi_reps = 5;
1156 hinfo->hi_updatecnt = 0;
1157 hinfo->hi_type = type;
1158 hinfo->hi_version = version;
1160 /* This is the name used for HostAnnouncement */
1161 (void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host,
1162 NETBIOS_NAME_SZ);
1163 (void) smb_strupr(hinfo->hi_nbname);
1164 /* 0x20: file server service */
1165 smb_init_name_struct((unsigned char *)hinfo->hi_nbname,
1166 NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4,
1167 htons(IPPORT_NETBIOS_DGM),
1168 NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
1169 &hinfo->hi_netname);
1171 list_insert_tail(&smb_binfo.bi_hlist, hinfo);
1172 smb_binfo.bi_hcnt++;
1173 } while (smb_nic_getnext(&ni) == SMB_NIC_SUCCESS);
1175 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1176 return (0);
1180 * smb_browser_non_master_duties
1182 * To advertise its presence, i.e. to publish itself as being available, a
1183 * non-browser server sends a HostAnnouncement browser frame. If the server
1184 * is a member of domain "D", this frame is sent to the NETBIOS unique name
1185 * D(1d) and mailslot "\\MAILSLOT\\BROWSE".
1187 static void
1188 smb_browser_non_master_duties(smb_hostinfo_t *hinfo, boolean_t remove)
1190 struct name_entry name;
1191 struct name_entry *dest;
1192 addr_entry_t addr;
1193 char resource_domain[SMB_PI_MAX_DOMAIN];
1195 smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
1196 remove, 0, NBT_MB);
1197 if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1198 return;
1200 (void) smb_strupr(resource_domain);
1202 smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
1203 0, 0, 0, 0, 0, &name);
1205 if ((dest = smb_name_find_name(&name))) {
1206 addr = dest->addr_list;
1207 addr.forw = addr.back = &addr;
1208 smb_name_unlock_name(dest);
1209 smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
1210 remove, &addr, NBT_MB);
1211 } else {
1212 smb_init_name_struct((unsigned char *)resource_domain,
1213 NBT_DMB, 0, 0, 0, 0, 0, &name);
1214 if ((dest = smb_name_find_name(&name))) {
1215 addr = dest->addr_list;
1216 addr.forw = addr.back = &addr;
1217 smb_name_unlock_name(dest);
1218 smb_browser_send_HostAnnouncement(hinfo,
1219 remove, hinfo->hi_interval, &addr, NBT_DMB);
1224 * One Minute announcements for first five
1225 * minutes, one minute longer each round
1226 * until 12 minutes and every 12 minutes
1227 * thereafter.
1229 if (--hinfo->hi_reps == 0) {
1230 if (hinfo->hi_interval < 12)
1231 hinfo->hi_interval++;
1233 hinfo->hi_reps = 1;
1236 hinfo->hi_nextannouce = hinfo->hi_interval;
1241 * SMB NetBIOS Browser Service
1243 /*ARGSUSED*/
1244 void *
1245 smb_browser_service(void *arg)
1247 smb_hostinfo_t *hinfo;
1249 smb_browser_infoinit();
1250 smb_browser_config();
1252 smb_netbios_event(NETBIOS_EVENT_BROWSER_START);
1254 restart:
1255 do {
1256 (void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
1257 hinfo = list_head(&smb_binfo.bi_hlist);
1259 while (hinfo) {
1260 if (--hinfo->hi_nextannouce > 0 ||
1261 hinfo->hi_nic.nic_bcast == 0) {
1262 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1263 continue;
1266 smb_browser_non_master_duties(hinfo, B_FALSE);
1268 /* Check to see whether reconfig is needed */
1269 (void) mutex_lock(&smb_binfo.bi_mtx);
1270 if (smb_binfo.bi_changed) {
1271 smb_binfo.bi_changed = B_FALSE;
1272 (void) mutex_unlock(&smb_binfo.bi_mtx);
1273 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1274 smb_browser_config();
1275 goto restart;
1277 (void) mutex_unlock(&smb_binfo.bi_mtx);
1279 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1282 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1283 smb_netbios_sleep(SECSPERMIN); /* 1 minute */
1284 } while (smb_netbios_running());
1286 smb_browser_infoterm();
1287 smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP);
1288 return (0);
1292 * smb_browser_netlogon
1294 * Sends SAMLOGON/NETLOGON request for all host/ips, except
1295 * aliases, to find a domain controller.
1297 * The dc argument will be set if a DC is found.
1299 boolean_t
1300 smb_browser_netlogon(char *domain, char *dc, uint32_t dc_len)
1302 smb_hostinfo_t *hinfo;
1303 boolean_t found = B_FALSE;
1304 timestruc_t to;
1305 int err;
1307 (void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
1308 hinfo = list_head(&smb_binfo.bi_hlist);
1309 while (hinfo) {
1310 if ((hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) == 0)
1311 smb_netlogon_request(&hinfo->hi_netname, domain);
1312 hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1314 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1316 bzero(dc, dc_len);
1317 to.tv_sec = 30;
1318 to.tv_nsec = 0;
1319 (void) mutex_lock(&ntdomain_mtx);
1320 while (ntdomain_info.n_ipaddr == 0) {
1321 err = cond_reltimedwait(&ntdomain_cv, &ntdomain_mtx, &to);
1322 if (err == ETIME)
1323 break;
1326 if (ntdomain_info.n_ipaddr != 0) {
1327 (void) strlcpy(dc, ntdomain_info.n_name, dc_len);
1328 found = B_TRUE;
1330 (void) mutex_unlock(&ntdomain_mtx);
1332 return (found);
1336 * smb_browser_infoinit
1338 * This function is called only once when the browser starts
1339 * to initialize the global smb_binfo structure.
1341 static void
1342 smb_browser_infoinit(void)
1344 (void) mutex_lock(&ntdomain_mtx);
1345 bzero(&ntdomain_info, sizeof (ntdomain_info));
1346 (void) mutex_unlock(&ntdomain_mtx);
1348 (void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
1349 list_create(&smb_binfo.bi_hlist, sizeof (smb_hostinfo_t),
1350 offsetof(smb_hostinfo_t, hi_lnd));
1351 smb_binfo.bi_hcnt = 0;
1352 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1354 (void) mutex_lock(&smb_binfo.bi_mtx);
1355 smb_binfo.bi_changed = B_FALSE;
1356 (void) mutex_unlock(&smb_binfo.bi_mtx);
1360 * smb_browser_infoterm
1362 * This function is called only once when the browser stops
1363 * to destroy the smb_binfo structure.
1365 static void
1366 smb_browser_infoterm(void)
1368 (void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
1369 smb_browser_infofree();
1370 list_destroy(&smb_binfo.bi_hlist);
1371 (void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1375 * smb_browser_infofree
1377 * Removes all the hostinfo structures from the browser list
1378 * and frees the allocated memory
1380 static void
1381 smb_browser_infofree(void)
1383 smb_hostinfo_t *hinfo;
1385 while ((hinfo = list_head(&smb_binfo.bi_hlist)) != NULL) {
1386 list_remove(&smb_binfo.bi_hlist, hinfo);
1387 free(hinfo);
1390 smb_binfo.bi_hcnt = 0;