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