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