xref: /onnv-gate/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c (revision 13082:81ec56bf6147)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*13082SJoyce.McIntosh@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
2510717Samw@Sun.COM #include <sys/tzfile.h>
268334SJose.Borrego@Sun.COM #include <errno.h>
275331Samw #include <stdlib.h>
285331Samw #include <stdio.h>
295331Samw #include <unistd.h>
305331Samw #include <syslog.h>
315331Samw #include <string.h>
325331Samw #include <strings.h>
335331Samw #include <time.h>
345331Samw #include <synch.h>
355331Samw #include <netdb.h>
365331Samw #include <sys/socket.h>
375331Samw #include <arpa/inet.h>
385331Samw 
395772Sas200622 #include <smbsrv/libsmb.h>
405331Samw #include <smbsrv/libsmbns.h>
4110966SJordan.Brown@Sun.COM #include <smbsrv/smb.h>
425331Samw #include <smbsrv/mailslot.h>
435331Samw #include <smbns_browser.h>
445331Samw #include <smbns_netbios.h>
455331Samw 
468334SJose.Borrego@Sun.COM /*
478334SJose.Borrego@Sun.COM  * ntdomain_info
488334SJose.Borrego@Sun.COM  * Temporary. It should be removed once NBTD is integrated.
498334SJose.Borrego@Sun.COM  */
508334SJose.Borrego@Sun.COM smb_ntdomain_t ntdomain_info;
518334SJose.Borrego@Sun.COM mutex_t ntdomain_mtx;
528334SJose.Borrego@Sun.COM cond_t ntdomain_cv;
538334SJose.Borrego@Sun.COM 
545331Samw #define	SMB_SERVER_SIGNATURE		0xaa550415
555331Samw 
566030Sjb150015 typedef struct smb_hostinfo {
576030Sjb150015 	list_node_t	hi_lnd;
586030Sjb150015 	smb_nic_t	hi_nic;
596030Sjb150015 	char		hi_nbname[NETBIOS_NAME_SZ];
606030Sjb150015 	name_entry_t	hi_netname;
616030Sjb150015 	uint32_t	hi_nextannouce;
626030Sjb150015 	int		hi_reps;
636030Sjb150015 	int		hi_interval;
646030Sjb150015 	uint8_t		hi_updatecnt;
656030Sjb150015 	uint32_t	hi_type;
6611963SAfshin.Ardakani@Sun.COM 	smb_version_t	hi_version;
676030Sjb150015 } smb_hostinfo_t;
685331Samw 
696030Sjb150015 typedef struct smb_browserinfo {
706030Sjb150015 	list_t		bi_hlist;
716030Sjb150015 	int		bi_hcnt;
726030Sjb150015 	rwlock_t	bi_hlist_rwl;
736030Sjb150015 	boolean_t	bi_changed;
746030Sjb150015 	mutex_t		bi_mtx;
756030Sjb150015 } smb_browserinfo_t;
765331Samw 
776030Sjb150015 static smb_browserinfo_t smb_binfo;
785331Samw 
796030Sjb150015 static int smb_browser_init(void);
806030Sjb150015 static void smb_browser_infoinit(void);
816030Sjb150015 static void smb_browser_infoterm(void);
826030Sjb150015 static void smb_browser_infofree(void);
835331Samw 
848334SJose.Borrego@Sun.COM 
856030Sjb150015 void
smb_browser_reconfig(void)866030Sjb150015 smb_browser_reconfig(void)
875331Samw {
886030Sjb150015 	(void) mutex_lock(&smb_binfo.bi_mtx);
896030Sjb150015 	smb_binfo.bi_changed = B_TRUE;
906030Sjb150015 	(void) mutex_unlock(&smb_binfo.bi_mtx);
915331Samw }
925331Samw 
935331Samw /*
945331Samw  * 3. Browser Overview
955331Samw  *
965331Samw  * Hosts involved in the browsing process can be separated into two
975331Samw  * distinct groups, browser clients and browser servers (often referred to
985331Samw  * simply as "browsers").
995331Samw  *
1005331Samw  * A browser is a server which maintains information about servers -
1015331Samw  * primarily the domain they are in and the services that they are running
1025331Samw  * -- and about domains. Browsers may assume several different roles in
1035331Samw  * their lifetimes, and dynamically switch between them.
1045331Samw  *
1055331Samw  *  Browser clients are of two types: workstations and (non-browser)
1065331Samw  * servers. In the context of browsing, workstations query browsers for the
1075331Samw  * information they contain; servers supply browsers the information by
1085331Samw  * registering with them. Note that, at times, browsers may themselves
1095331Samw  * behave as browser clients and query other browsers.
1105331Samw  *
1115331Samw  * For the purposes of this specification, a domain is simply a name with
1125331Samw  * which to associate a group of resources such as computers, servers and
1135331Samw  * users. Domains allow a convenient means for browser clients to restrict
1145331Samw  * the scope of a search when they query browser servers. Every domain has
1155331Samw  * a "master" server called the Primary Domain Controller (PDC) that
1165331Samw  * manages various  activities within the domain.
1175331Samw  *
1185331Samw  * One browser for each domain on a subnet is designated the Local Master
1195331Samw  * Browser for that domain. Servers in its domain on the subnet register
1205331Samw  * with it, as do the Local Master Browsers for other domains on the
1215331Samw  * subnet. It uses these registrations to maintain authoritative
1225331Samw  * information about its domain on its subnet. If there are other subnets
1235331Samw  * in the network, it also knows the name of the server running the
1245331Samw  * domain's Domain Master Browser; it registers with it, and uses it to
1255331Samw  * obtain information about the rest of the network (see below).
1265331Samw  *
1275331Samw  * Clients on a subnet query browsers designated as the Backup Browsers for
1285331Samw  * the subnet (not the Master Browser). Backup Browsers maintain a copy of
1295331Samw  * the information on the Local Master Browser; they get it by periodically
1305331Samw  * querying the Local Master Browser for all of its information. Clients
1315331Samw  * find the Backup Browsers by asking the Local Master Browser. Clients are
1325331Samw  * expected to spread their queries evenly across Backup Browsers to
1335331Samw  * balance the load.
1345331Samw  *
1355331Samw  * The Local Master Browser is dynamically elected automatically. Multiple
1365331Samw  * Backup Browser Servers may exist per subnet; they are selected from
1375331Samw  * among the potential browser servers by the Local Master Browser, which
1385331Samw  * is configured to select enough to handle the expected query load.
1395331Samw  *
1405331Samw  * When there are multiple subnets, a Domain Master Browser is assigned
1415331Samw  * the task of keeping the multiple subnets in synchronization. The Primary
1425331Samw  * Domain Controller (PDC) always acts as the Domain Master Browser. The
1435331Samw  * Domain Master Browser periodically acts as a client and queries all the
1445331Samw  * Local Master Browsers for its domain, asking them for a list containing
1455331Samw  * all the domains and all the servers in their domain known within their
1465331Samw  * subnets; it merges all the replies into a single master list. This
1475331Samw  * allows a Domain Master Browser server to act as a collection point for
1485331Samw  * inter-subnet browsing information. Local Master Browsers periodically
1495331Samw  * query the Domain Master Browser to retrieve the network-wide information
1505331Samw  * it maintains.
1515331Samw  *
1525331Samw  * When a domain spans only a single subnet, there will not be any distinct
1535331Samw  * Local Master Browser; this role will be handled by the Domain Master
1545331Samw  * Browser. Similarly, the Domain Master Browser is always the Local Master
1555331Samw  * Browser for the subnet it is on.
1565331Samw  *
1575331Samw  * When a browser client suspects that the Local Master Browser has failed,
1585331Samw  * the client will instigate an election in which the browser servers
1595331Samw  * participate, and some browser servers may change roles.
1605331Samw  *
1615331Samw  * Some characteristics of a good browsing mechanism include:
1625331Samw  * . minimal network traffic
1635331Samw  * . minimum server discovery time
1645331Samw  * . minimum change discovery latency
1655331Samw  * . immunity to machine failures
1665331Samw  *
1675331Samw  * Historically, Browser implementations had been very closely tied to
1685331Samw  * NETBIOS and datagrams. The early implementations caused a lot of
1695331Samw  * broadcast traffic. See Appendix D for an overview that presents how the
1705331Samw  * Browser specification evolved.
1715331Samw  *
1725331Samw  * 4. Browsing Protocol Architecture
1735331Samw  *
1745331Samw  * This section first describes the how the browsing protocol is layered,
1755331Samw  * then describes the roles of clients, servers, and browsers in the
1765331Samw  * browsing subsystem.
1775331Samw  *
1785331Samw  * 4.1 Layering of Browsing Protocol Requests
1795331Samw  *
1805331Samw  * Most of the browser functionality is implemented using mailslots.
1815331Samw  * Mailslots provide a mechanism for fast, unreliable unidirectional data
1825331Samw  * transfer; they are named via ASCII "mailslot (path) name". Mailslots are
1835331Samw  * implemented using the CIFS Transact SMB which is encapsulated in a
1845331Samw  * NETBIOS datagram. Browser protocol requests are sent to browser specific
1855331Samw  * mailslots using some browser-specific NETBIOS names. These datagrams can
1865331Samw  * either be unicast or broadcast, depending on whether the NETBIOS name is
1875331Samw  * a "unique name" or a "group name". Various data structures, which are
1885331Samw  * detailed subsequently within this document, flow as the data portion of
1895331Samw  * the Transact SMB.
1905331Samw  *
1915331Samw  * Here is an example of a generic browser SMB, showing how a browser
1925331Samw  * request is encapsulated in a TRANSACT SMB request. Note that the PID,
1935331Samw  * TID, MID, UID, and Flags are all 0 in mailslot requests.
1945331Samw  *
1955331Samw  * SMB: C transact, File = \MAILSLOT\BROWSE
1965331Samw  *   SMB: SMB Status = Error Success
1975331Samw  *     SMB: Error class = No Error
1985331Samw  *     SMB: Error code = No Error
1995331Samw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
2005331Samw  *     SMB: Tree ID   (TID) = 0 (0x0)
2015331Samw  *     SMB: Process ID  (PID) = 0 (0x0)
2025331Samw  *     SMB: User ID   (UID) = 0 (0x0)
2035331Samw  *     SMB: Multiplex ID (MID) = 0 (0x0)
2045331Samw  *     SMB: Flags Summary = 0 (0x0)
2055331Samw  *   SMB: Command = C transact
2065331Samw  *     SMB: Word count = 17
2075331Samw  *     SMB: Word parameters
2085331Samw  *     SMB: Total parm bytes = 0
2095331Samw  *     SMB: Total data bytes = 33
2105331Samw  *     SMB: Max parm bytes = 0
2115331Samw  *     SMB: Max data bytes = 0
2125331Samw  *     SMB: Max setup words = 0
2135331Samw  *     SMB: Transact Flags Summary = 0 (0x0)
2145331Samw  *       SMB: ...............0 = Leave session intact
2155331Samw  *       SMB: ..............0. = Response required
2165331Samw  *     SMB: Transact timeout = 0 (0x0)
2175331Samw  *     SMB: Parameter bytes = 0 (0x0)
2185331Samw  *     SMB: Parameter offset = 0 (0x0)
2195331Samw  *     SMB: Data bytes = 33 (0x21)
2205331Samw  *     SMB: Data offset = 86 (0x56)
2215331Samw  *     SMB: Setup word count = 3
2225331Samw  *     SMB: Setup words
2235331Samw  *     SMB: Mailslot opcode = Write mailslot
2245331Samw  *     SMB: Transaction priority = 1
2255331Samw  *     SMB: Mailslot class = Unreliable (broadcast)
2265331Samw  *     SMB: Byte count = 50
2275331Samw  *     SMB: Byte parameters
2285331Samw  *     SMB: Path name = \MAILSLOT\BROWSE
2295331Samw  *     SMB: Transaction data
2305331Samw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
2315331Samw  *
2325331Samw  * Note the SMB command is Transact, the opcode within the Transact SMB is
2335331Samw  * Mailslot Write, and the browser data structure is carried as the
2345331Samw  * Transact data.
2355331Samw  * The Transaction data begins with an opcode, that signifies the operation
2365331Samw  * and determines the size and structure of data that follows. This opcode
2375331Samw  * is named as per one of the below:
2385331Samw  *
2395331Samw  * HostAnnouncement         1
2405331Samw  * AnnouncementRequest      2
2415331Samw  * RequestElection          8
2425331Samw  * GetBackupListReq         9
2435331Samw  * GetBackupListResp        10
2445331Samw  * BecomeBackup             11
2455331Samw  * DomainAnnouncment        12
2465331Samw  * MasterAnnouncement       13
2475331Samw  * LocalMasterAnnouncement  15
2485331Samw  *
2495331Samw  * Browser datagrams are often referred to as simply browser frames. The
2505331Samw  * frames are in particular, referred to by the name of the opcode within
2515331Samw  * the Transaction data e.g. a GetBackupListReq browser frame, a
2525331Samw  * RequestElection browser frame, etc.
2535331Samw  *
2545331Samw  * The structures that are sent as the data portion of the Transact SMB are
2555331Samw  * described in section(s) 6.2 through 6.12 in this document. These
2565331Samw  * structures are tightly packed, i.e. there are no intervening pad bytes
2575331Samw  * in the structure, unless they are explicitly described as being there.
2585331Samw  * All quantities are sent in native Intel format and multi-byte values are
2595331Samw  * transmitted least significant byte first.
2605331Samw  *
2615331Samw  * Besides mailslots and Transaction SMBs, the other important piece of the
2625331Samw  * browser architecture is the NetServerEnum2 request. This request that
2635331Samw  * allows an application to interrogate a Browser Server and obtain a
2645331Samw  * complete list of resources (servers, domains, etc) known to that Browser
2655331Samw  * server. Details of the NetServerEnum2 request are presented in section
2665331Samw  * 6.4. Some examples of the NetServerEnum2 request being used are when a
2675331Samw  * Local Master Browser sends a NetServerEnum2 request to the Domain Master
2685331Samw  * Browser and vice versa. Another example is when a browser client sends a
2695331Samw  * NetServerEnum2 request to a Backup Browser server.
2705331Samw  *
2715331Samw  * 4.3 Non-Browser Server
2725331Samw  *
2735331Samw  * A non-browser server is a server that has some resource(s) or service(s)
2745331Samw  * it wishes to advertise as being available using the browsing protocol.
2755331Samw  * Examples of non-browser servers would be an SQL server, print server,
2765331Samw  * etc.
2775331Samw  *
2785331Samw  * A non-browser server MUST periodically send a HostAnnouncement browser
2795331Samw  * frame, specifying the type of resources or services it is advertising.
2805331Samw  * Details are in section 6.5.
2815331Samw  *
2825331Samw  * A non-browser server SHOULD announce itself relatively frequently when
2835331Samw  * it first starts up in order to make its presence quickly known to the
2845331Samw  * browsers and thence to potential clients. The frequency of the
2855331Samw  * announcements SHOULD then be gradually stretched, so as to minimize
2865331Samw  * network traffic. Typically,  non-browser servers announce themselves
2875331Samw  * once every minute upon start up and then gradually adjust the frequency
2885331Samw  * of the announcements to once every 12 minutes.
2895331Samw  *
2905331Samw  * A non-browser server SHOULD send a HostAnnouncement browser frame
2915331Samw  * specifying a type of  0 just prior to shutting down, to allow it to
2925331Samw  * quickly be removed from the list of available servers.
2935331Samw  *
2945331Samw  * A non-browser server MUST receive and process AnnouncementRequest frames
2955331Samw  * from the Local Master Browser, and MUST respond with a HostAnnouncement
2965331Samw  * frame, after a delay chosen randomly from the interval [0,30] seconds.
2975331Samw  * AnnouncementRequests typically happen when a Local Master Browser starts
2985331Samw  * up with an empty list of servers for the domain, and wants to fill it
2995331Samw  * quickly. The 30 second range for responses prevents the Master Browser
3005331Samw  * from becoming overloaded and losing replies, as well as preventing the
3015331Samw  * network from being flooded with responses.
3025331Samw  *
3035331Samw  * 4.4  Browser Servers
3045331Samw  *
3055331Samw  * The following sections describe the roles of the various types of
3065331Samw  * browser servers.
3075331Samw  *
3085331Samw  * 4.4.1  Potential Browser Server
3095331Samw  *
3105331Samw  * A Potential Browser server is a browser server that is capable of being
3115331Samw  * a Backup Browser server or Master Browser server, but is not currently
3125331Samw  * fulfilling either of those roles.
3135331Samw  *
3145331Samw  * A Potential Browser MUST set type SV_TYPE_POTENTIAL_BROWSER (see section
3155331Samw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
3165331Samw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
3175331Samw  * type of  0.
3185331Samw  *
3195331Samw  * A Potential Browser server MUST receive and process BecomeBackup frames
3205331Samw  * (see section 6.9) and become a backup browser upon their receipt.
3215331Samw  *
3225331Samw  * A Potential Browser MUST participate in browser elections (see section
3235331Samw  * 6.8).
3245331Samw  *
3255331Samw  * 4.4.2  Backup Browser
3265331Samw  *
3275331Samw  * Backup Browser servers are a subset of the Potential Browsers that have
3285331Samw  * been chosen by the Master Browser on their subnet to be the Backup
3295331Samw  * Browsers for the subnet.
3305331Samw  *
3315331Samw  * A Backup Browser MUST set type SV_TYPE_BACKUP_BROWSER (see section
3325331Samw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
3335331Samw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
3345331Samw  * type of  0.
3355331Samw  *
3365331Samw  * A Backup Browser MUST listen for a LocalMasterAnnouncement frame (see
3375331Samw  * section 6.10) from the Local Master Browser, and use it to set the name
3385331Samw  * of the Master Browser it queries for the server and domain lists.
3395331Samw  *
3405331Samw  * A  Backup Browsers MUST periodically make a NetServerEnum2 request of
3415331Samw  * the Master Browser on its subnet for its domain to get a list of servers
3425331Samw  * in that domain, as well as a list of domains. The period is a
3435331Samw  * configuration option balancing currency of the information with network
3445331Samw  * traffic costs - a typical value is 15 minutes.
3455331Samw  *
3465331Samw  * A Backup Browser SHOULD force an election by sending a RequestElection
3475331Samw  * frame (see section 6.7) if it does not get a response to its periodic
3485331Samw  * NetServeEnum2 request to the Master Browser.
3495331Samw  *
3505331Samw  * A Backup Browser MUST receive and process NetServerEnum2 requests from
3515331Samw  * browser clients, for its own domain and others. If the request is for a
3525331Samw  * list of servers in its domain, or for a list of domains, it can answer
3535331Samw  * from its internal lists. If the request is for a list of servers in a
3545331Samw  * domain different than the one it serves, it sends a NetServerEnum2
3555331Samw  * request to the Domain Master Browser for that domain (which it can in
3565331Samw  * find in its list of domains and their Domain Master Browsers).
3575331Samw  *
3585331Samw  * A Backup Browser MUST participate in browser elections (see section
3595331Samw  * 6.8).
3605331Samw  *
3615331Samw  * 4.4.3 Master Browser
3625331Samw  *
3635331Samw  * Master Browsers are responsible for:
3645331Samw  * . indicating it is a Master Browser
3655331Samw  * . receiving server announcements and building a list of such servers
3665331Samw  *   and keeping it reasonably up-to-date.
3675331Samw  * . returning lists of Backup Browsers to browser clients.
3685331Samw  * . ensuring an appropriate number of Backup Browsers are available.
3695331Samw  * . announcing their existence to other Master Browsers on their subnet,
3705331Samw  *   to the Domain Master Browser for their domain, and to all browsers in
3715331Samw  *   their domain on their subnet
3725331Samw  * . forwarding requests for lists of servers on other domains to the
3735331Samw  *   Master Browser for that domain
3745331Samw  * . keeping a list of domains in its subnet
3755331Samw  * . synchronizing with the Domain Master Browser (if any) for its domain
3765331Samw  * . participating in browser elections
3775331Samw  * . ensuring that there is only one Master Browser on its subnet
3785331Samw  *
3795331Samw  * A Master Browser MUST set type SV_TYPE_MASTER_BROWSER (see section
3805331Samw  * 6.4.1) in its HostAnnouncement until it is ready to shut down. In its
3815331Samw  * last HostAnnouncement frame before it shuts down, it SHOULD specify a
3825331Samw  * type of  0.
3835331Samw  *
3845331Samw  * A Master Browser MUST receive and process HostAnnouncement frames from
3855331Samw  * servers, adding the server name and other information to its servers
3865331Samw  * list; it must mark them as "local" entries. Periodically, it MUST check
3875331Samw  * all local server entries to see if a server's HostAnnouncement has timed
3885331Samw  * out (no HostAnnouncement received for three times the periodicity the
3895331Samw  * server gave in the last received HostAnnouncement) and remove timed-out
3905331Samw  * servers from its list.
3915331Samw  *
3925331Samw  * A Master Browser MUST receive and process DomainAnnouncement frames (see
3935331Samw  * section 6.12) and maintain the domain names and their associated (Local)
3945331Samw  * Master Browsers in its internal domain list until they time out; it must
3955331Samw  * mark these as "local" entries. Periodically, it MUST check all local
3965331Samw  * domain entries to see if a server's DomainAnnouncement has timed out (no
3975331Samw  * DomainAnnouncement received for three times the periodicity the server
3985331Samw  * gave in the last received DomainAnnouncement) and remove timed-out
3995331Samw  * servers from its list.
4005331Samw  *
4015331Samw  * A Master Browser MUST receive and process GetBackupListRequest frames
4025331Samw  * from clients, returning GetBackupListResponse frames containing a list
4035331Samw  * of the Backup Servers for its domain.
4045331Samw  *
4055331Samw  * A Master Browser MUST eventually send BecomeBackup frames (see section
4065331Samw  * 6.9) to one or more Potential Browser servers to increase the number of
4075331Samw  * Backup Browsers if there are not enough Backup Browsers to handle the
4085331Samw  * anticipated query load. Note: possible good times for checking for
4095331Samw  * sufficient backup browsers are after being elected, when timing out
4105331Samw  * server HostAnnouncements, and when receiving a server's HostAnnouncement
4115331Samw  * for the first time.
4125331Samw  *
4135331Samw  * A Master Browser MUST periodically announce itself and the domain it
4145331Samw  * serves to other (Local) Master Browsers on its subnet, by sending a
4155331Samw  * DomainAnnouncement frame (see section 6.12) to its subnet.
4165331Samw  *
4175331Samw  * A Master Browser MUST send a MasterAnnouncement frame (see section 6.11)
4185331Samw  * to the Domain Master Browser after it is first elected, and periodically
4195331Samw  * thereafter. This informs the Domain Master Browser of the presence of
4205331Samw  * all the Master Browsers.
4215331Samw  *
4225331Samw  * A Master Browser MUST periodically announce itself to all browsers for
4235331Samw  * its domain on its subnet by sending a LocalMasterAnnouncement frame (see
4245331Samw  * section 6.10).
4255331Samw  *
4265331Samw  * A Master Browser MUST receive and process NetServerEnum2 requests from
4275331Samw  * browser clients, for its own domain and others. If the request is for a
4285331Samw  * list of servers in its domain, or for a list of domains, it can answer
4295331Samw  * from its internal lists. Entries in its list marked "local" MUST have
4305331Samw  * the SV_TYPE_LOCAL_LIST_ONLY bit set in the returned results; it must be
4315331Samw  * clear for all other entries. If the request is for a list of servers in
4325331Samw  * a domain different than the one it serves, it sends a NetServerEnum2
4335331Samw  * request to the Domain Master Browser for that domain (which it can in
4345331Samw  * find in its list of domains and their Domain Master Browsers).
4355331Samw  *
4365331Samw  *     Note: The list of servers that the Master Browser maintains and
4375331Samw  *     returns to the Backup Browsers, is limited in size to 64K of
4385331Samw  *     data. This will limit the number of systems that can be in a
4395331Samw  *     browse list in a single workgroup or domain to approximately two
4405331Samw  *     thousand systems.
4415331Samw  *
4425331Samw  * A Master Browser SHOULD request all servers to register with it by
4435331Samw  * sending an AnnouncementRequest frame, if, on becoming the Master Browser
4445331Samw  * by winning an election, its server list is empty. Otherwise, clients
4455331Samw  * might get an incomplete list of servers until the servers' periodic
4465331Samw  * registrations fill the server list.
4475331Samw  *
4485331Samw  * If the Master Browser on a subnet is not the Primary Domain Controller
4495331Samw  * (PDC), then it is a Local Master Browser.
4505331Samw  *
4515331Samw  * A Local Master Browser MUST periodically synchronize with the Domain
4525331Samw  * Master Browser (which is the PDC). This synchronization is performed by
4535331Samw  * making a NetServerEnum2 request to the Domain Master Browser and merging
4545331Samw  * the results with its list of servers and domains. An entry from the
4555331Samw  * Domain Master Browser should be marked "non-local", and must not
4565331Samw  * overwrite an entry with the same name marked "local". The Domain Master
4575331Samw  * Browser is located as specified in Appendix B.
4585331Samw  *
4595331Samw  * A Master Browser MUST participate in browser elections (see section
4605331Samw  * 6.8).
4615331Samw  *
4625331Samw  * A Master Browser MUST, if it receives a HostAnnouncement,
4635331Samw  * DomainAnnouncement, or LocalMasterAnnouncement frame another system that
4645331Samw  * claims to be the Master Browser for its domain, demote itself from
4655331Samw  * Master Browser and force an election. This ensures that there is only
4665331Samw  * ever one Master Browser in each workgroup or domain.
4675331Samw  *
4685331Samw  * A Master Browser SHOULD, if it loses an election, become a Backup
4695331Samw  * Browser (without being told to do so by the new Master Browser). Since
4705331Samw  * it has more up-to-date information in its lists than a Potential
4715331Samw  * Browser, it is more efficient to have it be a Backup Browser than to
4725331Samw  * promote a Potential Browser.
4735331Samw  *
4745331Samw  * 4.4.3.1 Preferred Master Browser
4755331Samw  *
4765331Samw  * A Preferred Master Browser supports exactly the same protocol elements
4775331Samw  * as a Potential Browser, except as follows.
4785331Samw  *
4795331Samw  * A Preferred Master Browser MUST always force an election when it starts
4805331Samw  * up.
4815331Samw  *
4825331Samw  * A Preferred Master Browser MUST participate in browser elections (see
4835331Samw  * section 6.8).
4845331Samw  *
4855331Samw  * A Preferred Master Browser MUST set the Preferred Master bit in the
4865331Samw  * RequestElection frame (see section 6.7) to bias the election in its
4875331Samw  * favor.
4885331Samw  *
4895331Samw  * A Preferred Master Browser SHOULD, if it loses an election,
4905331Samw  * automatically become a Backup Browser, without being told to do so by
4915331Samw  * the Master Browser.
4925331Samw  *
4935331Samw  * 4.4.4 Domain Master Browser
4945331Samw  *
4955331Samw  * Since the Domain Master Browser always runs on the PDC, it must
4965331Samw  * implement all the protocols required of a PDC in addition to the
4975331Samw  * browsing protocol, and that is way beyond the scope of this
4985331Samw  * specification.
4995331Samw  *
5005331Samw  * 5. Mailslot Protocol Specification
5015331Samw  *
5025331Samw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
5035331Samw  * writes requests are encapsulated in TRANSACT SMBs. The following table
5045331Samw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
5055331Samw  * transaction:
5065331Samw  *
5075331Samw  *  Name            Value               Description
5085331Samw  *  Command         SMB_COM_TRANSACTION
5095331Samw  *  Name            <name>              STRING name of mail slot to write;
5105331Samw  *                                      must start with "\\MAILSLOT\\"
5115331Samw  *  SetupCount      3                   Always 3 for mailslot writes
5125331Samw  *  Setup[0]        1                   Command code == write mailslot
5135331Samw  *  Setup[1]        Ignored
5145331Samw  *  Setup[2]        Ignored
5155331Samw  *  TotalDataCount  n                   Size of data in bytes to write to
5165331Samw  *                                      the mailslot
5175331Samw  *  Data[ n ]                           The data to write to the mailslot
5185331Samw  *
5195331Samw  */
5205331Samw 
5215331Samw /*
5225331Samw  * SMB: C transact, File = \MAILSLOT\BROWSE
5235331Samw  *   SMB: SMB Status = Error Success
5245331Samw  *     SMB: Error class = No Error
5255331Samw  *     SMB: Error code = No Error
5265331Samw  *   SMB: Header: PID = 0x0000 TID = 0x0000 MID = 0x0000 UID = 0x0000
5275331Samw  *     SMB: Tree ID   (TID) = 0 (0x0)
5285331Samw  *     SMB: Process ID  (PID) = 0 (0x0)
5295331Samw  *     SMB: User ID   (UID) = 0 (0x0)
5305331Samw  *     SMB: Multiplex ID (MID) = 0 (0x0)
5315331Samw  *     SMB: Flags Summary = 0 (0x0)
5325331Samw  *   SMB: Command = C transact
5335331Samw  *     SMB: Word count = 17
5345331Samw  *     SMB: Word parameters
5355331Samw  *     SMB: Total parm bytes = 0
5365331Samw  *     SMB: Total data bytes = 33
5375331Samw  *     SMB: Max parm bytes = 0
5385331Samw  *     SMB: Max data bytes = 0
5395331Samw  *     SMB: Max setup words = 0
5405331Samw  *     SMB: Transact Flags Summary = 0 (0x0)
5415331Samw  *       SMB: ...............0 = Leave session intact
5425331Samw  *       SMB: ..............0. = Response required
5435331Samw  *     SMB: Transact timeout = 0 (0x0)
5445331Samw  *     SMB: Parameter bytes = 0 (0x0)
5455331Samw  *     SMB: Parameter offset = 0 (0x0)
5465331Samw  *     SMB: Data bytes = 33 (0x21)
5475331Samw  *     SMB: Data offset = 86 (0x56)
5485331Samw  *     SMB: Setup word count = 3
5495331Samw  *     SMB: Setup words
5505331Samw  *     SMB: Mailslot opcode = Write mailslot
5515331Samw  *     SMB: Transaction priority = 1
5525331Samw  *     SMB: Mailslot class = Unreliable (broadcast)
5535331Samw  *     SMB: Byte count = 50
5545331Samw  *     SMB: Byte parameters
5555331Samw  *     SMB: Path name = \MAILSLOT\BROWSE
5565331Samw  *     SMB: Transaction data
5575331Samw  *   SMB: Data: Number of data bytes remaining = 33 (0x0021)
5585331Samw  *
5595331Samw  * 5. Mailslot Protocol Specification
5605331Samw  *
5615331Samw  * The only transaction allowed to a mailslot is a mailslot write. Mailslot
5625331Samw  * writes requests are encapsulated in TRANSACT SMBs. The following table
5635331Samw  * shows the interpretation of the TRANSACT SMB parameters for a mailslot
5645331Samw  * transaction:
5655331Samw  *
5665331Samw  *  Name            Value               Description
5675331Samw  *  Command         SMB_COM_TRANSACTION
5685331Samw  *  Name            <name>              STRING name of mail slot to write;
5695331Samw  *                                      must start with "\MAILSLOT\"
5705331Samw  *  SetupCount      3                   Always 3 for mailslot writes
5715331Samw  *  Setup[0]        1                   Command code == write mailslot
5725331Samw  *  Setup[1]        Ignored
5735331Samw  *  Setup[2]        Ignored
5745331Samw  *  TotalDataCount  n                   Size of data in bytes to write to
5755331Samw  *                                      the mailslot
5765331Samw  *  Data[ n ]                           The data to write to the mailslot
5775331Samw  *
5785331Samw  *	Magic		0xFF 'S' 'M' 'B'
5795331Samw  *	smb_com 	a byte, the "first" command
5805331Samw  *	Error		a 4-byte union, ignored in a request
5815331Samw  *	smb_flg		a one byte set of eight flags
5825331Samw  *	smb_flg2	a two byte set of 16 flags
5835331Samw  *	.		twelve reserved bytes, have a role
5845331Samw  *			in connectionless transports (IPX, UDP?)
5855331Samw  *	smb_tid		a 16-bit tree ID, a mount point sorta,
5865331Samw  *			0xFFFF is this command does not have
5875331Samw  *			or require a tree context
5885331Samw  *	smb_pid		a 16-bit process ID
5895331Samw  *	smb_uid		a 16-bit user ID, specific to this "session"
5905331Samw  *			and mapped to a system (bona-fide) UID
5915331Samw  *	smb_mid		a 16-bit multiplex ID, used to differentiate
5925331Samw  *			multiple simultaneous requests from the same
5935331Samw  *			process (pid) (ref RPC "xid")
5945331Samw  */
5955331Samw 
5965331Samw int
smb_browser_load_transact_header(unsigned char * buffer,int maxcnt,int data_count,int reply,char * mailbox)5975331Samw smb_browser_load_transact_header(unsigned char *buffer, int maxcnt,
5986030Sjb150015     int data_count, int reply, char *mailbox)
5995331Samw {
6005331Samw 	smb_msgbuf_t mb;
6015331Samw 	int	mailboxlen;
6025331Samw 	char *fmt;
6035331Samw 	int result;
6045331Samw 	short	class = (reply == ONE_WAY_TRANSACTION) ? 2 : 0;
6055331Samw 
6065331Samw 	/*
6075331Samw 	 * If the mailboxlen is an even number we need to pad the
6085331Samw 	 * header so that the data starts on a word boundary.
6095331Samw 	 */
6105331Samw 	fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws";
6115331Samw 	mailboxlen = strlen(mailbox) + 1;
6125331Samw 
6135331Samw 	if ((mailboxlen & 0x01) == 0) {
6145331Samw 		++mailboxlen;
6155331Samw 		fmt = "Mb4.bw20.bwwwwb.wl2.wwwwb.wwwws.";
6165331Samw 	}
6175331Samw 
6185331Samw 	bzero(buffer, maxcnt);
6195331Samw 	smb_msgbuf_init(&mb, buffer, maxcnt, 0);
6205331Samw 
6215331Samw 	result = smb_msgbuf_encode(&mb, fmt,
6225331Samw 	    SMB_COM_TRANSACTION,	/* Command */
6235331Samw 	    0x18,
6245331Samw 	    0x3,
6255331Samw 	    17,				/* Count of parameter words */
6265331Samw 	    0,				/* Total Parameter words sent */
6275331Samw 	    data_count,			/* Total Data bytes sent */
6285331Samw 	    2,				/* Max Parameters to return */
6295331Samw 	    0,				/* Max data bytes to return */
6305331Samw 	    0,				/* Max setup bytes to return */
6315331Samw 	    reply,			/* No reply */
6325331Samw 	    0xffffffff,			/* Timeout */
6335331Samw 	    0,				/* Parameter bytes sent */
6345331Samw 	    0,				/* Parameter offset */
6355331Samw 	    data_count,			/* Data bytes sent */
6365331Samw 	    69 + mailboxlen,		/* Data offset */
6375331Samw 	    3,				/* Setup word count */
6385331Samw 	    1,				/* Setup word[0] */
6395331Samw 	    0,				/* Setup word[1] */
6405331Samw 	    class,			/* Setup word[2] */
6415331Samw 	    mailboxlen + data_count,	/* Total request bytes */
6425331Samw 	    mailbox);			/* Mailbox address */
6435331Samw 
6445331Samw 	smb_msgbuf_term(&mb);
6455331Samw 	return (result);
6465331Samw }
6475331Samw 
6485331Samw static int
smb_browser_addr_of_subnet(struct name_entry * name,smb_hostinfo_t * hinfo,struct name_entry * result)6496030Sjb150015 smb_browser_addr_of_subnet(struct name_entry *name, smb_hostinfo_t *hinfo,
6505331Samw     struct name_entry *result)
6515331Samw {
6525331Samw 	uint32_t ipaddr, mask, saddr;
65310717Samw@Sun.COM 	addr_entry_t *addr;
6545331Samw 
6556030Sjb150015 	if (name == NULL)
6565331Samw 		return (-1);
6575331Samw 
6586030Sjb150015 	if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS)
6595331Samw 		return (-1);
6606030Sjb150015 
6618670SJose.Borrego@Sun.COM 	ipaddr = hinfo->hi_nic.nic_ip.a_ipv4;
6626030Sjb150015 	mask = hinfo->hi_nic.nic_mask;
6635331Samw 
6645331Samw 	*result = *name;
6655331Samw 	addr = &name->addr_list;
6665331Samw 	do {
6675331Samw 		saddr = addr->sin.sin_addr.s_addr;
6685331Samw 		if ((saddr & mask) == (ipaddr & mask)) {
6695331Samw 			*result = *name;
6705331Samw 			result->addr_list = *addr;
6715331Samw 			result->addr_list.forw = result->addr_list.back =
6725331Samw 			    &result->addr_list;
6735331Samw 			return (0);
6745331Samw 		}
6755331Samw 		addr = addr->forw;
6765331Samw 	} while (addr != &name->addr_list);
6775331Samw 
6785331Samw 	return (-1);
6795331Samw }
6805331Samw 
6815331Samw 
6825331Samw static int
smb_browser_bcast_addr_of_subnet(struct name_entry * name,uint32_t bcast,struct name_entry * result)6836030Sjb150015 smb_browser_bcast_addr_of_subnet(struct name_entry *name, uint32_t bcast,
6845331Samw     struct name_entry *result)
6855331Samw {
6866030Sjb150015 	if (name != NULL && name != result)
6875331Samw 		*result = *name;
6885331Samw 
6895331Samw 	result->addr_list.sin.sin_family = AF_INET;
6905331Samw 	result->addr_list.sinlen = sizeof (result->addr_list.sin);
6916030Sjb150015 	result->addr_list.sin.sin_addr.s_addr = bcast;
69210717Samw@Sun.COM 	result->addr_list.sin.sin_port = htons(IPPORT_NETBIOS_DGM);
6935331Samw 	result->addr_list.forw = result->addr_list.back = &result->addr_list;
6945331Samw 	return (0);
6955331Samw }
6965331Samw 
6975331Samw /*
6985331Samw  * 6.5 HostAnnouncement Browser Frame
6995331Samw  *
7005331Samw  * To advertise its presence, i.e. to publish itself as being available, a
7015331Samw  * non-browser server sends a HostAnnouncement browser frame. If the server
7025331Samw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
7035331Samw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE". The definition of  the
7045331Samw  * HostAnnouncement frame is:
7055331Samw  *
7065331Samw  *     struct {
7075331Samw  *         unsigned short  Opcode;
7085331Samw  *         unsigned char   UpdateCount;
7095331Samw  *         uint32_t   Periodicity;
7105331Samw  *         unsigned char   ServerName[];
7115331Samw  *         unsigned char   VersionMajor;
7125331Samw  *         unsigned char   VersionMinor;
7135331Samw  *         uint32_t   Type;
7145331Samw  *         uint32_t   Signature;
7155331Samw  *         unsigned char   Comment[];
7165331Samw  *     }
7175331Samw  *
7185331Samw  * where:
7195331Samw  *      Opcode - Identifies this structure as a browser server
7205331Samw  *          announcement and is defined as HostAnnouncement with a
7215331Samw  *          value of decimal 1.
7225331Samw  *
7235331Samw  *      UpdateCount - must be sent as zero and ignored on receipt.
7245331Samw  *
7255331Samw  *      Periodicity - The announcement frequency of the server (in
7265331Samw  *          seconds). The server will be removed from the browse list
7275331Samw  *          if it has not been heard from in 3X its announcement
7285331Samw  *          frequency. In no case will the server be removed from the
7295331Samw  *          browse list before the period 3X has elapsed. Actual
7305331Samw  *          implementations may take more than 3X to actually remove
7315331Samw  *          the server from the browse list.
7325331Samw  *
7335331Samw  *      ServerName - Null terminated ASCII server name (up to 16 bytes
7345331Samw  *          in length).
7355331Samw  *
7365331Samw  *      VersionMajor - The major version number of the OS the server
7375331Samw  *          is running. it will be returned by NetServerEnum2.
7385331Samw  *
7395331Samw  *      VersionMinor - The minor version number of the OS the server
7405331Samw  *          is running. This is entirely informational and does not
7415331Samw  *          have any significance for the browsing protocol.
7425331Samw  *
7435331Samw  *      Type - Specifies the type of the server. The server type bits
7445331Samw  *          are specified in the NetServerEnum2 section.
7455331Samw  *
7465331Samw  *      Signature -  The browser protocol minor version number in the
7475331Samw  *          low 8 bits, the browser protocol major version number in
7485331Samw  *          the next higher 8 bits and the signature 0xaa55 in the
7495331Samw  *          high 16 bits of this field. Thus, for this version of the
7505331Samw  *          browser protocol (1.15) this field has the value
7515331Samw  *          0xaa55010f. This may used to isolate browser servers that
7525331Samw  *          are running out of revision browser software; otherwise,
7535331Samw  *          it is ignored.
7545331Samw  *
7555331Samw  *      Comment - Null terminated ASCII comment for the server.
7565331Samw  *          Limited to 43 bytes.
7575331Samw  *
7585331Samw  * When a non-browser server starts up, it announces itself in the manner
7595331Samw  * described once every minute. The frequency of these statements is
7605331Samw  * gradually stretched to once every 12 minutes.
7615331Samw  *
7625331Samw  * Note: older non-browser servers in a domain "D" sent HostAnnouncement
7635331Samw  * frames to the NETBIOS group name D(00). Non-Browser servers supporting
7645331Samw  * version 1.15 of the browsing protocol SHOULD NOT use this NETBIOS name,
7655331Samw  * but for backwards compatibility Master Browsers MAY receive and process
7665331Samw  * HostAnnouncement frames on this name as described above for D(1d).
7675331Samw  */
7685331Samw 
7696030Sjb150015 static void
smb_browser_send_HostAnnouncement(smb_hostinfo_t * hinfo,uint32_t next_announcement,boolean_t remove,addr_entry_t * addr,char suffix)7706030Sjb150015 smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo,
7716030Sjb150015     uint32_t next_announcement, boolean_t remove,
77210717Samw@Sun.COM     addr_entry_t *addr, char suffix)
7735331Samw {
7745331Samw 	smb_msgbuf_t mb;
7755331Samw 	int offset, announce_len, data_length;
7765331Samw 	struct name_entry dest_name;
7775331Samw 	unsigned char *buffer;
7785331Samw 	uint32_t type;
7795331Samw 	char resource_domain[SMB_PI_MAX_DOMAIN];
7805331Samw 
7815772Sas200622 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
7825772Sas200622 		return;
78310966SJordan.Brown@Sun.COM 	(void) smb_strupr(resource_domain);
7845331Samw 
7856030Sjb150015 	if (addr == NULL) {
7865331Samw 		/* Local master Browser */
7876030Sjb150015 		smb_init_name_struct((unsigned char *)resource_domain, suffix,
7885331Samw 		    0, 0, 0, 0, 0, &dest_name);
7896030Sjb150015 		if (smb_browser_bcast_addr_of_subnet(0, hinfo->hi_nic.nic_bcast,
7906030Sjb150015 		    &dest_name) < 0)
7915331Samw 			return;
7925331Samw 	} else {
7936030Sjb150015 		smb_init_name_struct((unsigned char *)resource_domain, suffix,
7945331Samw 		    0, 0, 0, 0, 0, &dest_name);
7955331Samw 		dest_name.addr_list = *addr;
7965331Samw 		dest_name.addr_list.forw = dest_name.addr_list.back =
7975331Samw 		    &dest_name.addr_list;
7985331Samw 	}
7995331Samw 
8005331Samw 	/* give some extra room */
80110717Samw@Sun.COM 	buffer = malloc(MAX_DATAGRAM_LENGTH * 2);
80210717Samw@Sun.COM 	if (buffer == NULL) {
80310717Samw@Sun.COM 		syslog(LOG_DEBUG, "smb browser: HostAnnouncement: %m");
8045331Samw 		return;
8055331Samw 	}
8065331Samw 
8076030Sjb150015 	data_length = 1 + 1 + 4 + 16 + 1 + 1 + 4 + 4 +
8086030Sjb150015 	    strlen(hinfo->hi_nic.nic_cmnt) + 1;
8095331Samw 
8106030Sjb150015 	offset = smb_browser_load_transact_header(buffer,
8116030Sjb150015 	    MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION,
8126030Sjb150015 	    MAILSLOT_BROWSE);
8135331Samw 
8146030Sjb150015 	if (offset < 0) {
8155331Samw 		free(buffer);
8165331Samw 		return;
8175331Samw 	}
8185331Samw 
8195331Samw 	/*
8205331Samw 	 * A non-browser server SHOULD send a HostAnnouncement browser frame
8215331Samw 	 * specifying a type of 0 just prior to shutting down, to allow it to
8225331Samw 	 * quickly be removed from the list of available servers.
8235331Samw 	 */
82410717Samw@Sun.COM 	if (remove || (!smb_netbios_running()))
8256030Sjb150015 		type = 0;
8266030Sjb150015 	else
8276030Sjb150015 		type = hinfo->hi_type;
8285331Samw 
8295331Samw 	smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0);
8306030Sjb150015 
8315331Samw 	announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls",
8326030Sjb150015 	    HOST_ANNOUNCEMENT,
8336030Sjb150015 	    ++hinfo->hi_updatecnt,
8345331Samw 	    next_announcement * 60000,	/* Periodicity in MilliSeconds */
8356030Sjb150015 	    hinfo->hi_nbname,
836*13082SJoyce.McIntosh@Sun.COM 	    (uint8_t)hinfo->hi_version.sv_major,
837*13082SJoyce.McIntosh@Sun.COM 	    (uint8_t)hinfo->hi_version.sv_minor,
8386030Sjb150015 	    type,
8396030Sjb150015 	    SMB_SERVER_SIGNATURE,
8406030Sjb150015 	    hinfo->hi_nic.nic_cmnt);
8415331Samw 
8425331Samw 	if (announce_len > 0)
8436030Sjb150015 		(void) smb_netbios_datagram_send(&hinfo->hi_netname, &dest_name,
8445331Samw 		    buffer, offset + announce_len);
8455331Samw 
8465331Samw 	free(buffer);
8475331Samw 	smb_msgbuf_term(&mb);
8485331Samw }
8495331Samw 
8506030Sjb150015 static void
smb_browser_process_AnnouncementRequest(struct datagram * datagram,char * mailbox)8515331Samw smb_browser_process_AnnouncementRequest(struct datagram *datagram,
8525331Samw     char *mailbox)
8535331Samw {
8546030Sjb150015 	smb_hostinfo_t *hinfo;
8556030Sjb150015 	uint32_t next_announcement;
8565331Samw 	uint32_t delay = random() % 29; /* in seconds */
8576030Sjb150015 	boolean_t h_found = B_FALSE;
8585331Samw 
8596030Sjb150015 	if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) {
86010717Samw@Sun.COM 		syslog(LOG_DEBUG, "smb browser: wrong mailbox (%s)", mailbox);
8615331Samw 		return;
8625331Samw 	}
8635331Samw 
86410717Samw@Sun.COM 	smb_netbios_sleep(delay);
8655331Samw 
8666030Sjb150015 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
8676030Sjb150015 	hinfo = list_head(&smb_binfo.bi_hlist);
8686030Sjb150015 	while (hinfo) {
8698670SJose.Borrego@Sun.COM 		if ((hinfo->hi_nic.nic_ip.a_ipv4 &
8708670SJose.Borrego@Sun.COM 		    hinfo->hi_nic.nic_mask) ==
8716030Sjb150015 		    (datagram->src.addr_list.sin.sin_addr.s_addr &
8726030Sjb150015 		    hinfo->hi_nic.nic_mask)) {
8736030Sjb150015 			h_found = B_TRUE;
8746030Sjb150015 			break;
8756030Sjb150015 		}
8766030Sjb150015 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
8775331Samw 	}
8786030Sjb150015 
8796030Sjb150015 	if (h_found) {
8806030Sjb150015 		next_announcement = hinfo->hi_nextannouce * 60 * 1000;
8816030Sjb150015 		smb_browser_send_HostAnnouncement(hinfo, next_announcement,
88210717Samw@Sun.COM 		    B_FALSE, &datagram->src.addr_list, NBT_MB);
8836030Sjb150015 	}
8846030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
8855331Samw }
8865331Samw 
8875331Samw void *
smb_browser_dispatch(void * arg)8885331Samw smb_browser_dispatch(void *arg)
8895331Samw {
8905331Samw 	struct datagram *datagram = (struct datagram *)arg;
8915331Samw 	smb_msgbuf_t 	mb;
8925331Samw 	int		rc;
8935331Samw 	unsigned char	command;
8945331Samw 	unsigned char	parameter_words;
8955331Samw 	unsigned short	total_parameter_words;
8965331Samw 	unsigned short	total_data_count;
8975331Samw 	unsigned short	max_parameters_to_return;
8985331Samw 	unsigned short	max_data_to_return;
8995331Samw 	unsigned char	max_setup_bytes_to_return;
9005331Samw 	unsigned short	reply;
9015331Samw 	unsigned short	parameter_bytes_sent;
9025331Samw 	unsigned short	parameter_offset;
9035331Samw 	unsigned short	data_bytes_sent;
9045331Samw 	unsigned short	data_offset;
9055331Samw 	unsigned char	setup_word_count;
9065331Samw 	unsigned short	setup_word_0;
9075331Samw 	unsigned short	setup_word_1;
9085331Samw 	unsigned short	setup_word_2;
9095331Samw 	unsigned short	total_request_bytes;
9105331Samw 	char 		*mailbox;
9115331Samw 	unsigned char	message_type;
9125331Samw 	unsigned char 	*data;
9135331Samw 	int		datalen;
9145331Samw 
91510717Samw@Sun.COM 	syslog(LOG_DEBUG, "smb browser: packet received");
9165331Samw 
9175331Samw 	smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0);
9185331Samw 	rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws",
9195331Samw 	    &command,			/* Command */
9205331Samw 	    &parameter_words,		/* Count of parameter words */
9215331Samw 	    &total_parameter_words,	/* Total Parameter words sent */
9225331Samw 	    &total_data_count,		/* Total Data bytes sent */
9235331Samw 	    &max_parameters_to_return,	/* Max Parameters to return */
9245331Samw 	    &max_data_to_return,	/* Max data bytes to return */
9255331Samw 	    &max_setup_bytes_to_return,	/* Max setup bytes to return */
9265331Samw 	    &reply,			/* No reply */
9275331Samw 	    &parameter_bytes_sent,	/* Parameter bytes sent */
9285331Samw 	    &parameter_offset,		/* Parameter offset */
9295331Samw 	    &data_bytes_sent,		/* Data bytes sent */
9305331Samw 	    &data_offset,		/* Data offset */
9315331Samw 	    &setup_word_count,		/* Setup word count */
9325331Samw 	    &setup_word_0,		/* Setup word[0] */
9335331Samw 	    &setup_word_1,		/* Setup word[1] */
9345331Samw 	    &setup_word_2,		/* Setup word[2] */
9355331Samw 	    &total_request_bytes,	/* Total request bytes */
9365331Samw 	    &mailbox);			/* Mailbox address */
9375331Samw 
9385331Samw 	if (rc < 0) {
93910717Samw@Sun.COM 		syslog(LOG_ERR, "smb browser: decode error");
9405331Samw 		smb_msgbuf_term(&mb);
9415331Samw 		free(datagram);
9425331Samw 		return (0);
9435331Samw 	}
9445331Samw 
9455331Samw 	data = &datagram->data[data_offset];
9465331Samw 	datalen = datagram->data_length - data_offset;
9475331Samw 
9485331Samw 	/*
9495331Samw 	 * The PDC location protocol, i.e. anything on the \\NET
9505331Samw 	 * mailslot, is handled by the smb_netlogon module.
9515331Samw 	 */
9525331Samw 	if (strncasecmp("\\MAILSLOT\\NET\\", mailbox, 14) == 0) {
9535331Samw 		smb_netlogon_receive(datagram, mailbox, data, datalen);
9545331Samw 		smb_msgbuf_term(&mb);
9555331Samw 		free(datagram);
9565331Samw 		return (0);
9575331Samw 	}
9585331Samw 
9595331Samw 	/*
9605331Samw 	 * If it's not a netlogon message, assume it's a browser request.
9615331Samw 	 * This is not the most elegant way to extract the command byte
9625331Samw 	 * but at least we no longer use it to get the netlogon opcode.
9635331Samw 	 */
9645331Samw 	message_type = datagram->data[data_offset];
9655331Samw 
9665331Samw 	switch (message_type) {
9675331Samw 	case ANNOUNCEMENT_REQUEST :
9685331Samw 		smb_browser_process_AnnouncementRequest(datagram, mailbox);
9695331Samw 		break;
9705331Samw 
9715331Samw 	default:
97210717Samw@Sun.COM 		syslog(LOG_DEBUG, "smb browser: invalid message type(%d, %x)",
9735331Samw 		    message_type, message_type);
9745331Samw 		break;
9755331Samw 	}
9765331Samw 
9775331Samw 	smb_msgbuf_term(&mb);
9785331Samw 	free(datagram);
9795331Samw 	return (0);
9805331Samw }
9815331Samw 
9825331Samw 
9835331Samw /*
9845331Samw  * 11.1 Registered unique names
9855331Samw  *
9865331Samw  *  <COMPUTER>(00)
9875331Samw  *     This name is used by all servers and clients to receive second
9885331Samw  *     class mailslot messages. A system must add this name in order to
9895331Samw  *     receive mailslot messages. The only browser requests that should
9905331Samw  *     appear on this name are BecomeBackup, GetBackupListResp,
9915331Samw  *     MasterAnnouncement, and LocalMasterAnnouncement frames. All other
9925331Samw  *     datagrams (other than the expected non-browser datagrams) may be
9935331Samw  *     ignored and an error logged.
9945331Samw  *
9955331Samw  *   <DOMAIN>(1d)
9965331Samw  *     This name is used to identify a master browser server for domain
9975331Samw  *     "DOMAIN" on a subnet.  A master browser server adds this name as a
9985331Samw  *     unique NETBIOS name when it becomes master browser. If the attempt
9995331Samw  *     to add the name fails, the master browser server assumes that there
10005331Samw  *     is another master in the domain and will fail to come up. It may
10015331Samw  *     log an error if the failure occurs more than 3 times in a row (this
10025331Samw  *     either indicates some form of network misconfiguration or a
10035331Samw  *     software error). The only requests that should appear on this name
10045331Samw  *     are GetBackupListRequest and HostAnnouncement requests. All other
10055331Samw  *     datagrams on this name may be ignored (and an error logged). If
10065331Samw  *     running a NETBIOS name service (NBNS, such as WINS), this name
10075331Samw  *     should not be registered with the NBNS.
10085331Samw  *
10095331Samw  *   <DOMAIN>(1b)
10105331Samw  *     This name is used to identify the Domain Master Browser for domain
10115331Samw  *     "DOMAIN" (which is also the primary domain controller). It is a
10125331Samw  *     unique name added only by the primary domain controller. The
10135331Samw  *     primary domain controller will respond to GetBackupListRequest on
10145331Samw  *     this name just as it responds to these requests on the <DOMAIN>(1d)
10155331Samw  *     name.
10165331Samw  *
10175331Samw  * 11.2 Registered group names
10185331Samw  *
10195331Samw  *   (01)(02)__MSBROWSE__(02)(01)
10205331Samw  *     This name is used by Master Browsers to announce themselves to the
10215331Samw  *     other Master Browsers on a subnet. It is added as a group name by
10225331Samw  *     all Master Browser servers. The only broadcasts that should appear
10235331Samw  *     on this name is DomainAnnouncement requests. All other datagrams
10245331Samw  *     can be ignored.
10255331Samw  *
10265331Samw  *   <DOMAIN>(00)
10275331Samw  *     This name is used by clients and servers in domain "DOMAIN" to
10285331Samw  *     process server announcements. The only requests that should appear
10295331Samw  *     on this name that the browser is interested in are
10305331Samw  *     AnnouncementRequest and NETLOGON_QUERY (to locate the PDC) packets.
10315331Samw  *     All other unidentifiable requests may be ignored (and an error
10325331Samw  *     logged).
10335331Samw  *
10345331Samw  *   <DOMAIN>(1E)
10355331Samw  *     This name is used for announcements to browsers for domain "DOMAIN"
10365331Samw  *     on a subnet. This name is registered by all the browser servers in
10375331Samw  *     the domain. The only requests that should appear on this name are
10385331Samw  *     RequestElection and AnnouncementRequest packets. All other
10395331Samw  *     datagrams may be ignored (and an error logged).
10405331Samw  *
10415331Samw  *   <DOMAIN>(1C)
10425331Samw  *     This name is registered by Primary Domain Controllers.
10435331Samw  */
10445331Samw 
10456030Sjb150015 static void
smb_browser_config(void)10465331Samw smb_browser_config(void)
10475331Samw {
10486030Sjb150015 	smb_hostinfo_t *hinfo;
10495331Samw 	struct name_entry	name;
10505331Samw 	struct name_entry	master;
10515331Samw 	struct name_entry	dest;
10525331Samw 	struct name_entry	*entry;
10535331Samw 	char resource_domain[SMB_PI_MAX_DOMAIN];
10546030Sjb150015 	int rc;
10555331Samw 
10566030Sjb150015 	if (smb_browser_init() != 0)
10576030Sjb150015 		return;
10586030Sjb150015 
10595772Sas200622 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
10605772Sas200622 		return;
106110966SJordan.Brown@Sun.COM 	(void) smb_strupr(resource_domain);
10625331Samw 
10635331Samw 	/* domain<00> */
106410717Samw@Sun.COM 	smb_init_name_struct((unsigned char *)resource_domain, NBT_WKSTA,
10655331Samw 	    0, 0, 0, 0, 0, &name);
10665331Samw 	entry = smb_name_find_name(&name);
10675331Samw 	smb_name_unlock_name(entry);
10685331Samw 
10696030Sjb150015 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
10706030Sjb150015 	hinfo = list_head(&smb_binfo.bi_hlist);
10716030Sjb150015 	while (hinfo) {
107210717Samw@Sun.COM 		smb_init_name_struct((unsigned char *)resource_domain,
107310717Samw@Sun.COM 		    NBT_WKSTA, 0, hinfo->hi_nic.nic_ip.a_ipv4,
107410717Samw@Sun.COM 		    htons(IPPORT_NETBIOS_DGM), NAME_ATTR_GROUP,
10758670SJose.Borrego@Sun.COM 		    NAME_ATTR_LOCAL, &name);
10765331Samw 		(void) smb_name_add_name(&name);
10776030Sjb150015 
10786030Sjb150015 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
10795331Samw 	}
10806030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
10815331Samw 
10825331Samw 	/* All our local master browsers */
108310717Samw@Sun.COM 	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
10845331Samw 	    0, 0, 0, 0, 0, &dest);
10855331Samw 	entry = smb_name_find_name(&dest);
10865331Samw 
10875331Samw 	if (entry) {
10886030Sjb150015 		(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
10896030Sjb150015 		hinfo = list_head(&smb_binfo.bi_hlist);
10906030Sjb150015 		while (hinfo) {
10916030Sjb150015 			rc = smb_browser_addr_of_subnet(entry, hinfo, &master);
10926030Sjb150015 			if (rc == 0) {
10935331Samw 				syslog(LOG_DEBUG,
109410717Samw@Sun.COM 				    "smb browser: master browser found at %s",
10955331Samw 				    inet_ntoa(master.addr_list.sin.sin_addr));
10965331Samw 			}
10976030Sjb150015 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
10985331Samw 		}
10996030Sjb150015 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11006030Sjb150015 
11015331Samw 		smb_name_unlock_name(entry);
11025331Samw 	}
11036030Sjb150015 
11046030Sjb150015 	/* Domain master browser */
11055331Samw 	smb_init_name_struct((unsigned char *)resource_domain,
110610717Samw@Sun.COM 	    NBT_DMB, 0, 0, 0, 0, 0, &dest);
11075331Samw 
11085331Samw 	if ((entry = smb_name_find_name(&dest)) != 0) {
110910717Samw@Sun.COM 		syslog(LOG_DEBUG,
111010717Samw@Sun.COM 		    "smb browser: domain master browser for %s is %s",
11115331Samw 		    resource_domain,
11125331Samw 		    inet_ntoa(entry->addr_list.sin.sin_addr));
11135331Samw 		smb_name_unlock_name(entry);
11145331Samw 	}
11155331Samw }
11165331Samw 
11176030Sjb150015 static int
smb_browser_init(void)11186030Sjb150015 smb_browser_init(void)
11195331Samw {
11206030Sjb150015 	smb_hostinfo_t *hinfo;
11216030Sjb150015 	smb_niciter_t ni;
11226030Sjb150015 	uint32_t type;
112311963SAfshin.Ardakani@Sun.COM 	smb_version_t version;
112411963SAfshin.Ardakani@Sun.COM 
112511963SAfshin.Ardakani@Sun.COM 	smb_config_get_version(&version);
11266030Sjb150015 
11276030Sjb150015 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
11286030Sjb150015 	smb_browser_infofree();
11295331Samw 
113011963SAfshin.Ardakani@Sun.COM 	if (smb_nic_getfirst(&ni) != SMB_NIC_SUCCESS) {
11316030Sjb150015 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11326030Sjb150015 		return (-1);
11336030Sjb150015 	}
11345331Samw 
11356030Sjb150015 	type = MY_SERVER_TYPE;
11366030Sjb150015 	if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)
11376030Sjb150015 		type |= SV_DOMAIN_MEMBER;
11386030Sjb150015 
11396030Sjb150015 	do {
11408334SJose.Borrego@Sun.COM 		if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
11418334SJose.Borrego@Sun.COM 		    (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS))
11425331Samw 			continue;
11435331Samw 
11446030Sjb150015 		hinfo = malloc(sizeof (smb_hostinfo_t));
11456030Sjb150015 		if (hinfo == NULL) {
11466030Sjb150015 			smb_browser_infofree();
11476030Sjb150015 			(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11486030Sjb150015 			return (-1);
11496030Sjb150015 		}
11505331Samw 
11516030Sjb150015 		hinfo->hi_nic = ni.ni_nic;
11526030Sjb150015 		/* One Minute announcements for first five */
11536030Sjb150015 		hinfo->hi_nextannouce = 1;
11546030Sjb150015 		hinfo->hi_interval = 1;
11556030Sjb150015 		hinfo->hi_reps = 5;
11566030Sjb150015 		hinfo->hi_updatecnt = 0;
11576030Sjb150015 		hinfo->hi_type = type;
115811963SAfshin.Ardakani@Sun.COM 		hinfo->hi_version = version;
11595331Samw 
11606030Sjb150015 		/* This is the name used for HostAnnouncement */
11616030Sjb150015 		(void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host,
11626030Sjb150015 		    NETBIOS_NAME_SZ);
116310966SJordan.Brown@Sun.COM 		(void) smb_strupr(hinfo->hi_nbname);
11646030Sjb150015 		/* 0x20: file server service  */
11656030Sjb150015 		smb_init_name_struct((unsigned char *)hinfo->hi_nbname,
116610717Samw@Sun.COM 		    NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4,
116710717Samw@Sun.COM 		    htons(IPPORT_NETBIOS_DGM),
116810717Samw@Sun.COM 		    NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
11698670SJose.Borrego@Sun.COM 		    &hinfo->hi_netname);
11705331Samw 
11716030Sjb150015 		list_insert_tail(&smb_binfo.bi_hlist, hinfo);
11726030Sjb150015 		smb_binfo.bi_hcnt++;
117311963SAfshin.Ardakani@Sun.COM 	} while (smb_nic_getnext(&ni) == SMB_NIC_SUCCESS);
11746030Sjb150015 
11756030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
11766030Sjb150015 	return (0);
11775331Samw }
11785331Samw 
11795331Samw /*
11805331Samw  * smb_browser_non_master_duties
11815331Samw  *
11825331Samw  * To advertise its presence, i.e. to publish itself as being available, a
11835331Samw  * non-browser server sends a HostAnnouncement browser frame. If the server
11845331Samw  * is a member of domain "D", this frame is sent to the NETBIOS unique name
11855331Samw  * D(1d) and mailslot "\\MAILSLOT\\BROWSE".
11865331Samw  */
11876030Sjb150015 static void
smb_browser_non_master_duties(smb_hostinfo_t * hinfo,boolean_t remove)11886030Sjb150015 smb_browser_non_master_duties(smb_hostinfo_t *hinfo, boolean_t remove)
11895331Samw {
11905331Samw 	struct name_entry name;
11915331Samw 	struct name_entry *dest;
119210717Samw@Sun.COM 	addr_entry_t addr;
11935331Samw 	char resource_domain[SMB_PI_MAX_DOMAIN];
11945331Samw 
11956030Sjb150015 	smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
119610717Samw@Sun.COM 	    remove, 0, NBT_MB);
11975772Sas200622 	if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0)
11985772Sas200622 		return;
11995331Samw 
120010966SJordan.Brown@Sun.COM 	(void) smb_strupr(resource_domain);
12015331Samw 
120210717Samw@Sun.COM 	smb_init_name_struct((unsigned char *)resource_domain, NBT_MB,
12035331Samw 	    0, 0, 0, 0, 0, &name);
12045331Samw 
12055331Samw 	if ((dest = smb_name_find_name(&name))) {
12065331Samw 		addr = dest->addr_list;
12075331Samw 		addr.forw = addr.back = &addr;
12085331Samw 		smb_name_unlock_name(dest);
12096030Sjb150015 		smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval,
121010717Samw@Sun.COM 		    remove, &addr, NBT_MB);
12115331Samw 	} else {
121210717Samw@Sun.COM 		smb_init_name_struct((unsigned char *)resource_domain,
121310717Samw@Sun.COM 		    NBT_DMB, 0, 0, 0, 0, 0, &name);
12145331Samw 		if ((dest = smb_name_find_name(&name))) {
12155331Samw 			addr = dest->addr_list;
12165331Samw 			addr.forw = addr.back = &addr;
12175331Samw 			smb_name_unlock_name(dest);
12186030Sjb150015 			smb_browser_send_HostAnnouncement(hinfo,
121910717Samw@Sun.COM 			    remove, hinfo->hi_interval, &addr, NBT_DMB);
12205331Samw 		}
12215331Samw 	}
12225331Samw 
12235331Samw 	/*
12245331Samw 	 * One Minute announcements for first five
12256030Sjb150015 	 * minutes, one minute longer each round
12265331Samw 	 * until 12 minutes and every 12 minutes
12275331Samw 	 * thereafter.
12285331Samw 	 */
12296030Sjb150015 	if (--hinfo->hi_reps == 0) {
12306030Sjb150015 		if (hinfo->hi_interval < 12)
12316030Sjb150015 			hinfo->hi_interval++;
12325331Samw 
12336030Sjb150015 		hinfo->hi_reps = 1;
12345331Samw 	}
12355331Samw 
12366030Sjb150015 	hinfo->hi_nextannouce = hinfo->hi_interval;
12375331Samw }
12385331Samw 
12395331Samw 
12405331Samw /*
124110717Samw@Sun.COM  * SMB NetBIOS Browser Service
12425331Samw  */
12435331Samw /*ARGSUSED*/
12445331Samw void *
smb_browser_service(void * arg)124510717Samw@Sun.COM smb_browser_service(void *arg)
12465331Samw {
12476030Sjb150015 	smb_hostinfo_t *hinfo;
12485331Samw 
12496030Sjb150015 	smb_browser_infoinit();
12505331Samw 	smb_browser_config();
12515331Samw 
125210717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_BROWSER_START);
12535331Samw 
12546030Sjb150015 restart:
12556030Sjb150015 	do {
12566030Sjb150015 		(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
12576030Sjb150015 		hinfo = list_head(&smb_binfo.bi_hlist);
125810717Samw@Sun.COM 
12596030Sjb150015 		while (hinfo) {
12606030Sjb150015 			if (--hinfo->hi_nextannouce > 0 ||
12616030Sjb150015 			    hinfo->hi_nic.nic_bcast == 0) {
12626030Sjb150015 				hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
12635331Samw 				continue;
12646030Sjb150015 			}
12656030Sjb150015 
12666030Sjb150015 			smb_browser_non_master_duties(hinfo, B_FALSE);
12675331Samw 
12686030Sjb150015 			/* Check to see whether reconfig is needed */
12696030Sjb150015 			(void) mutex_lock(&smb_binfo.bi_mtx);
12706030Sjb150015 			if (smb_binfo.bi_changed) {
12716030Sjb150015 				smb_binfo.bi_changed = B_FALSE;
12726030Sjb150015 				(void) mutex_unlock(&smb_binfo.bi_mtx);
12736030Sjb150015 				(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
12746030Sjb150015 				smb_browser_config();
12756030Sjb150015 				goto restart;
12766030Sjb150015 			}
12776030Sjb150015 			(void) mutex_unlock(&smb_binfo.bi_mtx);
12785331Samw 
12796030Sjb150015 			hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
12805331Samw 		}
128110717Samw@Sun.COM 
12826030Sjb150015 		(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
128310717Samw@Sun.COM 		smb_netbios_sleep(SECSPERMIN);	/* 1 minute */
128410717Samw@Sun.COM 	} while (smb_netbios_running());
12855331Samw 
12866030Sjb150015 	smb_browser_infoterm();
128710717Samw@Sun.COM 	smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP);
12885331Samw 	return (0);
12895331Samw }
12906030Sjb150015 
12916030Sjb150015 /*
12926030Sjb150015  * smb_browser_netlogon
12936030Sjb150015  *
12946030Sjb150015  * Sends SAMLOGON/NETLOGON request for all host/ips, except
12956030Sjb150015  * aliases, to find a domain controller.
12968334SJose.Borrego@Sun.COM  *
12978334SJose.Borrego@Sun.COM  * The dc argument will be set if a DC is found.
12986030Sjb150015  */
12998334SJose.Borrego@Sun.COM boolean_t
smb_browser_netlogon(char * domain,char * dc,uint32_t dc_len)13008334SJose.Borrego@Sun.COM smb_browser_netlogon(char *domain, char *dc, uint32_t dc_len)
13016030Sjb150015 {
13026030Sjb150015 	smb_hostinfo_t *hinfo;
13038334SJose.Borrego@Sun.COM 	boolean_t found = B_FALSE;
13048334SJose.Borrego@Sun.COM 	timestruc_t to;
13058334SJose.Borrego@Sun.COM 	int err;
13066030Sjb150015 
13076030Sjb150015 	(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
13086030Sjb150015 	hinfo = list_head(&smb_binfo.bi_hlist);
13096030Sjb150015 	while (hinfo) {
13106030Sjb150015 		if ((hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) == 0)
13119832Samw@Sun.COM 			smb_netlogon_request(&hinfo->hi_netname, domain);
13126030Sjb150015 		hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
13136030Sjb150015 	}
13146030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13158334SJose.Borrego@Sun.COM 
13168334SJose.Borrego@Sun.COM 	bzero(dc, dc_len);
13178334SJose.Borrego@Sun.COM 	to.tv_sec = 30;
13188334SJose.Borrego@Sun.COM 	to.tv_nsec = 0;
13198334SJose.Borrego@Sun.COM 	(void) mutex_lock(&ntdomain_mtx);
13208334SJose.Borrego@Sun.COM 	while (ntdomain_info.n_ipaddr == 0) {
13218334SJose.Borrego@Sun.COM 		err = cond_reltimedwait(&ntdomain_cv, &ntdomain_mtx, &to);
13228334SJose.Borrego@Sun.COM 		if (err == ETIME)
13238334SJose.Borrego@Sun.COM 			break;
13248334SJose.Borrego@Sun.COM 	}
13258334SJose.Borrego@Sun.COM 
13268334SJose.Borrego@Sun.COM 	if (ntdomain_info.n_ipaddr != 0) {
13278334SJose.Borrego@Sun.COM 		(void) strlcpy(dc, ntdomain_info.n_name, dc_len);
13288334SJose.Borrego@Sun.COM 		found = B_TRUE;
13298334SJose.Borrego@Sun.COM 	}
13308334SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ntdomain_mtx);
13318334SJose.Borrego@Sun.COM 
13328334SJose.Borrego@Sun.COM 	return (found);
13336030Sjb150015 }
13346030Sjb150015 
13356030Sjb150015 /*
13366030Sjb150015  * smb_browser_infoinit
13376030Sjb150015  *
133810717Samw@Sun.COM  * This function is called only once when the browser starts
133910717Samw@Sun.COM  * to initialize the global smb_binfo structure.
13406030Sjb150015  */
13416030Sjb150015 static void
smb_browser_infoinit(void)13426030Sjb150015 smb_browser_infoinit(void)
13436030Sjb150015 {
13448334SJose.Borrego@Sun.COM 	(void) mutex_lock(&ntdomain_mtx);
13458334SJose.Borrego@Sun.COM 	bzero(&ntdomain_info, sizeof (ntdomain_info));
13468334SJose.Borrego@Sun.COM 	(void) mutex_unlock(&ntdomain_mtx);
13478334SJose.Borrego@Sun.COM 
13486030Sjb150015 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
13496030Sjb150015 	list_create(&smb_binfo.bi_hlist, sizeof (smb_hostinfo_t),
13506030Sjb150015 	    offsetof(smb_hostinfo_t, hi_lnd));
13516030Sjb150015 	smb_binfo.bi_hcnt = 0;
13526030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13536030Sjb150015 
13546030Sjb150015 	(void) mutex_lock(&smb_binfo.bi_mtx);
13556030Sjb150015 	smb_binfo.bi_changed = B_FALSE;
13566030Sjb150015 	(void) mutex_unlock(&smb_binfo.bi_mtx);
13576030Sjb150015 }
13586030Sjb150015 
13596030Sjb150015 /*
13606030Sjb150015  * smb_browser_infoterm
13616030Sjb150015  *
136210717Samw@Sun.COM  * This function is called only once when the browser stops
136310717Samw@Sun.COM  * to destroy the smb_binfo structure.
13646030Sjb150015  */
13656030Sjb150015 static void
smb_browser_infoterm(void)13666030Sjb150015 smb_browser_infoterm(void)
13676030Sjb150015 {
13686030Sjb150015 	(void) rw_wrlock(&smb_binfo.bi_hlist_rwl);
13696030Sjb150015 	smb_browser_infofree();
13706030Sjb150015 	list_destroy(&smb_binfo.bi_hlist);
13716030Sjb150015 	(void) rw_unlock(&smb_binfo.bi_hlist_rwl);
13726030Sjb150015 }
13736030Sjb150015 
13746030Sjb150015 /*
13756030Sjb150015  * smb_browser_infofree
13766030Sjb150015  *
13776030Sjb150015  * Removes all the hostinfo structures from the browser list
13786030Sjb150015  * and frees the allocated memory
13796030Sjb150015  */
13806030Sjb150015 static void
smb_browser_infofree(void)13816030Sjb150015 smb_browser_infofree(void)
13826030Sjb150015 {
13836030Sjb150015 	smb_hostinfo_t *hinfo;
13846030Sjb150015 
13856030Sjb150015 	while ((hinfo = list_head(&smb_binfo.bi_hlist)) != NULL) {
13866030Sjb150015 		list_remove(&smb_binfo.bi_hlist, hinfo);
13876030Sjb150015 		free(hinfo);
13886030Sjb150015 	}
13896030Sjb150015 
13906030Sjb150015 	smb_binfo.bi_hcnt = 0;
13916030Sjb150015 }
1392