15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
228670SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
235331Samw * Use is subject to license terms.
245331Samw */
255331Samw
265331Samw /*
275331Samw * This module handles the primary domain controller location protocol.
285331Samw * The document claims to be version 1.15 of the browsing protocol. It also
295331Samw * claims to specify the mailslot protocol.
305331Samw *
315331Samw * The NETLOGON protocol uses \MAILSLOT\NET mailslots. The protocol
325331Samw * specification is incomplete, contains errors and is out-of-date but
335331Samw * it does provide some useful background information. The document
345331Samw * doesn't mention the NETLOGON_SAMLOGON version of the protocol.
355331Samw */
365331Samw
375331Samw #include <stdlib.h>
385331Samw #include <syslog.h>
395331Samw #include <alloca.h>
405331Samw #include <arpa/inet.h>
415331Samw #include <resolv.h>
425331Samw
435331Samw #include <smbsrv/mailslot.h>
445331Samw #include <smbsrv/libsmbns.h>
455331Samw #include <smbns_browser.h>
465331Samw #include <smbns_netbios.h>
475331Samw
485331Samw static void smb_netlogon_query(struct name_entry *server, char *mailbox,
495331Samw char *domain);
505331Samw
519832Samw@Sun.COM static void smb_netlogon_samlogon(struct name_entry *, char *,
529832Samw@Sun.COM char *, smb_sid_t *);
535331Samw
545331Samw static void smb_netlogon_send(struct name_entry *name, char *domain,
555331Samw unsigned char *buffer, int count);
565331Samw
575331Samw static void smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr);
587052Samw static int smb_better_dc(uint32_t cur_ip, uint32_t new_ip);
595331Samw
608334SJose.Borrego@Sun.COM /*
618334SJose.Borrego@Sun.COM * ntdomain_info
628334SJose.Borrego@Sun.COM * Temporary. It should be removed once NBTD is integrated.
638334SJose.Borrego@Sun.COM */
648334SJose.Borrego@Sun.COM extern smb_ntdomain_t ntdomain_info;
658334SJose.Borrego@Sun.COM extern mutex_t ntdomain_mtx;
668334SJose.Borrego@Sun.COM extern cond_t ntdomain_cv;
675331Samw
685331Samw /*
695331Samw * smb_netlogon_request
705331Samw *
715331Samw * This is the entry point locating the resource domain PDC. A netlogon
725331Samw * request is sent using the specified protocol on the specified network.
735331Samw * Note that we need to know the domain SID in order to use the samlogon
745331Samw * format.
755331Samw *
765331Samw * Netlogon responses are received asynchronously and eventually handled
775331Samw * in smb_netlogon_receive.
785331Samw */
795331Samw void
smb_netlogon_request(struct name_entry * server,char * domain)809832Samw@Sun.COM smb_netlogon_request(struct name_entry *server, char *domain)
815331Samw {
8210717Samw@Sun.COM smb_domain_t di;
839832Samw@Sun.COM smb_sid_t *sid = NULL;
849832Samw@Sun.COM int protocol = NETLOGON_PROTO_NETLOGON;
855331Samw
866030Sjb150015 if (domain == NULL || *domain == '\0')
875331Samw return;
885331Samw
898334SJose.Borrego@Sun.COM (void) mutex_lock(&ntdomain_mtx);
908334SJose.Borrego@Sun.COM (void) strlcpy(ntdomain_info.n_domain, domain,
918334SJose.Borrego@Sun.COM sizeof (ntdomain_info.n_domain));
928334SJose.Borrego@Sun.COM (void) mutex_unlock(&ntdomain_mtx);
935331Samw
949832Samw@Sun.COM smb_config_getdomaininfo(di.di_nbname, NULL, di.di_sid, NULL, NULL);
95*10966SJordan.Brown@Sun.COM if (smb_strcasecmp(di.di_nbname, domain, 0) == 0) {
969832Samw@Sun.COM if ((sid = smb_sid_fromstr(di.di_sid)) != NULL)
979832Samw@Sun.COM protocol = NETLOGON_PROTO_SAMLOGON;
989832Samw@Sun.COM }
999832Samw@Sun.COM
1009832Samw@Sun.COM if (protocol == NETLOGON_PROTO_SAMLOGON)
1019832Samw@Sun.COM smb_netlogon_samlogon(server, MAILSLOT_NETLOGON_SAMLOGON_RDC,
1029832Samw@Sun.COM domain, sid);
1036030Sjb150015 else
1049832Samw@Sun.COM smb_netlogon_query(server, MAILSLOT_NETLOGON_RDC, domain);
1059832Samw@Sun.COM
1069832Samw@Sun.COM smb_sid_free(sid);
1075331Samw }
1085331Samw
1095331Samw /*
1105331Samw * smb_netlogon_receive
1115331Samw *
1125331Samw * This is where we handle all incoming NetLogon messages. Currently, we
1135331Samw * ignore requests from anyone else. We are only interested in responses
1145331Samw * to our own requests. The NetLogonResponse provides the name of the PDC.
1155331Samw * If we don't already have a controller name, we use the name provided
1165331Samw * in the message. Otherwise we use the name already in the environment.
1175331Samw */
1185331Samw void
smb_netlogon_receive(struct datagram * datagram,char * mailbox,unsigned char * data,int datalen)1195331Samw smb_netlogon_receive(struct datagram *datagram,
1205331Samw char *mailbox,
1215331Samw unsigned char *data,
1225331Samw int datalen)
1235331Samw {
1245331Samw struct netlogon_opt {
1255331Samw char *mailslot;
1265331Samw void (*handler)();
1275331Samw } netlogon_opt[] = {
1285331Samw { MAILSLOT_NETLOGON_RDC, smb_netlogon_rdc_rsp },
1295331Samw { MAILSLOT_NETLOGON_SAMLOGON_RDC, smb_netlogon_rdc_rsp },
1305331Samw };
1315331Samw
1325331Samw smb_msgbuf_t mb;
1335331Samw unsigned short opcode;
1345331Samw char src_name[SMB_PI_MAX_HOST];
135*10966SJordan.Brown@Sun.COM smb_wchar_t unicode_src_name[SMB_PI_MAX_HOST];
1365331Samw uint32_t src_ipaddr;
1375331Samw char *junk;
1385331Samw char *primary;
1395331Samw char *domain;
1405331Samw int i;
1415331Samw char ipstr[16];
1425331Samw int rc;
1435331Samw
1445331Samw src_ipaddr = datagram->src.addr_list.sin.sin_addr.s_addr;
1455331Samw
1465331Samw /*
1475331Samw * The datagram->src.name is in oem codepage format.
1485331Samw * Therefore, we need to convert it to unicode and
1495331Samw * store it in multi-bytes format.
1505331Samw */
151*10966SJordan.Brown@Sun.COM (void) oemtoucs(unicode_src_name, (char *)datagram->src.name,
152*10966SJordan.Brown@Sun.COM SMB_PI_MAX_HOST, OEM_CPG_850);
153*10966SJordan.Brown@Sun.COM (void) smb_wcstombs(src_name, unicode_src_name, SMB_PI_MAX_HOST);
1545331Samw
1555331Samw (void) trim_whitespace(src_name);
1565331Samw
1575331Samw (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr), ipstr,
1585331Samw sizeof (ipstr));
1595331Samw syslog(LOG_DEBUG, "NetLogonReceive: src=%s [%s], mbx=%s",
1605331Samw src_name, ipstr, mailbox);
1615331Samw
1625331Samw smb_msgbuf_init(&mb, data, datalen, 0);
1635331Samw
1645331Samw if (smb_msgbuf_decode(&mb, "w", &opcode) < 0) {
1655331Samw syslog(LOG_ERR, "NetLogonReceive: decode error");
1665331Samw smb_msgbuf_term(&mb);
1675331Samw return;
1685331Samw }
1695331Samw
1705331Samw switch (opcode) {
1715331Samw case LOGON_PRIMARY_RESPONSE:
1725331Samw /*
1735331Samw * Message contains:
1745331Samw * PDC name (MBS), PDC name (Unicode), Domain name (unicode)
1755331Samw */
1765331Samw rc = smb_msgbuf_decode(&mb, "sUU", &junk, &primary, &domain);
1775331Samw if (rc < 0) {
1785331Samw syslog(LOG_ERR,
1795331Samw "NetLogonResponse: opcode %d decode error",
1805331Samw opcode);
1815331Samw smb_msgbuf_term(&mb);
1825331Samw return;
1835331Samw }
1845331Samw break;
1855331Samw
1865331Samw case LOGON_SAM_LOGON_RESPONSE:
1875331Samw case LOGON_SAM_USER_UNKNOWN:
1885331Samw /*
1895331Samw * Message contains:
1905331Samw * PDC name, User name, Domain name (all unicode)
1915331Samw */
1925331Samw rc = smb_msgbuf_decode(&mb, "UUU", &primary, &junk, &domain);
1935331Samw if (rc < 0) {
1945331Samw syslog(LOG_ERR,
1955331Samw "NetLogonResponse: opcode %d decode error",
1965331Samw opcode);
1975331Samw smb_msgbuf_term(&mb);
1985331Samw return;
1995331Samw }
2005331Samw
2015331Samw /*
2025331Samw * skip past the "\\" prefix
2035331Samw */
2045331Samw primary += strspn(primary, "\\");
2055331Samw break;
2065331Samw
2075331Samw default:
2085331Samw /*
2095331Samw * We don't respond to PDC discovery requests.
2105331Samw */
2115331Samw syslog(LOG_DEBUG, "NetLogonReceive: opcode 0x%04x", opcode);
2125331Samw smb_msgbuf_term(&mb);
2135331Samw return;
2145331Samw }
2155331Samw
21610717Samw@Sun.COM if (domain == NULL || primary == NULL) {
2175331Samw syslog(LOG_ERR, "NetLogonResponse: malformed packet");
2185331Samw smb_msgbuf_term(&mb);
2195331Samw return;
2205331Samw }
2215331Samw
22210717Samw@Sun.COM syslog(LOG_DEBUG, "DC Offer Domain=%s PDC=%s From=%s",
2235331Samw domain, primary, src_name);
2245331Samw
2258334SJose.Borrego@Sun.COM (void) mutex_lock(&ntdomain_mtx);
2268334SJose.Borrego@Sun.COM if (strcasecmp(domain, ntdomain_info.n_domain)) {
2275331Samw syslog(LOG_DEBUG, "NetLogonResponse: other domain "
2288334SJose.Borrego@Sun.COM "%s, requested %s", domain, ntdomain_info.n_domain);
2295331Samw smb_msgbuf_term(&mb);
2308334SJose.Borrego@Sun.COM (void) mutex_unlock(&ntdomain_mtx);
2315331Samw return;
2325331Samw }
2338334SJose.Borrego@Sun.COM (void) mutex_unlock(&ntdomain_mtx);
2345331Samw
2355331Samw for (i = 0; i < sizeof (netlogon_opt)/sizeof (netlogon_opt[0]); ++i) {
2365331Samw if (strcasecmp(netlogon_opt[i].mailslot, mailbox) == 0) {
2375331Samw syslog(LOG_DEBUG, "NetLogonReceive: %s", mailbox);
2385331Samw (*netlogon_opt[i].handler)(primary, src_ipaddr);
2395331Samw smb_msgbuf_term(&mb);
2405331Samw return;
2415331Samw }
2425331Samw }
2435331Samw
2445331Samw syslog(LOG_DEBUG, "NetLogonReceive[%s]: unknown mailslot", mailbox);
2455331Samw smb_msgbuf_term(&mb);
2465331Samw }
2475331Samw
2485331Samw
2495331Samw
2505331Samw /*
2515331Samw * smb_netlogon_query
2525331Samw *
2535331Samw * Build and send a LOGON_PRIMARY_QUERY to the MAILSLOT_NETLOGON. At some
2545331Samw * point we should receive a LOGON_PRIMARY_RESPONSE in the mailslot we
2555331Samw * specify in the request.
2565331Samw *
2575331Samw * struct NETLOGON_QUERY {
2585331Samw * unsigned short Opcode; # LOGON_PRIMARY_QUERY
2595331Samw * char ComputerName[]; # ASCII hostname. The response
2605331Samw * # is sent to <ComputerName>(00).
2615331Samw * char MailslotName[]; # MAILSLOT_NETLOGON
2625331Samw * char Pad[]; # Pad to short
2635331Samw * wchar_t ComputerName[] # UNICODE hostname
2645331Samw * DWORD NT_Version; # 0x00000001
2655331Samw * WORD LmNTToken; # 0xffff
2665331Samw * WORD Lm20Token; # 0xffff
2675331Samw * };
2685331Samw */
2695331Samw static void
smb_netlogon_query(struct name_entry * server,char * mailbox,char * domain)2705331Samw smb_netlogon_query(struct name_entry *server,
2715331Samw char *mailbox,
2725331Samw char *domain)
2735331Samw {
2745331Samw smb_msgbuf_t mb;
2755331Samw int offset, announce_len, data_length, name_lengths;
2765331Samw unsigned char buffer[MAX_DATAGRAM_LENGTH];
2777961SNatalie.Li@Sun.COM char hostname[NETBIOS_NAME_SZ];
2785331Samw
2797961SNatalie.Li@Sun.COM if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
2805331Samw return;
2815331Samw
2825331Samw name_lengths = strlen(mailbox)+1+strlen(hostname)+1;
2835331Samw
2845331Samw /*
2855331Samw * The (name_lengths & 1) part is to word align the name_lengths
2865331Samw * before the wc equiv strlen and the "+ 2" is to cover the two
2875331Samw * zero bytes that terminate the wchar string.
2885331Samw */
2895331Samw data_length = sizeof (short) + name_lengths + (name_lengths & 1) +
290*10966SJordan.Brown@Sun.COM smb_wcequiv_strlen(hostname) + 2 + sizeof (long) + sizeof (short) +
2915331Samw sizeof (short);
2925331Samw
2935331Samw offset = smb_browser_load_transact_header(buffer,
2945331Samw sizeof (buffer), data_length, ONE_WAY_TRANSACTION,
2955331Samw MAILSLOT_NETLOGON);
2965331Samw
2975331Samw if (offset < 0)
2985331Samw return;
2995331Samw
3005331Samw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0);
3015331Samw
3025331Samw announce_len = smb_msgbuf_encode(&mb, "wssUlww",
3035331Samw (short)LOGON_PRIMARY_QUERY,
3045331Samw hostname,
3055331Samw mailbox,
3065331Samw hostname,
3075331Samw 0x1,
3085331Samw 0xffff,
3095331Samw 0xffff);
3105331Samw
3115331Samw if (announce_len <= 0) {
3125331Samw smb_msgbuf_term(&mb);
3135331Samw syslog(LOG_ERR, "NetLogonQuery: encode error");
3145331Samw return;
3155331Samw }
3165331Samw
3175331Samw smb_netlogon_send(server, domain, buffer, offset + announce_len);
3185331Samw smb_msgbuf_term(&mb);
3195331Samw }
3205331Samw
3215331Samw
3225331Samw /*
3235331Samw * smb_netlogon_samlogon
3245331Samw *
3255331Samw * The SamLogon version of the NetLogon request uses the workstation trust
3265331Samw * account and, I think, may be a prerequisite to the challenge/response
3275331Samw * netr authentication. The trust account username is the hostname with a
3285331Samw * $ appended. The mailslot for this request is MAILSLOT_NTLOGON. At some
3295331Samw * we should receive a LOGON_SAM_LOGON_RESPONSE in the mailslot we
3305331Samw * specify in the request.
3315331Samw *
3325331Samw * struct NETLOGON_SAM_LOGON {
3335331Samw * unsigned short Opcode; # LOGON_SAM_LOGON_REQUEST
3345331Samw * unsigned short RequestCount; # 0
3355331Samw * wchar_t UnicodeComputerName; # hostname
3365331Samw * wchar_t UnicodeUserName; # hostname$
3375331Samw * char *MailslotName; # response mailslot
3385331Samw * DWORD AllowableAccountControlBits; # 0x80 = WorkstationTrustAccount
3395331Samw * DWORD DomainSidSize; # domain sid length in bytes
3405331Samw * BYTE *DomainSid; # domain sid
3415331Samw * uint32_t NT_Version; # 0x00000001
3425331Samw * unsigned short LmNTToken; # 0xffff
3435331Samw * unsigned short Lm20Token; # 0xffff
3445331Samw * };
3455331Samw */
3465331Samw static void
smb_netlogon_samlogon(struct name_entry * server,char * mailbox,char * domain,smb_sid_t * domain_sid)3475331Samw smb_netlogon_samlogon(struct name_entry *server,
3485331Samw char *mailbox,
3499832Samw@Sun.COM char *domain,
3509832Samw@Sun.COM smb_sid_t *domain_sid)
3515331Samw {
3525331Samw smb_msgbuf_t mb;
3535331Samw unsigned domain_sid_len;
3545331Samw char *username;
3555331Samw unsigned char buffer[MAX_DATAGRAM_LENGTH];
3565331Samw int offset;
3575331Samw int announce_len;
3585331Samw int data_length;
3595331Samw int name_length;
3607961SNatalie.Li@Sun.COM char hostname[NETBIOS_NAME_SZ];
3615331Samw
3625331Samw syslog(LOG_DEBUG, "NetLogonSamLogonReq: %s", domain);
3635331Samw
3647961SNatalie.Li@Sun.COM if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
3655331Samw return;
3665331Samw
3675331Samw /*
3685331Samw * The username will be the trust account name on the PDC.
3695331Samw */
3705331Samw name_length = strlen(hostname) + 2;
3715331Samw username = alloca(name_length);
3725331Samw (void) snprintf(username, name_length, "%s$", hostname);
3735331Samw
3749832Samw@Sun.COM domain_sid_len = smb_sid_len(domain_sid);
3755331Samw /*
3765331Samw * Add 2 to wide-char equivalent strlen to cover the
3775331Samw * two zero bytes that terminate the wchar string.
3785331Samw */
3795331Samw name_length = strlen(mailbox)+1;
3805331Samw
3815331Samw data_length = sizeof (short)
3825331Samw + sizeof (short)
383*10966SJordan.Brown@Sun.COM + smb_wcequiv_strlen(hostname) + 2
384*10966SJordan.Brown@Sun.COM + smb_wcequiv_strlen(username) + 2
3855331Samw + name_length
3865331Samw + sizeof (long)
3875331Samw + sizeof (long)
3885331Samw + domain_sid_len + 3 /* padding */
3895331Samw + sizeof (long)
3905331Samw + sizeof (short)
3915331Samw + sizeof (short);
3925331Samw
3935331Samw offset = smb_browser_load_transact_header(buffer,
3945331Samw sizeof (buffer), data_length, ONE_WAY_TRANSACTION,
3955331Samw MAILSLOT_NTLOGON);
3965331Samw
3975331Samw if (offset < 0) {
3985331Samw syslog(LOG_ERR, "NetLogonSamLogonReq: header error");
3995331Samw return;
4005331Samw }
4015331Samw
4025331Samw /*
4035331Samw * The domain SID is padded with 3 leading zeros.
4045331Samw */
4055331Samw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0);
4065331Samw announce_len = smb_msgbuf_encode(&mb, "wwUUsll3.#clww",
4075331Samw (short)LOGON_SAM_LOGON_REQUEST,
4085331Samw 0, /* RequestCount */
4095331Samw hostname, /* UnicodeComputerName */
4105331Samw username, /* UnicodeUserName */
4115331Samw mailbox, /* MailslotName */
4125331Samw 0x00000080, /* AllowableAccountControlBits */
4135331Samw domain_sid_len, /* DomainSidSize */
4145331Samw domain_sid_len, domain_sid, /* DomainSid */
4155331Samw 0x00000001, /* NT_Version */
4165331Samw 0xffff, /* LmNTToken */
4175331Samw 0xffff); /* Lm20Token */
4185331Samw
4195331Samw if (announce_len <= 0) {
4205331Samw syslog(LOG_ERR, "NetLogonSamLogonReq: encode error");
4215331Samw smb_msgbuf_term(&mb);
4225331Samw return;
4235331Samw }
4245331Samw
4255331Samw smb_netlogon_send(server, domain, buffer, offset + announce_len);
4265331Samw smb_msgbuf_term(&mb);
4275331Samw }
4285331Samw
4295331Samw
4305331Samw /*
4315331Samw * Send a query for each version of the protocol.
4325331Samw */
4335331Samw static void
smb_netlogon_send(struct name_entry * name,char * domain,unsigned char * buffer,int count)4345331Samw smb_netlogon_send(struct name_entry *name,
4355331Samw char *domain,
4365331Samw unsigned char *buffer,
4375331Samw int count)
4385331Samw {
4395331Samw static char suffix[] = { 0x1B, 0x1C };
4405331Samw struct name_entry dname;
4415331Samw struct name_entry *dest;
4425331Samw struct name_entry *dest_dup;
4435331Samw int i;
4445331Samw
4455331Samw for (i = 0; i < sizeof (suffix)/sizeof (suffix[0]); i++) {
4465331Samw smb_init_name_struct((unsigned char *)domain, suffix[i],
4475331Samw 0, 0, 0, 0, 0, &dname);
4485331Samw
44910717Samw@Sun.COM syslog(LOG_DEBUG, "SmbNetlogonSend");
45010717Samw@Sun.COM smb_netbios_name_logf(&dname);
4515331Samw if ((dest = smb_name_find_name(&dname)) != 0) {
4525331Samw dest_dup = smb_netbios_name_dup(dest, 1);
4535331Samw smb_name_unlock_name(dest);
4545331Samw if (dest_dup) {
4558334SJose.Borrego@Sun.COM (void) smb_netbios_datagram_send(name,
4568334SJose.Borrego@Sun.COM dest_dup, buffer, count);
4575331Samw free(dest_dup);
4585331Samw }
4595331Samw } else {
46010717Samw@Sun.COM syslog(LOG_DEBUG,
46110717Samw@Sun.COM "SmbNetlogonSend: could not find %s<0x%X>",
4625331Samw domain, suffix[i]);
4635331Samw }
4645331Samw }
4655331Samw }
4665331Samw
4675331Samw /*
4685331Samw * smb_netlogon_rdc_rsp
4695331Samw *
4705331Samw * This is where we process netlogon responses for the resource domain.
4715331Samw * The src_name is the real name of the remote machine.
4725331Samw */
4735331Samw static void
smb_netlogon_rdc_rsp(char * src_name,uint32_t src_ipaddr)4745331Samw smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr)
4755331Samw {
4765331Samw static int initialized = 0;
4775331Samw uint32_t ipaddr;
4788670SJose.Borrego@Sun.COM uint32_t prefer_ipaddr;
4798670SJose.Borrego@Sun.COM char ipstr[INET_ADDRSTRLEN];
4808670SJose.Borrego@Sun.COM char srcip[INET_ADDRSTRLEN];
4815331Samw int rc;
4825331Samw
4838670SJose.Borrego@Sun.COM (void) inet_ntop(AF_INET, &src_ipaddr, srcip, INET_ADDRSTRLEN);
4845331Samw
4858670SJose.Borrego@Sun.COM rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, INET_ADDRSTRLEN);
4865772Sas200622 if (rc == SMBD_SMF_OK) {
4875772Sas200622 rc = inet_pton(AF_INET, ipstr, &prefer_ipaddr);
4885331Samw if (rc == 0)
4895331Samw prefer_ipaddr = 0;
4905331Samw
4915331Samw if (!initialized) {
4925331Samw syslog(LOG_DEBUG, "SMB DC Preference: %s", ipstr);
4935331Samw initialized = 1;
4945331Samw }
4955331Samw }
4965331Samw
4978334SJose.Borrego@Sun.COM (void) mutex_lock(&ntdomain_mtx);
4985331Samw syslog(LOG_DEBUG, "DC Offer [%s]: %s [%s]",
4998334SJose.Borrego@Sun.COM ntdomain_info.n_domain, src_name, srcip);
5005331Samw
5018334SJose.Borrego@Sun.COM if (ntdomain_info.n_ipaddr != 0) {
5028670SJose.Borrego@Sun.COM if (prefer_ipaddr != 0 &&
5038670SJose.Borrego@Sun.COM prefer_ipaddr == ntdomain_info.n_ipaddr) {
5045331Samw syslog(LOG_DEBUG, "DC for %s: %s [%s]",
5058334SJose.Borrego@Sun.COM ntdomain_info.n_domain, src_name, srcip);
5068334SJose.Borrego@Sun.COM (void) mutex_unlock(&ntdomain_mtx);
5075331Samw return;
5085331Samw }
5095331Samw
5108334SJose.Borrego@Sun.COM ipaddr = ntdomain_info.n_ipaddr;
5115331Samw } else
5125331Samw ipaddr = 0;
5135331Samw
5147052Samw if (smb_better_dc(ipaddr, src_ipaddr) ||
5155331Samw (prefer_ipaddr != 0 && prefer_ipaddr == src_ipaddr)) {
5168334SJose.Borrego@Sun.COM /* set nbtd cache */
5178334SJose.Borrego@Sun.COM (void) strlcpy(ntdomain_info.n_name, src_name,
5188334SJose.Borrego@Sun.COM SMB_PI_MAX_DOMAIN);
5198334SJose.Borrego@Sun.COM ntdomain_info.n_ipaddr = src_ipaddr;
5208334SJose.Borrego@Sun.COM (void) cond_broadcast(&ntdomain_cv);
5215331Samw syslog(LOG_DEBUG, "DC discovered for %s: %s [%s]",
5228334SJose.Borrego@Sun.COM ntdomain_info.n_domain, src_name, srcip);
5235331Samw }
5248334SJose.Borrego@Sun.COM (void) mutex_unlock(&ntdomain_mtx);
5255331Samw }
5265331Samw
5275331Samw static int
smb_better_dc(uint32_t cur_ip,uint32_t new_ip)5287052Samw smb_better_dc(uint32_t cur_ip, uint32_t new_ip)
5295331Samw {
5308670SJose.Borrego@Sun.COM smb_inaddr_t ipaddr;
5318670SJose.Borrego@Sun.COM
5325331Samw /*
5335331Samw * If we don't have any current DC,
5345331Samw * then use the new one of course.
5355331Samw */
5368670SJose.Borrego@Sun.COM
5375331Samw if (cur_ip == 0)
5385331Samw return (1);
5399021Samw@Sun.COM /*
5409021Samw@Sun.COM * see if there is a DC in the
5419021Samw@Sun.COM * same subnet
5429021Samw@Sun.COM */
5435331Samw
5448670SJose.Borrego@Sun.COM ipaddr.a_family = AF_INET;
5458670SJose.Borrego@Sun.COM ipaddr.a_ipv4 = cur_ip;
5469021Samw@Sun.COM if (smb_nic_is_same_subnet(&ipaddr))
5475331Samw return (0);
5486030Sjb150015
5498670SJose.Borrego@Sun.COM ipaddr.a_family = AF_INET;
5508670SJose.Borrego@Sun.COM ipaddr.a_ipv4 = new_ip;
5519021Samw@Sun.COM if (smb_nic_is_same_subnet(&ipaddr))
5525331Samw return (1);
5535331Samw /*
5545331Samw * Otherwise, just keep the old one.
5555331Samw */
5565331Samw return (0);
5575331Samw }
558