17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 536e852a1SRaja Andra * Common Development and Distribution License (the "License"). 636e852a1SRaja Andra * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*a87701e9SGary Mills * Copyright 2015 Gary Mills 2336e852a1SRaja Andra * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*a87701e9SGary Mills * 26*a87701e9SGary Mills * Copyright 2015 RackTop Systems. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <time.h> 317c478bd9Sstevel@tonic-gate #include <sys/time.h> 327c478bd9Sstevel@tonic-gate #include <lber.h> 337c478bd9Sstevel@tonic-gate #include <ldap.h> 347c478bd9Sstevel@tonic-gate #include <signal.h> 357c478bd9Sstevel@tonic-gate #include <pthread.h> 367c478bd9Sstevel@tonic-gate #include "db_headers.h" 377c478bd9Sstevel@tonic-gate #include "db.h" 387c478bd9Sstevel@tonic-gate #include "db_mindex.h" 397c478bd9Sstevel@tonic-gate #include "db_dictionary.h" 407c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 417c478bd9Sstevel@tonic-gate #include "ldap_map.h" 427c478bd9Sstevel@tonic-gate #include "ldap_glob.h" 437c478bd9Sstevel@tonic-gate #include "ldap_util.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate extern db_dictionary *InUseDictionary; 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate extern "C" { 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate typedef struct { 527c478bd9Sstevel@tonic-gate db_mindex *mindex; 537c478bd9Sstevel@tonic-gate __nis_table_mapping_t *t; 547c478bd9Sstevel@tonic-gate db_query *qin; 557c478bd9Sstevel@tonic-gate db_query *q; 567c478bd9Sstevel@tonic-gate char *dbId; 577c478bd9Sstevel@tonic-gate nis_object *dirObj; 587c478bd9Sstevel@tonic-gate int isDeferred; 597c478bd9Sstevel@tonic-gate char *tableName; 607c478bd9Sstevel@tonic-gate } __entries_from_ldap_arg_t; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static void *entriesFromLDAPthread(void *); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate int entriesFromLDAPreal(__entries_from_ldap_arg_t *); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #ifdef SET_ENTRY_FLAGS 697c478bd9Sstevel@tonic-gate static uint_t 707c478bd9Sstevel@tonic-gate entryFlagsFromTable(uint_t tf) { 717c478bd9Sstevel@tonic-gate uint_t ef = 0; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate if ((tf & TA_BINARY) != 0) 747c478bd9Sstevel@tonic-gate ef |= EN_BINARY; 757c478bd9Sstevel@tonic-gate if ((tf & TA_CRYPT) != 0) 767c478bd9Sstevel@tonic-gate ef |= EN_CRYPT; 777c478bd9Sstevel@tonic-gate if ((tf & TA_XDR) != 0) 787c478bd9Sstevel@tonic-gate ef |= EN_XDR; 797c478bd9Sstevel@tonic-gate if ((tf & TA_ASN1) != 0) 807c478bd9Sstevel@tonic-gate ef |= EN_ASN1; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate return (ef); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate #endif /* SET_ENTRY_FLAGS */ 857c478bd9Sstevel@tonic-gate 8636e852a1SRaja Andra static void setOid(nis_object *obj); 8736e852a1SRaja Andra 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Retrieve container entries from LDAP per 't' and 'qin'/'q'. 907c478bd9Sstevel@tonic-gate * This is a helper function for db_mindex::queryLDAP(); see 917c478bd9Sstevel@tonic-gate * that function for details of the parameters (except doAsynch). 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * If 'doAsynch' is set, and the retrieval is an enumeration 947c478bd9Sstevel@tonic-gate * (qin == NULL), the retrieval is performed in a detached 957c478bd9Sstevel@tonic-gate * thread. In this case, the return code just reflects the 967c478bd9Sstevel@tonic-gate * setup and launch of the detached thread. Retrieval will 977c478bd9Sstevel@tonic-gate * complete asynchronously. 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate int 1007c478bd9Sstevel@tonic-gate db_mindex::entriesFromLDAP(__nis_table_mapping_t *t, db_query *qin, db_query *q, 1017c478bd9Sstevel@tonic-gate char *dbId, nis_object *dirObj, int doAsynch) { 1027c478bd9Sstevel@tonic-gate __entries_from_ldap_arg_t *arg; 1037c478bd9Sstevel@tonic-gate int stat; 1047c478bd9Sstevel@tonic-gate db_status dstat; 1058d0852b7SRichard Lowe const char *myself = "db_mindex::entriesFromLDAP"; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate arg = (__entries_from_ldap_arg_t *)am(myself, sizeof (*arg)); 1087c478bd9Sstevel@tonic-gate if (arg == 0) { 1097c478bd9Sstevel@tonic-gate freeQuery(q); 1107c478bd9Sstevel@tonic-gate if (dirObj != 0) 1117c478bd9Sstevel@tonic-gate nis_destroy_object(dirObj); 1127c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate arg->mindex = this; 1167c478bd9Sstevel@tonic-gate arg->t = t; 1177c478bd9Sstevel@tonic-gate arg->qin = qin; 1187c478bd9Sstevel@tonic-gate arg->q = q; 1197c478bd9Sstevel@tonic-gate arg->dbId = dbId; 1207c478bd9Sstevel@tonic-gate arg->dirObj = dirObj; 1217c478bd9Sstevel@tonic-gate arg->tableName = t->objName; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Check if an enumeration thread is running; if so, then regardless 1257c478bd9Sstevel@tonic-gate * of whether or not the current operation is an enumeration, we 1267c478bd9Sstevel@tonic-gate * just return success, and let our caller get the data from the 1277c478bd9Sstevel@tonic-gate * existing (deferred) DB. 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 1307c478bd9Sstevel@tonic-gate if (table->mapping.enumTid != 0) { 1317c478bd9Sstevel@tonic-gate int doReturn = 0; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate stat = pthread_kill(table->mapping.enumTid, 0); 1347c478bd9Sstevel@tonic-gate if (stat == ESRCH) { 1357c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1367c478bd9Sstevel@tonic-gate "%s: Enumeration thread %d not found for \"%s\"; exit status = %d (%s)", 1377c478bd9Sstevel@tonic-gate myself, table->mapping.enumTid, 1387c478bd9Sstevel@tonic-gate NIL(t->objName), table->mapping.enumStat, 1397c478bd9Sstevel@tonic-gate ldap_err2string(table->mapping.enumStat)); 1407c478bd9Sstevel@tonic-gate /* Reflect the fact that no enum thread is running */ 1417c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 1427c478bd9Sstevel@tonic-gate table->mapping.enumStat = -1; 1437c478bd9Sstevel@tonic-gate /* Cleanup deferred mode */ 1447c478bd9Sstevel@tonic-gate if (table->mapping.enumDeferred) { 1457c478bd9Sstevel@tonic-gate dstat = InUseDictionary->commit(t->objPath); 1467c478bd9Sstevel@tonic-gate if (dstat == DB_SUCCESS) { 1477c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 1487c478bd9Sstevel@tonic-gate } else { 1497c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 1507c478bd9Sstevel@tonic-gate "%s: DB error %d committing \"%s\"", 1517c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate } else if (stat == 0) { 1557c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1567c478bd9Sstevel@tonic-gate "%s: Enumeration thread %d already running for \"%s\"", 1577c478bd9Sstevel@tonic-gate myself, table->mapping.enumTid, 1587c478bd9Sstevel@tonic-gate NIL(t->objName)); 1597c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 1607c478bd9Sstevel@tonic-gate doReturn = 1; 1617c478bd9Sstevel@tonic-gate } else { 1627c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1637c478bd9Sstevel@tonic-gate "%s: Error %d looking for enumeration thread %d for \"%s\"", 1647c478bd9Sstevel@tonic-gate myself, stat, table->mapping.enumTid, 1657c478bd9Sstevel@tonic-gate NIL(t->objName)); 1667c478bd9Sstevel@tonic-gate doReturn = 1; 1677c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate if (doReturn) { 1707c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 1717c478bd9Sstevel@tonic-gate sfree(arg); 1727c478bd9Sstevel@tonic-gate freeQuery(q); 1737c478bd9Sstevel@tonic-gate if (dirObj != 0) 1747c478bd9Sstevel@tonic-gate nis_destroy_object(dirObj); 1757c478bd9Sstevel@tonic-gate return (stat); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * If we're enumerating (and hence expect that retrieving all data, 1817c478bd9Sstevel@tonic-gate * and updating the local DB, might take a while), create a deferred- 1827c478bd9Sstevel@tonic-gate * update table that clients can use while we are updating the real 1837c478bd9Sstevel@tonic-gate * one. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate if (doAsynch && qin == 0) { 1867c478bd9Sstevel@tonic-gate if ((dstat = InUseDictionary->defer(t->objPath)) == 1877c478bd9Sstevel@tonic-gate DB_SUCCESS) { 1887c478bd9Sstevel@tonic-gate arg->isDeferred = 1; 1897c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 1; 1907c478bd9Sstevel@tonic-gate } else { 1917c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1927c478bd9Sstevel@tonic-gate "%s: Unable to defer updates for \"%s\" (status=%d);" 1937c478bd9Sstevel@tonic-gate " updating in place", 1947c478bd9Sstevel@tonic-gate myself, NIL(t->objName), dstat); 1957c478bd9Sstevel@tonic-gate arg->isDeferred = 0; 1967c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate } else { 1997c478bd9Sstevel@tonic-gate arg->isDeferred = 0; 2007c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* If enumerating, perform the operation in a separate thread */ 2047c478bd9Sstevel@tonic-gate if (doAsynch && qin == 0) { 2057c478bd9Sstevel@tonic-gate pthread_t tid; 2067c478bd9Sstevel@tonic-gate pthread_attr_t attr; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 2097c478bd9Sstevel@tonic-gate #ifdef FORCE_SYNCHRONOUS 2107c478bd9Sstevel@tonic-gate #else 2117c478bd9Sstevel@tonic-gate (void) pthread_attr_setdetachstate(&attr, 2127c478bd9Sstevel@tonic-gate PTHREAD_CREATE_DETACHED); 2137c478bd9Sstevel@tonic-gate #endif /* FORCE_SYNCHRONOUS */ 2147c478bd9Sstevel@tonic-gate stat = pthread_create(&tid, &attr, entriesFromLDAPthread, arg); 2157c478bd9Sstevel@tonic-gate if (stat != 0) { 2167c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 2177c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 2187c478bd9Sstevel@tonic-gate "%s: Error %d creating new thread; using current one", 2197c478bd9Sstevel@tonic-gate myself, stat); 220*a87701e9SGary Mills stat = entriesFromLDAPreal(arg); 2217c478bd9Sstevel@tonic-gate return (stat); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate table->mapping.enumTid = tid; 2257c478bd9Sstevel@tonic-gate table->mapping.enumStat = -1; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 2287c478bd9Sstevel@tonic-gate * We're now returning to the caller, who will get data 2297c478bd9Sstevel@tonic-gate * from: 2307c478bd9Sstevel@tonic-gate * 2317c478bd9Sstevel@tonic-gate * The deferred DB, if an enumeration thread already 2327c478bd9Sstevel@tonic-gate * was running, and deferred mode was on, or 2337c478bd9Sstevel@tonic-gate * 2347c478bd9Sstevel@tonic-gate * The original DB, if we just started an enumeration 2357c478bd9Sstevel@tonic-gate * thread. In this case, our caller (several levels up) 2367c478bd9Sstevel@tonic-gate * is holding a lock on the db_mindex/db_table, which 2377c478bd9Sstevel@tonic-gate * means that the enum thread will have to wait for 2387c478bd9Sstevel@tonic-gate * our caller once it's done the LDAP retrieval, and 2397c478bd9Sstevel@tonic-gate * wants to update the DB. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 2427c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 2437c478bd9Sstevel@tonic-gate #ifdef FORCE_SYNCHRONOUS 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate int tstat; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate stat = pthread_join(tid, (void **)&tstat); 2487c478bd9Sstevel@tonic-gate if (stat == 0) { 2497c478bd9Sstevel@tonic-gate stat = tstat; 2507c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 2517c478bd9Sstevel@tonic-gate "%s: thread %d => %d", 2527c478bd9Sstevel@tonic-gate myself, tid, tstat); 2537c478bd9Sstevel@tonic-gate } else { 2547c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2557c478bd9Sstevel@tonic-gate "%s: pthread_join(%d) => %d", 2567c478bd9Sstevel@tonic-gate myself, tid, stat); 2577c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate #endif /* FORCE_SYNCHRONOUS */ 2617c478bd9Sstevel@tonic-gate } else { 2627c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 263*a87701e9SGary Mills stat = entriesFromLDAPreal(arg); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate return (stat); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate extern "C" { 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * We use this 'extern "C"' function in order to make sure that 2737c478bd9Sstevel@tonic-gate * pthread_create() doesn't have any problems trying to invoke a 2747c478bd9Sstevel@tonic-gate * C++ function. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate static void * 2777c478bd9Sstevel@tonic-gate entriesFromLDAPthread(void *voidarg) { 2787c478bd9Sstevel@tonic-gate __entries_from_ldap_arg_t *arg; 2797c478bd9Sstevel@tonic-gate db *dbase; 2807c478bd9Sstevel@tonic-gate db_table_desc *tbl = 0; 2817c478bd9Sstevel@tonic-gate char *tableName; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate arg = (__entries_from_ldap_arg_t *)voidarg; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* Lock to prevent removal */ 2867c478bd9Sstevel@tonic-gate (void) __nis_lock_db_table(arg->tableName, 1, 0, 2877c478bd9Sstevel@tonic-gate "entriesFromLDAPthread"); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * It's possible that the db_mindex for the table has changed, 2917c478bd9Sstevel@tonic-gate * or disappeared, between now and the time when our parent 2927c478bd9Sstevel@tonic-gate * thread released its lock on the table. Hence, we search the 2937c478bd9Sstevel@tonic-gate * dictionary to re-acquire the 'db', and the db_mindex. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate tableName = internalTableName(arg->tableName); 2967c478bd9Sstevel@tonic-gate if (tableName != 0) { 2977c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 2987c478bd9Sstevel@tonic-gate db_mindex *oldMindex = arg->mindex; 2997c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate dbase = InUseDictionary->find_table(tableName, &tbl, FALSE); 3027c478bd9Sstevel@tonic-gate if (dbase != 0) 3037c478bd9Sstevel@tonic-gate arg->mindex = dbase->mindex(); 3047c478bd9Sstevel@tonic-gate else 3057c478bd9Sstevel@tonic-gate arg->mindex = 0; 3067c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 3077c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 3087c478bd9Sstevel@tonic-gate "entriesFromLDAPthread: %s -> %s -> 0x%x (0x%x)", 3097c478bd9Sstevel@tonic-gate NIL(arg->tableName), NIL(tableName), 3107c478bd9Sstevel@tonic-gate arg->mindex, oldMindex); 3117c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 3127c478bd9Sstevel@tonic-gate sfree(tableName); 3137c478bd9Sstevel@tonic-gate tableName = 0; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 316*a87701e9SGary Mills (void) entriesFromLDAPreal(arg); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate (void) __nis_ulock_db_table(arg->tableName, 1, 0, 3197c478bd9Sstevel@tonic-gate "entriesFromLDAPthread"); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate freeQuery(arg->q); 3227c478bd9Sstevel@tonic-gate if (arg->dirObj != 0) 3237c478bd9Sstevel@tonic-gate nis_destroy_object(arg->dirObj); 3247c478bd9Sstevel@tonic-gate sfree(arg); 325*a87701e9SGary Mills return (NULL); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate int 3317c478bd9Sstevel@tonic-gate entriesFromLDAPreal(__entries_from_ldap_arg_t *arg) { 3327c478bd9Sstevel@tonic-gate db_mindex *mindex; 3337c478bd9Sstevel@tonic-gate db_table *table; 3347c478bd9Sstevel@tonic-gate __nis_table_mapping_t *t; 3357c478bd9Sstevel@tonic-gate db_query *q, *qin; 3367c478bd9Sstevel@tonic-gate char *dbId; 3377c478bd9Sstevel@tonic-gate nis_object *dirObj; 3387c478bd9Sstevel@tonic-gate int i, na, nau, nq = 0, xid = 0; 3397c478bd9Sstevel@tonic-gate int ret, stat = LDAP_SUCCESS, stat2, stat3; 3407c478bd9Sstevel@tonic-gate int lstat; 3417c478bd9Sstevel@tonic-gate __nis_obj_attr_t **oa = 0; 3427c478bd9Sstevel@tonic-gate db_query **res; 3437c478bd9Sstevel@tonic-gate entry_object **ea; 3447c478bd9Sstevel@tonic-gate long numEa; 3457c478bd9Sstevel@tonic-gate bool_t doEnum; 3467c478bd9Sstevel@tonic-gate db_status dstat; 3477c478bd9Sstevel@tonic-gate struct timeval start; 3488d0852b7SRichard Lowe const char *myself = 3497c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal"; 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if (arg == 0) 3527c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 3537c478bd9Sstevel@tonic-gate mindex = arg->mindex; 3547c478bd9Sstevel@tonic-gate t = arg->t; 3557c478bd9Sstevel@tonic-gate q = arg->q; 3567c478bd9Sstevel@tonic-gate qin = arg->qin; 3577c478bd9Sstevel@tonic-gate dbId = arg->dbId; 3587c478bd9Sstevel@tonic-gate dirObj = arg->dirObj; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate table = (mindex != 0) ? mindex->getTable() : 0; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (mindex == 0 || t == 0 || table == 0) { 3637c478bd9Sstevel@tonic-gate /* We haven't done anything, so rollback should be OK */ 3647c478bd9Sstevel@tonic-gate if (arg->isDeferred && t != 0) { 3657c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 3667c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 3677c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 3687c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 3697c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 3727c478bd9Sstevel@tonic-gate * would have disappeared. However, since 3737c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 3747c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate if (table != 0) { 3777c478bd9Sstevel@tonic-gate (void) mutex_lock(&table-> 3787c478bd9Sstevel@tonic-gate mapping.enumLock); 3797c478bd9Sstevel@tonic-gate table->mapping.enumStat = 3807c478bd9Sstevel@tonic-gate LDAP_PARAM_ERROR; 3817c478bd9Sstevel@tonic-gate table->mapping.enumTime = 0; 3827c478bd9Sstevel@tonic-gate table->mapping.enumEntries = 0; 3837c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 3847c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table-> 3857c478bd9Sstevel@tonic-gate mapping.enumLock); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate if (qin == 0) 3937c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: enumerating \"%s%s%s\"", 3947c478bd9Sstevel@tonic-gate myself, dbId ? dbId : "", dbId ? ":" : "", 3957c478bd9Sstevel@tonic-gate NIL(t->objName)); 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate (void) gettimeofday(&start, 0); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* Getting table entries */ 4007c478bd9Sstevel@tonic-gate res = mapFromLDAP(t, q, &nq, dbId, &stat, &oa); 4017c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 4027c478bd9Sstevel@tonic-gate logmsg(MSG_ALWAYS, LOG_INFO, 4037c478bd9Sstevel@tonic-gate "%s: mapFromLDAP() => 0x%x, status=%d %s; nq = %d", 4047c478bd9Sstevel@tonic-gate myself, res, stat, stat == LDAP_SUCCESS ? "" : 4057c478bd9Sstevel@tonic-gate ldap_err2string(stat), nq); 4067c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Keep track of the number of NIS+ entries we got back; 4107c478bd9Sstevel@tonic-gate * note that the number of LDAP entries may have been 4117c478bd9Sstevel@tonic-gate * smaller or larger. 4127c478bd9Sstevel@tonic-gate */ 4137c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 4147c478bd9Sstevel@tonic-gate table->mapping.enumEntries = nq; 4157c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate /* 4187c478bd9Sstevel@tonic-gate * If we get LDAP_NO_SUCH_OBJECT, we need to delete the entries 4197c478bd9Sstevel@tonic-gate * in the table, so we can't just return. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate if (res == 0 && stat != LDAP_NO_SUCH_OBJECT) { 4227c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 4237c478bd9Sstevel@tonic-gate "%s: mapFromLDAP() => 0x0, status=%d (%s)", 4247c478bd9Sstevel@tonic-gate myself, stat, ldap_err2string(stat)); 4257c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 4267c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 4277c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 4287c478bd9Sstevel@tonic-gate struct timeval end; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 4317c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 4327c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 4357c478bd9Sstevel@tonic-gate * would have disappeared. However, since 4367c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 4377c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 4407c478bd9Sstevel@tonic-gate table->mapping.enumStat = stat; 4417c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 4427c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 4437c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 4447c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 4457c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 4467c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate table->mapping.enumTime = 4497c478bd9Sstevel@tonic-gate 1000000*end.tv_sec + end.tv_usec; 4507c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 4517c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate return (stat); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * Need to disable write-through to LDAP, for which we need a lock 4597c478bd9Sstevel@tonic-gate * on our db_mindex ('mindex'); we're also updating the table, so 4607c478bd9Sstevel@tonic-gate * we need a write lock on that as well. However, before locking the 4617c478bd9Sstevel@tonic-gate * mindex, we need to maintain lock integrity by acquiring the 4627c478bd9Sstevel@tonic-gate * trans log lock. Note that actually beginning a transaction is 4637c478bd9Sstevel@tonic-gate * expensive, so we defer that until we know that we really need 4647c478bd9Sstevel@tonic-gate * to update. 4657c478bd9Sstevel@tonic-gate */ 4667c478bd9Sstevel@tonic-gate lstat = lockTransLog(myself, 1, 1); 4677c478bd9Sstevel@tonic-gate if (lstat != 0) { 4687c478bd9Sstevel@tonic-gate if (lstat == EBUSY) 4697c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 4707c478bd9Sstevel@tonic-gate "%s: transaction log busy; no LDAP update for \"%s\"", 4717c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 4727c478bd9Sstevel@tonic-gate else 4737c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 4747c478bd9Sstevel@tonic-gate "%s: Error %d locking transaction log; no LDAP update for \"%s\"", 4757c478bd9Sstevel@tonic-gate myself, lstat, NIL(t->objName)); 4767c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 4777c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 4787c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 4797c478bd9Sstevel@tonic-gate struct timeval end; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 4827c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 4837c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 4867c478bd9Sstevel@tonic-gate * would have disappeared. However, since 4877c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 4887c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 4917c478bd9Sstevel@tonic-gate table->mapping.enumStat = LDAP_OPERATIONS_ERROR; 4927c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 4937c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 4947c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 4957c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 4967c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 4977c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate table->mapping.enumTime = 1000000*end.tv_sec + 5007c478bd9Sstevel@tonic-gate end.tv_usec; 5017c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 5027c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * If we have any updates, we'll call db::sync_log, which write- 5107c478bd9Sstevel@tonic-gate * locks the 'db' instance. In order to avoid a dead-lock with 5117c478bd9Sstevel@tonic-gate * threads performing a DB lookup (which will lock the 'db' and 5127c478bd9Sstevel@tonic-gate * then the 'db_mindex'), we need hence need to lock in the 5137c478bd9Sstevel@tonic-gate * following order: 5147c478bd9Sstevel@tonic-gate * 5157c478bd9Sstevel@tonic-gate * trans.log (already holding that one) 5167c478bd9Sstevel@tonic-gate * db 5177c478bd9Sstevel@tonic-gate * db_mindex 5187c478bd9Sstevel@tonic-gate * db_table 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate TRYWRITELOCK(((db *)mindex->getDbPtr()), stat, 5217c478bd9Sstevel@tonic-gate "w db db_mindex::entriesFromLDAPreal"); 5227c478bd9Sstevel@tonic-gate if (stat == 0) { 5237c478bd9Sstevel@tonic-gate TRYWRITELOCK(mindex, stat2, "w db_mindex::entriesFromLDAPreal"); 5247c478bd9Sstevel@tonic-gate if (stat2 == 0) { 5257c478bd9Sstevel@tonic-gate TRYWRITELOCK(table, stat3, 5267c478bd9Sstevel@tonic-gate "table w db_mindex::entriesFromLDAPreal"); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if (stat != 0 || stat2 != 0 || stat3 != 0) { 5317c478bd9Sstevel@tonic-gate if (stat != 0) { 5327c478bd9Sstevel@tonic-gate if (stat == EBUSY) 5337c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 5347c478bd9Sstevel@tonic-gate "%s: 'db' busy; no LDAP update for \"%s\"", 5357c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 5367c478bd9Sstevel@tonic-gate else 5377c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5387c478bd9Sstevel@tonic-gate "%s: 'db' lock error %d; no LDAP update for \"%s\"", 5397c478bd9Sstevel@tonic-gate myself, stat, NIL(t->objName)); 5407c478bd9Sstevel@tonic-gate } else if (stat2 != 0) { 5417c478bd9Sstevel@tonic-gate if (stat2 == EBUSY) 5427c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 5437c478bd9Sstevel@tonic-gate "%s: 'db_mindex' busy; no LDAP update for \"%s\"", 5447c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 5457c478bd9Sstevel@tonic-gate else 5467c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5477c478bd9Sstevel@tonic-gate "%s: 'db_mindex' lock error %d; no LDAP update for \"%s\"", 5487c478bd9Sstevel@tonic-gate myself, stat2, NIL(t->objName)); 5497c478bd9Sstevel@tonic-gate } else { 5507c478bd9Sstevel@tonic-gate if (stat3 == EBUSY) 5517c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 5527c478bd9Sstevel@tonic-gate "%s: 'db_table' busy; no LDAP update for \"%s\"", 5537c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 5547c478bd9Sstevel@tonic-gate else 5557c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 5567c478bd9Sstevel@tonic-gate "%s: 'db_table' lock error %d; no LDAP update for \"%s\"", 5577c478bd9Sstevel@tonic-gate myself, stat3, NIL(t->objName)); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate freeQueries(res, nq); 5607c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 5617c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 5627c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 5637c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 5647c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 5657c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 5667c478bd9Sstevel@tonic-gate /* 5677c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 5687c478bd9Sstevel@tonic-gate * would have disappeared. However, since 5697c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 5707c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 5717c478bd9Sstevel@tonic-gate */ 5727c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 5737c478bd9Sstevel@tonic-gate table->mapping.enumStat = LDAP_OPERATIONS_ERROR; 5747c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 5757c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate if (stat == 0) { 5797c478bd9Sstevel@tonic-gate if (stat2 == 0) { 5807c478bd9Sstevel@tonic-gate WRITEUNLOCK2(mindex, ((db *)mindex->getDbPtr()), 5817c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 5827c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 5837c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu", 5847c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu db"); 5857c478bd9Sstevel@tonic-gate } else { 5867c478bd9Sstevel@tonic-gate WRITEUNLOCK(((db *)mindex->getDbPtr()), 5877c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 5887c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu db"); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate unlockTransLog(myself, 1); 5927c478bd9Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 5967c478bd9Sstevel@tonic-gate mindex->setNoWriteThrough(); 5977c478bd9Sstevel@tonic-gate mindex->setNoLDAPquery(); 5987c478bd9Sstevel@tonic-gate if (qin == 0) { 5997c478bd9Sstevel@tonic-gate table->setEnumMode(0); 6007c478bd9Sstevel@tonic-gate doEnum = TRUE; 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate /* 6037c478bd9Sstevel@tonic-gate * If there is no non-indexed table mapping, we must filter 6047c478bd9Sstevel@tonic-gate * the enum mode (i.e., deletion candidates) array to only 6057c478bd9Sstevel@tonic-gate * contain those entries that match the indexes. 6067c478bd9Sstevel@tonic-gate */ 6077c478bd9Sstevel@tonic-gate if (haveIndexedMapping(t)) { 6087c478bd9Sstevel@tonic-gate entry_object **tea = table->gettab(); 6097c478bd9Sstevel@tonic-gate long i, ntea = table->getsize(); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * Walk through the entry array, and remove any enum 6147c478bd9Sstevel@tonic-gate * array entry that _doesn't_ match the index(es). 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gate for (i = 0; i < ntea; i++) { 6177c478bd9Sstevel@tonic-gate db_query *q; 6187c478bd9Sstevel@tonic-gate __nis_table_mapping_t **tp; 6197c478bd9Sstevel@tonic-gate int numMatches; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if (tea[i] == 0) 6227c478bd9Sstevel@tonic-gate continue; 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate q = pseudoEntryObj2Query(tea[i], 0, 0); 6257c478bd9Sstevel@tonic-gate if (q == 0) 6267c478bd9Sstevel@tonic-gate continue; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate tp = selectTableMapping(t, q, 0, 0, dbId, 6297c478bd9Sstevel@tonic-gate &numMatches); 6307c478bd9Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) 6317c478bd9Sstevel@tonic-gate table->enumTouch(i); 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate sfree(tp); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate freeQuery(q); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: %d entries from LDAP", 6407c478bd9Sstevel@tonic-gate myself, nq); 6417c478bd9Sstevel@tonic-gate } else { 6427c478bd9Sstevel@tonic-gate db_index_entry *dbie; 6437c478bd9Sstevel@tonic-gate long i, count; 6447c478bd9Sstevel@tonic-gate bool_t valid; 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 6477c478bd9Sstevel@tonic-gate * Find the entries in the DB that currently match the 6487c478bd9Sstevel@tonic-gate * query, and add them to the enum array. Those that 6497c478bd9Sstevel@tonic-gate * remain untouched when we've processed the LDAP data 6507c478bd9Sstevel@tonic-gate * don't currently exist in LDAP, and should be deleted 6517c478bd9Sstevel@tonic-gate * from the DB. 6527c478bd9Sstevel@tonic-gate */ 6537c478bd9Sstevel@tonic-gate dbie = mindex->satisfy_query_dbonly(qin, &count, FALSE, &valid); 6547c478bd9Sstevel@tonic-gate if (dbie != 0 && valid && count > 0) { 6557c478bd9Sstevel@tonic-gate table->setEnumMode(count); 6567c478bd9Sstevel@tonic-gate doEnum = TRUE; 6577c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 6587c478bd9Sstevel@tonic-gate table->enumSetup(dbie->getlocation(), i); 6597c478bd9Sstevel@tonic-gate dbie = dbie->getnextresult(); 6607c478bd9Sstevel@tonic-gate if (dbie == 0) 6617c478bd9Sstevel@tonic-gate break; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate } else { 6647c478bd9Sstevel@tonic-gate doEnum = FALSE; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate entry_col ec[NIS_MAXCOLUMNS+1]; 6697c478bd9Sstevel@tonic-gate for (i = 0, na = 0; i < nq; i++) { 6707c478bd9Sstevel@tonic-gate entry_object eo, *e; 6717c478bd9Sstevel@tonic-gate table_col *tc; 6727c478bd9Sstevel@tonic-gate nis_object o, *to; 6737c478bd9Sstevel@tonic-gate int j, nc; 6747c478bd9Sstevel@tonic-gate db_qcomp *qc; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate if (res[i] == 0) 6777c478bd9Sstevel@tonic-gate continue; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 6807c478bd9Sstevel@tonic-gate printQuery(res[i], t); 6817c478bd9Sstevel@tonic-gate printObjAttr(oa[i]); 6827c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* Assemble an object from the query and attributes */ 6857c478bd9Sstevel@tonic-gate (void) memset(&o, 0, sizeof (o)); 6867c478bd9Sstevel@tonic-gate if (oa[i] != 0) { 6877c478bd9Sstevel@tonic-gate o.zo_owner = oa[i]->zo_owner; 6887c478bd9Sstevel@tonic-gate o.zo_group = oa[i]->zo_group; 6897c478bd9Sstevel@tonic-gate o.zo_domain = oa[i]->zo_domain; 6907c478bd9Sstevel@tonic-gate o.zo_access = oa[i]->zo_access; 6917c478bd9Sstevel@tonic-gate o.zo_ttl = oa[i]->zo_ttl; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate if ((to = t->obj) != 0) { 6947c478bd9Sstevel@tonic-gate o.zo_name = to->zo_name; 6957c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_type = 6967c478bd9Sstevel@tonic-gate to->zo_data.objdata_u.ta_data.ta_type; 6977c478bd9Sstevel@tonic-gate tc = to->zo_data.objdata_u.ta_data.ta_cols.ta_cols_val; 6987c478bd9Sstevel@tonic-gate if (to->zo_data.objdata_u.ta_data.ta_cols.ta_cols_len 6997c478bd9Sstevel@tonic-gate != t->numColumns) 7007c478bd9Sstevel@tonic-gate tc = 0; 7017c478bd9Sstevel@tonic-gate if (o.zo_owner == 0) 7027c478bd9Sstevel@tonic-gate o.zo_owner = to->zo_owner; 7037c478bd9Sstevel@tonic-gate if (o.zo_group == 0) 7047c478bd9Sstevel@tonic-gate o.zo_group = to->zo_group; 7057c478bd9Sstevel@tonic-gate if (o.zo_domain == 0) 7067c478bd9Sstevel@tonic-gate o.zo_domain = to->zo_domain; 7077c478bd9Sstevel@tonic-gate if (o.zo_access == 0) 7087c478bd9Sstevel@tonic-gate o.zo_access = to->zo_access; 7097c478bd9Sstevel@tonic-gate if (o.zo_ttl == 0) 7107c478bd9Sstevel@tonic-gate o.zo_ttl = to->zo_ttl; 7117c478bd9Sstevel@tonic-gate } else { 7127c478bd9Sstevel@tonic-gate tc = 0; 7138d0852b7SRichard Lowe o.zo_owner = (nis_name)""; 7148d0852b7SRichard Lowe o.zo_group = (nis_name)""; 7158d0852b7SRichard Lowe o.zo_domain = (nis_name)""; 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate o.zo_data.zo_type = NIS_ENTRY_OBJ; 7197c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_len = 7207c478bd9Sstevel@tonic-gate t->numColumns + 1; 7217c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_val = ec; 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate (void) memset(&ec, 0, sizeof (ec)); 7247c478bd9Sstevel@tonic-gate nc = res[i]->size(); 7257c478bd9Sstevel@tonic-gate qc = res[i]->queryloc(); 7267c478bd9Sstevel@tonic-gate if (qc == 0) { 7277c478bd9Sstevel@tonic-gate freeQuery(res[i]); 7287c478bd9Sstevel@tonic-gate continue; 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate for (j = 0; j < nc; j++) { 7317c478bd9Sstevel@tonic-gate int ic = 1+ qc[j].which_index; 7327c478bd9Sstevel@tonic-gate if (ic < 1 || ic > t->numColumns) 7337c478bd9Sstevel@tonic-gate continue; 7347c478bd9Sstevel@tonic-gate #ifdef SET_ENTRY_FLAGS 7357c478bd9Sstevel@tonic-gate if (tc != 0) 7367c478bd9Sstevel@tonic-gate ec[ic].ec_flags = 7377c478bd9Sstevel@tonic-gate entryFlagsFromTable(tc[ic-1].tc_flags); 7387c478bd9Sstevel@tonic-gate #else 7397c478bd9Sstevel@tonic-gate /* 7407c478bd9Sstevel@tonic-gate * In theory, the entry flags should be derived 7417c478bd9Sstevel@tonic-gate * from the table flags. However, that doesn't 7427c478bd9Sstevel@tonic-gate * seem to be the way that the DB code has done 7437c478bd9Sstevel@tonic-gate * things so far, so leave the entry flags unset. 7447c478bd9Sstevel@tonic-gate */ 7457c478bd9Sstevel@tonic-gate #endif /* SET_ENTRY_FLAGS */ 7467c478bd9Sstevel@tonic-gate qc[j].index_value->get_value( 7477c478bd9Sstevel@tonic-gate &ec[ic].ec_value.ec_value_val, 7487c478bd9Sstevel@tonic-gate (int *)&ec[ic].ec_value.ec_value_len); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate setOid(&o); 7527c478bd9Sstevel@tonic-gate e = makePseudoEntryObj(&o, &eo, t->obj); 7537c478bd9Sstevel@tonic-gate if (e == 0) { 7547c478bd9Sstevel@tonic-gate freeQuery(res[i]); 7557c478bd9Sstevel@tonic-gate continue; 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* 7597c478bd9Sstevel@tonic-gate * 'o' is currently a pseudo-object of type entry, with 7607c478bd9Sstevel@tonic-gate * column zero used for an XDR:ed version of the entry_obj, 7617c478bd9Sstevel@tonic-gate * column one the real column zero of the entry, etc. 7627c478bd9Sstevel@tonic-gate * We now need a real NIS_ENTRY_OBJ object, so move the 7637c478bd9Sstevel@tonic-gate * entry_col array one step left. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_len = t->numColumns; 7667c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_val = &ec[1]; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate stat = mindex->updateTableEntry(e, 1, t->objName, &o, t->obj, 7697c478bd9Sstevel@tonic-gate o.zo_oid.mtime, &xid); 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * LDAP_SUCCESS => Entry added or modified 7727c478bd9Sstevel@tonic-gate * LDAP_COMPARE_TRUE => Entry same as existing one 7737c478bd9Sstevel@tonic-gate * other => Error 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 7767c478bd9Sstevel@tonic-gate na++; 7777c478bd9Sstevel@tonic-gate } else if (stat == LDAP_COMPARE_TRUE) { 7787c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 7797c478bd9Sstevel@tonic-gate } else { 7807c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 7817c478bd9Sstevel@tonic-gate "%s: Error adding entry to \"%s\": %s", 7827c478bd9Sstevel@tonic-gate myself, NIL(t->objName), 7837c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if (e->en_cols.en_cols_val != 0) 7877c478bd9Sstevel@tonic-gate sfree(e->en_cols.en_cols_val[0].ec_value.ec_value_val); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate freeQuery(res[i]); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate sfree(res); 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate /* Take care of deletes if we enumerated the table */ 7957c478bd9Sstevel@tonic-gate if (doEnum) { 7967c478bd9Sstevel@tonic-gate ea = table->endEnumMode(&numEa); 7977c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 7987c478bd9Sstevel@tonic-gate "%s: %d entries added/updated", myself, na); 7997c478bd9Sstevel@tonic-gate nau = na; 8007c478bd9Sstevel@tonic-gate } else 8017c478bd9Sstevel@tonic-gate ea = 0; 8027c478bd9Sstevel@tonic-gate if (ea != 0) { 8037c478bd9Sstevel@tonic-gate uint32_t nowt = time(0); 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate for (i = 0; i < numEa; i++) { 8067c478bd9Sstevel@tonic-gate int st; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate if (ea[i] == 0) 8097c478bd9Sstevel@tonic-gate continue; 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate st = mindex->updateTableEntry(ea[i], 0, t->objName, 0, 8127c478bd9Sstevel@tonic-gate t->obj, nowt, &xid); 8137c478bd9Sstevel@tonic-gate if (st == LDAP_SUCCESS) { 8147c478bd9Sstevel@tonic-gate na++; 8157c478bd9Sstevel@tonic-gate } else { 8167c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 8177c478bd9Sstevel@tonic-gate "%s: Error removing directory entry for \"%s\": %s", 8187c478bd9Sstevel@tonic-gate myself, NIL(t->objName), 8197c478bd9Sstevel@tonic-gate ldap_err2string(st)); 8207c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 8217c478bd9Sstevel@tonic-gate stat = st; 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 8257c478bd9Sstevel@tonic-gate struct timeval now; 8267c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, 0); 8277c478bd9Sstevel@tonic-gate table->mapping.enumExpire = now.tv_sec + 8287c478bd9Sstevel@tonic-gate table->mapping.ttl; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate if (doEnum) 8317c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 8327c478bd9Sstevel@tonic-gate "%s: %d entries deleted", myself, na-nau); 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate sfree(ea); 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* If we called log_action() successfully, we need to sync the log */ 8387c478bd9Sstevel@tonic-gate if (na > 0) 8397c478bd9Sstevel@tonic-gate (void) ((db *)mindex->getDbPtr())->sync_log(); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (xid != 0 && na > 0 && stat == LDAP_SUCCESS) 8427c478bd9Sstevel@tonic-gate ret = endTransaction(xid, dirObj); 8437c478bd9Sstevel@tonic-gate else if (xid != 0) 8447c478bd9Sstevel@tonic-gate ret = abort_transaction(xid); 8457c478bd9Sstevel@tonic-gate else 8467c478bd9Sstevel@tonic-gate ret = 0; 8477c478bd9Sstevel@tonic-gate if (ret != 0) { 8487c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 8497c478bd9Sstevel@tonic-gate "%s: Error %s transaction for \"%s\"", 8507c478bd9Sstevel@tonic-gate myself, (na > 0 && stat == LDAP_SUCCESS) ? 8517c478bd9Sstevel@tonic-gate "ending" : "aborting", 8527c478bd9Sstevel@tonic-gate NIL(t->objName)); 8537c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate mindex->clearNoLDAPquery(); 8577c478bd9Sstevel@tonic-gate mindex->clearNoWriteThrough(); 8587c478bd9Sstevel@tonic-gate freeObjAttr(oa, nq); 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 8617c478bd9Sstevel@tonic-gate printbuf(); 8627c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (doEnum) 8657c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 8667c478bd9Sstevel@tonic-gate "%s: enumeration \"%s\" done", myself, NIL(t->objName)); 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * Rollback doesn't recover data written to disk, so 8717c478bd9Sstevel@tonic-gate * we should commit even if we're returning failure. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate dstat = InUseDictionary->commit(t->objPath); 8747c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 8757c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 8767c478bd9Sstevel@tonic-gate "%s: DB error %d committing \"%s\"", 8777c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 8817c478bd9Sstevel@tonic-gate if (arg->isDeferred && dstat == DB_SUCCESS) 8827c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 8837c478bd9Sstevel@tonic-gate table->mapping.enumStat = stat; 8847c478bd9Sstevel@tonic-gate { 8857c478bd9Sstevel@tonic-gate struct timeval end; 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 8887c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 8897c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 8907c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 8917c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 8927c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate table->mapping.enumTime = 1000000*end.tv_sec + end.tv_usec; 8957c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 8967c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 8977c478bd9Sstevel@tonic-gate LOG_WARNING, 8987c478bd9Sstevel@tonic-gate #else 8997c478bd9Sstevel@tonic-gate LOG_INFO, 9007c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 9017c478bd9Sstevel@tonic-gate "%s: %d entries in %ld usec => %ld usec/entry", 9027c478bd9Sstevel@tonic-gate NIL(t->objName), table->mapping.enumEntries, 9037c478bd9Sstevel@tonic-gate table->mapping.enumTime, 9047c478bd9Sstevel@tonic-gate table->mapping.enumTime/ 9057c478bd9Sstevel@tonic-gate (table->mapping.enumEntries != 0 ? 9067c478bd9Sstevel@tonic-gate table->mapping.enumEntries : 1)); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 9097c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(table, stat3, "table wu db_mindex::entriesFromLDAPreal"); 9127c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(mindex, stat2, "db_mindex::entriesFromLDAPreal wu"); 9137c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(((db *)mindex->getDbPtr()), lstat, 9147c478bd9Sstevel@tonic-gate "db db_mindex::entriesFromLDAPreal wu"); 9157c478bd9Sstevel@tonic-gate unlockTransLog(myself, 1); 9167c478bd9Sstevel@tonic-gate if (stat3 != 0) 9177c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 9187c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db_table", myself, stat3); 9197c478bd9Sstevel@tonic-gate if (stat2 != 0) 9207c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 9217c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db_mindex", myself, stat2); 9227c478bd9Sstevel@tonic-gate if (lstat != 0) 9237c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 9247c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db", myself, lstat); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate return (stat); 9277c478bd9Sstevel@tonic-gate } 92836e852a1SRaja Andra /* 92936e852a1SRaja Andra * Sets the oid (i.e., the creation and modification times) for the 93036e852a1SRaja Andra * specified object. In order to avoid retrieving the old incarnation 93136e852a1SRaja Andra * (if any) from the DB first, we're punting and setting both mtime 93236e852a1SRaja Andra * and ctime to the current time. 93336e852a1SRaja Andra */ 93436e852a1SRaja Andra static void 93536e852a1SRaja Andra setOid(nis_object *obj) { 93636e852a1SRaja Andra if (obj != 0) { 93736e852a1SRaja Andra obj->zo_oid.ctime = obj->zo_oid.mtime = time(0); 93836e852a1SRaja Andra } 93936e852a1SRaja Andra } 940