xref: /illumos-gate/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c (revision 9fb67ea305c66b6a297583b9b0db6796b0dfe497)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26a0aa776eSAlan Wright #include <sys/tzfile.h>
278d7e4166Sjose borrego #include <errno.h>
28da6c28aaSamw #include <stdlib.h>
29da6c28aaSamw #include <stdio.h>
30da6c28aaSamw #include <unistd.h>
31da6c28aaSamw #include <syslog.h>
32da6c28aaSamw #include <string.h>
33da6c28aaSamw #include <strings.h>
34da6c28aaSamw #include <time.h>
35da6c28aaSamw #include <synch.h>
36da6c28aaSamw #include <netdb.h>
37da6c28aaSamw #include <sys/socket.h>
38da6c28aaSamw #include <arpa/inet.h>
39da6c28aaSamw 
40dc20a302Sas #include <smbsrv/libsmb.h>
41da6c28aaSamw #include <smbsrv/libsmbns.h>
42bbf6f00cSJordan Brown #include <smbsrv/smb.h>
43da6c28aaSamw #include <smbsrv/mailslot.h>
44da6c28aaSamw #include <smbns_browser.h>
45da6c28aaSamw #include <smbns_netbios.h>
46da6c28aaSamw 
478d7e4166Sjose borrego /*
488d7e4166Sjose borrego  * ntdomain_info
498d7e4166Sjose borrego  * Temporary. It should be removed once NBTD is integrated.
508d7e4166Sjose borrego  */
518d7e4166Sjose borrego smb_ntdomain_t ntdomain_info;
528d7e4166Sjose borrego mutex_t ntdomain_mtx;
538d7e4166Sjose borrego cond_t ntdomain_cv;
548d7e4166Sjose borrego 
55da6c28aaSamw #define	SMB_SERVER_SIGNATURE		0xaa550415
56da6c28aaSamw 
577b59d02dSjb typedef struct smb_hostinfo {
587b59d02dSjb 	list_node_t	hi_lnd;
597b59d02dSjb 	smb_nic_t	hi_nic;
607b59d02dSjb 	char		hi_nbname[NETBIOS_NAME_SZ];
617b59d02dSjb 	name_entry_t	hi_netname;
627b59d02dSjb 	uint32_t	hi_nextannouce;
637b59d02dSjb 	int		hi_reps;
647b59d02dSjb 	int		hi_interval;
657b59d02dSjb 	uint8_t		hi_updatecnt;
667b59d02dSjb 	uint32_t	hi_type;
67*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_version_t	hi_version;
687b59d02dSjb } smb_hostinfo_t;
697b59d02dSjb 
707b59d02dSjb typedef struct smb_browserinfo {
717b59d02dSjb 	list_t		bi_hlist;
727b59d02dSjb 	int		bi_hcnt;
737b59d02dSjb 	rwlock_t	bi_hlist_rwl;
747b59d02dSjb 	boolean_t	bi_changed;
757b59d02dSjb 	mutex_t		bi_mtx;
767b59d02dSjb } smb_browserinfo_t;
777b59d02dSjb 
787b59d02dSjb static smb_browserinfo_t smb_binfo;
797b59d02dSjb 
807b59d02dSjb static int smb_browser_init(void);
817b59d02dSjb static void smb_browser_infoinit(void);
827b59d02dSjb static void smb_browser_infoterm(void);
837b59d02dSjb static void smb_browser_infofree(void);
84da6c28aaSamw 
858d7e4166Sjose borrego 
867b59d02dSjb void
877b59d02dSjb smb_browser_reconfig(void)
88da6c28aaSamw {
897b59d02dSjb 	(void) mutex_lock(&smb_binfo.bi_mtx);
907b59d02dSjb 	smb_binfo.bi_changed = B_TRUE;
917b59d02dSjb 	(void) mutex_unlock(&smb_binfo.bi_mtx);
92da6c28aaSamw }
93da6c28aaSamw 
94da6c28aaSamw /*
95da6c28aaSamw  * 3. Browser Overview
96da6c28aaSamw  *
97da6c28aaSamw  * Hosts involved in the browsing process can be separated into two
98da6c28aaSamw  * distinct groups, browser clients and browser servers (often referred to
99da6c28aaSamw  * simply as "browsers").
100da6c28aaSamw  *
101da6c28aaSamw  * A browser is a server which maintains information about servers -
102da6c28aaSamw  * primarily the domain they are in and the services that they are running
103da6c28aaSamw  * -- and about domains. Browsers may assume several different roles in
104da6c28aaSamw  * their lifetimes, and dynamically switch between them.
105da6c28aaSamw  *
106da6c28aaSamw  *  Browser clients are of two types: workstations and (non-browser)
107da6c28aaSamw  * servers. In the context of browsing, workstations query browsers for the
108da6c28aaSamw  * information they contain; servers supply browsers the information by
109da6c28aaSamw  * registering with them. Note that, at times, browsers may themselves
110da6c28aaSamw  * behave as browser clients and query other browsers.
111da6c28aaSamw  *
112da6c28aaSamw  * For the purposes of this specification, a domain is simply a name with
113da6c28aaSamw  * which to associate a group of resources such as computers, servers and
114da6c28aaSamw  * users. Domains allow a convenient means for browser clients to restrict
115da6c28aaSamw  * the scope of a search when they query browser servers. Every domain has
116da6c28aaSamw  * a "master" server called the Primary Domain Controller (PDC) that
117da6c28aaSamw  * manages various  activities within the domain.
118da6c28aaSamw  *
119da6c28aaSamw  * One browser for each domain on a subnet is designated the Local Master
120da6c28aaSamw  * Browser for that domain. Servers in its domain on the subnet register
121da6c28aaSamw  * with it, as do the Local Master Browsers for other domains on the
122da6c28aaSamw  * subnet. It uses these registrations to maintain authoritative
123da6c28aaSamw  * information about its domain on its subnet. If there are other subnets
124da6c28aaSamw  * in the network, it also knows the name of the server running the
125da6c28aaSamw  * domain's Domain Master Browser; it registers with it, and uses it to
126da6c28aaSamw  * obtain information about the rest of the network (see below).
127da6c28aaSamw  *
128da6c28aaSamw  * Clients on a subnet query browsers designated as the Backup Browsers for
129da6c28aaSamw  * the subnet (not the Master Browser). Backup Browsers maintain a copy of
130da6c28aaSamw  * the information on the Local Master Browser; they get it by periodically
131da6c28aaSamw  * querying the Local Master Browser for all of its information. Clients
132da6c28aaSamw  * find the Backup Browsers by asking the Local Master Browser. Clients are
133da6c28aaSamw  * expected to spread their queries evenly across Backup Browsers to
134da6c28aaSamw  * balance the load.
135da6c28aaSamw  *
136da6c28aaSamw  * The Local Master Browser is dynamically elected automatically. Multiple
137da6c28aaSamw  * Backup Browser Servers may exist per subnet; they are selected from
138da6c28aaSamw  * among the potential browser servers by the Local Master Browser, which
139da6c28aaSamw  * is configured to select enough to handle the expected query load.
140da6c28aaSamw  *
141da6c28aaSamw  * When there are multiple subnets, a Domain Master Browser is assigned
142da6c28aaSamw  * the task of keeping the multiple subnets in synchronization. The Primary
143da6c28aaSamw  * Domain Controller (PDC) always acts as the Domain Master Browser. The
144da6c28aaSamw  * Domain Master Browser periodically acts as a client and queries all the
145da6c28aaSamw  * Local Master Browsers for its domain, asking them for a list containing
146da6c28aaSamw  * all the domains and all the servers in their domain known within their
147da6c28aaSamw  * subnets; it merges all the replies into a single master list. This
148da6c28aaSamw  * allows a Domain Master Browser server to act as a collection point for
149da6c28aaSamw  * inter-subnet browsing information. Local Master Browsers periodically
150da6c28aaSamw  * query the Domain Master Browser to retrieve the network-wide information
151da6c28aaSamw  * it maintains.
152da6c28aaSamw  *
153da6c28aaSamw  * When a domain spans only a single subnet, there will not be any distinct
154da6c28aaSamw  * Local Master Browser; this role will be handled by the Domain Master
155da6c28aaSamw  * Browser. Similarly, the Domain Master Browser is always the Local Master
156da6c28aaSamw  * Browser for the subnet it is on.
157da6c28aaSamw  *
158da6c28aaSamw  * When a browser client suspects that the Local Master Browser has failed,
159da6c28aaSamw  * the client will instigate an election in which the browser servers
160da6c28aaSamw  * participate, and some browser servers may change roles.
161da6c28aaSamw  *
162da6c28aaSamw  * Some characteristics of a good browsing mechanism include:
163da6c28aaSamw  * . minimal network traffic
164da6c28aaSamw  * . minimum server discovery time
165da6c28aaSamw  * . minimum change discovery latency
166da6c28aaSamw  * . immunity to machine failures
167da6c28aaSamw  *
168da6c28aaSamw  * Historically, Browser implementations had been very closely tied to
169da6c28aaSamw  * NETBIOS and datagrams. The early implementations caused a lot of
170da6c28aaSamw  * broadcast traffic. See Appendix D for an overview that presents how the
171da6c28aaSamw  * Browser specification evolved.
172da6c28aaSamw  *
173da6c28aaSamw  * 4. Browsing Protocol Architecture
174da6c28aaSamw  *
175da6c28aaSamw  * This section first describes the how the browsing protocol is layered,
176da6c28aaSamw  * then describes the roles of clients, servers, and browsers in the
177da6c28aaSamw  * browsing subsystem.
178da6c28aaSamw  *
179da6c28aaSamw  * 4.1 Layering of Browsing Protocol Requests
180da6c28aaSamw  *
181da6c28aaSamw  * Most of the browser functionality is implemented using mailslots.
182da6c28aaSamw  * Mailslots provide a mechanism for fast, unreliable unidirectional data
183da6c28aaSamw  * transfer; they are named via ASCII "mailslot (path) name". Mailslots are
184da6c28aaSamw  * implemented using the CIFS Transact SMB which is encapsulated in a
185da6c28aaSamw  * NETBIOS datagram. Browser protocol requests are sent to browser specific
186da6c28aaSamw  * mailslots using some browser-specific NETBIOS names. These datagrams can
187da6c28aaSamw  * either be unicast or broadcast, depending on whether the NETBIOS name is
188da6c28aaSamw  * a "unique name" or a "group name". Various data structures, which are
189da6c28aaSamw  * detailed subsequently within this document, flow as the data portion of
190da6c28aaSamw  * the Transact SMB.
191da6c28aaSamw  *
192da6c28aaSamw  * Here is an example of a generic browser SMB, showing how a browser
193da6c28aaSamw  * request is encapsulated in a TRANSACT SMB request. Note that the PID,
194da6c28aaSamw  * TID, MID, UID, and Flags are all 0 in mailslot requests.
195da6c28aaSamw  *
196da6c28aaSamw  * SMB: C transact, File = \MAILSLOT\BROWSE
197da6c28aaSamw  *   SMB: SMB Status = Error Success
198da6c28aaSamw  *     SMB: Error class = No Error
199da6c28aaSamw  *     SMB: Error code = No Error
200da6c28aaSamw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
201da6c28aaSamw  *     SMB: Tree ID   (TID) = 0 (0x0)
202da6c28aaSamw  *     SMB: Process ID  (PID) = 0 (0x0)
203da6c28aaSamw  *     SMB: User ID   (UID) = 0 (0x0)
204da6c28aaSamw  *     SMB: Multiplex ID (MID) = 0 (0x0)
205da6c28aaSamw  *     SMB: Flags Summary = 0 (0x0)
206da6c28aaSamw  *   SMB: Command = C transact
207da6c28aaSamw  *     SMB: Word count = 17
208da6c28aaSamw  *     SMB: Word parameters
209da6c28aaSamw  *     SMB: Total parm bytes = 0
210da6c28aaSamw  *     SMB: Total data bytes = 33
211da6c28aaSamw  *     SMB: Max parm bytes = 0
212da6c28aaSamw  *     SMB: Max data bytes = 0
213da6c28aaSamw  *     SMB: Max setup words = 0
214da6c28aaSamw  *     SMB: Transact Flags Summary = 0 (0x0)
215da6c28aaSamw  *       SMB: ...............0 = Leave session intact
216da6c28aaSamw  *       SMB: ..............0. = Response required
217da6c28aaSamw  *     SMB: Transact timeout = 0 (0x0)
218da6c28aaSamw  *     SMB: Parameter bytes = 0 (0x0)
219da6c28aaSamw  *     SMB: Parameter offset = 0 (0x0)
220da6c28aaSamw  *     SMB: Data bytes = 33 (0x21)
221da6c28aaSamw  *     SMB: Data offset = 86 (0x56)
222da6c28aaSamw  *     SMB: Setup word count = 3
223da6c28aaSamw  *     SMB: Setup words
224da6c28aaSamw  *     SMB: Mailslot opcode = Write mailslot
225da6c28aaSamw  *     SMB: Transaction priority = 1
226da6c28aaSamw  *     SMB: Mailslot class = Unreliable (broadcast)
227da6c28aaSamw  *     SMB: Byte count = 50
228da6c28aaSamw  *     SMB: Byte parameters
229da6c28aaSamw  *     SMB: Path name = \MAILSLOT\BROWSE
230da6c28aaSamw  *     SMB: Transaction data
231da6c28aaSamw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
232da6c28aaSamw  *
233da6c28aaSamw  * Note the SMB command is Transact, the opcode within the Transact SMB is
234da6c28aaSamw  * Mailslot Write, and the browser data structure is carried as the
235da6c28aaSamw  * Transact data.
236da6c28aaSamw  * The Transaction data begins with an opcode, that signifies the operation
237da6c28aaSamw  * and determines the size and structure of data that follows. This opcode
238da6c28aaSamw  * is named as per one of the below:
239da6c28aaSamw  *
240da6c28aaSamw  * HostAnnouncement         1
241da6c28aaSamw  * AnnouncementRequest      2
242da6c28aaSamw  * RequestElection          8
243da6c28aaSamw  * GetBackupListReq         9
244da6c28aaSamw  * GetBackupListResp        10
245da6c28aaSamw  * BecomeBackup             11
246da6c28aaSamw  * DomainAnnouncment        12
247da6c28aaSamw  * MasterAnnouncement       13
248da6c28aaSamw  * LocalMasterAnnouncement  15
249da6c28aaSamw  *
250da6c28aaSamw  * Browser datagrams are often referred to as simply browser frames. The
251da6c28aaSamw  * frames are in particular, referred to by the name of the opcode within
252da6c28aaSamw  * the Transaction data e.g. a GetBackupListReq browser frame, a
253da6c28aaSamw  * RequestElection browser frame, etc.
254da6c28aaSamw  *
255da6c28aaSamw  * The structures that are sent as the data portion of the Transact SMB are
256da6c28aaSamw  * described in section(s) 6.2 through 6.12 in this document. These
257da6c28aaSamw  * structures are tightly packed, i.e. there are no intervening pad bytes
258da6c28aaSamw  * in the structure, unless they are explicitly described as being there.
259da6c28aaSamw  * All quantities are sent in native Intel format and multi-byte values are
260da6c28aaSamw  * transmitted least significant byte first.
261da6c28aaSamw  *
262da6c28aaSamw  * Besides mailslots and Transaction SMBs, the other important piece of the
263da6c28aaSamw  * browser architecture is the NetServerEnum2 request. This request that
264da6c28aaSamw  * allows an application to interrogate a Browser Server and obtain a
265da6c28aaSamw  * complete list of resources (servers, domains, etc) known to that Browser
266da6c28aaSamw  * server. Details of the NetServerEnum2 request are presented in section
267da6c28aaSamw  * 6.4. Some examples of the NetServerEnum2 request being used are when a
268da6c28aaSamw  * Local Master Browser sends a NetServerEnum2 request to the Domain Master
269da6c28aaSamw  * Browser and vice versa. Another example is when a browser client sends a
270da6c28aaSamw  * NetServerEnum2 request to a Backup Browser server.
271da6c28aaSamw  *
272da6c28aaSamw  * 4.3 Non-Browser Server
273da6c28aaSamw  *
274da6c28aaSamw  * A non-browser server is a server that has some resource(s) or service(s)
275da6c28aaSamw  * it wishes to advertise as being available using the browsing protocol.
276da6c28aaSamw  * Examples of non-browser servers would be an SQL server, print server,
277da6c28aaSamw  * etc.
278da6c28aaSamw  *
279da6c28aaSamw  * A non-browser server MUST periodically send a HostAnnouncement browser
280da6c28aaSamw  * frame, specifying the type of resources or services it is advertising.
281da6c28aaSamw  * Details are in section 6.5.
282da6c28aaSamw  *
283da6c28aaSamw  * A non-browser server SHOULD announce itself relatively frequently when
284da6c28aaSamw  * it first starts up in order to make its presence quickly known to the
285da6c28aaSamw  * browsers and thence to potential clients. The frequency of the
286da6c28aaSamw  * announcements SHOULD then be gradually stretched, so as to minimize
287da6c28aaSamw  * network traffic. Typically,  non-browser servers announce themselves
288da6c28aaSamw  * once every minute upon start up and then gradually adjust the frequency
289da6c28aaSamw  * of the announcements to once every 12 minutes.
290da6c28aaSamw  *
291da6c28aaSamw  * A non-browser server SHOULD send a HostAnnouncement browser frame
292da6c28aaSamw  * specifying a type of  0 just prior to shutting down, to allow it to
293da6c28aaSamw  * quickly be removed from the list of available servers.
294da6c28aaSamw  *
295da6c28aaSamw  * A non-browser server MUST receive and process AnnouncementRequest frames
296da6c28aaSamw  * from the Local Master Browser, and MUST respond with a HostAnnouncement
297da6c28aaSamw  * frame, after a delay chosen randomly from the interval [0,30] seconds.
298da6c28aaSamw  * AnnouncementRequests typically happen when a Local Master Browser starts
299da6c28aaSamw  * up with an empty list of servers for the domain, and wants to fill it
300da6c28aaSamw  * quickly. The 30 second range for responses prevents the Master Browser
301da6c28aaSamw  * from becoming overloaded and losing replies, as well as preventing the
302da6c28aaSamw  * network from being flooded with responses.
303da6c28aaSamw  *
304da6c28aaSamw  * 4.4  Browser Servers
305da6c28aaSamw  *
306da6c28aaSamw  * The following sections describe the roles of the various types of
307da6c28aaSamw  * browser servers.
308da6c28aaSamw  *
309da6c28aaSamw  * 4.4.1  Potential Browser Server
310da6c28aaSamw  *
311da6c28aaSamw  * A Potential Browser server is a browser server that is capable of being
312da6c28aaSamw  * a Backup Browser server or Master Browser server, but is not currently
313da6c28aaSamw  * fulfilling either of those roles.
314da6c28aaSamw  *
315da6c28aaSamw  * A Potential Browser MUST set type SV_TYPE_POTENTIAL_BROWSER (see section
316da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
317da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
318da6c28aaSamw  * type of  0.
319da6c28aaSamw  *
320da6c28aaSamw  * A Potential Browser server MUST receive and process BecomeBackup frames
321da6c28aaSamw  * (see section 6.9) and become a backup browser upon their receipt.
322da6c28aaSamw  *
323da6c28aaSamw  * A Potential Browser MUST participate in browser elections (see section
324da6c28aaSamw  * 6.8).
325da6c28aaSamw  *
326da6c28aaSamw  * 4.4.2  Backup Browser
327da6c28aaSamw  *
328da6c28aaSamw  * Backup Browser servers are a subset of the Potential Browsers that have
329da6c28aaSamw  * been chosen by the Master Browser on their subnet to be the Backup
330da6c28aaSamw  * Browsers for the subnet.
331da6c28aaSamw  *
332da6c28aaSamw  * A Backup Browser MUST set type SV_TYPE_BACKUP_BROWSER (see section
333da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
334da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
335da6c28aaSamw  * type of  0.
336da6c28aaSamw  *
337da6c28aaSamw  * A Backup Browser MUST listen for a LocalMasterAnnouncement frame (see
338da6c28aaSamw  * section 6.10) from the Local Master Browser, and use it to set the name
339da6c28aaSamw  * of the Master Browser it queries for the server and domain lists.
340da6c28aaSamw  *
341da6c28aaSamw  * A  Backup Browsers MUST periodically make a NetServerEnum2 request of
342da6c28aaSamw  * the Master Browser on its subnet for its domain to get a list of servers
343da6c28aaSamw  * in that domain, as well as a list of domains. The period is a
344da6c28aaSamw  * configuration option balancing currency of the information with network
345da6c28aaSamw  * traffic costs - a typical value is 15 minutes.
346da6c28aaSamw  *
347da6c28aaSamw  * A Backup Browser SHOULD force an election by sending a RequestElection
348da6c28aaSamw  * frame (see section 6.7) if it does not get a response to its periodic
349da6c28aaSamw  * NetServeEnum2 request to the Master Browser.
350da6c28aaSamw  *
351da6c28aaSamw  * A Backup Browser MUST receive and process NetServerEnum2 requests from
352da6c28aaSamw  * browser clients, for its own domain and others. If the request is for a
353da6c28aaSamw  * list of servers in its domain, or for a list of domains, it can answer
354da6c28aaSamw  * from its internal lists. If the request is for a list of servers in a
355da6c28aaSamw  * domain different than the one it serves, it sends a NetServerEnum2
356da6c28aaSamw  * request to the Domain Master Browser for that domain (which it can in
357da6c28aaSamw  * find in its list of domains and their Domain Master Browsers).
358da6c28aaSamw  *
359da6c28aaSamw  * A Backup Browser MUST participate in browser elections (see section
360da6c28aaSamw  * 6.8).
361da6c28aaSamw  *
362da6c28aaSamw  * 4.4.3 Master Browser
363da6c28aaSamw  *
364da6c28aaSamw  * Master Browsers are responsible for:
365da6c28aaSamw  * . indicating it is a Master Browser
366da6c28aaSamw  * . receiving server announcements and building a list of such servers
367da6c28aaSamw  *   and keeping it reasonably up-to-date.
368da6c28aaSamw  * . returning lists of Backup Browsers to browser clients.
369da6c28aaSamw  * . ensuring an appropriate number of Backup Browsers are available.
370da6c28aaSamw  * . announcing their existence to other Master Browsers on their subnet,
371da6c28aaSamw  *   to the Domain Master Browser for their domain, and to all browsers in
372da6c28aaSamw  *   their domain on their subnet
373da6c28aaSamw  * . forwarding requests for lists of servers on other domains to the
374da6c28aaSamw  *   Master Browser for that domain
375da6c28aaSamw  * . keeping a list of domains in its subnet
376da6c28aaSamw  * . synchronizing with the Domain Master Browser (if any) for its domain
377da6c28aaSamw  * . participating in browser elections
378da6c28aaSamw  * . ensuring that there is only one Master Browser on its subnet
379da6c28aaSamw  *
380da6c28aaSamw  * A Master Browser MUST set type SV_TYPE_MASTER_BROWSER (see section
381da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
382da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
383da6c28aaSamw  * type of  0.
384da6c28aaSamw  *
385da6c28aaSamw  * A Master Browser MUST receive and process HostAnnouncement frames from
386da6c28aaSamw  * servers, adding the server name and other information to its servers
387da6c28aaSamw  * list; it must mark them as "local" entries. Periodically, it MUST check
388da6c28aaSamw  * all local server entries to see if a server's HostAnnouncement has timed
389da6c28aaSamw  * out (no HostAnnouncement received for three times the periodicity the
390da6c28aaSamw  * server gave in the last received HostAnnouncement) and remove timed-out
391da6c28aaSamw  * servers from its list.
392da6c28aaSamw  *
393da6c28aaSamw  * A Master Browser MUST receive and process DomainAnnouncement frames (see
394da6c28aaSamw  * section 6.12) and maintain the domain names and their associated (Local)
395da6c28aaSamw  * Master Browsers in its internal domain list until they time out; it must
396da6c28aaSamw  * mark these as "local" entries. Periodically, it MUST check all local
397da6c28aaSamw  * domain entries to see if a server's DomainAnnouncement has timed out (no
398da6c28aaSamw  * DomainAnnouncement received for three times the periodicity the server
399da6c28aaSamw  * gave in the last received DomainAnnouncement) and remove timed-out
400da6c28aaSamw  * servers from its list.
401da6c28aaSamw  *
402da6c28aaSamw  * A Master Browser MUST receive and process GetBackupListRequest frames
403da6c28aaSamw  * from clients, returning GetBackupListResponse frames containing a list
404da6c28aaSamw  * of the Backup Servers for its domain.
405da6c28aaSamw  *
406da6c28aaSamw  * A Master Browser MUST eventually send BecomeBackup frames (see section
407da6c28aaSamw  * 6.9) to one or more Potential Browser servers to increase the number of
408da6c28aaSamw  * Backup Browsers if there are not enough Backup Browsers to handle the
409da6c28aaSamw  * anticipated query load. Note: possible good times for checking for
410da6c28aaSamw  * sufficient backup browsers are after being elected, when timing out
411da6c28aaSamw  * server HostAnnouncements, and when receiving a server's HostAnnouncement
412da6c28aaSamw  * for the first time.
413da6c28aaSamw  *
414da6c28aaSamw  * A Master Browser MUST periodically announce itself and the domain it
415da6c28aaSamw  * serves to other (Local) Master Browsers on its subnet, by sending a
416da6c28aaSamw  * DomainAnnouncement frame (see section 6.12) to its subnet.
417da6c28aaSamw  *
418da6c28aaSamw  * A Master Browser MUST send a MasterAnnouncement frame (see section 6.11)
419da6c28aaSamw  * to the Domain Master Browser after it is first elected, and periodically
420da6c28aaSamw  * thereafter. This informs the Domain Master Browser of the presence of
421da6c28aaSamw  * all the Master Browsers.
422da6c28aaSamw  *
423da6c28aaSamw  * A Master Browser MUST periodically announce itself to all browsers for
424da6c28aaSamw  * its domain on its subnet by sending a LocalMasterAnnouncement frame (see
425da6c28aaSamw  * section 6.10).
426da6c28aaSamw  *
427da6c28aaSamw  * A Master Browser MUST receive and process NetServerEnum2 requests from
428da6c28aaSamw  * browser clients, for its own domain and others. If the request is for a
429da6c28aaSamw  * list of servers in its domain, or for a list of domains, it can answer
430da6c28aaSamw  * from its internal lists. Entries in its list marked "local" MUST have
431da6c28aaSamw  * the SV_TYPE_LOCAL_LIST_ONLY bit set in the returned results; it must be
432da6c28aaSamw  * clear for all other entries. If the request is for a list of servers in
433da6c28aaSamw  * a domain different than the one it serves, it sends a NetServerEnum2
434da6c28aaSamw  * request to the Domain Master Browser for that domain (which it can in
435da6c28aaSamw  * find in its list of domains and their Domain Master Browsers).
436da6c28aaSamw  *
437da6c28aaSamw  *     Note: The list of servers that the Master Browser maintains and
438da6c28aaSamw  *     returns to the Backup Browsers, is limited in size to 64K of
439da6c28aaSamw  *     data. This will limit the number of systems that can be in a
440da6c28aaSamw  *     browse list in a single workgroup or domain to approximately two
441da6c28aaSamw  *     thousand systems.
442da6c28aaSamw  *
443da6c28aaSamw  * A Master Browser SHOULD request all servers to register with it by
444da6c28aaSamw  * sending an AnnouncementRequest frame, if, on becoming the Master Browser
445da6c28aaSamw  * by winning an election, its server list is empty. Otherwise, clients
446da6c28aaSamw  * might get an incomplete list of servers until the servers' periodic
447da6c28aaSamw  * registrations fill the server list.
448da6c28aaSamw  *
449da6c28aaSamw  * If the Master Browser on a subnet is not the Primary Domain Controller
450da6c28aaSamw  * (PDC), then it is a Local Master Browser.
451da6c28aaSamw  *
452da6c28aaSamw  * A Local Master Browser MUST periodically synchronize with the Domain
453da6c28aaSamw  * Master Browser (which is the PDC). This synchronization is performed by
454da6c28aaSamw  * making a NetServerEnum2 request to the Domain Master Browser and merging
455da6c28aaSamw  * the results with its list of servers and domains. An entry from the
456da6c28aaSamw  * Domain Master Browser should be marked "non-local", and must not
457da6c28aaSamw  * overwrite an entry with the same name marked "local". The Domain Master
458da6c28aaSamw  * Browser is located as specified in Appendix B.
459da6c28aaSamw  *
460da6c28aaSamw  * A Master Browser MUST participate in browser elections (see section
461da6c28aaSamw  * 6.8).
462da6c28aaSamw  *
463da6c28aaSamw  * A Master Browser MUST, if it receives a HostAnnouncement,
464da6c28aaSamw  * DomainAnnouncement, or LocalMasterAnnouncement frame another system that
465da6c28aaSamw  * claims to be the Master Browser for its domain, demote itself from
466da6c28aaSamw  * Master Browser and force an election. This ensures that there is only
467da6c28aaSamw  * ever one Master Browser in each workgroup or domain.
468da6c28aaSamw  *
469da6c28aaSamw  * A Master Browser SHOULD, if it loses an election, become a Backup
470da6c28aaSamw  * Browser (without being told to do so by the new Master Browser). Since
471da6c28aaSamw  * it has more up-to-date information in its lists than a Potential
472da6c28aaSamw  * Browser, it is more efficient to have it be a Backup Browser than to
473da6c28aaSamw  * promote a Potential Browser.
474da6c28aaSamw  *
475da6c28aaSamw  * 4.4.3.1 Preferred Master Browser
476da6c28aaSamw  *
477da6c28aaSamw  * A Preferred Master Browser supports exactly the same protocol elements
478da6c28aaSamw  * as a Potential Browser, except as follows.
479da6c28aaSamw  *
480da6c28aaSamw  * A Preferred Master Browser MUST always force an election when it starts
481da6c28aaSamw  * up.
482da6c28aaSamw  *
483da6c28aaSamw  * A Preferred Master Browser MUST participate in browser elections (see
484da6c28aaSamw  * section 6.8).
485da6c28aaSamw  *
486da6c28aaSamw  * A Preferred Master Browser MUST set the Preferred Master bit in the
487da6c28aaSamw  * RequestElection frame (see section 6.7) to bias the election in its
488da6c28aaSamw  * favor.
489da6c28aaSamw  *
490da6c28aaSamw  * A Preferred Master Browser SHOULD, if it loses an election,
491da6c28aaSamw  * automatically become a Backup Browser, without being told to do so by
492da6c28aaSamw  * the Master Browser.
493da6c28aaSamw  *
494da6c28aaSamw  * 4.4.4 Domain Master Browser
495da6c28aaSamw  *
496da6c28aaSamw  * Since the Domain Master Browser always runs on the PDC, it must
497da6c28aaSamw  * implement all the protocols required of a PDC in addition to the
498da6c28aaSamw  * browsing protocol, and that is way beyond the scope of this
499da6c28aaSamw  * specification.
500da6c28aaSamw  *
501da6c28aaSamw  * 5. Mailslot Protocol Specification
502da6c28aaSamw  *
503da6c28aaSamw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
504da6c28aaSamw  * writes requests are encapsulated in TRANSACT SMBs. The following table
505da6c28aaSamw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
506da6c28aaSamw  * transaction:
507da6c28aaSamw  *
508da6c28aaSamw  *  Name            Value               Description
509da6c28aaSamw  *  Command         SMB_COM_TRANSACTION
510da6c28aaSamw  *  Name            <name>              STRING name of mail slot to write;
511da6c28aaSamw  *                                      must start with "\\MAILSLOT\\"
512da6c28aaSamw  *  SetupCount      3                   Always 3 for mailslot writes
513da6c28aaSamw  *  Setup[0]        1                   Command code == write mailslot
514da6c28aaSamw  *  Setup[1]        Ignored
515da6c28aaSamw  *  Setup[2]        Ignored
516da6c28aaSamw  *  TotalDataCount  n                   Size of data in bytes to write to
517da6c28aaSamw  *                                      the mailslot
518da6c28aaSamw  *  Data[ n ]                           The data to write to the mailslot
519da6c28aaSamw  *
520da6c28aaSamw  */
521da6c28aaSamw 
522da6c28aaSamw /*
523da6c28aaSamw  * SMB: C transact, File = \MAILSLOT\BROWSE
524da6c28aaSamw  *   SMB: SMB Status = Error Success
525da6c28aaSamw  *     SMB: Error class = No Error
526da6c28aaSamw  *     SMB: Error code = No Error
527da6c28aaSamw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
528da6c28aaSamw  *     SMB: Tree ID   (TID) = 0 (0x0)
529da6c28aaSamw  *     SMB: Process ID  (PID) = 0 (0x0)
530da6c28aaSamw  *     SMB: User ID   (UID) = 0 (0x0)
531da6c28aaSamw  *     SMB: Multiplex ID (MID) = 0 (0x0)
532da6c28aaSamw  *     SMB: Flags Summary = 0 (0x0)
533da6c28aaSamw  *   SMB: Command = C transact
534da6c28aaSamw  *     SMB: Word count = 17
535da6c28aaSamw  *     SMB: Word parameters
536da6c28aaSamw  *     SMB: Total parm bytes = 0
537da6c28aaSamw  *     SMB: Total data bytes = 33
538da6c28aaSamw  *     SMB: Max parm bytes = 0
539da6c28aaSamw  *     SMB: Max data bytes = 0
540da6c28aaSamw  *     SMB: Max setup words = 0
541da6c28aaSamw  *     SMB: Transact Flags Summary = 0 (0x0)
542da6c28aaSamw  *       SMB: ...............0 = Leave session intact
543da6c28aaSamw  *       SMB: ..............0. = Response required
544da6c28aaSamw  *     SMB: Transact timeout = 0 (0x0)
545da6c28aaSamw  *     SMB: Parameter bytes = 0 (0x0)
546da6c28aaSamw  *     SMB: Parameter offset = 0 (0x0)
547da6c28aaSamw  *     SMB: Data bytes = 33 (0x21)
548da6c28aaSamw  *     SMB: Data offset = 86 (0x56)
549da6c28aaSamw  *     SMB: Setup word count = 3
550da6c28aaSamw  *     SMB: Setup words
551da6c28aaSamw  *     SMB: Mailslot opcode = Write mailslot
552da6c28aaSamw  *     SMB: Transaction priority = 1
553da6c28aaSamw  *     SMB: Mailslot class = Unreliable (broadcast)
554da6c28aaSamw  *     SMB: Byte count = 50
555da6c28aaSamw  *     SMB: Byte parameters
556da6c28aaSamw  *     SMB: Path name = \MAILSLOT\BROWSE
557da6c28aaSamw  *     SMB: Transaction data
558da6c28aaSamw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
559da6c28aaSamw  *
560da6c28aaSamw  * 5. Mailslot Protocol Specification
561da6c28aaSamw  *
562da6c28aaSamw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
563da6c28aaSamw  * writes requests are encapsulated in TRANSACT SMBs. The following table
564da6c28aaSamw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
565da6c28aaSamw  * transaction:
566da6c28aaSamw  *
567da6c28aaSamw  *  Name            Value               Description
568da6c28aaSamw  *  Command         SMB_COM_TRANSACTION
569da6c28aaSamw  *  Name            <name>              STRING name of mail slot to write;
570da6c28aaSamw  *                                      must start with "\MAILSLOT\"
571da6c28aaSamw  *  SetupCount      3                   Always 3 for mailslot writes
572da6c28aaSamw  *  Setup[0]        1                   Command code == write mailslot
573da6c28aaSamw  *  Setup[1]        Ignored
574da6c28aaSamw  *  Setup[2]        Ignored
575da6c28aaSamw  *  TotalDataCount  n                   Size of data in bytes to write to
576da6c28aaSamw  *                                      the mailslot
577da6c28aaSamw  *  Data[ n ]                           The data to write to the mailslot
578da6c28aaSamw  *
579da6c28aaSamw  *	Magic		0xFF 'S' 'M' 'B'
580da6c28aaSamw  *	smb_com 	a byte, the "first" command
581da6c28aaSamw  *	Error		a 4-byte union, ignored in a request
582da6c28aaSamw  *	smb_flg		a one byte set of eight flags
583da6c28aaSamw  *	smb_flg2	a two byte set of 16 flags
584da6c28aaSamw  *	.		twelve reserved bytes, have a role
585da6c28aaSamw  *			in connectionless transports (IPX, UDP?)
586da6c28aaSamw  *	smb_tid		a 16-bit tree ID, a mount point sorta,
587da6c28aaSamw  *			0xFFFF is this command does not have
588da6c28aaSamw  *			or require a tree context
589da6c28aaSamw  *	smb_pid		a 16-bit process ID
590da6c28aaSamw  *	smb_uid		a 16-bit user ID, specific to this "session"
591da6c28aaSamw  *			and mapped to a system (bona-fide) UID
592da6c28aaSamw  *	smb_mid		a 16-bit multiplex ID, used to differentiate
593da6c28aaSamw  *			multiple simultaneous requests from the same
594da6c28aaSamw  *			process (pid) (ref RPC "xid")
595da6c28aaSamw  */
596da6c28aaSamw 
597da6c28aaSamw int
598da6c28aaSamw smb_browser_load_transact_header(unsigned char *buffer, int maxcnt,
5997b59d02dSjb     int data_count, int reply, char *mailbox)
600da6c28aaSamw {
601da6c28aaSamw 	smb_msgbuf_t mb;
602da6c28aaSamw 	int	mailboxlen;
603da6c28aaSamw 	char *fmt;
604da6c28aaSamw 	int result;
605da6c28aaSamw 	short	class = (reply == ONE_WAY_TRANSACTION) ? 2 : 0;
606da6c28aaSamw 
607da6c28aaSamw 	/*
608da6c28aaSamw 	 * If the mailboxlen is an even number we need to pad the
609da6c28aaSamw 	 * header so that the data starts on a word boundary.
610da6c28aaSamw 	 */
611da6c28aaSamw 	fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws";
612da6c28aaSamw 	mailboxlen = strlen(mailbox) + 1;
613da6c28aaSamw 
614da6c28aaSamw 	if ((mailboxlen & 0x01) == 0) {
615da6c28aaSamw 		++mailboxlen;
616da6c28aaSamw 		fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws.";
617da6c28aaSamw 	}
618da6c28aaSamw 
619da6c28aaSamw 	bzero(buffer, maxcnt);
620da6c28aaSamw 	smb_msgbuf_init(&mb, buffer, maxcnt, 0);
621da6c28aaSamw 
622da6c28aaSamw 	result = smb_msgbuf_encode(&mb, fmt,
623da6c28aaSamw 	    SMB_COM_TRANSACTION,	/* Command */
624da6c28aaSamw 	    0x18,
625da6c28aaSamw 	    0x3,
626da6c28aaSamw 	    17,				/* Count of parameter words */
627da6c28aaSamw 	    0,				/* Total Parameter words sent */
628da6c28aaSamw 	    data_count,			/* Total Data bytes sent */
629da6c28aaSamw 	    2,				/* Max Parameters to return */
630da6c28aaSamw 	    0,				/* Max data bytes to return */
631da6c28aaSamw 	    0,				/* Max setup bytes to return */
632da6c28aaSamw 	    reply,			/* No reply */
633da6c28aaSamw 	    0xffffffff,			/* Timeout */
634da6c28aaSamw 	    0,				/* Parameter bytes sent */
635da6c28aaSamw 	    0,				/* Parameter offset */
636da6c28aaSamw 	    data_count,			/* Data bytes sent */
637da6c28aaSamw 	    69 + mailboxlen,		/* Data offset */
638da6c28aaSamw 	    3,				/* Setup word count */
639da6c28aaSamw 	    1,				/* Setup word[0] */
640da6c28aaSamw 	    0,				/* Setup word[1] */
641da6c28aaSamw 	    class,			/* Setup word[2] */
642da6c28aaSamw 	    mailboxlen + data_count,	/* Total request bytes */
643da6c28aaSamw 	    mailbox);			/* Mailbox address */
644da6c28aaSamw 
645da6c28aaSamw 	smb_msgbuf_term(&mb);
646da6c28aaSamw 	return (result);
647da6c28aaSamw }
648da6c28aaSamw 
649da6c28aaSamw static int
6507b59d02dSjb smb_browser_addr_of_subnet(struct name_entry *name, smb_hostinfo_t *hinfo,
651da6c28aaSamw     struct name_entry *result)
652da6c28aaSamw {
653da6c28aaSamw 	uint32_t ipaddr, mask, saddr;
654a0aa776eSAlan Wright 	addr_entry_t *addr;
655da6c28aaSamw 
6567b59d02dSjb 	if (name == NULL)
657da6c28aaSamw 		return (-1);
658da6c28aaSamw 
6597b59d02dSjb 	if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS)
660da6c28aaSamw 		return (-1);
6617b59d02dSjb 
6627f667e74Sjose borrego 	ipaddr = hinfo->hi_nic.nic_ip.a_ipv4;
6637b59d02dSjb 	mask = hinfo->hi_nic.nic_mask;
664da6c28aaSamw 
665da6c28aaSamw 	*result = *name;
666da6c28aaSamw 	addr = &name->addr_list;
667da6c28aaSamw 	do {
668da6c28aaSamw 		saddr = addr->sin.sin_addr.s_addr;
669da6c28aaSamw 		if ((saddr & mask) == (ipaddr & mask)) {
670da6c28aaSamw 			*result = *name;
671da6c28aaSamw 			result->addr_list = *addr;
672da6c28aaSamw 			result->addr_list.forw = result->addr_list.back =
673da6c28aaSamw 			    &result->addr_list;
674da6c28aaSamw 			return (0);
675da6c28aaSamw 		}
676da6c28aaSamw 		addr = addr->forw;
677da6c28aaSamw 	} while (addr != &name->addr_list);
678da6c28aaSamw 
679da6c28aaSamw 	return (-1);
680da6c28aaSamw }
681da6c28aaSamw 
682da6c28aaSamw 
683da6c28aaSamw static int
6847b59d02dSjb smb_browser_bcast_addr_of_subnet(struct name_entry *name, uint32_t bcast,
685da6c28aaSamw     struct name_entry *result)
686da6c28aaSamw {
6877b59d02dSjb 	if (name != NULL && name != result)
688da6c28aaSamw 		*result = *name;
689da6c28aaSamw 
690da6c28aaSamw 	result->addr_list.sin.sin_family = AF_INET;
691da6c28aaSamw 	result->addr_list.sinlen = sizeof (result->addr_list.sin);
6927b59d02dSjb 	result->addr_list.sin.sin_addr.s_addr = bcast;
693a0aa776eSAlan Wright 	result->addr_list.sin.sin_port = htons(IPPORT_NETBIOS_DGM);
694da6c28aaSamw 	result->addr_list.forw = result->addr_list.back = &result->addr_list;
695da6c28aaSamw 	return (0);
696da6c28aaSamw }
697da6c28aaSamw 
698da6c28aaSamw /*
699da6c28aaSamw  * 6.5 HostAnnouncement Browser Frame
700da6c28aaSamw  *
701da6c28aaSamw  * To advertise its presence, i.e. to publish itself as being available, a
702da6c28aaSamw  * non-browser server sends a HostAnnouncement browser frame. If the server
703da6c28aaSamw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
704da6c28aaSamw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE". The definition of  the
705da6c28aaSamw  * HostAnnouncement frame is:
706da6c28aaSamw  *
707da6c28aaSamw  *     struct {
708da6c28aaSamw  *         unsigned short  Opcode;
709da6c28aaSamw  *         unsigned char   UpdateCount;
710da6c28aaSamw  *         uint32_t   Periodicity;
711da6c28aaSamw  *         unsigned char   ServerName[];
712da6c28aaSamw  *         unsigned char   VersionMajor;
713da6c28aaSamw  *         unsigned char   VersionMinor;
714da6c28aaSamw  *         uint32_t   Type;
715da6c28aaSamw  *         uint32_t   Signature;
716da6c28aaSamw  *         unsigned char   Comment[];
717da6c28aaSamw  *     }
718da6c28aaSamw  *
719da6c28aaSamw  * where:
720da6c28aaSamw  *      Opcode - Identifies this structure as a browser server
721da6c28aaSamw  *          announcement and is defined as HostAnnouncement with a
722da6c28aaSamw  *          value of decimal 1.
723da6c28aaSamw  *
724da6c28aaSamw  *      UpdateCount - must be sent as zero and ignored on receipt.
725da6c28aaSamw  *
726da6c28aaSamw  *      Periodicity - The announcement frequency of the server (in
727da6c28aaSamw  *          seconds). The server will be removed from the browse list
728da6c28aaSamw  *          if it has not been heard from in 3X its announcement
729da6c28aaSamw  *          frequency. In no case will the server be removed from the
730da6c28aaSamw  *          browse list before the period 3X has elapsed. Actual
731da6c28aaSamw  *          implementations may take more than 3X to actually remove
732da6c28aaSamw  *          the server from the browse list.
733da6c28aaSamw  *
734da6c28aaSamw  *      ServerName - Null terminated ASCII server name (up to 16 bytes
735da6c28aaSamw  *          in length).
736da6c28aaSamw  *
737da6c28aaSamw  *      VersionMajor - The major version number of the OS the server
738da6c28aaSamw  *          is running. it will be returned by NetServerEnum2.
739da6c28aaSamw  *
740da6c28aaSamw  *      VersionMinor - The minor version number of the OS the server
741da6c28aaSamw  *          is running. This is entirely informational and does not
742da6c28aaSamw  *          have any significance for the browsing protocol.
743da6c28aaSamw  *
744da6c28aaSamw  *      Type - Specifies the type of the server. The server type bits
745da6c28aaSamw  *          are specified in the NetServerEnum2 section.
746da6c28aaSamw  *
747da6c28aaSamw  *      Signature -  The browser protocol minor version number in the
748da6c28aaSamw  *          low 8 bits, the browser protocol major version number in
749da6c28aaSamw  *          the next higher 8 bits and the signature 0xaa55 in the
750da6c28aaSamw  *          high 16 bits of this field. Thus, for this version of the
751da6c28aaSamw  *          browser protocol (1.15) this field has the value
752da6c28aaSamw  *          0xaa55010f. This may used to isolate browser servers that
753da6c28aaSamw  *          are running out of revision browser software; otherwise,
754da6c28aaSamw  *          it is ignored.
755da6c28aaSamw  *
756da6c28aaSamw  *      Comment - Null terminated ASCII comment for the server.
757da6c28aaSamw  *          Limited to 43 bytes.
758da6c28aaSamw  *
759da6c28aaSamw  * When a non-browser server starts up, it announces itself in the manner
760da6c28aaSamw  * described once every minute. The frequency of these statements is
761da6c28aaSamw  * gradually stretched to once every 12 minutes.
762da6c28aaSamw  *
763da6c28aaSamw  * Note: older non-browser servers in a domain "D" sent HostAnnouncement
764da6c28aaSamw  * frames to the NETBIOS group name D(00). Non-Browser servers supporting
765da6c28aaSamw  * version 1.15 of the browsing protocol SHOULD NOT use this NETBIOS name,
766da6c28aaSamw  * but for backwards compatibility Master Browsers MAY receive and process
767da6c28aaSamw  * HostAnnouncement frames on this name as described above for D(1d).
768da6c28aaSamw  */
769da6c28aaSamw 
7707b59d02dSjb static void
7717b59d02dSjb smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo,
7727b59d02dSjb     uint32_t next_announcement, boolean_t remove,
773a0aa776eSAlan Wright     addr_entry_t *addr, char suffix)
774da6c28aaSamw {
775da6c28aaSamw 	smb_msgbuf_t mb;
776da6c28aaSamw 	int offset, announce_len, data_length;
777da6c28aaSamw 	struct name_entry dest_name;
778da6c28aaSamw 	unsigned char *buffer;
779da6c28aaSamw 	uint32_t type;
780da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
781da6c28aaSamw 
782dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
783dc20a302Sas 		return;
784bbf6f00cSJordan Brown 	(void) smb_strupr(resource_domain);
785da6c28aaSamw 
7867b59d02dSjb 	if (addr == NULL) {
787da6c28aaSamw 		/* Local master Browser */
7887b59d02dSjb 		smb_init_name_struct((unsigned char *)resource_domain, suffix,
789da6c28aaSamw 		    0, 0, 0, 0, 0, &dest_name);
7907b59d02dSjb 		if (smb_browser_bcast_addr_of_subnet(0, hinfo->hi_nic.nic_bcast,
7917b59d02dSjb 		    &dest_name) < 0)
792da6c28aaSamw 			return;
793da6c28aaSamw 	} else {
7947b59d02dSjb 		smb_init_name_struct((unsigned char *)resource_domain, suffix,
795da6c28aaSamw 		    0, 0, 0, 0, 0, &dest_name);
796da6c28aaSamw 		dest_name.addr_list = *addr;
797da6c28aaSamw 		dest_name.addr_list.forw = dest_name.addr_list.back =
798da6c28aaSamw 		    &dest_name.addr_list;
799da6c28aaSamw 	}
800da6c28aaSamw 
801da6c28aaSamw 	/* give some extra room */
802a0aa776eSAlan Wright 	buffer = malloc(MAX_DATAGRAM_LENGTH * 2);
803a0aa776eSAlan Wright 	if (buffer == NULL) {
804a0aa776eSAlan Wright 		syslog(LOG_DEBUG, "smb browser: HostAnnouncement: %m");
805da6c28aaSamw 		return;
806da6c28aaSamw 	}
807da6c28aaSamw 
808da6c28aaSamw 	data_length = 1 + 1 + 4 + 16 + 1 + 1 + 4 + 4 +
8097b59d02dSjb 	    strlen(hinfo->hi_nic.nic_cmnt) + 1;
810da6c28aaSamw 
8117b59d02dSjb 	offset = smb_browser_load_transact_header(buffer,
812da6c28aaSamw 	    MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION,
8137b59d02dSjb 	    MAILSLOT_BROWSE);
814da6c28aaSamw 
8157b59d02dSjb 	if (offset < 0) {
816da6c28aaSamw 		free(buffer);
817da6c28aaSamw 		return;
818da6c28aaSamw 	}
819da6c28aaSamw 
820da6c28aaSamw 	/*
821da6c28aaSamw 	 * A non-browser server SHOULD send a HostAnnouncement browser frame
822da6c28aaSamw 	 * specifying a type of 0 just prior to shutting down, to allow it to
823da6c28aaSamw 	 * quickly be removed from the list of available servers.
824da6c28aaSamw 	 */
825a0aa776eSAlan Wright 	if (remove || (!smb_netbios_running()))
8267b59d02dSjb 		type = 0;
8277b59d02dSjb 	else
8287b59d02dSjb 		type = hinfo->hi_type;
829da6c28aaSamw 
830da6c28aaSamw 	smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0);
8317b59d02dSjb 
832da6c28aaSamw 	announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls",
8337b59d02dSjb 	    HOST_ANNOUNCEMENT,
8347b59d02dSjb 	    ++hinfo->hi_updatecnt,
835da6c28aaSamw 	    next_announcement * 60000,	/* Periodicity in MilliSeconds */
8367b59d02dSjb 	    hinfo->hi_nbname,
837*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    hinfo->hi_version.sv_major,
838*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    hinfo->hi_version.sv_minor,
8397b59d02dSjb 	    type,
8407b59d02dSjb 	    SMB_SERVER_SIGNATURE,
8417b59d02dSjb 	    hinfo->hi_nic.nic_cmnt);
842da6c28aaSamw 
843da6c28aaSamw 	if (announce_len > 0)
8447b59d02dSjb 		(void) smb_netbios_datagram_send(&hinfo->hi_netname, &dest_name,
845da6c28aaSamw 		    buffer, offset + announce_len);
846da6c28aaSamw 
847da6c28aaSamw 	free(buffer);
848da6c28aaSamw 	smb_msgbuf_term(&mb);
849da6c28aaSamw }
850da6c28aaSamw 
8517b59d02dSjb static void
852da6c28aaSamw smb_browser_process_AnnouncementRequest(struct datagram *datagram,
853da6c28aaSamw     char *mailbox)
854da6c28aaSamw {
8557b59d02dSjb 	smb_hostinfo_t *hinfo;
8567b59d02dSjb 	uint32_t next_announcement;
857da6c28aaSamw 	uint32_t delay = random() % 29; /* in seconds */
8587b59d02dSjb 	boolean_t h_found = B_FALSE;
859da6c28aaSamw 
8607b59d02dSjb 	if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) {
861a0aa776eSAlan Wright 		syslog(LOG_DEBUG, "smb browser: wrong mailbox (%s)", mailbox);
862da6c28aaSamw 		return;
863da6c28aaSamw 	}
864da6c28aaSamw 
865a0aa776eSAlan Wright 	smb_netbios_sleep(delay);
866da6c28aaSamw 
8677b59d02dSjb 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
8687b59d02dSjb 	hinfo = list_head(&smb_binfo.bi_hlist);
8697b59d02dSjb 	while (hinfo) {
8707f667e74Sjose borrego 		if ((hinfo->hi_nic.nic_ip.a_ipv4 &
8717f667e74Sjose borrego 		    hinfo->hi_nic.nic_mask) ==
8727b59d02dSjb 		    (datagram->src.addr_list.sin.sin_addr.s_addr &
8737b59d02dSjb 		    hinfo->hi_nic.nic_mask)) {
8747b59d02dSjb 			h_found = B_TRUE;
8757b59d02dSjb 			break;
8767b59d02dSjb 		}
8777b59d02dSjb 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
8787b59d02dSjb 	}
8797b59d02dSjb 
8807b59d02dSjb 	if (h_found) {
8817b59d02dSjb 		next_announcement = hinfo->hi_nextannouce * 60 * 1000;
8827b59d02dSjb 		smb_browser_send_HostAnnouncement(hinfo, next_announcement,
883a0aa776eSAlan Wright 		    B_FALSE, &datagram->src.addr_list, NBT_MB);
884da6c28aaSamw 	}
8857b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
886da6c28aaSamw }
887da6c28aaSamw 
888da6c28aaSamw void *
889da6c28aaSamw smb_browser_dispatch(void *arg)
890da6c28aaSamw {
891da6c28aaSamw 	struct datagram *datagram = (struct datagram *)arg;
892da6c28aaSamw 	smb_msgbuf_t 	mb;
893da6c28aaSamw 	int		rc;
894da6c28aaSamw 	unsigned char	command;
895da6c28aaSamw 	unsigned char	parameter_words;
896da6c28aaSamw 	unsigned short	total_parameter_words;
897da6c28aaSamw 	unsigned short	total_data_count;
898da6c28aaSamw 	unsigned short	max_parameters_to_return;
899da6c28aaSamw 	unsigned short	max_data_to_return;
900da6c28aaSamw 	unsigned char	max_setup_bytes_to_return;
901da6c28aaSamw 	unsigned short	reply;
902da6c28aaSamw 	unsigned short	parameter_bytes_sent;
903da6c28aaSamw 	unsigned short	parameter_offset;
904da6c28aaSamw 	unsigned short	data_bytes_sent;
905da6c28aaSamw 	unsigned short	data_offset;
906da6c28aaSamw 	unsigned char	setup_word_count;
907da6c28aaSamw 	unsigned short	setup_word_0;
908da6c28aaSamw 	unsigned short	setup_word_1;
909da6c28aaSamw 	unsigned short	setup_word_2;
910da6c28aaSamw 	unsigned short	total_request_bytes;
911da6c28aaSamw 	char 		*mailbox;
912da6c28aaSamw 	unsigned char	message_type;
913da6c28aaSamw 	unsigned char 	*data;
914da6c28aaSamw 	int		datalen;
915da6c28aaSamw 
916a0aa776eSAlan Wright 	syslog(LOG_DEBUG, "smb browser: packet received");
917da6c28aaSamw 
918da6c28aaSamw 	smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0);
919da6c28aaSamw 	rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws",
920da6c28aaSamw 	    &command,			/* Command */
921da6c28aaSamw 	    &parameter_words,		/* Count of parameter words */
922da6c28aaSamw 	    &total_parameter_words,	/* Total Parameter words sent */
923da6c28aaSamw 	    &total_data_count,		/* Total Data bytes sent */
924da6c28aaSamw 	    &max_parameters_to_return,	/* Max Parameters to return */
925da6c28aaSamw 	    &max_data_to_return,	/* Max data bytes to return */
926da6c28aaSamw 	    &max_setup_bytes_to_return,	/* Max setup bytes to return */
927da6c28aaSamw 	    &reply,			/* No reply */
928da6c28aaSamw 	    &parameter_bytes_sent,	/* Parameter bytes sent */
929da6c28aaSamw 	    &parameter_offset,		/* Parameter offset */
930da6c28aaSamw 	    &data_bytes_sent,		/* Data bytes sent */
931da6c28aaSamw 	    &data_offset,		/* Data offset */
932da6c28aaSamw 	    &setup_word_count,		/* Setup word count */
933da6c28aaSamw 	    &setup_word_0,		/* Setup word[0] */
934da6c28aaSamw 	    &setup_word_1,		/* Setup word[1] */
935da6c28aaSamw 	    &setup_word_2,		/* Setup word[2] */
936da6c28aaSamw 	    &total_request_bytes,	/* Total request bytes */
937da6c28aaSamw 	    &mailbox);			/* Mailbox address */
938da6c28aaSamw 
939da6c28aaSamw 	if (rc < 0) {
940a0aa776eSAlan Wright 		syslog(LOG_ERR, "smb browser: decode error");
941da6c28aaSamw 		smb_msgbuf_term(&mb);
942da6c28aaSamw 		free(datagram);
943da6c28aaSamw 		return (0);
944da6c28aaSamw 	}
945da6c28aaSamw 
946da6c28aaSamw 	data = &datagram->data[data_offset];
947da6c28aaSamw 	datalen = datagram->data_length - data_offset;
948da6c28aaSamw 
949da6c28aaSamw 	/*
950da6c28aaSamw 	 * The PDC location protocol, i.e. anything on the \\NET
951da6c28aaSamw 	 * mailslot, is handled by the smb_netlogon module.
952da6c28aaSamw 	 */
953da6c28aaSamw 	if (strncasecmp("\\MAILSLOT\\NET\\", mailbox, 14) == 0) {
954da6c28aaSamw 		smb_netlogon_receive(datagram, mailbox, data, datalen);
955da6c28aaSamw 		smb_msgbuf_term(&mb);
956da6c28aaSamw 		free(datagram);
957da6c28aaSamw 		return (0);
958da6c28aaSamw 	}
959da6c28aaSamw 
960da6c28aaSamw 	/*
961da6c28aaSamw 	 * If it's not a netlogon message, assume it's a browser request.
962da6c28aaSamw 	 * This is not the most elegant way to extract the command byte
963da6c28aaSamw 	 * but at least we no longer use it to get the netlogon opcode.
964da6c28aaSamw 	 */
965da6c28aaSamw 	message_type = datagram->data[data_offset];
966da6c28aaSamw 
967da6c28aaSamw 	switch (message_type) {
968da6c28aaSamw 	case ANNOUNCEMENT_REQUEST :
969da6c28aaSamw 		smb_browser_process_AnnouncementRequest(datagram, mailbox);
970da6c28aaSamw 		break;
971da6c28aaSamw 
972da6c28aaSamw 	default:
973a0aa776eSAlan Wright 		syslog(LOG_DEBUG, "smb browser: invalid message type(%d, %x)",
974da6c28aaSamw 		    message_type, message_type);
975da6c28aaSamw 		break;
976da6c28aaSamw 	}
977da6c28aaSamw 
978da6c28aaSamw 	smb_msgbuf_term(&mb);
979da6c28aaSamw 	free(datagram);
980da6c28aaSamw 	return (0);
981da6c28aaSamw }
982da6c28aaSamw 
983da6c28aaSamw 
984da6c28aaSamw /*
985da6c28aaSamw  * 11.1 Registered unique names
986da6c28aaSamw  *
987da6c28aaSamw  *  <COMPUTER>(00)
988da6c28aaSamw  *     This name is used by all servers and clients to receive second
989da6c28aaSamw  *     class mailslot messages. A system must add this name in order to
990da6c28aaSamw  *     receive mailslot messages. The only browser requests that should
991da6c28aaSamw  *     appear on this name are BecomeBackup, GetBackupListResp,
992da6c28aaSamw  *     MasterAnnouncement, and LocalMasterAnnouncement frames. All other
993da6c28aaSamw  *     datagrams (other than the expected non-browser datagrams) may be
994da6c28aaSamw  *     ignored and an error logged.
995da6c28aaSamw  *
996da6c28aaSamw  *   <DOMAIN>(1d)
997da6c28aaSamw  *     This name is used to identify a master browser server for domain
998da6c28aaSamw  *     "DOMAIN" on a subnet.  A master browser server adds this name as a
999da6c28aaSamw  *     unique NETBIOS name when it becomes master browser. If the attempt
1000da6c28aaSamw  *     to add the name fails, the master browser server assumes that there
1001da6c28aaSamw  *     is another master in the domain and will fail to come up. It may
1002da6c28aaSamw  *     log an error if the failure occurs more than 3 times in a row (this
1003da6c28aaSamw  *     either indicates some form of network misconfiguration or a
1004da6c28aaSamw  *     software error). The only requests that should appear on this name
1005da6c28aaSamw  *     are GetBackupListRequest and HostAnnouncement requests. All other
1006da6c28aaSamw  *     datagrams on this name may be ignored (and an error logged). If
1007da6c28aaSamw  *     running a NETBIOS name service (NBNS, such as WINS), this name
1008da6c28aaSamw  *     should not be registered with the NBNS.
1009da6c28aaSamw  *
1010da6c28aaSamw  *   <DOMAIN>(1b)
1011da6c28aaSamw  *     This name is used to identify the Domain Master Browser for domain
1012da6c28aaSamw  *     "DOMAIN" (which is also the primary domain controller). It is a
1013da6c28aaSamw  *     unique name added only by the primary domain controller. The
1014da6c28aaSamw  *     primary domain controller will respond to GetBackupListRequest on
1015da6c28aaSamw  *     this name just as it responds to these requests on the <DOMAIN>(1d)
1016da6c28aaSamw  *     name.
1017da6c28aaSamw  *
1018da6c28aaSamw  * 11.2 Registered group names
1019da6c28aaSamw  *
1020da6c28aaSamw  *   (01)(02)__MSBROWSE__(02)(01)
1021da6c28aaSamw  *     This name is used by Master Browsers to announce themselves to the
1022da6c28aaSamw  *     other Master Browsers on a subnet. It is added as a group name by
1023da6c28aaSamw  *     all Master Browser servers. The only broadcasts that should appear
1024da6c28aaSamw  *     on this name is DomainAnnouncement requests. All other datagrams
1025da6c28aaSamw  *     can be ignored.
1026da6c28aaSamw  *
1027da6c28aaSamw  *   <DOMAIN>(00)
1028da6c28aaSamw  *     This name is used by clients and servers in domain "DOMAIN" to
1029da6c28aaSamw  *     process server announcements. The only requests that should appear
1030da6c28aaSamw  *     on this name that the browser is interested in are
1031da6c28aaSamw  *     AnnouncementRequest and NETLOGON_QUERY (to locate the PDC) packets.
1032da6c28aaSamw  *     All other unidentifiable requests may be ignored (and an error
1033da6c28aaSamw  *     logged).
1034da6c28aaSamw  *
1035da6c28aaSamw  *   <DOMAIN>(1E)
1036da6c28aaSamw  *     This name is used for announcements to browsers for domain "DOMAIN"
1037da6c28aaSamw  *     on a subnet. This name is registered by all the browser servers in
1038da6c28aaSamw  *     the domain. The only requests that should appear on this name are
1039da6c28aaSamw  *     RequestElection and AnnouncementRequest packets. All other
1040da6c28aaSamw  *     datagrams may be ignored (and an error logged).
1041da6c28aaSamw  *
1042da6c28aaSamw  *   <DOMAIN>(1C)
1043da6c28aaSamw  *     This name is registered by Primary Domain Controllers.
1044da6c28aaSamw  */
1045da6c28aaSamw 
10467b59d02dSjb static void
1047da6c28aaSamw smb_browser_config(void)
1048da6c28aaSamw {
10497b59d02dSjb 	smb_hostinfo_t *hinfo;
1050da6c28aaSamw 	struct name_entry	name;
1051da6c28aaSamw 	struct name_entry	master;
1052da6c28aaSamw 	struct name_entry	dest;
1053da6c28aaSamw 	struct name_entry	*entry;
1054da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
10557b59d02dSjb 	int rc;
10567b59d02dSjb 
10577b59d02dSjb 	if (smb_browser_init() != 0)
10587b59d02dSjb 		return;
1059da6c28aaSamw 
1060dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1061dc20a302Sas 		return;
1062bbf6f00cSJordan Brown 	(void) smb_strupr(resource_domain);
1063da6c28aaSamw 
1064da6c28aaSamw 	/* domain<00> */
1065a0aa776eSAlan Wright 	smb_init_name_struct((unsigned char *)resource_domain, NBT_WKSTA,
1066da6c28aaSamw 	    0, 0, 0, 0, 0, &name);
1067da6c28aaSamw 	entry = smb_name_find_name(&name);
1068da6c28aaSamw 	smb_name_unlock_name(entry);
1069da6c28aaSamw 
10707b59d02dSjb 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
10717b59d02dSjb 	hinfo = list_head(&smb_binfo.bi_hlist);
10727b59d02dSjb 	while (hinfo) {
1073a0aa776eSAlan Wright 		smb_init_name_struct((unsigned char *)resource_domain,
1074a0aa776eSAlan Wright 		    NBT_WKSTA, 0, hinfo->hi_nic.nic_ip.a_ipv4,
1075a0aa776eSAlan Wright 		    htons(IPPORT_NETBIOS_DGM), NAME_ATTR_GROUP,
10767f667e74Sjose borrego 		    NAME_ATTR_LOCAL, &name);
1077da6c28aaSamw 		(void) smb_name_add_name(&name);
10787b59d02dSjb 
10797b59d02dSjb 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1080da6c28aaSamw 	}
10817b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1082da6c28aaSamw 
1083da6c28aaSamw 	/* All our local master browsers */
1084a0aa776eSAlan Wright 	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
1085da6c28aaSamw 	    0, 0, 0, 0, 0, &dest);
1086da6c28aaSamw 	entry = smb_name_find_name(&dest);
1087da6c28aaSamw 
1088da6c28aaSamw 	if (entry) {
10897b59d02dSjb 		(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
10907b59d02dSjb 		hinfo = list_head(&smb_binfo.bi_hlist);
10917b59d02dSjb 		while (hinfo) {
10927b59d02dSjb 			rc = smb_browser_addr_of_subnet(entry, hinfo, &master);
10937b59d02dSjb 			if (rc == 0) {
1094da6c28aaSamw 				syslog(LOG_DEBUG,
1095a0aa776eSAlan Wright 				    "smb browser: master browser found at %s",
1096da6c28aaSamw 				    inet_ntoa(master.addr_list.sin.sin_addr));
1097da6c28aaSamw 			}
10987b59d02dSjb 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1099da6c28aaSamw 		}
11007b59d02dSjb 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11017b59d02dSjb 
1102da6c28aaSamw 		smb_name_unlock_name(entry);
1103da6c28aaSamw 	}
11047b59d02dSjb 
11057b59d02dSjb 	/* Domain master browser */
1106da6c28aaSamw 	smb_init_name_struct((unsigned char *)resource_domain,
1107a0aa776eSAlan Wright 	    NBT_DMB, 0, 0, 0, 0, 0, &dest);
1108da6c28aaSamw 
1109da6c28aaSamw 	if ((entry = smb_name_find_name(&dest)) != 0) {
1110a0aa776eSAlan Wright 		syslog(LOG_DEBUG,
1111a0aa776eSAlan Wright 		    "smb browser: domain master browser for %s is %s",
1112da6c28aaSamw 		    resource_domain,
1113da6c28aaSamw 		    inet_ntoa(entry->addr_list.sin.sin_addr));
1114da6c28aaSamw 		smb_name_unlock_name(entry);
1115da6c28aaSamw 	}
1116da6c28aaSamw }
1117da6c28aaSamw 
11187b59d02dSjb static int
11197b59d02dSjb smb_browser_init(void)
1120da6c28aaSamw {
11217b59d02dSjb 	smb_hostinfo_t *hinfo;
11227b59d02dSjb 	smb_niciter_t ni;
11237b59d02dSjb 	uint32_t type;
1124*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_version_t version;
1125*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1126*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_config_get_version(&version);
1127da6c28aaSamw 
11287b59d02dSjb 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
11297b59d02dSjb 	smb_browser_infofree();
1130da6c28aaSamw 
1131*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_nic_getfirst(&ni) != SMB_NIC_SUCCESS) {
11327b59d02dSjb 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11337b59d02dSjb 		return (-1);
1134da6c28aaSamw 	}
1135da6c28aaSamw 
11367b59d02dSjb 	type = MY_SERVER_TYPE;
11377b59d02dSjb 	if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)
11387b59d02dSjb 		type |= SV_DOMAIN_MEMBER;
11397b59d02dSjb 
11407b59d02dSjb 	do {
11418d7e4166Sjose borrego 		if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
11428d7e4166Sjose borrego 		    (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS))
11437b59d02dSjb 			continue;
11447b59d02dSjb 
11457b59d02dSjb 		hinfo = malloc(sizeof (smb_hostinfo_t));
11467b59d02dSjb 		if (hinfo == NULL) {
11477b59d02dSjb 			smb_browser_infofree();
11487b59d02dSjb 			(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11497b59d02dSjb 			return (-1);
11507b59d02dSjb 		}
11517b59d02dSjb 
11527b59d02dSjb 		hinfo->hi_nic = ni.ni_nic;
11537b59d02dSjb 		/* One Minute announcements for first five */
11547b59d02dSjb 		hinfo->hi_nextannouce = 1;
11557b59d02dSjb 		hinfo->hi_interval = 1;
11567b59d02dSjb 		hinfo->hi_reps = 5;
11577b59d02dSjb 		hinfo->hi_updatecnt = 0;
11587b59d02dSjb 		hinfo->hi_type = type;
1159*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		hinfo->hi_version = version;
11607b59d02dSjb 
11617b59d02dSjb 		/* This is the name used for HostAnnouncement */
11627b59d02dSjb 		(void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host,
11637b59d02dSjb 		    NETBIOS_NAME_SZ);
1164bbf6f00cSJordan Brown 		(void) smb_strupr(hinfo->hi_nbname);
11657b59d02dSjb 		/* 0x20: file server service  */
11667b59d02dSjb 		smb_init_name_struct((unsigned char *)hinfo->hi_nbname,
1167a0aa776eSAlan Wright 		    NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4,
1168a0aa776eSAlan Wright 		    htons(IPPORT_NETBIOS_DGM),
1169a0aa776eSAlan Wright 		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
11707f667e74Sjose borrego 		    &hinfo->hi_netname);
11717b59d02dSjb 
11727b59d02dSjb 		list_insert_tail(&smb_binfo.bi_hlist, hinfo);
11737b59d02dSjb 		smb_binfo.bi_hcnt++;
1174*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} while (smb_nic_getnext(&ni) == SMB_NIC_SUCCESS);
11757b59d02dSjb 
11767b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11777b59d02dSjb 	return (0);
1178da6c28aaSamw }
1179da6c28aaSamw 
1180da6c28aaSamw /*
1181da6c28aaSamw  * smb_browser_non_master_duties
1182da6c28aaSamw  *
1183da6c28aaSamw  * To advertise its presence, i.e. to publish itself as being available, a
1184da6c28aaSamw  * non-browser server sends a HostAnnouncement browser frame. If the server
1185da6c28aaSamw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
1186da6c28aaSamw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE".
1187da6c28aaSamw  */
11887b59d02dSjb static void
11897b59d02dSjb smb_browser_non_master_duties(smb_hostinfo_t *hinfo, boolean_t remove)
1190da6c28aaSamw {
1191da6c28aaSamw 	struct name_entry name;
1192da6c28aaSamw 	struct name_entry *dest;
1193a0aa776eSAlan Wright 	addr_entry_t addr;
1194da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
1195da6c28aaSamw 
11967b59d02dSjb 	smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
1197a0aa776eSAlan Wright 	    remove, 0, NBT_MB);
1198dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1199dc20a302Sas 		return;
1200da6c28aaSamw 
1201bbf6f00cSJordan Brown 	(void) smb_strupr(resource_domain);
1202da6c28aaSamw 
1203a0aa776eSAlan Wright 	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
1204da6c28aaSamw 	    0, 0, 0, 0, 0, &name);
1205da6c28aaSamw 
1206da6c28aaSamw 	if ((dest = smb_name_find_name(&name))) {
1207da6c28aaSamw 		addr = dest->addr_list;
1208da6c28aaSamw 		addr.forw = addr.back = &addr;
1209da6c28aaSamw 		smb_name_unlock_name(dest);
12107b59d02dSjb 		smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
1211a0aa776eSAlan Wright 		    remove, &addr, NBT_MB);
1212da6c28aaSamw 	} else {
1213a0aa776eSAlan Wright 		smb_init_name_struct((unsigned char *)resource_domain,
1214a0aa776eSAlan Wright 		    NBT_DMB, 0, 0, 0, 0, 0, &name);
1215da6c28aaSamw 		if ((dest = smb_name_find_name(&name))) {
1216da6c28aaSamw 			addr = dest->addr_list;
1217da6c28aaSamw 			addr.forw = addr.back = &addr;
1218da6c28aaSamw 			smb_name_unlock_name(dest);
12197b59d02dSjb 			smb_browser_send_HostAnnouncement(hinfo,
1220a0aa776eSAlan Wright 			    remove, hinfo->hi_interval, &addr, NBT_DMB);
1221da6c28aaSamw 		}
1222da6c28aaSamw 	}
1223da6c28aaSamw 
1224da6c28aaSamw 	/*
1225da6c28aaSamw 	 * One Minute announcements for first five
12267b59d02dSjb 	 * minutes, one minute longer each round
1227da6c28aaSamw 	 * until 12 minutes and every 12 minutes
1228da6c28aaSamw 	 * thereafter.
1229da6c28aaSamw 	 */
12307b59d02dSjb 	if (--hinfo->hi_reps == 0) {
12317b59d02dSjb 		if (hinfo->hi_interval < 12)
12327b59d02dSjb 			hinfo->hi_interval++;
1233da6c28aaSamw 
12347b59d02dSjb 		hinfo->hi_reps = 1;
1235da6c28aaSamw 	}
1236da6c28aaSamw 
12377b59d02dSjb 	hinfo->hi_nextannouce = hinfo->hi_interval;
1238da6c28aaSamw }
1239da6c28aaSamw 
1240da6c28aaSamw 
1241da6c28aaSamw /*
1242a0aa776eSAlan Wright  * SMB NetBIOS Browser Service
1243da6c28aaSamw  */
1244da6c28aaSamw /*ARGSUSED*/
1245da6c28aaSamw void *
1246a0aa776eSAlan Wright smb_browser_service(void *arg)
1247da6c28aaSamw {
12487b59d02dSjb 	smb_hostinfo_t *hinfo;
1249da6c28aaSamw 
12507b59d02dSjb 	smb_browser_infoinit();
1251da6c28aaSamw 	smb_browser_config();
1252da6c28aaSamw 
1253a0aa776eSAlan Wright 	smb_netbios_event(NETBIOS_EVENT_BROWSER_START);
1254da6c28aaSamw 
12557b59d02dSjb restart:
12567b59d02dSjb 	do {
12577b59d02dSjb 		(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
12587b59d02dSjb 		hinfo = list_head(&smb_binfo.bi_hlist);
1259a0aa776eSAlan Wright 
12607b59d02dSjb 		while (hinfo) {
12617b59d02dSjb 			if (--hinfo->hi_nextannouce > 0 ||
12627b59d02dSjb 			    hinfo->hi_nic.nic_bcast == 0) {
12637b59d02dSjb 				hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1264da6c28aaSamw 				continue;
12657b59d02dSjb 			}
1266da6c28aaSamw 
12677b59d02dSjb 			smb_browser_non_master_duties(hinfo, B_FALSE);
1268da6c28aaSamw 
12697b59d02dSjb 			/* Check to see whether reconfig is needed */
12707b59d02dSjb 			(void) mutex_lock(&smb_binfo.bi_mtx);
12717b59d02dSjb 			if (smb_binfo.bi_changed) {
12727b59d02dSjb 				smb_binfo.bi_changed = B_FALSE;
12737b59d02dSjb 				(void) mutex_unlock(&smb_binfo.bi_mtx);
12747b59d02dSjb 				(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
12757b59d02dSjb 				smb_browser_config();
12767b59d02dSjb 				goto restart;
12777b59d02dSjb 			}
12787b59d02dSjb 			(void) mutex_unlock(&smb_binfo.bi_mtx);
1279da6c28aaSamw 
12807b59d02dSjb 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
1281da6c28aaSamw 		}
1282a0aa776eSAlan Wright 
12837b59d02dSjb 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
1284a0aa776eSAlan Wright 		smb_netbios_sleep(SECSPERMIN);	/* 1 minute */
1285a0aa776eSAlan Wright 	} while (smb_netbios_running());
1286da6c28aaSamw 
12877b59d02dSjb 	smb_browser_infoterm();
1288a0aa776eSAlan Wright 	smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP);
1289da6c28aaSamw 	return (0);
1290da6c28aaSamw }
12917b59d02dSjb 
12927b59d02dSjb /*
12937b59d02dSjb  * smb_browser_netlogon
12947b59d02dSjb  *
12957b59d02dSjb  * Sends SAMLOGON/NETLOGON request for all host/ips, except
12967b59d02dSjb  * aliases, to find a domain controller.
12978d7e4166Sjose borrego  *
12988d7e4166Sjose borrego  * The dc argument will be set if a DC is found.
12997b59d02dSjb  */
13008d7e4166Sjose borrego boolean_t
13018d7e4166Sjose borrego smb_browser_netlogon(char *domain, char *dc, uint32_t dc_len)
13027b59d02dSjb {
13037b59d02dSjb 	smb_hostinfo_t *hinfo;
13048d7e4166Sjose borrego 	boolean_t found = B_FALSE;
13058d7e4166Sjose borrego 	timestruc_t to;
13068d7e4166Sjose borrego 	int err;
13077b59d02dSjb 
13087b59d02dSjb 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
13097b59d02dSjb 	hinfo = list_head(&smb_binfo.bi_hlist);
13107b59d02dSjb 	while (hinfo) {
13117b59d02dSjb 		if ((hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) == 0)
131229bd2886SAlan Wright 			smb_netlogon_request(&hinfo->hi_netname, domain);
13137b59d02dSjb 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
13147b59d02dSjb 	}
13157b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13168d7e4166Sjose borrego 
13178d7e4166Sjose borrego 	bzero(dc, dc_len);
13188d7e4166Sjose borrego 	to.tv_sec = 30;
13198d7e4166Sjose borrego 	to.tv_nsec = 0;
13208d7e4166Sjose borrego 	(void) mutex_lock(&ntdomain_mtx);
13218d7e4166Sjose borrego 	while (ntdomain_info.n_ipaddr == 0) {
13228d7e4166Sjose borrego 		err = cond_reltimedwait(&ntdomain_cv, &ntdomain_mtx, &to);
13238d7e4166Sjose borrego 		if (err == ETIME)
13248d7e4166Sjose borrego 			break;
13258d7e4166Sjose borrego 	}
13268d7e4166Sjose borrego 
13278d7e4166Sjose borrego 	if (ntdomain_info.n_ipaddr != 0) {
13288d7e4166Sjose borrego 		(void) strlcpy(dc, ntdomain_info.n_name, dc_len);
13298d7e4166Sjose borrego 		found = B_TRUE;
13308d7e4166Sjose borrego 	}
13318d7e4166Sjose borrego 	(void) mutex_unlock(&ntdomain_mtx);
13328d7e4166Sjose borrego 
13338d7e4166Sjose borrego 	return (found);
13347b59d02dSjb }
13357b59d02dSjb 
13367b59d02dSjb /*
13377b59d02dSjb  * smb_browser_infoinit
13387b59d02dSjb  *
1339a0aa776eSAlan Wright  * This function is called only once when the browser starts
1340a0aa776eSAlan Wright  * to initialize the global smb_binfo structure.
13417b59d02dSjb  */
13427b59d02dSjb static void
13437b59d02dSjb smb_browser_infoinit(void)
13447b59d02dSjb {
13458d7e4166Sjose borrego 	(void) mutex_lock(&ntdomain_mtx);
13468d7e4166Sjose borrego 	bzero(&ntdomain_info, sizeof (ntdomain_info));
13478d7e4166Sjose borrego 	(void) mutex_unlock(&ntdomain_mtx);
13488d7e4166Sjose borrego 
13497b59d02dSjb 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
13507b59d02dSjb 	list_create(&smb_binfo.bi_hlist, sizeof (smb_hostinfo_t),
13517b59d02dSjb 	    offsetof(smb_hostinfo_t, hi_lnd));
13527b59d02dSjb 	smb_binfo.bi_hcnt = 0;
13537b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13547b59d02dSjb 
13557b59d02dSjb 	(void) mutex_lock(&smb_binfo.bi_mtx);
13567b59d02dSjb 	smb_binfo.bi_changed = B_FALSE;
13577b59d02dSjb 	(void) mutex_unlock(&smb_binfo.bi_mtx);
13587b59d02dSjb }
13597b59d02dSjb 
13607b59d02dSjb /*
13617b59d02dSjb  * smb_browser_infoterm
13627b59d02dSjb  *
1363a0aa776eSAlan Wright  * This function is called only once when the browser stops
1364a0aa776eSAlan Wright  * to destroy the smb_binfo structure.
13657b59d02dSjb  */
13667b59d02dSjb static void
13677b59d02dSjb smb_browser_infoterm(void)
13687b59d02dSjb {
13697b59d02dSjb 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
13707b59d02dSjb 	smb_browser_infofree();
13717b59d02dSjb 	list_destroy(&smb_binfo.bi_hlist);
13727b59d02dSjb 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13737b59d02dSjb }
13747b59d02dSjb 
13757b59d02dSjb /*
13767b59d02dSjb  * smb_browser_infofree
13777b59d02dSjb  *
13787b59d02dSjb  * Removes all the hostinfo structures from the browser list
13797b59d02dSjb  * and frees the allocated memory
13807b59d02dSjb  */
13817b59d02dSjb static void
13827b59d02dSjb smb_browser_infofree(void)
13837b59d02dSjb {
13847b59d02dSjb 	smb_hostinfo_t *hinfo;
13857b59d02dSjb 
13867b59d02dSjb 	while ((hinfo = list_head(&smb_binfo.bi_hlist)) != NULL) {
13877b59d02dSjb 		list_remove(&smb_binfo.bi_hlist, hinfo);
13887b59d02dSjb 		free(hinfo);
13897b59d02dSjb 	}
13907b59d02dSjb 
13917b59d02dSjb 	smb_binfo.bi_hcnt = 0;
13927b59d02dSjb }
1393