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 /* 227f667e74Sjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26a0aa776eSAlan Wright #include <sys/tzfile.h> 278d7e4166Sjose borrego #include <errno.h> 28da6c28aaSamw #include <stdlib.h> 29da6c28aaSamw #include <stdio.h> 30da6c28aaSamw #include <unistd.h> 31da6c28aaSamw #include <syslog.h> 32da6c28aaSamw #include <string.h> 33da6c28aaSamw #include <strings.h> 34da6c28aaSamw #include <time.h> 35da6c28aaSamw #include <synch.h> 36da6c28aaSamw #include <netdb.h> 37da6c28aaSamw #include <sys/socket.h> 38da6c28aaSamw #include <arpa/inet.h> 39da6c28aaSamw 40dc20a302Sas #include <smbsrv/libsmb.h> 41da6c28aaSamw #include <smbsrv/libsmbns.h> 42*bbf6f00cSJordan Brown #include <smbsrv/smb.h> 43da6c28aaSamw #include <smbsrv/mailslot.h> 44da6c28aaSamw #include <smbns_browser.h> 45da6c28aaSamw #include <smbns_netbios.h> 46da6c28aaSamw 478d7e4166Sjose borrego /* 488d7e4166Sjose borrego * ntdomain_info 498d7e4166Sjose borrego * Temporary. It should be removed once NBTD is integrated. 508d7e4166Sjose borrego */ 518d7e4166Sjose borrego smb_ntdomain_t ntdomain_info; 528d7e4166Sjose borrego mutex_t ntdomain_mtx; 538d7e4166Sjose borrego cond_t ntdomain_cv; 548d7e4166Sjose borrego 55da6c28aaSamw #define SMB_SERVER_SIGNATURE 0xaa550415 56da6c28aaSamw 577b59d02dSjb typedef struct smb_hostinfo { 587b59d02dSjb list_node_t hi_lnd; 597b59d02dSjb smb_nic_t hi_nic; 607b59d02dSjb char hi_nbname[NETBIOS_NAME_SZ]; 617b59d02dSjb name_entry_t hi_netname; 627b59d02dSjb uint32_t hi_nextannouce; 637b59d02dSjb int hi_reps; 647b59d02dSjb int hi_interval; 657b59d02dSjb uint8_t hi_updatecnt; 667b59d02dSjb uint32_t hi_type; 677b59d02dSjb } smb_hostinfo_t; 687b59d02dSjb 697b59d02dSjb typedef struct smb_browserinfo { 707b59d02dSjb list_t bi_hlist; 717b59d02dSjb int bi_hcnt; 727b59d02dSjb rwlock_t bi_hlist_rwl; 737b59d02dSjb boolean_t bi_changed; 747b59d02dSjb mutex_t bi_mtx; 757b59d02dSjb } smb_browserinfo_t; 767b59d02dSjb 777b59d02dSjb static smb_browserinfo_t smb_binfo; 787b59d02dSjb 797b59d02dSjb static int smb_browser_init(void); 807b59d02dSjb static void smb_browser_infoinit(void); 817b59d02dSjb static void smb_browser_infoterm(void); 827b59d02dSjb static void smb_browser_infofree(void); 83da6c28aaSamw 848d7e4166Sjose borrego 857b59d02dSjb void 867b59d02dSjb smb_browser_reconfig(void) 87da6c28aaSamw { 887b59d02dSjb (void) mutex_lock(&smb_binfo.bi_mtx); 897b59d02dSjb smb_binfo.bi_changed = B_TRUE; 907b59d02dSjb (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 597da6c28aaSamw smb_browser_load_transact_header(unsigned char *buffer, int maxcnt, 5987b59d02dSjb 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 6497b59d02dSjb 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 6557b59d02dSjb if (name == NULL) 656da6c28aaSamw return (-1); 657da6c28aaSamw 6587b59d02dSjb if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) 659da6c28aaSamw return (-1); 6607b59d02dSjb 6617f667e74Sjose borrego ipaddr = hinfo->hi_nic.nic_ip.a_ipv4; 6627b59d02dSjb 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 6837b59d02dSjb smb_browser_bcast_addr_of_subnet(struct name_entry *name, uint32_t bcast, 684da6c28aaSamw struct name_entry *result) 685da6c28aaSamw { 6867b59d02dSjb 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); 6917b59d02dSjb 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 7697b59d02dSjb static void 7707b59d02dSjb smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo, 7717b59d02dSjb 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 781dc20a302Sas if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) 782dc20a302Sas return; 783*bbf6f00cSJordan Brown (void) smb_strupr(resource_domain); 784da6c28aaSamw 7857b59d02dSjb if (addr == NULL) { 786da6c28aaSamw /* Local master Browser */ 7877b59d02dSjb smb_init_name_struct((unsigned char *)resource_domain, suffix, 788da6c28aaSamw 0, 0, 0, 0, 0, &dest_name); 7897b59d02dSjb if (smb_browser_bcast_addr_of_subnet(0, hinfo->hi_nic.nic_bcast, 7907b59d02dSjb &dest_name) < 0) 791da6c28aaSamw return; 792da6c28aaSamw } else { 7937b59d02dSjb 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 + 8087b59d02dSjb strlen(hinfo->hi_nic.nic_cmnt) + 1; 809da6c28aaSamw 8107b59d02dSjb offset = smb_browser_load_transact_header(buffer, 811da6c28aaSamw MAX_DATAGRAM_LENGTH, data_length, ONE_WAY_TRANSACTION, 8127b59d02dSjb MAILSLOT_BROWSE); 813da6c28aaSamw 8147b59d02dSjb 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())) 8257b59d02dSjb type = 0; 8267b59d02dSjb else 8277b59d02dSjb type = hinfo->hi_type; 828da6c28aaSamw 829da6c28aaSamw smb_msgbuf_init(&mb, buffer + offset, MAX_DATAGRAM_LENGTH - offset, 0); 8307b59d02dSjb 831da6c28aaSamw announce_len = smb_msgbuf_encode(&mb, "bbl16cbblls", 8327b59d02dSjb HOST_ANNOUNCEMENT, 8337b59d02dSjb ++hinfo->hi_updatecnt, 834da6c28aaSamw next_announcement * 60000, /* Periodicity in MilliSeconds */ 8357b59d02dSjb hinfo->hi_nbname, 8367b59d02dSjb SMB_VERSION_MAJOR, 8377b59d02dSjb SMB_VERSION_MINOR, 8387b59d02dSjb type, 8397b59d02dSjb SMB_SERVER_SIGNATURE, 8407b59d02dSjb hinfo->hi_nic.nic_cmnt); 841da6c28aaSamw 842da6c28aaSamw if (announce_len > 0) 8437b59d02dSjb (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 8507b59d02dSjb static void 851da6c28aaSamw smb_browser_process_AnnouncementRequest(struct datagram *datagram, 852da6c28aaSamw char *mailbox) 853da6c28aaSamw { 8547b59d02dSjb smb_hostinfo_t *hinfo; 8557b59d02dSjb uint32_t next_announcement; 856da6c28aaSamw uint32_t delay = random() % 29; /* in seconds */ 8577b59d02dSjb boolean_t h_found = B_FALSE; 858da6c28aaSamw 8597b59d02dSjb 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 8667b59d02dSjb (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); 8677b59d02dSjb hinfo = list_head(&smb_binfo.bi_hlist); 8687b59d02dSjb while (hinfo) { 8697f667e74Sjose borrego if ((hinfo->hi_nic.nic_ip.a_ipv4 & 8707f667e74Sjose borrego hinfo->hi_nic.nic_mask) == 8717b59d02dSjb (datagram->src.addr_list.sin.sin_addr.s_addr & 8727b59d02dSjb hinfo->hi_nic.nic_mask)) { 8737b59d02dSjb h_found = B_TRUE; 8747b59d02dSjb break; 8757b59d02dSjb } 8767b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 8777b59d02dSjb } 8787b59d02dSjb 8797b59d02dSjb if (h_found) { 8807b59d02dSjb next_announcement = hinfo->hi_nextannouce * 60 * 1000; 8817b59d02dSjb smb_browser_send_HostAnnouncement(hinfo, next_announcement, 882a0aa776eSAlan Wright B_FALSE, &datagram->src.addr_list, NBT_MB); 883da6c28aaSamw } 8847b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 885da6c28aaSamw } 886da6c28aaSamw 887da6c28aaSamw void * 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 10457b59d02dSjb static void 1046da6c28aaSamw smb_browser_config(void) 1047da6c28aaSamw { 10487b59d02dSjb 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]; 10547b59d02dSjb int rc; 10557b59d02dSjb 10567b59d02dSjb if (smb_browser_init() != 0) 10577b59d02dSjb return; 1058da6c28aaSamw 1059dc20a302Sas if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) 1060dc20a302Sas return; 1061*bbf6f00cSJordan 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 10697b59d02dSjb (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); 10707b59d02dSjb hinfo = list_head(&smb_binfo.bi_hlist); 10717b59d02dSjb 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); 10777b59d02dSjb 10787b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 1079da6c28aaSamw } 10807b59d02dSjb (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) { 10887b59d02dSjb (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); 10897b59d02dSjb hinfo = list_head(&smb_binfo.bi_hlist); 10907b59d02dSjb while (hinfo) { 10917b59d02dSjb rc = smb_browser_addr_of_subnet(entry, hinfo, &master); 10927b59d02dSjb 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 } 10977b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 1098da6c28aaSamw } 10997b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 11007b59d02dSjb 1101da6c28aaSamw smb_name_unlock_name(entry); 1102da6c28aaSamw } 11037b59d02dSjb 11047b59d02dSjb /* 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 11177b59d02dSjb static int 11187b59d02dSjb smb_browser_init(void) 1119da6c28aaSamw { 11207b59d02dSjb smb_hostinfo_t *hinfo; 11217b59d02dSjb smb_niciter_t ni; 11227b59d02dSjb uint32_t type; 1123da6c28aaSamw 11247b59d02dSjb (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); 11257b59d02dSjb smb_browser_infofree(); 1126da6c28aaSamw 11277b59d02dSjb if (smb_nic_getfirst(&ni) != 0) { 11287b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 11297b59d02dSjb return (-1); 1130da6c28aaSamw } 1131da6c28aaSamw 11327b59d02dSjb type = MY_SERVER_TYPE; 11337b59d02dSjb if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) 11347b59d02dSjb type |= SV_DOMAIN_MEMBER; 11357b59d02dSjb 11367b59d02dSjb do { 11378d7e4166Sjose borrego if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) || 11388d7e4166Sjose borrego (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) 11397b59d02dSjb continue; 11407b59d02dSjb 11417b59d02dSjb hinfo = malloc(sizeof (smb_hostinfo_t)); 11427b59d02dSjb if (hinfo == NULL) { 11437b59d02dSjb smb_browser_infofree(); 11447b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 11457b59d02dSjb return (-1); 11467b59d02dSjb } 11477b59d02dSjb 11487b59d02dSjb hinfo->hi_nic = ni.ni_nic; 11497b59d02dSjb /* One Minute announcements for first five */ 11507b59d02dSjb hinfo->hi_nextannouce = 1; 11517b59d02dSjb hinfo->hi_interval = 1; 11527b59d02dSjb hinfo->hi_reps = 5; 11537b59d02dSjb hinfo->hi_updatecnt = 0; 11547b59d02dSjb hinfo->hi_type = type; 11557b59d02dSjb 11567b59d02dSjb /* This is the name used for HostAnnouncement */ 11577b59d02dSjb (void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host, 11587b59d02dSjb NETBIOS_NAME_SZ); 1159*bbf6f00cSJordan Brown (void) smb_strupr(hinfo->hi_nbname); 11607b59d02dSjb /* 0x20: file server service */ 11617b59d02dSjb smb_init_name_struct((unsigned char *)hinfo->hi_nbname, 1162a0aa776eSAlan Wright NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4, 1163a0aa776eSAlan Wright htons(IPPORT_NETBIOS_DGM), 1164a0aa776eSAlan Wright NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, 11657f667e74Sjose borrego &hinfo->hi_netname); 11667b59d02dSjb 11677b59d02dSjb list_insert_tail(&smb_binfo.bi_hlist, hinfo); 11687b59d02dSjb smb_binfo.bi_hcnt++; 11697b59d02dSjb } while (smb_nic_getnext(&ni) == 0); 11707b59d02dSjb 11717b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 11727b59d02dSjb return (0); 1173da6c28aaSamw } 1174da6c28aaSamw 1175da6c28aaSamw /* 1176da6c28aaSamw * smb_browser_non_master_duties 1177da6c28aaSamw * 1178da6c28aaSamw * To advertise its presence, i.e. to publish itself as being available, a 1179da6c28aaSamw * non-browser server sends a HostAnnouncement browser frame. If the server 1180da6c28aaSamw * is a member of domain "D", this frame is sent to the NETBIOS unique name 1181da6c28aaSamw * D(1d) and mailslot "\\MAILSLOT\\BROWSE". 1182da6c28aaSamw */ 11837b59d02dSjb static void 11847b59d02dSjb smb_browser_non_master_duties(smb_hostinfo_t *hinfo, boolean_t remove) 1185da6c28aaSamw { 1186da6c28aaSamw struct name_entry name; 1187da6c28aaSamw struct name_entry *dest; 1188a0aa776eSAlan Wright addr_entry_t addr; 1189da6c28aaSamw char resource_domain[SMB_PI_MAX_DOMAIN]; 1190da6c28aaSamw 11917b59d02dSjb smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, 1192a0aa776eSAlan Wright remove, 0, NBT_MB); 1193dc20a302Sas if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) 1194dc20a302Sas return; 1195da6c28aaSamw 1196*bbf6f00cSJordan Brown (void) smb_strupr(resource_domain); 1197da6c28aaSamw 1198a0aa776eSAlan Wright smb_init_name_struct((unsigned char *)resource_domain, NBT_MB, 1199da6c28aaSamw 0, 0, 0, 0, 0, &name); 1200da6c28aaSamw 1201da6c28aaSamw if ((dest = smb_name_find_name(&name))) { 1202da6c28aaSamw addr = dest->addr_list; 1203da6c28aaSamw addr.forw = addr.back = &addr; 1204da6c28aaSamw smb_name_unlock_name(dest); 12057b59d02dSjb smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, 1206a0aa776eSAlan Wright remove, &addr, NBT_MB); 1207da6c28aaSamw } else { 1208a0aa776eSAlan Wright smb_init_name_struct((unsigned char *)resource_domain, 1209a0aa776eSAlan Wright NBT_DMB, 0, 0, 0, 0, 0, &name); 1210da6c28aaSamw if ((dest = smb_name_find_name(&name))) { 1211da6c28aaSamw addr = dest->addr_list; 1212da6c28aaSamw addr.forw = addr.back = &addr; 1213da6c28aaSamw smb_name_unlock_name(dest); 12147b59d02dSjb smb_browser_send_HostAnnouncement(hinfo, 1215a0aa776eSAlan Wright remove, hinfo->hi_interval, &addr, NBT_DMB); 1216da6c28aaSamw } 1217da6c28aaSamw } 1218da6c28aaSamw 1219da6c28aaSamw /* 1220da6c28aaSamw * One Minute announcements for first five 12217b59d02dSjb * minutes, one minute longer each round 1222da6c28aaSamw * until 12 minutes and every 12 minutes 1223da6c28aaSamw * thereafter. 1224da6c28aaSamw */ 12257b59d02dSjb if (--hinfo->hi_reps == 0) { 12267b59d02dSjb if (hinfo->hi_interval < 12) 12277b59d02dSjb hinfo->hi_interval++; 1228da6c28aaSamw 12297b59d02dSjb hinfo->hi_reps = 1; 1230da6c28aaSamw } 1231da6c28aaSamw 12327b59d02dSjb hinfo->hi_nextannouce = hinfo->hi_interval; 1233da6c28aaSamw } 1234da6c28aaSamw 1235da6c28aaSamw 1236da6c28aaSamw /* 1237a0aa776eSAlan Wright * SMB NetBIOS Browser Service 1238da6c28aaSamw */ 1239da6c28aaSamw /*ARGSUSED*/ 1240da6c28aaSamw void * 1241a0aa776eSAlan Wright smb_browser_service(void *arg) 1242da6c28aaSamw { 12437b59d02dSjb smb_hostinfo_t *hinfo; 1244da6c28aaSamw 12457b59d02dSjb smb_browser_infoinit(); 1246da6c28aaSamw smb_browser_config(); 1247da6c28aaSamw 1248a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_BROWSER_START); 1249da6c28aaSamw 12507b59d02dSjb restart: 12517b59d02dSjb do { 12527b59d02dSjb (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); 12537b59d02dSjb hinfo = list_head(&smb_binfo.bi_hlist); 1254a0aa776eSAlan Wright 12557b59d02dSjb while (hinfo) { 12567b59d02dSjb if (--hinfo->hi_nextannouce > 0 || 12577b59d02dSjb hinfo->hi_nic.nic_bcast == 0) { 12587b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 1259da6c28aaSamw continue; 12607b59d02dSjb } 1261da6c28aaSamw 12627b59d02dSjb smb_browser_non_master_duties(hinfo, B_FALSE); 1263da6c28aaSamw 12647b59d02dSjb /* Check to see whether reconfig is needed */ 12657b59d02dSjb (void) mutex_lock(&smb_binfo.bi_mtx); 12667b59d02dSjb if (smb_binfo.bi_changed) { 12677b59d02dSjb smb_binfo.bi_changed = B_FALSE; 12687b59d02dSjb (void) mutex_unlock(&smb_binfo.bi_mtx); 12697b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 12707b59d02dSjb smb_browser_config(); 12717b59d02dSjb goto restart; 12727b59d02dSjb } 12737b59d02dSjb (void) mutex_unlock(&smb_binfo.bi_mtx); 1274da6c28aaSamw 12757b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 1276da6c28aaSamw } 1277a0aa776eSAlan Wright 12787b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 1279a0aa776eSAlan Wright smb_netbios_sleep(SECSPERMIN); /* 1 minute */ 1280a0aa776eSAlan Wright } while (smb_netbios_running()); 1281da6c28aaSamw 12827b59d02dSjb smb_browser_infoterm(); 1283a0aa776eSAlan Wright smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP); 1284da6c28aaSamw return (0); 1285da6c28aaSamw } 12867b59d02dSjb 12877b59d02dSjb /* 12887b59d02dSjb * smb_browser_netlogon 12897b59d02dSjb * 12907b59d02dSjb * Sends SAMLOGON/NETLOGON request for all host/ips, except 12917b59d02dSjb * aliases, to find a domain controller. 12928d7e4166Sjose borrego * 12938d7e4166Sjose borrego * The dc argument will be set if a DC is found. 12947b59d02dSjb */ 12958d7e4166Sjose borrego boolean_t 12968d7e4166Sjose borrego smb_browser_netlogon(char *domain, char *dc, uint32_t dc_len) 12977b59d02dSjb { 12987b59d02dSjb smb_hostinfo_t *hinfo; 12998d7e4166Sjose borrego boolean_t found = B_FALSE; 13008d7e4166Sjose borrego timestruc_t to; 13018d7e4166Sjose borrego int err; 13027b59d02dSjb 13037b59d02dSjb (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); 13047b59d02dSjb hinfo = list_head(&smb_binfo.bi_hlist); 13057b59d02dSjb while (hinfo) { 13067b59d02dSjb if ((hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS) == 0) 130729bd2886SAlan Wright smb_netlogon_request(&hinfo->hi_netname, domain); 13087b59d02dSjb hinfo = list_next(&smb_binfo.bi_hlist, hinfo); 13097b59d02dSjb } 13107b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 13118d7e4166Sjose borrego 13128d7e4166Sjose borrego bzero(dc, dc_len); 13138d7e4166Sjose borrego to.tv_sec = 30; 13148d7e4166Sjose borrego to.tv_nsec = 0; 13158d7e4166Sjose borrego (void) mutex_lock(&ntdomain_mtx); 13168d7e4166Sjose borrego while (ntdomain_info.n_ipaddr == 0) { 13178d7e4166Sjose borrego err = cond_reltimedwait(&ntdomain_cv, &ntdomain_mtx, &to); 13188d7e4166Sjose borrego if (err == ETIME) 13198d7e4166Sjose borrego break; 13208d7e4166Sjose borrego } 13218d7e4166Sjose borrego 13228d7e4166Sjose borrego if (ntdomain_info.n_ipaddr != 0) { 13238d7e4166Sjose borrego (void) strlcpy(dc, ntdomain_info.n_name, dc_len); 13248d7e4166Sjose borrego found = B_TRUE; 13258d7e4166Sjose borrego } 13268d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 13278d7e4166Sjose borrego 13288d7e4166Sjose borrego return (found); 13297b59d02dSjb } 13307b59d02dSjb 13317b59d02dSjb /* 13327b59d02dSjb * smb_browser_infoinit 13337b59d02dSjb * 1334a0aa776eSAlan Wright * This function is called only once when the browser starts 1335a0aa776eSAlan Wright * to initialize the global smb_binfo structure. 13367b59d02dSjb */ 13377b59d02dSjb static void 13387b59d02dSjb smb_browser_infoinit(void) 13397b59d02dSjb { 13408d7e4166Sjose borrego (void) mutex_lock(&ntdomain_mtx); 13418d7e4166Sjose borrego bzero(&ntdomain_info, sizeof (ntdomain_info)); 13428d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 13438d7e4166Sjose borrego 13447b59d02dSjb (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); 13457b59d02dSjb list_create(&smb_binfo.bi_hlist, sizeof (smb_hostinfo_t), 13467b59d02dSjb offsetof(smb_hostinfo_t, hi_lnd)); 13477b59d02dSjb smb_binfo.bi_hcnt = 0; 13487b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 13497b59d02dSjb 13507b59d02dSjb (void) mutex_lock(&smb_binfo.bi_mtx); 13517b59d02dSjb smb_binfo.bi_changed = B_FALSE; 13527b59d02dSjb (void) mutex_unlock(&smb_binfo.bi_mtx); 13537b59d02dSjb } 13547b59d02dSjb 13557b59d02dSjb /* 13567b59d02dSjb * smb_browser_infoterm 13577b59d02dSjb * 1358a0aa776eSAlan Wright * This function is called only once when the browser stops 1359a0aa776eSAlan Wright * to destroy the smb_binfo structure. 13607b59d02dSjb */ 13617b59d02dSjb static void 13627b59d02dSjb smb_browser_infoterm(void) 13637b59d02dSjb { 13647b59d02dSjb (void) rw_wrlock(&smb_binfo.bi_hlist_rwl); 13657b59d02dSjb smb_browser_infofree(); 13667b59d02dSjb list_destroy(&smb_binfo.bi_hlist); 13677b59d02dSjb (void) rw_unlock(&smb_binfo.bi_hlist_rwl); 13687b59d02dSjb } 13697b59d02dSjb 13707b59d02dSjb /* 13717b59d02dSjb * smb_browser_infofree 13727b59d02dSjb * 13737b59d02dSjb * Removes all the hostinfo structures from the browser list 13747b59d02dSjb * and frees the allocated memory 13757b59d02dSjb */ 13767b59d02dSjb static void 13777b59d02dSjb smb_browser_infofree(void) 13787b59d02dSjb { 13797b59d02dSjb smb_hostinfo_t *hinfo; 13807b59d02dSjb 13817b59d02dSjb while ((hinfo = list_head(&smb_binfo.bi_hlist)) != NULL) { 13827b59d02dSjb list_remove(&smb_binfo.bi_hlist, hinfo); 13837b59d02dSjb free(hinfo); 13847b59d02dSjb } 13857b59d02dSjb 13867b59d02dSjb smb_binfo.bi_hcnt = 0; 13877b59d02dSjb } 1388