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*dc20a302Sas  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27da6c28aaSamw 
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 
40*dc20a302Sas #include <smbsrv/libsmb.h>
41da6c28aaSamw #include <smbsrv/libsmbns.h>
42da6c28aaSamw 
43da6c28aaSamw #include <smbsrv/cifs.h>
44da6c28aaSamw #include <smbsrv/mailslot.h>
45da6c28aaSamw 
46da6c28aaSamw #include <smbns_browser.h>
47da6c28aaSamw #include <smbns_netbios.h>
48da6c28aaSamw 
49da6c28aaSamw #define	SMB_SERVER_SIGNATURE		0xaa550415
50da6c28aaSamw 
51da6c28aaSamw /*
52da6c28aaSamw  * Macro definitions:
53da6c28aaSamw  */
54da6c28aaSamw static char	*lanman = MAILSLOT_LANMAN;
55da6c28aaSamw static char	*browse	= MAILSLOT_BROWSE;
56da6c28aaSamw 
57da6c28aaSamw typedef struct server_info {
58da6c28aaSamw 	uint32_t type;
59da6c28aaSamw 	uint32_t signature;
60da6c28aaSamw 	char major;
61da6c28aaSamw 	char minor;
62da6c28aaSamw 	char hostname[NETBIOS_NAME_SZ];
63da6c28aaSamw 	char comment[SMB_PI_MAX_COMMENT];
64da6c28aaSamw 	char update_count;
65da6c28aaSamw 	struct name_entry name;
66da6c28aaSamw } server_info_t;
67da6c28aaSamw 
68da6c28aaSamw #define	BROWSER_NF_INVALID 0x00
69da6c28aaSamw #define	BROWSER_NF_VALID   0x01
70da6c28aaSamw 
71da6c28aaSamw typedef struct browser_netinfo {
72da6c28aaSamw 	uint32_t flags;
73da6c28aaSamw 	int	next_announce;
74da6c28aaSamw 	int	reps;
75da6c28aaSamw 	int	interval;
76da6c28aaSamw 	server_info_t server;
77da6c28aaSamw 	mutex_t mtx;
78da6c28aaSamw } browser_netinfo_t;
79da6c28aaSamw 
80da6c28aaSamw /*
81da6c28aaSamw  * Local Data Definitions:
82da6c28aaSamw  */
83da6c28aaSamw static struct browser_netinfo smb_browser_info[SMB_PI_MAX_NETWORKS];
84da6c28aaSamw 
85da6c28aaSamw static void smb_browser_init(void);
86da6c28aaSamw 
87da6c28aaSamw static inline browser_netinfo_t *
88da6c28aaSamw smb_browser_getnet(int net)
89da6c28aaSamw {
90da6c28aaSamw 	browser_netinfo_t *subnet;
91da6c28aaSamw 
92da6c28aaSamw 	if (net < smb_nic_get_num()) {
93da6c28aaSamw 		subnet = &smb_browser_info[net];
94da6c28aaSamw 		(void) mutex_lock(&subnet->mtx);
95da6c28aaSamw 		if (subnet->flags & BROWSER_NF_VALID)
96da6c28aaSamw 			return (subnet);
97da6c28aaSamw 	}
98da6c28aaSamw 
99da6c28aaSamw 	return (0);
100da6c28aaSamw }
101da6c28aaSamw 
102da6c28aaSamw static inline void
103da6c28aaSamw smb_browser_putnet(browser_netinfo_t *netinfo)
104da6c28aaSamw {
105da6c28aaSamw 	if (netinfo)
106da6c28aaSamw 		(void) mutex_unlock(&netinfo->mtx);
107da6c28aaSamw }
108da6c28aaSamw 
109da6c28aaSamw /*
110da6c28aaSamw  * 3. Browser Overview
111da6c28aaSamw  *
112da6c28aaSamw  * Hosts involved in the browsing process can be separated into two
113da6c28aaSamw  * distinct groups, browser clients and browser servers (often referred to
114da6c28aaSamw  * simply as "browsers").
115da6c28aaSamw  *
116da6c28aaSamw  * A browser is a server which maintains information about servers -
117da6c28aaSamw  * primarily the domain they are in and the services that they are running
118da6c28aaSamw  * -- and about domains. Browsers may assume several different roles in
119da6c28aaSamw  * their lifetimes, and dynamically switch between them.
120da6c28aaSamw  *
121da6c28aaSamw  *  Browser clients are of two types: workstations and (non-browser)
122da6c28aaSamw  * servers. In the context of browsing, workstations query browsers for the
123da6c28aaSamw  * information they contain; servers supply browsers the information by
124da6c28aaSamw  * registering with them. Note that, at times, browsers may themselves
125da6c28aaSamw  * behave as browser clients and query other browsers.
126da6c28aaSamw  *
127da6c28aaSamw  * For the purposes of this specification, a domain is simply a name with
128da6c28aaSamw  * which to associate a group of resources such as computers, servers and
129da6c28aaSamw  * users. Domains allow a convenient means for browser clients to restrict
130da6c28aaSamw  * the scope of a search when they query browser servers. Every domain has
131da6c28aaSamw  * a "master" server called the Primary Domain Controller (PDC) that
132da6c28aaSamw  * manages various  activities within the domain.
133da6c28aaSamw  *
134da6c28aaSamw  * One browser for each domain on a subnet is designated the Local Master
135da6c28aaSamw  * Browser for that domain. Servers in its domain on the subnet register
136da6c28aaSamw  * with it, as do the Local Master Browsers for other domains on the
137da6c28aaSamw  * subnet. It uses these registrations to maintain authoritative
138da6c28aaSamw  * information about its domain on its subnet. If there are other subnets
139da6c28aaSamw  * in the network, it also knows the name of the server running the
140da6c28aaSamw  * domain's Domain Master Browser; it registers with it, and uses it to
141da6c28aaSamw  * obtain information about the rest of the network (see below).
142da6c28aaSamw  *
143da6c28aaSamw  * Clients on a subnet query browsers designated as the Backup Browsers for
144da6c28aaSamw  * the subnet (not the Master Browser). Backup Browsers maintain a copy of
145da6c28aaSamw  * the information on the Local Master Browser; they get it by periodically
146da6c28aaSamw  * querying the Local Master Browser for all of its information. Clients
147da6c28aaSamw  * find the Backup Browsers by asking the Local Master Browser. Clients are
148da6c28aaSamw  * expected to spread their queries evenly across Backup Browsers to
149da6c28aaSamw  * balance the load.
150da6c28aaSamw  *
151da6c28aaSamw  * The Local Master Browser is dynamically elected automatically. Multiple
152da6c28aaSamw  * Backup Browser Servers may exist per subnet; they are selected from
153da6c28aaSamw  * among the potential browser servers by the Local Master Browser, which
154da6c28aaSamw  * is configured to select enough to handle the expected query load.
155da6c28aaSamw  *
156da6c28aaSamw  * When there are multiple subnets, a Domain Master Browser is assigned
157da6c28aaSamw  * the task of keeping the multiple subnets in synchronization. The Primary
158da6c28aaSamw  * Domain Controller (PDC) always acts as the Domain Master Browser. The
159da6c28aaSamw  * Domain Master Browser periodically acts as a client and queries all the
160da6c28aaSamw  * Local Master Browsers for its domain, asking them for a list containing
161da6c28aaSamw  * all the domains and all the servers in their domain known within their
162da6c28aaSamw  * subnets; it merges all the replies into a single master list. This
163da6c28aaSamw  * allows a Domain Master Browser server to act as a collection point for
164da6c28aaSamw  * inter-subnet browsing information. Local Master Browsers periodically
165da6c28aaSamw  * query the Domain Master Browser to retrieve the network-wide information
166da6c28aaSamw  * it maintains.
167da6c28aaSamw  *
168da6c28aaSamw  * When a domain spans only a single subnet, there will not be any distinct
169da6c28aaSamw  * Local Master Browser; this role will be handled by the Domain Master
170da6c28aaSamw  * Browser. Similarly, the Domain Master Browser is always the Local Master
171da6c28aaSamw  * Browser for the subnet it is on.
172da6c28aaSamw  *
173da6c28aaSamw  * When a browser client suspects that the Local Master Browser has failed,
174da6c28aaSamw  * the client will instigate an election in which the browser servers
175da6c28aaSamw  * participate, and some browser servers may change roles.
176da6c28aaSamw  *
177da6c28aaSamw  * Some characteristics of a good browsing mechanism include:
178da6c28aaSamw  * . minimal network traffic
179da6c28aaSamw  * . minimum server discovery time
180da6c28aaSamw  * . minimum change discovery latency
181da6c28aaSamw  * . immunity to machine failures
182da6c28aaSamw  *
183da6c28aaSamw  * Historically, Browser implementations had been very closely tied to
184da6c28aaSamw  * NETBIOS and datagrams. The early implementations caused a lot of
185da6c28aaSamw  * broadcast traffic. See Appendix D for an overview that presents how the
186da6c28aaSamw  * Browser specification evolved.
187da6c28aaSamw  *
188da6c28aaSamw  * 4. Browsing Protocol Architecture
189da6c28aaSamw  *
190da6c28aaSamw  * This section first describes the how the browsing protocol is layered,
191da6c28aaSamw  * then describes the roles of clients, servers, and browsers in the
192da6c28aaSamw  * browsing subsystem.
193da6c28aaSamw  *
194da6c28aaSamw  * 4.1 Layering of Browsing Protocol Requests
195da6c28aaSamw  *
196da6c28aaSamw  * Most of the browser functionality is implemented using mailslots.
197da6c28aaSamw  * Mailslots provide a mechanism for fast, unreliable unidirectional data
198da6c28aaSamw  * transfer; they are named via ASCII "mailslot (path) name". Mailslots are
199da6c28aaSamw  * implemented using the CIFS Transact SMB which is encapsulated in a
200da6c28aaSamw  * NETBIOS datagram. Browser protocol requests are sent to browser specific
201da6c28aaSamw  * mailslots using some browser-specific NETBIOS names. These datagrams can
202da6c28aaSamw  * either be unicast or broadcast, depending on whether the NETBIOS name is
203da6c28aaSamw  * a "unique name" or a "group name". Various data structures, which are
204da6c28aaSamw  * detailed subsequently within this document, flow as the data portion of
205da6c28aaSamw  * the Transact SMB.
206da6c28aaSamw  *
207da6c28aaSamw  * Here is an example of a generic browser SMB, showing how a browser
208da6c28aaSamw  * request is encapsulated in a TRANSACT SMB request. Note that the PID,
209da6c28aaSamw  * TID, MID, UID, and Flags are all 0 in mailslot requests.
210da6c28aaSamw  *
211da6c28aaSamw  * SMB: C transact, File = \MAILSLOT\BROWSE
212da6c28aaSamw  *   SMB: SMB Status = Error Success
213da6c28aaSamw  *     SMB: Error class = No Error
214da6c28aaSamw  *     SMB: Error code = No Error
215da6c28aaSamw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
216da6c28aaSamw  *     SMB: Tree ID   (TID) = 0 (0x0)
217da6c28aaSamw  *     SMB: Process ID  (PID) = 0 (0x0)
218da6c28aaSamw  *     SMB: User ID   (UID) = 0 (0x0)
219da6c28aaSamw  *     SMB: Multiplex ID (MID) = 0 (0x0)
220da6c28aaSamw  *     SMB: Flags Summary = 0 (0x0)
221da6c28aaSamw  *   SMB: Command = C transact
222da6c28aaSamw  *     SMB: Word count = 17
223da6c28aaSamw  *     SMB: Word parameters
224da6c28aaSamw  *     SMB: Total parm bytes = 0
225da6c28aaSamw  *     SMB: Total data bytes = 33
226da6c28aaSamw  *     SMB: Max parm bytes = 0
227da6c28aaSamw  *     SMB: Max data bytes = 0
228da6c28aaSamw  *     SMB: Max setup words = 0
229da6c28aaSamw  *     SMB: Transact Flags Summary = 0 (0x0)
230da6c28aaSamw  *       SMB: ...............0 = Leave session intact
231da6c28aaSamw  *       SMB: ..............0. = Response required
232da6c28aaSamw  *     SMB: Transact timeout = 0 (0x0)
233da6c28aaSamw  *     SMB: Parameter bytes = 0 (0x0)
234da6c28aaSamw  *     SMB: Parameter offset = 0 (0x0)
235da6c28aaSamw  *     SMB: Data bytes = 33 (0x21)
236da6c28aaSamw  *     SMB: Data offset = 86 (0x56)
237da6c28aaSamw  *     SMB: Setup word count = 3
238da6c28aaSamw  *     SMB: Setup words
239da6c28aaSamw  *     SMB: Mailslot opcode = Write mailslot
240da6c28aaSamw  *     SMB: Transaction priority = 1
241da6c28aaSamw  *     SMB: Mailslot class = Unreliable (broadcast)
242da6c28aaSamw  *     SMB: Byte count = 50
243da6c28aaSamw  *     SMB: Byte parameters
244da6c28aaSamw  *     SMB: Path name = \MAILSLOT\BROWSE
245da6c28aaSamw  *     SMB: Transaction data
246da6c28aaSamw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
247da6c28aaSamw  *
248da6c28aaSamw  * Note the SMB command is Transact, the opcode within the Transact SMB is
249da6c28aaSamw  * Mailslot Write, and the browser data structure is carried as the
250da6c28aaSamw  * Transact data.
251da6c28aaSamw  * The Transaction data begins with an opcode, that signifies the operation
252da6c28aaSamw  * and determines the size and structure of data that follows. This opcode
253da6c28aaSamw  * is named as per one of the below:
254da6c28aaSamw  *
255da6c28aaSamw  * HostAnnouncement         1
256da6c28aaSamw  * AnnouncementRequest      2
257da6c28aaSamw  * RequestElection          8
258da6c28aaSamw  * GetBackupListReq         9
259da6c28aaSamw  * GetBackupListResp        10
260da6c28aaSamw  * BecomeBackup             11
261da6c28aaSamw  * DomainAnnouncment        12
262da6c28aaSamw  * MasterAnnouncement       13
263da6c28aaSamw  * LocalMasterAnnouncement  15
264da6c28aaSamw  *
265da6c28aaSamw  * Browser datagrams are often referred to as simply browser frames. The
266da6c28aaSamw  * frames are in particular, referred to by the name of the opcode within
267da6c28aaSamw  * the Transaction data e.g. a GetBackupListReq browser frame, a
268da6c28aaSamw  * RequestElection browser frame, etc.
269da6c28aaSamw  *
270da6c28aaSamw  * The structures that are sent as the data portion of the Transact SMB are
271da6c28aaSamw  * described in section(s) 6.2 through 6.12 in this document. These
272da6c28aaSamw  * structures are tightly packed, i.e. there are no intervening pad bytes
273da6c28aaSamw  * in the structure, unless they are explicitly described as being there.
274da6c28aaSamw  * All quantities are sent in native Intel format and multi-byte values are
275da6c28aaSamw  * transmitted least significant byte first.
276da6c28aaSamw  *
277da6c28aaSamw  * Besides mailslots and Transaction SMBs, the other important piece of the
278da6c28aaSamw  * browser architecture is the NetServerEnum2 request. This request that
279da6c28aaSamw  * allows an application to interrogate a Browser Server and obtain a
280da6c28aaSamw  * complete list of resources (servers, domains, etc) known to that Browser
281da6c28aaSamw  * server. Details of the NetServerEnum2 request are presented in section
282da6c28aaSamw  * 6.4. Some examples of the NetServerEnum2 request being used are when a
283da6c28aaSamw  * Local Master Browser sends a NetServerEnum2 request to the Domain Master
284da6c28aaSamw  * Browser and vice versa. Another example is when a browser client sends a
285da6c28aaSamw  * NetServerEnum2 request to a Backup Browser server.
286da6c28aaSamw  *
287da6c28aaSamw  * 4.3 Non-Browser Server
288da6c28aaSamw  *
289da6c28aaSamw  * A non-browser server is a server that has some resource(s) or service(s)
290da6c28aaSamw  * it wishes to advertise as being available using the browsing protocol.
291da6c28aaSamw  * Examples of non-browser servers would be an SQL server, print server,
292da6c28aaSamw  * etc.
293da6c28aaSamw  *
294da6c28aaSamw  * A non-browser server MUST periodically send a HostAnnouncement browser
295da6c28aaSamw  * frame, specifying the type of resources or services it is advertising.
296da6c28aaSamw  * Details are in section 6.5.
297da6c28aaSamw  *
298da6c28aaSamw  * A non-browser server SHOULD announce itself relatively frequently when
299da6c28aaSamw  * it first starts up in order to make its presence quickly known to the
300da6c28aaSamw  * browsers and thence to potential clients. The frequency of the
301da6c28aaSamw  * announcements SHOULD then be gradually stretched, so as to minimize
302da6c28aaSamw  * network traffic. Typically,  non-browser servers announce themselves
303da6c28aaSamw  * once every minute upon start up and then gradually adjust the frequency
304da6c28aaSamw  * of the announcements to once every 12 minutes.
305da6c28aaSamw  *
306da6c28aaSamw  * A non-browser server SHOULD send a HostAnnouncement browser frame
307da6c28aaSamw  * specifying a type of  0 just prior to shutting down, to allow it to
308da6c28aaSamw  * quickly be removed from the list of available servers.
309da6c28aaSamw  *
310da6c28aaSamw  * A non-browser server MUST receive and process AnnouncementRequest frames
311da6c28aaSamw  * from the Local Master Browser, and MUST respond with a HostAnnouncement
312da6c28aaSamw  * frame, after a delay chosen randomly from the interval [0,30] seconds.
313da6c28aaSamw  * AnnouncementRequests typically happen when a Local Master Browser starts
314da6c28aaSamw  * up with an empty list of servers for the domain, and wants to fill it
315da6c28aaSamw  * quickly. The 30 second range for responses prevents the Master Browser
316da6c28aaSamw  * from becoming overloaded and losing replies, as well as preventing the
317da6c28aaSamw  * network from being flooded with responses.
318da6c28aaSamw  *
319da6c28aaSamw  * 4.4  Browser Servers
320da6c28aaSamw  *
321da6c28aaSamw  * The following sections describe the roles of the various types of
322da6c28aaSamw  * browser servers.
323da6c28aaSamw  *
324da6c28aaSamw  * 4.4.1  Potential Browser Server
325da6c28aaSamw  *
326da6c28aaSamw  * A Potential Browser server is a browser server that is capable of being
327da6c28aaSamw  * a Backup Browser server or Master Browser server, but is not currently
328da6c28aaSamw  * fulfilling either of those roles.
329da6c28aaSamw  *
330da6c28aaSamw  * A Potential Browser MUST set type SV_TYPE_POTENTIAL_BROWSER (see section
331da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
332da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
333da6c28aaSamw  * type of  0.
334da6c28aaSamw  *
335da6c28aaSamw  * A Potential Browser server MUST receive and process BecomeBackup frames
336da6c28aaSamw  * (see section 6.9) and become a backup browser upon their receipt.
337da6c28aaSamw  *
338da6c28aaSamw  * A Potential Browser MUST participate in browser elections (see section
339da6c28aaSamw  * 6.8).
340da6c28aaSamw  *
341da6c28aaSamw  * 4.4.2  Backup Browser
342da6c28aaSamw  *
343da6c28aaSamw  * Backup Browser servers are a subset of the Potential Browsers that have
344da6c28aaSamw  * been chosen by the Master Browser on their subnet to be the Backup
345da6c28aaSamw  * Browsers for the subnet.
346da6c28aaSamw  *
347da6c28aaSamw  * A Backup Browser MUST set type SV_TYPE_BACKUP_BROWSER (see section
348da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
349da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
350da6c28aaSamw  * type of  0.
351da6c28aaSamw  *
352da6c28aaSamw  * A Backup Browser MUST listen for a LocalMasterAnnouncement frame (see
353da6c28aaSamw  * section 6.10) from the Local Master Browser, and use it to set the name
354da6c28aaSamw  * of the Master Browser it queries for the server and domain lists.
355da6c28aaSamw  *
356da6c28aaSamw  * A  Backup Browsers MUST periodically make a NetServerEnum2 request of
357da6c28aaSamw  * the Master Browser on its subnet for its domain to get a list of servers
358da6c28aaSamw  * in that domain, as well as a list of domains. The period is a
359da6c28aaSamw  * configuration option balancing currency of the information with network
360da6c28aaSamw  * traffic costs - a typical value is 15 minutes.
361da6c28aaSamw  *
362da6c28aaSamw  * A Backup Browser SHOULD force an election by sending a RequestElection
363da6c28aaSamw  * frame (see section 6.7) if it does not get a response to its periodic
364da6c28aaSamw  * NetServeEnum2 request to the Master Browser.
365da6c28aaSamw  *
366da6c28aaSamw  * A Backup Browser MUST receive and process NetServerEnum2 requests from
367da6c28aaSamw  * browser clients, for its own domain and others. If the request is for a
368da6c28aaSamw  * list of servers in its domain, or for a list of domains, it can answer
369da6c28aaSamw  * from its internal lists. If the request is for a list of servers in a
370da6c28aaSamw  * domain different than the one it serves, it sends a NetServerEnum2
371da6c28aaSamw  * request to the Domain Master Browser for that domain (which it can in
372da6c28aaSamw  * find in its list of domains and their Domain Master Browsers).
373da6c28aaSamw  *
374da6c28aaSamw  * A Backup Browser MUST participate in browser elections (see section
375da6c28aaSamw  * 6.8).
376da6c28aaSamw  *
377da6c28aaSamw  * 4.4.3 Master Browser
378da6c28aaSamw  *
379da6c28aaSamw  * Master Browsers are responsible for:
380da6c28aaSamw  * . indicating it is a Master Browser
381da6c28aaSamw  * . receiving server announcements and building a list of such servers
382da6c28aaSamw  *   and keeping it reasonably up-to-date.
383da6c28aaSamw  * . returning lists of Backup Browsers to browser clients.
384da6c28aaSamw  * . ensuring an appropriate number of Backup Browsers are available.
385da6c28aaSamw  * . announcing their existence to other Master Browsers on their subnet,
386da6c28aaSamw  *   to the Domain Master Browser for their domain, and to all browsers in
387da6c28aaSamw  *   their domain on their subnet
388da6c28aaSamw  * . forwarding requests for lists of servers on other domains to the
389da6c28aaSamw  *   Master Browser for that domain
390da6c28aaSamw  * . keeping a list of domains in its subnet
391da6c28aaSamw  * . synchronizing with the Domain Master Browser (if any) for its domain
392da6c28aaSamw  * . participating in browser elections
393da6c28aaSamw  * . ensuring that there is only one Master Browser on its subnet
394da6c28aaSamw  *
395da6c28aaSamw  * A Master Browser MUST set type SV_TYPE_MASTER_BROWSER (see section
396da6c28aaSamw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
397da6c28aaSamw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
398da6c28aaSamw  * type of  0.
399da6c28aaSamw  *
400da6c28aaSamw  * A Master Browser MUST receive and process HostAnnouncement frames from
401da6c28aaSamw  * servers, adding the server name and other information to its servers
402da6c28aaSamw  * list; it must mark them as "local" entries. Periodically, it MUST check
403da6c28aaSamw  * all local server entries to see if a server's HostAnnouncement has timed
404da6c28aaSamw  * out (no HostAnnouncement received for three times the periodicity the
405da6c28aaSamw  * server gave in the last received HostAnnouncement) and remove timed-out
406da6c28aaSamw  * servers from its list.
407da6c28aaSamw  *
408da6c28aaSamw  * A Master Browser MUST receive and process DomainAnnouncement frames (see
409da6c28aaSamw  * section 6.12) and maintain the domain names and their associated (Local)
410da6c28aaSamw  * Master Browsers in its internal domain list until they time out; it must
411da6c28aaSamw  * mark these as "local" entries. Periodically, it MUST check all local
412da6c28aaSamw  * domain entries to see if a server's DomainAnnouncement has timed out (no
413da6c28aaSamw  * DomainAnnouncement received for three times the periodicity the server
414da6c28aaSamw  * gave in the last received DomainAnnouncement) and remove timed-out
415da6c28aaSamw  * servers from its list.
416da6c28aaSamw  *
417da6c28aaSamw  * A Master Browser MUST receive and process GetBackupListRequest frames
418da6c28aaSamw  * from clients, returning GetBackupListResponse frames containing a list
419da6c28aaSamw  * of the Backup Servers for its domain.
420da6c28aaSamw  *
421da6c28aaSamw  * A Master Browser MUST eventually send BecomeBackup frames (see section
422da6c28aaSamw  * 6.9) to one or more Potential Browser servers to increase the number of
423da6c28aaSamw  * Backup Browsers if there are not enough Backup Browsers to handle the
424da6c28aaSamw  * anticipated query load. Note: possible good times for checking for
425da6c28aaSamw  * sufficient backup browsers are after being elected, when timing out
426da6c28aaSamw  * server HostAnnouncements, and when receiving a server's HostAnnouncement
427da6c28aaSamw  * for the first time.
428da6c28aaSamw  *
429da6c28aaSamw  * A Master Browser MUST periodically announce itself and the domain it
430da6c28aaSamw  * serves to other (Local) Master Browsers on its subnet, by sending a
431da6c28aaSamw  * DomainAnnouncement frame (see section 6.12) to its subnet.
432da6c28aaSamw  *
433da6c28aaSamw  * A Master Browser MUST send a MasterAnnouncement frame (see section 6.11)
434da6c28aaSamw  * to the Domain Master Browser after it is first elected, and periodically
435da6c28aaSamw  * thereafter. This informs the Domain Master Browser of the presence of
436da6c28aaSamw  * all the Master Browsers.
437da6c28aaSamw  *
438da6c28aaSamw  * A Master Browser MUST periodically announce itself to all browsers for
439da6c28aaSamw  * its domain on its subnet by sending a LocalMasterAnnouncement frame (see
440da6c28aaSamw  * section 6.10).
441da6c28aaSamw  *
442da6c28aaSamw  * A Master Browser MUST receive and process NetServerEnum2 requests from
443da6c28aaSamw  * browser clients, for its own domain and others. If the request is for a
444da6c28aaSamw  * list of servers in its domain, or for a list of domains, it can answer
445da6c28aaSamw  * from its internal lists. Entries in its list marked "local" MUST have
446da6c28aaSamw  * the SV_TYPE_LOCAL_LIST_ONLY bit set in the returned results; it must be
447da6c28aaSamw  * clear for all other entries. If the request is for a list of servers in
448da6c28aaSamw  * a domain different than the one it serves, it sends a NetServerEnum2
449da6c28aaSamw  * request to the Domain Master Browser for that domain (which it can in
450da6c28aaSamw  * find in its list of domains and their Domain Master Browsers).
451da6c28aaSamw  *
452da6c28aaSamw  *     Note: The list of servers that the Master Browser maintains and
453da6c28aaSamw  *     returns to the Backup Browsers, is limited in size to 64K of
454da6c28aaSamw  *     data. This will limit the number of systems that can be in a
455da6c28aaSamw  *     browse list in a single workgroup or domain to approximately two
456da6c28aaSamw  *     thousand systems.
457da6c28aaSamw  *
458da6c28aaSamw  * A Master Browser SHOULD request all servers to register with it by
459da6c28aaSamw  * sending an AnnouncementRequest frame, if, on becoming the Master Browser
460da6c28aaSamw  * by winning an election, its server list is empty. Otherwise, clients
461da6c28aaSamw  * might get an incomplete list of servers until the servers' periodic
462da6c28aaSamw  * registrations fill the server list.
463da6c28aaSamw  *
464da6c28aaSamw  * If the Master Browser on a subnet is not the Primary Domain Controller
465da6c28aaSamw  * (PDC), then it is a Local Master Browser.
466da6c28aaSamw  *
467da6c28aaSamw  * A Local Master Browser MUST periodically synchronize with the Domain
468da6c28aaSamw  * Master Browser (which is the PDC). This synchronization is performed by
469da6c28aaSamw  * making a NetServerEnum2 request to the Domain Master Browser and merging
470da6c28aaSamw  * the results with its list of servers and domains. An entry from the
471da6c28aaSamw  * Domain Master Browser should be marked "non-local", and must not
472da6c28aaSamw  * overwrite an entry with the same name marked "local". The Domain Master
473da6c28aaSamw  * Browser is located as specified in Appendix B.
474da6c28aaSamw  *
475da6c28aaSamw  * A Master Browser MUST participate in browser elections (see section
476da6c28aaSamw  * 6.8).
477da6c28aaSamw  *
478da6c28aaSamw  * A Master Browser MUST, if it receives a HostAnnouncement,
479da6c28aaSamw  * DomainAnnouncement, or LocalMasterAnnouncement frame another system that
480da6c28aaSamw  * claims to be the Master Browser for its domain, demote itself from
481da6c28aaSamw  * Master Browser and force an election. This ensures that there is only
482da6c28aaSamw  * ever one Master Browser in each workgroup or domain.
483da6c28aaSamw  *
484da6c28aaSamw  * A Master Browser SHOULD, if it loses an election, become a Backup
485da6c28aaSamw  * Browser (without being told to do so by the new Master Browser). Since
486da6c28aaSamw  * it has more up-to-date information in its lists than a Potential
487da6c28aaSamw  * Browser, it is more efficient to have it be a Backup Browser than to
488da6c28aaSamw  * promote a Potential Browser.
489da6c28aaSamw  *
490da6c28aaSamw  * 4.4.3.1 Preferred Master Browser
491da6c28aaSamw  *
492da6c28aaSamw  * A Preferred Master Browser supports exactly the same protocol elements
493da6c28aaSamw  * as a Potential Browser, except as follows.
494da6c28aaSamw  *
495da6c28aaSamw  * A Preferred Master Browser MUST always force an election when it starts
496da6c28aaSamw  * up.
497da6c28aaSamw  *
498da6c28aaSamw  * A Preferred Master Browser MUST participate in browser elections (see
499da6c28aaSamw  * section 6.8).
500da6c28aaSamw  *
501da6c28aaSamw  * A Preferred Master Browser MUST set the Preferred Master bit in the
502da6c28aaSamw  * RequestElection frame (see section 6.7) to bias the election in its
503da6c28aaSamw  * favor.
504da6c28aaSamw  *
505da6c28aaSamw  * A Preferred Master Browser SHOULD, if it loses an election,
506da6c28aaSamw  * automatically become a Backup Browser, without being told to do so by
507da6c28aaSamw  * the Master Browser.
508da6c28aaSamw  *
509da6c28aaSamw  * 4.4.4 Domain Master Browser
510da6c28aaSamw  *
511da6c28aaSamw  * Since the Domain Master Browser always runs on the PDC, it must
512da6c28aaSamw  * implement all the protocols required of a PDC in addition to the
513da6c28aaSamw  * browsing protocol, and that is way beyond the scope of this
514da6c28aaSamw  * specification.
515da6c28aaSamw  *
516da6c28aaSamw  * 5. Mailslot Protocol Specification
517da6c28aaSamw  *
518da6c28aaSamw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
519da6c28aaSamw  * writes requests are encapsulated in TRANSACT SMBs. The following table
520da6c28aaSamw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
521da6c28aaSamw  * transaction:
522da6c28aaSamw  *
523da6c28aaSamw  *  Name            Value               Description
524da6c28aaSamw  *  Command         SMB_COM_TRANSACTION
525da6c28aaSamw  *  Name            <name>              STRING name of mail slot to write;
526da6c28aaSamw  *                                      must start with "\\MAILSLOT\\"
527da6c28aaSamw  *  SetupCount      3                   Always 3 for mailslot writes
528da6c28aaSamw  *  Setup[0]        1                   Command code == write mailslot
529da6c28aaSamw  *  Setup[1]        Ignored
530da6c28aaSamw  *  Setup[2]        Ignored
531da6c28aaSamw  *  TotalDataCount  n                   Size of data in bytes to write to
532da6c28aaSamw  *                                      the mailslot
533da6c28aaSamw  *  Data[ n ]                           The data to write to the mailslot
534da6c28aaSamw  *
535da6c28aaSamw  */
536da6c28aaSamw 
537da6c28aaSamw /*
538da6c28aaSamw  * SMB: C transact, File = \MAILSLOT\BROWSE
539da6c28aaSamw  *   SMB: SMB Status = Error Success
540da6c28aaSamw  *     SMB: Error class = No Error
541da6c28aaSamw  *     SMB: Error code = No Error
542da6c28aaSamw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
543da6c28aaSamw  *     SMB: Tree ID   (TID) = 0 (0x0)
544da6c28aaSamw  *     SMB: Process ID  (PID) = 0 (0x0)
545da6c28aaSamw  *     SMB: User ID   (UID) = 0 (0x0)
546da6c28aaSamw  *     SMB: Multiplex ID (MID) = 0 (0x0)
547da6c28aaSamw  *     SMB: Flags Summary = 0 (0x0)
548da6c28aaSamw  *   SMB: Command = C transact
549da6c28aaSamw  *     SMB: Word count = 17
550da6c28aaSamw  *     SMB: Word parameters
551da6c28aaSamw  *     SMB: Total parm bytes = 0
552da6c28aaSamw  *     SMB: Total data bytes = 33
553da6c28aaSamw  *     SMB: Max parm bytes = 0
554da6c28aaSamw  *     SMB: Max data bytes = 0
555da6c28aaSamw  *     SMB: Max setup words = 0
556da6c28aaSamw  *     SMB: Transact Flags Summary = 0 (0x0)
557da6c28aaSamw  *       SMB: ...............0 = Leave session intact
558da6c28aaSamw  *       SMB: ..............0. = Response required
559da6c28aaSamw  *     SMB: Transact timeout = 0 (0x0)
560da6c28aaSamw  *     SMB: Parameter bytes = 0 (0x0)
561da6c28aaSamw  *     SMB: Parameter offset = 0 (0x0)
562da6c28aaSamw  *     SMB: Data bytes = 33 (0x21)
563da6c28aaSamw  *     SMB: Data offset = 86 (0x56)
564da6c28aaSamw  *     SMB: Setup word count = 3
565da6c28aaSamw  *     SMB: Setup words
566da6c28aaSamw  *     SMB: Mailslot opcode = Write mailslot
567da6c28aaSamw  *     SMB: Transaction priority = 1
568da6c28aaSamw  *     SMB: Mailslot class = Unreliable (broadcast)
569da6c28aaSamw  *     SMB: Byte count = 50
570da6c28aaSamw  *     SMB: Byte parameters
571da6c28aaSamw  *     SMB: Path name = \MAILSLOT\BROWSE
572da6c28aaSamw  *     SMB: Transaction data
573da6c28aaSamw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
574da6c28aaSamw  *
575da6c28aaSamw  * 5. Mailslot Protocol Specification
576da6c28aaSamw  *
577da6c28aaSamw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
578da6c28aaSamw  * writes requests are encapsulated in TRANSACT SMBs. The following table
579da6c28aaSamw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
580da6c28aaSamw  * transaction:
581da6c28aaSamw  *
582da6c28aaSamw  *  Name            Value               Description
583da6c28aaSamw  *  Command         SMB_COM_TRANSACTION
584da6c28aaSamw  *  Name            <name>              STRING name of mail slot to write;
585da6c28aaSamw  *                                      must start with "\MAILSLOT\"
586da6c28aaSamw  *  SetupCount      3                   Always 3 for mailslot writes
587da6c28aaSamw  *  Setup[0]        1                   Command code == write mailslot
588da6c28aaSamw  *  Setup[1]        Ignored
589da6c28aaSamw  *  Setup[2]        Ignored
590da6c28aaSamw  *  TotalDataCount  n                   Size of data in bytes to write to
591da6c28aaSamw  *                                      the mailslot
592da6c28aaSamw  *  Data[ n ]                           The data to write to the mailslot
593da6c28aaSamw  *
594da6c28aaSamw  *	Magic		0xFF 'S' 'M' 'B'
595da6c28aaSamw  *	smb_com 	a byte, the "first" command
596da6c28aaSamw  *	Error		a 4-byte union, ignored in a request
597da6c28aaSamw  *	smb_flg		a one byte set of eight flags
598da6c28aaSamw  *	smb_flg2	a two byte set of 16 flags
599da6c28aaSamw  *	.		twelve reserved bytes, have a role
600da6c28aaSamw  *			in connectionless transports (IPX, UDP?)
601da6c28aaSamw  *	smb_tid		a 16-bit tree ID, a mount point sorta,
602da6c28aaSamw  *			0xFFFF is this command does not have
603da6c28aaSamw  *			or require a tree context
604da6c28aaSamw  *	smb_pid		a 16-bit process ID
605da6c28aaSamw  *	smb_uid		a 16-bit user ID, specific to this "session"
606da6c28aaSamw  *			and mapped to a system (bona-fide) UID
607da6c28aaSamw  *	smb_mid		a 16-bit multiplex ID, used to differentiate
608da6c28aaSamw  *			multiple simultaneous requests from the same
609da6c28aaSamw  *			process (pid) (ref RPC "xid")
610da6c28aaSamw  */
611da6c28aaSamw 
612da6c28aaSamw int
613da6c28aaSamw smb_browser_load_transact_header(unsigned char *buffer, int maxcnt,
614da6c28aaSamw 	int data_count, int reply, char *mailbox)
615da6c28aaSamw {
616da6c28aaSamw 	smb_msgbuf_t mb;
617da6c28aaSamw 	int	mailboxlen;
618da6c28aaSamw 	char *fmt;
619da6c28aaSamw 	int result;
620da6c28aaSamw 	short	class = (reply == ONE_WAY_TRANSACTION) ? 2 : 0;
621da6c28aaSamw 
622da6c28aaSamw 	/*
623da6c28aaSamw 	 * If the mailboxlen is an even number we need to pad the
624da6c28aaSamw 	 * header so that the data starts on a word boundary.
625da6c28aaSamw 	 */
626da6c28aaSamw 	fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws";
627da6c28aaSamw 	mailboxlen = strlen(mailbox) + 1;
628da6c28aaSamw 
629da6c28aaSamw 	if ((mailboxlen & 0x01) == 0) {
630da6c28aaSamw 		++mailboxlen;
631da6c28aaSamw 		fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws.";
632da6c28aaSamw 	}
633da6c28aaSamw 
634da6c28aaSamw 	bzero(buffer, maxcnt);
635da6c28aaSamw 	smb_msgbuf_init(&mb, buffer, maxcnt, 0);
636da6c28aaSamw 
637da6c28aaSamw 	result = smb_msgbuf_encode(&mb, fmt,
638da6c28aaSamw 	    SMB_COM_TRANSACTION,	/* Command */
639da6c28aaSamw 	    0x18,
640da6c28aaSamw 	    0x3,
641da6c28aaSamw 	    17,				/* Count of parameter words */
642da6c28aaSamw 	    0,				/* Total Parameter words sent */
643da6c28aaSamw 	    data_count,			/* Total Data bytes sent */
644da6c28aaSamw 	    2,				/* Max Parameters to return */
645da6c28aaSamw 	    0,				/* Max data bytes to return */
646da6c28aaSamw 	    0,				/* Max setup bytes to return */
647da6c28aaSamw 	    reply,			/* No reply */
648da6c28aaSamw 	    0xffffffff,			/* Timeout */
649da6c28aaSamw 	    0,				/* Parameter bytes sent */
650da6c28aaSamw 	    0,				/* Parameter offset */
651da6c28aaSamw 	    data_count,			/* Data bytes sent */
652da6c28aaSamw 	    69 + mailboxlen,		/* Data offset */
653da6c28aaSamw 	    3,				/* Setup word count */
654da6c28aaSamw 	    1,				/* Setup word[0] */
655da6c28aaSamw 	    0,				/* Setup word[1] */
656da6c28aaSamw 	    class,			/* Setup word[2] */
657da6c28aaSamw 	    mailboxlen + data_count,	/* Total request bytes */
658da6c28aaSamw 	    mailbox);			/* Mailbox address */
659da6c28aaSamw 
660da6c28aaSamw 	smb_msgbuf_term(&mb);
661da6c28aaSamw 	return (result);
662da6c28aaSamw }
663da6c28aaSamw 
664da6c28aaSamw /*
665da6c28aaSamw  * smb_net_id
666da6c28aaSamw  *
667da6c28aaSamw  * Lookup for the given IP in the NICs info table.
668da6c28aaSamw  * If it finds a matching entry it'll return the index,
669da6c28aaSamw  * otherwise returns -1.
670da6c28aaSamw  *
671da6c28aaSamw  * SMB network table and SMB browser info table share
672da6c28aaSamw  * the same index.
673da6c28aaSamw  */
674da6c28aaSamw int
675da6c28aaSamw smb_net_id(uint32_t ipaddr)
676da6c28aaSamw {
677da6c28aaSamw 	uint32_t myaddr, mask;
678da6c28aaSamw 	int net, smb_nc_cnt;
679da6c28aaSamw 
680da6c28aaSamw 	smb_nc_cnt = smb_nic_get_num();
681da6c28aaSamw 	for (net = 0; net < smb_nc_cnt; net++) {
682da6c28aaSamw 		net_cfg_t cfg;
683da6c28aaSamw 		if (smb_nic_get_byind(net, &cfg) == NULL)
684da6c28aaSamw 			break;
685da6c28aaSamw 		mask = cfg.mask;
686da6c28aaSamw 		myaddr = cfg.ip;
687da6c28aaSamw 		if ((ipaddr & mask) == (myaddr & mask))
688da6c28aaSamw 			return (net);
689da6c28aaSamw 	}
690da6c28aaSamw 
691da6c28aaSamw 	return (-1);
692da6c28aaSamw }
693da6c28aaSamw 
694da6c28aaSamw /*
695da6c28aaSamw  * smb_browser_get_srvname
696da6c28aaSamw  *
697da6c28aaSamw  */
698da6c28aaSamw struct name_entry *
699da6c28aaSamw smb_browser_get_srvname(unsigned short netid)
700da6c28aaSamw {
701da6c28aaSamw 	if (netid < smb_nic_get_num())
702da6c28aaSamw 		return (&(smb_browser_info[netid].server.name));
703da6c28aaSamw 
704da6c28aaSamw 	return (NULL);
705da6c28aaSamw }
706da6c28aaSamw 
707da6c28aaSamw static int
708da6c28aaSamw smb_browser_addr_of_subnet(struct name_entry *name, int subnet,
709da6c28aaSamw     struct name_entry *result)
710da6c28aaSamw {
711da6c28aaSamw 	uint32_t ipaddr, mask, saddr;
712da6c28aaSamw 	struct addr_entry *addr;
713da6c28aaSamw 	int smb_nc_cnt;
714da6c28aaSamw 	net_cfg_t cfg;
715da6c28aaSamw 
716da6c28aaSamw 	smb_nc_cnt = smb_nic_get_num();
717da6c28aaSamw 	if ((name == 0) || subnet >= smb_nc_cnt)
718da6c28aaSamw 		return (-1);
719da6c28aaSamw 
720da6c28aaSamw 	if (smb_nic_get_byind(subnet, &cfg) == NULL)
721da6c28aaSamw 		return (-1);
722da6c28aaSamw 	ipaddr = cfg.ip;
723da6c28aaSamw 	mask = cfg.mask;
724da6c28aaSamw 
725da6c28aaSamw 	*result = *name;
726da6c28aaSamw 	addr = &name->addr_list;
727da6c28aaSamw 	do {
728da6c28aaSamw 		saddr = addr->sin.sin_addr.s_addr;
729da6c28aaSamw 		if ((saddr & mask) == (ipaddr & mask)) {
730da6c28aaSamw 			*result = *name;
731da6c28aaSamw 			result->addr_list = *addr;
732da6c28aaSamw 			result->addr_list.forw = result->addr_list.back =
733da6c28aaSamw 			    &result->addr_list;
734da6c28aaSamw 			return (0);
735da6c28aaSamw 		}
736da6c28aaSamw 		addr = addr->forw;
737da6c28aaSamw 	} while (addr != &name->addr_list);
738da6c28aaSamw 
739da6c28aaSamw 	return (-1);
740da6c28aaSamw }
741da6c28aaSamw 
742da6c28aaSamw 
743da6c28aaSamw static int
744da6c28aaSamw smb_browser_bcast_addr_of_subnet(struct name_entry *name, int net,
745da6c28aaSamw     struct name_entry *result)
746da6c28aaSamw {
747da6c28aaSamw 	uint32_t broadcast;
748da6c28aaSamw 	int smb_nc_cnt;
749da6c28aaSamw 	net_cfg_t cfg;
750da6c28aaSamw 
751da6c28aaSamw 	smb_nc_cnt = smb_nic_get_num();
752da6c28aaSamw 	if (net >= smb_nc_cnt)
753da6c28aaSamw 		return (-1);
754da6c28aaSamw 
755da6c28aaSamw 	if (name != 0 && name != result)
756da6c28aaSamw 		*result = *name;
757da6c28aaSamw 
758da6c28aaSamw 	if (smb_nic_get_byind(net, &cfg) == NULL)
759da6c28aaSamw 		return (-1);
760da6c28aaSamw 
761da6c28aaSamw 	broadcast = cfg.broadcast;
762da6c28aaSamw 	result->addr_list.sin.sin_family = AF_INET;
763da6c28aaSamw 	result->addr_list.sinlen = sizeof (result->addr_list.sin);
764da6c28aaSamw 	result->addr_list.sin.sin_addr.s_addr = broadcast;
765da6c28aaSamw 	result->addr_list.sin.sin_port = htons(DGM_SRVC_UDP_PORT);
766da6c28aaSamw 	result->addr_list.forw = result->addr_list.back = &result->addr_list;
767da6c28aaSamw 	return (0);
768da6c28aaSamw }
769da6c28aaSamw 
770da6c28aaSamw /*
771da6c28aaSamw  * 6.5 HostAnnouncement Browser Frame
772da6c28aaSamw  *
773da6c28aaSamw  * To advertise its presence, i.e. to publish itself as being available, a
774da6c28aaSamw  * non-browser server sends a HostAnnouncement browser frame. If the server
775da6c28aaSamw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
776da6c28aaSamw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE". The definition of  the
777da6c28aaSamw  * HostAnnouncement frame is:
778da6c28aaSamw  *
779da6c28aaSamw  *     struct {
780da6c28aaSamw  *         unsigned short  Opcode;
781da6c28aaSamw  *         unsigned char   UpdateCount;
782da6c28aaSamw  *         uint32_t   Periodicity;
783da6c28aaSamw  *         unsigned char   ServerName[];
784da6c28aaSamw  *         unsigned char   VersionMajor;
785da6c28aaSamw  *         unsigned char   VersionMinor;
786da6c28aaSamw  *         uint32_t   Type;
787da6c28aaSamw  *         uint32_t   Signature;
788da6c28aaSamw  *         unsigned char   Comment[];
789da6c28aaSamw  *     }
790da6c28aaSamw  *
791da6c28aaSamw  * where:
792da6c28aaSamw  *      Opcode - Identifies this structure as a browser server
793da6c28aaSamw  *          announcement and is defined as HostAnnouncement with a
794da6c28aaSamw  *          value of decimal 1.
795da6c28aaSamw  *
796da6c28aaSamw  *      UpdateCount - must be sent as zero and ignored on receipt.
797da6c28aaSamw  *
798da6c28aaSamw  *      Periodicity - The announcement frequency of the server (in
799da6c28aaSamw  *          seconds). The server will be removed from the browse list
800da6c28aaSamw  *          if it has not been heard from in 3X its announcement
801da6c28aaSamw  *          frequency. In no case will the server be removed from the
802da6c28aaSamw  *          browse list before the period 3X has elapsed. Actual
803da6c28aaSamw  *          implementations may take more than 3X to actually remove
804da6c28aaSamw  *          the server from the browse list.
805da6c28aaSamw  *
806da6c28aaSamw  *      ServerName - Null terminated ASCII server name (up to 16 bytes
807da6c28aaSamw  *          in length).
808da6c28aaSamw  *
809da6c28aaSamw  *      VersionMajor - The major version number of the OS the server
810da6c28aaSamw  *          is running. it will be returned by NetServerEnum2.
811da6c28aaSamw  *
812da6c28aaSamw  *      VersionMinor - The minor version number of the OS the server
813da6c28aaSamw  *          is running. This is entirely informational and does not
814da6c28aaSamw  *          have any significance for the browsing protocol.
815da6c28aaSamw  *
816da6c28aaSamw  *      Type - Specifies the type of the server. The server type bits
817da6c28aaSamw  *          are specified in the NetServerEnum2 section.
818da6c28aaSamw  *
819da6c28aaSamw  *      Signature -  The browser protocol minor version number in the
820da6c28aaSamw  *          low 8 bits, the browser protocol major version number in
821da6c28aaSamw  *          the next higher 8 bits and the signature 0xaa55 in the
822da6c28aaSamw  *          high 16 bits of this field. Thus, for this version of the
823da6c28aaSamw  *          browser protocol (1.15) this field has the value
824da6c28aaSamw  *          0xaa55010f. This may used to isolate browser servers that
825da6c28aaSamw  *          are running out of revision browser software; otherwise,
826da6c28aaSamw  *          it is ignored.
827da6c28aaSamw  *
828da6c28aaSamw  *      Comment - Null terminated ASCII comment for the server.
829da6c28aaSamw  *          Limited to 43 bytes.
830da6c28aaSamw  *
831da6c28aaSamw  * When a non-browser server starts up, it announces itself in the manner
832da6c28aaSamw  * described once every minute. The frequency of these statements is
833da6c28aaSamw  * gradually stretched to once every 12 minutes.
834da6c28aaSamw  *
835da6c28aaSamw  * Note: older non-browser servers in a domain "D" sent HostAnnouncement
836da6c28aaSamw  * frames to the NETBIOS group name D(00). Non-Browser servers supporting
837da6c28aaSamw  * version 1.15 of the browsing protocol SHOULD NOT use this NETBIOS name,
838da6c28aaSamw  * but for backwards compatibility Master Browsers MAY receive and process
839da6c28aaSamw  * HostAnnouncement frames on this name as described above for D(1d).
840da6c28aaSamw  */
841da6c28aaSamw 
842da6c28aaSamw void
843da6c28aaSamw smb_browser_send_HostAnnouncement(int net, int32_t next_announcement,
844da6c28aaSamw     struct addr_entry *addr, char suffix)
845da6c28aaSamw {
846da6c28aaSamw 	smb_msgbuf_t mb;
847da6c28aaSamw 	int offset, announce_len, data_length;
848da6c28aaSamw 	struct name_entry dest_name;
849da6c28aaSamw 	struct name_entry server_name;
850da6c28aaSamw 	struct browser_netinfo *subnet;
851da6c28aaSamw 	server_info_t *server;
852da6c28aaSamw 	unsigned char *buffer;
853da6c28aaSamw 	uint32_t type;
854da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
855da6c28aaSamw 
856*dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
857*dc20a302Sas 		return;
858da6c28aaSamw 	(void) utf8_strupr(resource_domain);
859da6c28aaSamw 
860da6c28aaSamw 	if (addr == 0) {
861da6c28aaSamw 		/* Local master Browser */
862da6c28aaSamw 		smb_init_name_struct(
863da6c28aaSamw 		    (unsigned char *)resource_domain, suffix,
864da6c28aaSamw 		    0, 0, 0, 0, 0, &dest_name);
865da6c28aaSamw 		if (smb_browser_bcast_addr_of_subnet(0, net, &dest_name) < 0)
866da6c28aaSamw 			return;
867da6c28aaSamw 	} else {
868da6c28aaSamw 		smb_init_name_struct(
869da6c28aaSamw 		    (unsigned char *)resource_domain, suffix,
870da6c28aaSamw 		    0, 0, 0, 0, 0, &dest_name);
871da6c28aaSamw 		dest_name.addr_list = *addr;
872da6c28aaSamw 		dest_name.addr_list.forw = dest_name.addr_list.back =
873da6c28aaSamw 		    &dest_name.addr_list;
874da6c28aaSamw 	}
875da6c28aaSamw 
876da6c28aaSamw 	/* give some extra room */
877da6c28aaSamw 	buffer = (unsigned char *)malloc(MAX_DATAGRAM_LENGTH * 2);
878da6c28aaSamw 	if (buffer == 0) {
879da6c28aaSamw 		syslog(LOG_ERR, "HostAnnouncement: resource shortage");
880da6c28aaSamw 		return;
881da6c28aaSamw 	}
882da6c28aaSamw 
883da6c28aaSamw 	subnet = smb_browser_getnet(net);
884da6c28aaSamw 	if (subnet == 0) {
885da6c28aaSamw 		free(buffer);
886da6c28aaSamw 		return;
887da6c28aaSamw 	}
888da6c28aaSamw 
889da6c28aaSamw 	server = &subnet->server;
890da6c28aaSamw 
891da6c28aaSamw 	data_length = 1 + 1 + 4 + 16 + 1 + 1 + 4 + 4 +
892da6c28aaSamw 	    strlen(server->comment) + 1;
893da6c28aaSamw 
894da6c28aaSamw 	if ((offset = smb_browser_load_transact_header(buffer,
895da6c28aaSamw 	    MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION,
896da6c28aaSamw 	    browse)) < 0) {
897da6c28aaSamw 
898da6c28aaSamw 		smb_browser_putnet(subnet);
899da6c28aaSamw 		free(buffer);
900da6c28aaSamw 		return;
901da6c28aaSamw 	}
902da6c28aaSamw 
903da6c28aaSamw 	/*
904da6c28aaSamw 	 * A non-browser server SHOULD send a HostAnnouncement browser frame
905da6c28aaSamw 	 * specifying a type of 0 just prior to shutting down, to allow it to
906da6c28aaSamw 	 * quickly be removed from the list of available servers.
907da6c28aaSamw 	 */
908da6c28aaSamw 	type = (nb_status.state & NETBIOS_SHUTTING_DOWN) ? 0 : server->type;
909da6c28aaSamw 
910da6c28aaSamw 	smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0);
911da6c28aaSamw 	announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls",
912da6c28aaSamw 	    (char)HOST_ANNOUNCEMENT,	/* Announcement opcode */
913da6c28aaSamw 	    (char)++subnet->server.update_count,
914da6c28aaSamw 	    next_announcement * 60000,	/* Periodicity in MilliSeconds */
915da6c28aaSamw 	    server->hostname, /* Server name */
916da6c28aaSamw 	    server->major,	/* our major version */
917da6c28aaSamw 	    server->minor,	/* our minor version */
918da6c28aaSamw 	    type,		/* server type  */
919da6c28aaSamw 	    server->signature,	/* Signature */
920da6c28aaSamw 	    server->comment);	/* Let 'em know */
921da6c28aaSamw 
922da6c28aaSamw 	server_name = server->name;
923da6c28aaSamw 	smb_browser_putnet(subnet);
924da6c28aaSamw 
925da6c28aaSamw 	if (announce_len > 0)
926da6c28aaSamw 		(void) smb_netbios_datagram_send(&server_name, &dest_name,
927da6c28aaSamw 		    buffer, offset + announce_len);
928da6c28aaSamw 
929da6c28aaSamw 	free(buffer);
930da6c28aaSamw 	smb_msgbuf_term(&mb);
931da6c28aaSamw }
932da6c28aaSamw 
933da6c28aaSamw void
934da6c28aaSamw smb_browser_process_AnnouncementRequest(struct datagram *datagram,
935da6c28aaSamw     char *mailbox)
936da6c28aaSamw {
937da6c28aaSamw 	struct browser_netinfo *subnet;
938da6c28aaSamw 	unsigned int next_announcement;
939da6c28aaSamw 	uint32_t delay = random() % 29; /* in seconds */
940da6c28aaSamw 	int	net;
941da6c28aaSamw 
942da6c28aaSamw 	if (strcmp(mailbox, lanman) != 0) {
943da6c28aaSamw 		syslog(LOG_DEBUG, "smb_browse: Wrong Mailbox (%s)", mailbox);
944da6c28aaSamw 		return;
945da6c28aaSamw 	}
946da6c28aaSamw 
947da6c28aaSamw 	net = smb_net_id(datagram->src.addr_list.sin.sin_addr.s_addr);
948da6c28aaSamw 	if (net < 0) {
949da6c28aaSamw 		/* We don't know who this is so ignore it... */
950da6c28aaSamw 		return;
951da6c28aaSamw 	}
952da6c28aaSamw 
953da6c28aaSamw 	(void) sleep(delay);
954da6c28aaSamw 
955da6c28aaSamw 	subnet = smb_browser_getnet(net);
956da6c28aaSamw 	if (subnet) {
957da6c28aaSamw 		next_announcement = subnet->next_announce * 60 * 1000;
958da6c28aaSamw 		smb_browser_putnet(subnet);
959da6c28aaSamw 		smb_browser_send_HostAnnouncement(net, next_announcement,
960da6c28aaSamw 		    &datagram->src.addr_list, 0x1D);
961da6c28aaSamw 	}
962da6c28aaSamw }
963da6c28aaSamw 
964da6c28aaSamw void *
965da6c28aaSamw smb_browser_dispatch(void *arg)
966da6c28aaSamw {
967da6c28aaSamw 	struct datagram *datagram = (struct datagram *)arg;
968da6c28aaSamw 	smb_msgbuf_t 	mb;
969da6c28aaSamw 	int		rc;
970da6c28aaSamw 	unsigned char	command;
971da6c28aaSamw 	unsigned char	parameter_words;
972da6c28aaSamw 	unsigned short	total_parameter_words;
973da6c28aaSamw 	unsigned short	total_data_count;
974da6c28aaSamw 	unsigned short	max_parameters_to_return;
975da6c28aaSamw 	unsigned short	max_data_to_return;
976da6c28aaSamw 	unsigned char	max_setup_bytes_to_return;
977da6c28aaSamw 	unsigned short	reply;
978da6c28aaSamw 	unsigned short	parameter_bytes_sent;
979da6c28aaSamw 	unsigned short	parameter_offset;
980da6c28aaSamw 	unsigned short	data_bytes_sent;
981da6c28aaSamw 	unsigned short	data_offset;
982da6c28aaSamw 	unsigned char	setup_word_count;
983da6c28aaSamw 	unsigned short	setup_word_0;
984da6c28aaSamw 	unsigned short	setup_word_1;
985da6c28aaSamw 	unsigned short	setup_word_2;
986da6c28aaSamw 	unsigned short	total_request_bytes;
987da6c28aaSamw 	char 		*mailbox;
988da6c28aaSamw 	unsigned char	message_type;
989da6c28aaSamw 	unsigned char 	*data;
990da6c28aaSamw 	int		datalen;
991da6c28aaSamw 
992da6c28aaSamw 	syslog(LOG_DEBUG, "smb_browse: packet_received");
993da6c28aaSamw 
994da6c28aaSamw 	smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0);
995da6c28aaSamw 	rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws",
996da6c28aaSamw 	    &command,			/* Command */
997da6c28aaSamw 	    &parameter_words,		/* Count of parameter words */
998da6c28aaSamw 	    &total_parameter_words,	/* Total Parameter words sent */
999da6c28aaSamw 	    &total_data_count,		/* Total Data bytes sent */
1000da6c28aaSamw 	    &max_parameters_to_return,	/* Max Parameters to return */
1001da6c28aaSamw 	    &max_data_to_return,	/* Max data bytes to return */
1002da6c28aaSamw 	    &max_setup_bytes_to_return,	/* Max setup bytes to return */
1003da6c28aaSamw 	    &reply,			/* No reply */
1004da6c28aaSamw 	    &parameter_bytes_sent,	/* Parameter bytes sent */
1005da6c28aaSamw 	    &parameter_offset,		/* Parameter offset */
1006da6c28aaSamw 	    &data_bytes_sent,		/* Data bytes sent */
1007da6c28aaSamw 	    &data_offset,		/* Data offset */
1008da6c28aaSamw 	    &setup_word_count,		/* Setup word count */
1009da6c28aaSamw 	    &setup_word_0,		/* Setup word[0] */
1010da6c28aaSamw 	    &setup_word_1,		/* Setup word[1] */
1011da6c28aaSamw 	    &setup_word_2,		/* Setup word[2] */
1012da6c28aaSamw 	    &total_request_bytes,	/* Total request bytes */
1013da6c28aaSamw 	    &mailbox);			/* Mailbox address */
1014da6c28aaSamw 
1015da6c28aaSamw 	if (rc < 0) {
1016da6c28aaSamw 		syslog(LOG_ERR, "smb_browser_dispatch: decode error");
1017da6c28aaSamw 		smb_msgbuf_term(&mb);
1018da6c28aaSamw 		free(datagram);
1019da6c28aaSamw 		return (0);
1020da6c28aaSamw 	}
1021da6c28aaSamw 
1022da6c28aaSamw 	data = &datagram->data[data_offset];
1023da6c28aaSamw 	datalen = datagram->data_length - data_offset;
1024da6c28aaSamw 
1025da6c28aaSamw 	/*
1026da6c28aaSamw 	 * The PDC location protocol, i.e. anything on the \\NET
1027da6c28aaSamw 	 * mailslot, is handled by the smb_netlogon module.
1028da6c28aaSamw 	 */
1029da6c28aaSamw 	if (strncasecmp("\\MAILSLOT\\NET\\", mailbox, 14) == 0) {
1030da6c28aaSamw 		smb_netlogon_receive(datagram, mailbox, data, datalen);
1031da6c28aaSamw 		smb_msgbuf_term(&mb);
1032da6c28aaSamw 		free(datagram);
1033da6c28aaSamw 		return (0);
1034da6c28aaSamw 	}
1035da6c28aaSamw 
1036da6c28aaSamw 	/*
1037da6c28aaSamw 	 * If it's not a netlogon message, assume it's a browser request.
1038da6c28aaSamw 	 * This is not the most elegant way to extract the command byte
1039da6c28aaSamw 	 * but at least we no longer use it to get the netlogon opcode.
1040da6c28aaSamw 	 */
1041da6c28aaSamw 	message_type = datagram->data[data_offset];
1042da6c28aaSamw 
1043da6c28aaSamw 	switch (message_type) {
1044da6c28aaSamw 	case ANNOUNCEMENT_REQUEST :
1045da6c28aaSamw 		smb_browser_process_AnnouncementRequest(datagram, mailbox);
1046da6c28aaSamw 		break;
1047da6c28aaSamw 
1048da6c28aaSamw 	default:
1049da6c28aaSamw 		syslog(LOG_DEBUG, "smb_browse: invalid message_type(%d, %x)",
1050da6c28aaSamw 		    message_type, message_type);
1051da6c28aaSamw 		break;
1052da6c28aaSamw 	}
1053da6c28aaSamw 
1054da6c28aaSamw 	smb_msgbuf_term(&mb);
1055da6c28aaSamw 	free(datagram);
1056da6c28aaSamw 	return (0);
1057da6c28aaSamw }
1058da6c28aaSamw 
1059da6c28aaSamw 
1060da6c28aaSamw /*
1061da6c28aaSamw  * 11.1 Registered unique names
1062da6c28aaSamw  *
1063da6c28aaSamw  *  <COMPUTER>(00)
1064da6c28aaSamw  *     This name is used by all servers and clients to receive second
1065da6c28aaSamw  *     class mailslot messages. A system must add this name in order to
1066da6c28aaSamw  *     receive mailslot messages. The only browser requests that should
1067da6c28aaSamw  *     appear on this name are BecomeBackup, GetBackupListResp,
1068da6c28aaSamw  *     MasterAnnouncement, and LocalMasterAnnouncement frames. All other
1069da6c28aaSamw  *     datagrams (other than the expected non-browser datagrams) may be
1070da6c28aaSamw  *     ignored and an error logged.
1071da6c28aaSamw  *
1072da6c28aaSamw  *   <DOMAIN>(1d)
1073da6c28aaSamw  *     This name is used to identify a master browser server for domain
1074da6c28aaSamw  *     "DOMAIN" on a subnet.  A master browser server adds this name as a
1075da6c28aaSamw  *     unique NETBIOS name when it becomes master browser. If the attempt
1076da6c28aaSamw  *     to add the name fails, the master browser server assumes that there
1077da6c28aaSamw  *     is another master in the domain and will fail to come up. It may
1078da6c28aaSamw  *     log an error if the failure occurs more than 3 times in a row (this
1079da6c28aaSamw  *     either indicates some form of network misconfiguration or a
1080da6c28aaSamw  *     software error). The only requests that should appear on this name
1081da6c28aaSamw  *     are GetBackupListRequest and HostAnnouncement requests. All other
1082da6c28aaSamw  *     datagrams on this name may be ignored (and an error logged). If
1083da6c28aaSamw  *     running a NETBIOS name service (NBNS, such as WINS), this name
1084da6c28aaSamw  *     should not be registered with the NBNS.
1085da6c28aaSamw  *
1086da6c28aaSamw  *   <DOMAIN>(1b)
1087da6c28aaSamw  *     This name is used to identify the Domain Master Browser for domain
1088da6c28aaSamw  *     "DOMAIN" (which is also the primary domain controller). It is a
1089da6c28aaSamw  *     unique name added only by the primary domain controller. The
1090da6c28aaSamw  *     primary domain controller will respond to GetBackupListRequest on
1091da6c28aaSamw  *     this name just as it responds to these requests on the <DOMAIN>(1d)
1092da6c28aaSamw  *     name.
1093da6c28aaSamw  *
1094da6c28aaSamw  * 11.2 Registered group names
1095da6c28aaSamw  *
1096da6c28aaSamw  *   (01)(02)__MSBROWSE__(02)(01)
1097da6c28aaSamw  *     This name is used by Master Browsers to announce themselves to the
1098da6c28aaSamw  *     other Master Browsers on a subnet. It is added as a group name by
1099da6c28aaSamw  *     all Master Browser servers. The only broadcasts that should appear
1100da6c28aaSamw  *     on this name is DomainAnnouncement requests. All other datagrams
1101da6c28aaSamw  *     can be ignored.
1102da6c28aaSamw  *
1103da6c28aaSamw  *   <DOMAIN>(00)
1104da6c28aaSamw  *     This name is used by clients and servers in domain "DOMAIN" to
1105da6c28aaSamw  *     process server announcements. The only requests that should appear
1106da6c28aaSamw  *     on this name that the browser is interested in are
1107da6c28aaSamw  *     AnnouncementRequest and NETLOGON_QUERY (to locate the PDC) packets.
1108da6c28aaSamw  *     All other unidentifiable requests may be ignored (and an error
1109da6c28aaSamw  *     logged).
1110da6c28aaSamw  *
1111da6c28aaSamw  *   <DOMAIN>(1E)
1112da6c28aaSamw  *     This name is used for announcements to browsers for domain "DOMAIN"
1113da6c28aaSamw  *     on a subnet. This name is registered by all the browser servers in
1114da6c28aaSamw  *     the domain. The only requests that should appear on this name are
1115da6c28aaSamw  *     RequestElection and AnnouncementRequest packets. All other
1116da6c28aaSamw  *     datagrams may be ignored (and an error logged).
1117da6c28aaSamw  *
1118da6c28aaSamw  *   <DOMAIN>(1C)
1119da6c28aaSamw  *     This name is registered by Primary Domain Controllers.
1120da6c28aaSamw  */
1121da6c28aaSamw 
1122da6c28aaSamw void
1123da6c28aaSamw smb_browser_config(void)
1124da6c28aaSamw {
1125da6c28aaSamw 	struct name_entry	name;
1126da6c28aaSamw 	struct name_entry	master;
1127da6c28aaSamw 	struct name_entry	dest;
1128da6c28aaSamw 	struct name_entry	*entry;
1129da6c28aaSamw 	int smb_nc_cnt;
1130da6c28aaSamw 	net_cfg_t cfg;
1131da6c28aaSamw 	int net;
1132da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
1133da6c28aaSamw 
1134da6c28aaSamw 	smb_browser_init();
1135*dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1136*dc20a302Sas 		return;
1137da6c28aaSamw 	(void) utf8_strupr(resource_domain);
1138da6c28aaSamw 
1139da6c28aaSamw 	/* domain<00> */
1140da6c28aaSamw 	smb_init_name_struct((unsigned char *)resource_domain, 0x00,
1141da6c28aaSamw 	    0, 0, 0, 0, 0, &name);
1142da6c28aaSamw 	entry = smb_name_find_name(&name);
1143da6c28aaSamw 	smb_name_unlock_name(entry);
1144da6c28aaSamw 
1145da6c28aaSamw 	smb_nc_cnt = smb_nic_get_num();
1146da6c28aaSamw 	for (net = 0; net < smb_nc_cnt; net++) {
1147da6c28aaSamw 		if (smb_nic_get_byind(net, &cfg) == NULL)
1148da6c28aaSamw 			break;
1149da6c28aaSamw 		if (cfg.exclude)
1150da6c28aaSamw 			continue;
1151da6c28aaSamw 		smb_init_name_struct(
1152da6c28aaSamw 		    (unsigned char *)resource_domain, 0x00, 0,
1153da6c28aaSamw 		    cfg.ip, htons(DGM_SRVC_UDP_PORT),
1154da6c28aaSamw 		    NAME_ATTR_GROUP, NAME_ATTR_LOCAL, &name);
1155da6c28aaSamw 		(void) smb_name_add_name(&name);
1156da6c28aaSamw 	}
1157da6c28aaSamw 
1158da6c28aaSamw 	/* All our local master browsers */
1159da6c28aaSamw 	smb_init_name_struct((unsigned char *)resource_domain, 0x1D,
1160da6c28aaSamw 	    0, 0, 0, 0, 0, &dest);
1161da6c28aaSamw 	entry = smb_name_find_name(&dest);
1162da6c28aaSamw 
1163da6c28aaSamw 	if (entry) {
1164da6c28aaSamw 		for (net = 0; net < smb_nc_cnt; net++) {
1165da6c28aaSamw 			if (smb_browser_addr_of_subnet(entry, net, &master)
1166da6c28aaSamw 			    == 0) {
1167da6c28aaSamw 				syslog(LOG_DEBUG,
1168da6c28aaSamw 				    "smbd: Master browser found at %s",
1169da6c28aaSamw 				    inet_ntoa(master.addr_list.sin.sin_addr));
1170da6c28aaSamw 			}
1171da6c28aaSamw 		}
1172da6c28aaSamw 		smb_name_unlock_name(entry);
1173da6c28aaSamw 	}
1174da6c28aaSamw 	smb_init_name_struct((unsigned char *)resource_domain,
1175da6c28aaSamw 	    0x1B, 0, 0, 0, 0, 0, &dest);
1176da6c28aaSamw 
1177da6c28aaSamw 	if ((entry = smb_name_find_name(&dest)) != 0) {
1178da6c28aaSamw 		syslog(LOG_DEBUG, "smbd: Domain Master browser for %s is %s",
1179da6c28aaSamw 		    resource_domain,
1180da6c28aaSamw 		    inet_ntoa(entry->addr_list.sin.sin_addr));
1181da6c28aaSamw 		smb_name_unlock_name(entry);
1182da6c28aaSamw 	}
1183da6c28aaSamw }
1184da6c28aaSamw 
1185da6c28aaSamw static void
1186da6c28aaSamw smb_browser_init()
1187da6c28aaSamw {
1188da6c28aaSamw 	struct browser_netinfo *subnet;
1189da6c28aaSamw 	struct server_info *server;
1190da6c28aaSamw 	char cmnt[SMB_PI_MAX_COMMENT], hostname[MAXHOSTNAMELEN];
1191da6c28aaSamw 	int i, j;
1192da6c28aaSamw 	int smb_nc_cnt;
1193da6c28aaSamw 	net_cfg_t cfg;
1194da6c28aaSamw 
1195da6c28aaSamw 	(void) smb_gethostname(hostname, MAXHOSTNAMELEN, 1);
1196*dc20a302Sas 	(void) smb_config_getstr(SMB_CI_SYS_CMNT, cmnt, sizeof (cmnt));
1197da6c28aaSamw 
1198da6c28aaSamw 	smb_nc_cnt = smb_nic_get_num();
1199da6c28aaSamw 	for (i = 0; i < smb_nc_cnt; i++) {
1200da6c28aaSamw 		if (smb_nic_get_byind(i, &cfg) == NULL)
1201da6c28aaSamw 			break;
1202da6c28aaSamw 		if (cfg.exclude)
1203da6c28aaSamw 			continue;
1204da6c28aaSamw 
1205da6c28aaSamw 		subnet = &smb_browser_info[i];
1206da6c28aaSamw 		(void) mutex_lock(&subnet->mtx);
1207da6c28aaSamw 
1208da6c28aaSamw 		/* One Minute announcements for first five */
1209da6c28aaSamw 		subnet->flags = BROWSER_NF_VALID;
1210da6c28aaSamw 		subnet->next_announce = 1;
1211da6c28aaSamw 		subnet->interval = 1;
1212da6c28aaSamw 		subnet->reps = 5;
1213da6c28aaSamw 
1214da6c28aaSamw 		server = &subnet->server;
1215da6c28aaSamw 		bzero(server, sizeof (struct server_info));
1216da6c28aaSamw 
1217da6c28aaSamw 		server->type = MY_SERVER_TYPE;
1218da6c28aaSamw 		server->major = SMB_VERSION_MAJOR;
1219da6c28aaSamw 		server->minor = SMB_VERSION_MINOR;
1220da6c28aaSamw 		server->signature = SMB_SERVER_SIGNATURE;
1221da6c28aaSamw 		(void) strlcpy(server->comment, cmnt, SMB_PI_MAX_COMMENT);
1222da6c28aaSamw 
1223da6c28aaSamw 		(void) snprintf(server->hostname, NETBIOS_NAME_SZ, "%.15s",
1224da6c28aaSamw 		    hostname);
1225da6c28aaSamw 
1226da6c28aaSamw 		/*
1227da6c28aaSamw 		 * 00 is workstation service.
1228da6c28aaSamw 		 * 20 is file server service.
1229da6c28aaSamw 		 */
1230da6c28aaSamw 		smb_init_name_struct((unsigned char *)server->hostname, 0x20, 0,
1231da6c28aaSamw 		    cfg.ip, htons(DGM_SRVC_UDP_PORT),
1232da6c28aaSamw 		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &server->name);
1233da6c28aaSamw 
1234da6c28aaSamw 		(void) mutex_unlock(&subnet->mtx);
1235da6c28aaSamw 	}
1236da6c28aaSamw 
1237da6c28aaSamw 	/* Invalidate unconfigured NICs */
1238da6c28aaSamw 	for (j = i; j < SMB_PI_MAX_NETWORKS; j++) {
1239da6c28aaSamw 		subnet = &smb_browser_info[j];
1240da6c28aaSamw 		(void) mutex_lock(&subnet->mtx);
1241da6c28aaSamw 		subnet->flags = BROWSER_NF_INVALID;
1242da6c28aaSamw 		(void) mutex_unlock(&subnet->mtx);
1243da6c28aaSamw 	}
1244da6c28aaSamw }
1245da6c28aaSamw 
1246da6c28aaSamw /*
1247da6c28aaSamw  * smb_browser_non_master_duties
1248da6c28aaSamw  *
1249da6c28aaSamw  * To advertise its presence, i.e. to publish itself as being available, a
1250da6c28aaSamw  * non-browser server sends a HostAnnouncement browser frame. If the server
1251da6c28aaSamw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
1252da6c28aaSamw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE".
1253da6c28aaSamw  */
1254da6c28aaSamw void
1255da6c28aaSamw smb_browser_non_master_duties(int net)
1256da6c28aaSamw {
1257da6c28aaSamw 	struct browser_netinfo *subnet;
1258da6c28aaSamw 	struct name_entry name;
1259da6c28aaSamw 	struct name_entry *dest;
1260da6c28aaSamw 	struct addr_entry addr;
1261da6c28aaSamw 	int interval;
1262da6c28aaSamw 	char resource_domain[SMB_PI_MAX_DOMAIN];
1263da6c28aaSamw 
1264da6c28aaSamw 	subnet = smb_browser_getnet(net);
1265da6c28aaSamw 	if (subnet == 0)
1266da6c28aaSamw 		return;
1267da6c28aaSamw 
1268da6c28aaSamw 	interval = subnet->interval;
1269da6c28aaSamw 	smb_browser_putnet(subnet);
1270da6c28aaSamw 
1271da6c28aaSamw 	smb_browser_send_HostAnnouncement(net, interval, 0, 0x1D);
1272*dc20a302Sas 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
1273*dc20a302Sas 		return;
1274da6c28aaSamw 
1275da6c28aaSamw 	(void) utf8_strupr(resource_domain);
1276da6c28aaSamw 
1277da6c28aaSamw 	smb_init_name_struct((unsigned char *)resource_domain, 0x1D,
1278da6c28aaSamw 	    0, 0, 0, 0, 0, &name);
1279da6c28aaSamw 
1280da6c28aaSamw 	if ((dest = smb_name_find_name(&name))) {
1281da6c28aaSamw 		addr = dest->addr_list;
1282da6c28aaSamw 		addr.forw = addr.back = &addr;
1283da6c28aaSamw 		smb_name_unlock_name(dest);
1284da6c28aaSamw 		smb_browser_send_HostAnnouncement(net, interval, &addr, 0x1D);
1285da6c28aaSamw 	} else {
1286da6c28aaSamw 		smb_init_name_struct(
1287da6c28aaSamw 		    (unsigned char *)resource_domain, 0x1B,
1288da6c28aaSamw 		    0, 0, 0, 0, 0, &name);
1289da6c28aaSamw 		if ((dest = smb_name_find_name(&name))) {
1290da6c28aaSamw 			addr = dest->addr_list;
1291da6c28aaSamw 			addr.forw = addr.back = &addr;
1292da6c28aaSamw 			smb_name_unlock_name(dest);
1293da6c28aaSamw 			smb_browser_send_HostAnnouncement(net, interval,
1294da6c28aaSamw 			    &addr, 0x1B);
1295da6c28aaSamw 		}
1296da6c28aaSamw 	}
1297da6c28aaSamw 
1298da6c28aaSamw 	subnet = smb_browser_getnet(net);
1299da6c28aaSamw 	/*
1300da6c28aaSamw 	 * One Minute announcements for first five
1301da6c28aaSamw 	 * minutes, one munute longer each round
1302da6c28aaSamw 	 * until 12 minutes and every 12 minutes
1303da6c28aaSamw 	 * thereafter.
1304da6c28aaSamw 	 */
1305da6c28aaSamw 	if (--subnet->reps == 0) {
1306da6c28aaSamw 		if (subnet->interval < 12)
1307da6c28aaSamw 			subnet->interval++;
1308da6c28aaSamw 
1309da6c28aaSamw 		subnet->reps = 1;
1310da6c28aaSamw 	}
1311da6c28aaSamw 
1312da6c28aaSamw 	subnet->next_announce = subnet->interval;
1313da6c28aaSamw 	smb_browser_putnet(subnet);
1314da6c28aaSamw }
1315da6c28aaSamw 
1316da6c28aaSamw 
1317da6c28aaSamw /*
1318da6c28aaSamw  * browser_sleep
1319da6c28aaSamw  *
1320da6c28aaSamw  * Put browser in 1 minute sleep if netbios services are not
1321da6c28aaSamw  * shutting down and both name and datagram services are still
1322da6c28aaSamw  * running. It'll wake up after 1 minute or if one of the above
1323da6c28aaSamw  * conditions go false. It checks the conditions again and return
1324da6c28aaSamw  * 1 if everything is ok or 0 if browser shouldn't continue
1325da6c28aaSamw  * running.
1326da6c28aaSamw  */
1327da6c28aaSamw static int
1328da6c28aaSamw browser_sleep()
1329da6c28aaSamw {
1330da6c28aaSamw 	int slept = 0;
1331da6c28aaSamw 	timestruc_t to;
1332da6c28aaSamw 
1333da6c28aaSamw 	(void) mutex_lock(&nb_status.mtx);
1334da6c28aaSamw 	while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) &&
1335da6c28aaSamw 	    (nb_status.state & NETBIOS_NAME_SVC_RUNNING) &&
1336da6c28aaSamw 	    (nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING)) {
1337da6c28aaSamw 
1338da6c28aaSamw 		if (slept) {
1339da6c28aaSamw 			(void) mutex_unlock(&nb_status.mtx);
1340da6c28aaSamw 			return (1);
1341da6c28aaSamw 		}
1342da6c28aaSamw 
1343da6c28aaSamw 		to.tv_sec = 60;  /* 1 minute */
1344da6c28aaSamw 		to.tv_nsec = 0;
1345da6c28aaSamw 		(void) cond_reltimedwait(&nb_status.cv, &nb_status.mtx, &to);
1346da6c28aaSamw 		slept = 1;
1347da6c28aaSamw 	}
1348da6c28aaSamw 	(void) mutex_unlock(&nb_status.mtx);
1349da6c28aaSamw 
1350da6c28aaSamw 	return (0);
1351da6c28aaSamw }
1352da6c28aaSamw 
1353da6c28aaSamw /*
1354da6c28aaSamw  * smb_browser_start
1355da6c28aaSamw  *
1356da6c28aaSamw  * Smb Netbios browser daemon.
1357da6c28aaSamw  */
1358da6c28aaSamw /*ARGSUSED*/
1359da6c28aaSamw void *
1360da6c28aaSamw smb_browser_daemon(void *arg)
1361da6c28aaSamw {
1362da6c28aaSamw 	int	net;
1363da6c28aaSamw 	int next_announce;
1364da6c28aaSamw 	struct browser_netinfo *subnet;
1365da6c28aaSamw 	int run = 1;
1366da6c28aaSamw 	int smb_nc_cnt;
1367da6c28aaSamw 	net_cfg_t cfg;
1368da6c28aaSamw 
1369da6c28aaSamw 	smb_browser_config();
1370da6c28aaSamw 
1371da6c28aaSamw 	nb_status.state |= NETBIOS_BROWSER_RUNNING;
1372da6c28aaSamw 
1373da6c28aaSamw 	while (run) {
1374da6c28aaSamw 		smb_nc_cnt = smb_nic_get_num();
1375da6c28aaSamw 		for (net = 0; net < smb_nc_cnt; net++) {
1376da6c28aaSamw 			if (smb_nic_get_byind(net, &cfg) == NULL)
1377da6c28aaSamw 				break;
1378da6c28aaSamw 			if (cfg.exclude)
1379da6c28aaSamw 				continue;
1380da6c28aaSamw 
1381da6c28aaSamw 			subnet = smb_browser_getnet(net);
1382da6c28aaSamw 			next_announce = --subnet->next_announce;
1383da6c28aaSamw 			smb_browser_putnet(subnet);
1384da6c28aaSamw 
1385da6c28aaSamw 			if (next_announce > 0 || cfg.broadcast == 0)
1386da6c28aaSamw 				continue;
1387da6c28aaSamw 
1388da6c28aaSamw 			smb_browser_non_master_duties(net);
1389da6c28aaSamw 		}
1390da6c28aaSamw 
1391da6c28aaSamw 		run = browser_sleep();
1392da6c28aaSamw 	}
1393da6c28aaSamw 
1394da6c28aaSamw 	smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 0);
1395da6c28aaSamw 	return (0);
1396da6c28aaSamw }
1397