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