Print this page
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-2225 Unable to join NexentaStor to 2008 AD

*** 20,30 **** */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * ! * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* * This file defines the domain environment values and the domain * database interface. The database is a single linked list of --- 20,30 ---- */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * ! * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* * This file defines the domain environment values and the domain * database interface. The database is a single linked list of
*** 35,44 **** --- 35,45 ---- #include <sys/stat.h> #include <sys/list.h> #include <stdio.h> #include <strings.h> #include <string.h> + #include <syslog.h> #include <unistd.h> #include <stdlib.h> #include <synch.h> #include <pwd.h> #include <grp.h>
*** 68,81 **** #define SMB_DCACHE_WRLOCK 1 typedef struct smb_domain_cache { list_t dc_cache; rwlock_t dc_cache_lck; - mutex_t dc_mtx; - cond_t dc_cv; uint32_t dc_state; uint32_t dc_nops; smb_dcinfo_t dc_dci; } smb_domain_cache_t; static smb_domain_cache_t smb_dcache; --- 69,85 ---- #define SMB_DCACHE_WRLOCK 1 typedef struct smb_domain_cache { list_t dc_cache; rwlock_t dc_cache_lck; uint32_t dc_state; uint32_t dc_nops; + mutex_t dc_mtx; + cond_t dc_cv; + /* domain controller information */ + cond_t dc_dci_cv; + boolean_t dc_dci_valid; smb_dcinfo_t dc_dci; } smb_domain_cache_t; static smb_domain_cache_t smb_dcache;
*** 88,98 **** static void smb_dcache_destroy(void); static uint32_t smb_dcache_lock(int); static void smb_dcache_unlock(void); static void smb_dcache_remove(smb_domain_t *); static uint32_t smb_dcache_add(smb_domain_t *); ! static boolean_t smb_dcache_getdc(smb_dcinfo_t *); static void smb_dcache_setdc(const smb_dcinfo_t *); static boolean_t smb_dcache_wait(void); static uint32_t smb_dcache_updating(void); static void smb_dcache_ready(void); --- 92,102 ---- static void smb_dcache_destroy(void); static uint32_t smb_dcache_lock(int); static void smb_dcache_unlock(void); static void smb_dcache_remove(smb_domain_t *); static uint32_t smb_dcache_add(smb_domain_t *); ! static boolean_t smb_dcache_getdc(smb_dcinfo_t *, boolean_t); static void smb_dcache_setdc(const smb_dcinfo_t *); static boolean_t smb_dcache_wait(void); static uint32_t smb_dcache_updating(void); static void smb_dcache_ready(void);
*** 111,120 **** --- 115,125 ---- smb_dcache_create(); if ((rc = smb_domain_add_local()) != 0) return (rc); + bzero(&di, sizeof (di)); smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di); (void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di); return (smb_domain_add_primary(secmode)); }
*** 287,318 **** } /* * Returns primary domain information plus the name of * the selected domain controller. */ boolean_t smb_domain_getinfo(smb_domainex_t *dxi) { boolean_t rv; /* Note: this waits for the dcache lock. */ rv = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary); ! if (rv) ! rv = smb_dcache_getdc(&dxi->d_dci); ! return (rv); } /* * Get the name of the current DC (if any) * Does NOT block. */ void smb_domain_current_dc(smb_dcinfo_t *dci) { ! (void) smb_dcache_getdc(dci); } /* * Transfer the cache to updating state. * In this state any request for reading the cache would --- 292,342 ---- } /* * Returns primary domain information plus the name of * the selected domain controller. + * + * Returns TRUE on success. */ boolean_t smb_domain_getinfo(smb_domainex_t *dxi) { boolean_t rv; /* Note: this waits for the dcache lock. */ rv = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary); ! if (!rv) { ! syslog(LOG_ERR, "smb_domain_getinfo: no primary domain"); ! return (B_FALSE); ! } ! /* ! * The 2nd arg TRUE means this will wait for DC info. ! * ! * Note that we do NOT hold the dcache rwlock here ! * (not even as reader) because we already have what we ! * need from the dcache (our primary domain) and we don't ! * want to interfere with the DC locator which will take ! * the dcache lock as write to update the domain info. ! */ ! rv = smb_dcache_getdc(&dxi->d_dci, B_TRUE); ! if (!rv) { ! syslog(LOG_ERR, "smb_domain_getinfo: no DC info"); ! return (B_FALSE); ! } ! ! return (B_TRUE); } /* * Get the name of the current DC (if any) * Does NOT block. */ void smb_domain_current_dc(smb_dcinfo_t *dci) { ! (void) smb_dcache_getdc(dci, B_FALSE); } /* * Transfer the cache to updating state. * In this state any request for reading the cache would
*** 332,341 **** --- 356,377 ---- { smb_dcache_ready(); } /* + * Mark the current domain controller (DC) info invalid + * until the DC locator call smb_domain_update(). + */ + void + smb_domain_bad_dc(void) + { + (void) mutex_lock(&smb_dcache.dc_mtx); + smb_dcache.dc_dci_valid = B_FALSE; + (void) mutex_unlock(&smb_dcache.dc_mtx); + } + + /* * Updates the cache with given information for the primary * domain, possible trusted domains and the selected domain * controller. * * Before adding the new entries existing entries of type
*** 482,491 **** --- 518,528 ---- char *forest, char *guid, smb_domain_t *di) { if (di == NULL || forest == NULL || guid == NULL) return; + /* Caller zeros out *di before this. */ smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN); (void) strlcpy(di->di_u.di_dns.ddi_guid, guid, UUID_PRINTABLE_STRING_LENGTH); }
*** 498,507 **** --- 535,545 ---- smb_domain_trust_t *ti; if (di == NULL) return; + /* Caller zeros out *di before this. */ di->di_type = SMB_DOMAIN_TRUSTED; ti = &di->di_u.di_trust; smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); ti->dti_trust_direction = trust_dir; ti->dti_trust_type = trust_type;
*** 538,547 **** --- 576,586 ---- if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) { free(lsidstr); return (SMB_DOMAIN_NOMACHINE_SID); } + bzero(&di, sizeof (di)); *fq_name = '\0'; (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN); smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di); (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di);
*** 570,579 **** --- 609,619 ---- rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_name, NETBIOS_NAME_SZ); if ((rc != SMBD_SMF_OK) || (*nb_name == '\0')) return (SMB_DOMAIN_NODOMAIN_NAME); + bzero(&di, sizeof (di)); (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN); smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di); (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di); return (SMB_DOMAIN_SUCCESS); }
*** 594,603 **** --- 634,644 ---- list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t), offsetof(smb_domain_t, di_lnd)); smb_dcache.dc_nops = 0; bzero(&smb_dcache.dc_dci, sizeof (smb_dcache.dc_dci)); + smb_dcache.dc_dci_valid = B_FALSE; smb_dcache.dc_state = SMB_DCACHE_STATE_READY; (void) mutex_unlock(&smb_dcache.dc_mtx); } /*
*** 650,659 **** --- 691,701 ---- { (void) mutex_lock(&smb_dcache.dc_mtx); switch (smb_dcache.dc_state) { case SMB_DCACHE_STATE_NONE: case SMB_DCACHE_STATE_DESTROYING: + default: (void) mutex_unlock(&smb_dcache.dc_mtx); return (SMB_DOMAIN_INTERNAL_ERR); case SMB_DCACHE_STATE_UPDATING: if (mode == SMB_DCACHE_RDLOCK) {
*** 664,675 **** if (!smb_dcache_wait()) { (void) mutex_unlock(&smb_dcache.dc_mtx); return (SMB_DOMAIN_INTERNAL_ERR); } } ! default: smb_dcache.dc_nops++; break; } (void) mutex_unlock(&smb_dcache.dc_mtx); --- 706,718 ---- if (!smb_dcache_wait()) { (void) mutex_unlock(&smb_dcache.dc_mtx); return (SMB_DOMAIN_INTERNAL_ERR); } } + /* FALLTHROUGH */ ! case SMB_DCACHE_STATE_READY: smb_dcache.dc_nops++; break; } (void) mutex_unlock(&smb_dcache.dc_mtx);
*** 730,752 **** static void smb_dcache_setdc(const smb_dcinfo_t *dci) { (void) mutex_lock(&smb_dcache.dc_mtx); smb_dcache.dc_dci = *dci; /* struct assignment! */ (void) mutex_unlock(&smb_dcache.dc_mtx); } /* ! * Return B_TRUE if we have DC information. */ static boolean_t ! smb_dcache_getdc(smb_dcinfo_t *dci) { (void) mutex_lock(&smb_dcache.dc_mtx); *dci = smb_dcache.dc_dci; /* struct assignment! */ (void) mutex_unlock(&smb_dcache.dc_mtx); ! return (dci->dc_name[0] != '\0'); } /* * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in * UPDATING state. Upon wake up returns true if cache is --- 773,816 ---- static void smb_dcache_setdc(const smb_dcinfo_t *dci) { (void) mutex_lock(&smb_dcache.dc_mtx); smb_dcache.dc_dci = *dci; /* struct assignment! */ + smb_dcache.dc_dci_valid = B_TRUE; + (void) cond_broadcast(&smb_dcache.dc_dci_cv); (void) mutex_unlock(&smb_dcache.dc_mtx); } /* ! * Get information about our domain controller. If the wait arg ! * is true, wait for the DC locator to finish before copying. ! * Returns TRUE on success (have DC info). */ static boolean_t ! smb_dcache_getdc(smb_dcinfo_t *dci, boolean_t wait) { + timestruc_t to; + boolean_t rv; + int err; + + to.tv_sec = time(NULL) + SMB_DCACHE_UPDATE_WAIT; + to.tv_nsec = 0; + (void) mutex_lock(&smb_dcache.dc_mtx); + + while (wait && !smb_dcache.dc_dci_valid) { + err = cond_timedwait(&smb_dcache.dc_dci_cv, + &smb_dcache.dc_mtx, &to); + if (err == ETIME) + break; + } *dci = smb_dcache.dc_dci; /* struct assignment! */ + rv = smb_dcache.dc_dci_valid; + (void) mutex_unlock(&smb_dcache.dc_mtx); ! ! return (rv); } /* * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in * UPDATING state. Upon wake up returns true if cache is
*** 756,769 **** smb_dcache_wait(void) { timestruc_t to; int err; ! to.tv_sec = SMB_DCACHE_UPDATE_WAIT; to.tv_nsec = 0; while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) { ! err = cond_reltimedwait(&smb_dcache.dc_cv, &smb_dcache.dc_mtx, &to); if (err == ETIME) break; } --- 820,835 ---- smb_dcache_wait(void) { timestruc_t to; int err; ! assert(MUTEX_HELD(&smb_dcache.dc_mtx)); ! ! to.tv_sec = time(NULL) + SMB_DCACHE_UPDATE_WAIT; to.tv_nsec = 0; while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) { ! err = cond_timedwait(&smb_dcache.dc_cv, &smb_dcache.dc_mtx, &to); if (err == ETIME) break; }