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 /*
2236e852a1SRaja Andra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2336e852a1SRaja Andra  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <malloc.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <time.h>
347c478bd9Sstevel@tonic-gate #include "db_headers.h"
357c478bd9Sstevel@tonic-gate #include "db.h"
367c478bd9Sstevel@tonic-gate #include "db_mindex.h"
377c478bd9Sstevel@tonic-gate #include "db_pickle.h"
387c478bd9Sstevel@tonic-gate #include "nisdb_mt.h"
397c478bd9Sstevel@tonic-gate #include "nisdb_ldap.h"
407c478bd9Sstevel@tonic-gate #include "ldap_nisdbquery.h"
417c478bd9Sstevel@tonic-gate #include "ldap_map.h"
427c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h"
437c478bd9Sstevel@tonic-gate #include "ldap_scheme.h"
447c478bd9Sstevel@tonic-gate #include "ldap_parse.h"
457c478bd9Sstevel@tonic-gate #include "nis_hashitem.h"
467c478bd9Sstevel@tonic-gate #include "nis_db.h"
477c478bd9Sstevel@tonic-gate #include "ldap_glob.h"
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /* Pass through configuration information to the table */
507c478bd9Sstevel@tonic-gate bool_t
configure(char * tablePath)517c478bd9Sstevel@tonic-gate db_mindex::configure(char *tablePath) {
527c478bd9Sstevel@tonic-gate 	if (tablePath == NULL)
537c478bd9Sstevel@tonic-gate 		return (FALSE);
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	if (objPath.ptr != 0)
567c478bd9Sstevel@tonic-gate 		free(objPath.ptr);
577c478bd9Sstevel@tonic-gate 	objPath.ptr = strdup(tablePath);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	if (table != NULL) {
607c478bd9Sstevel@tonic-gate 		return (table->configure(tablePath));
617c478bd9Sstevel@tonic-gate 	} else {
627c478bd9Sstevel@tonic-gate 		/* Defer table config until we have a table instance */
637c478bd9Sstevel@tonic-gate 		return (objPath.ptr != NULL);
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * The noWriteThrough flag is used to prevent modifies/updates to LDAP
697c478bd9Sstevel@tonic-gate  * while we're incorporating log data into the in-memory tables.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate void
setNoWriteThrough(void)727c478bd9Sstevel@tonic-gate db_mindex::setNoWriteThrough(void) {
737c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
747c478bd9Sstevel@tonic-gate 	noWriteThrough.flag++;
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate void
clearNoWriteThrough(void)787c478bd9Sstevel@tonic-gate db_mindex::clearNoWriteThrough(void) {
797c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
807c478bd9Sstevel@tonic-gate 	if (noWriteThrough.flag > 0)
817c478bd9Sstevel@tonic-gate 		noWriteThrough.flag--;
827c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
837c478bd9Sstevel@tonic-gate 	else
847c478bd9Sstevel@tonic-gate 		abort();
857c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * The noLDAPquery flag is used to prevent recursive LDAP queries when
907c478bd9Sstevel@tonic-gate  * satisfy_query() is re-entered as we add an entry from queryLDAP().
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate void
setNoLDAPquery(void)937c478bd9Sstevel@tonic-gate db_mindex::setNoLDAPquery(void) {
947c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
957c478bd9Sstevel@tonic-gate 	noLDAPquery.flag++;
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate void
clearNoLDAPquery(void)997c478bd9Sstevel@tonic-gate db_mindex::clearNoLDAPquery(void) {
1007c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
1017c478bd9Sstevel@tonic-gate 	if (noLDAPquery.flag > 0)
1027c478bd9Sstevel@tonic-gate 		noLDAPquery.flag--;
1037c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1047c478bd9Sstevel@tonic-gate 	else
1057c478bd9Sstevel@tonic-gate 		abort();
1067c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  * The initialLoad flag tells us if an add or remove is done as part of
1117c478bd9Sstevel@tonic-gate  * the initial load of data, in which case we should use the initial TTLs.
1127c478bd9Sstevel@tonic-gate  */
1137c478bd9Sstevel@tonic-gate void
setInitialLoad(void)1147c478bd9Sstevel@tonic-gate db_mindex::setInitialLoad(void) {
1157c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
1167c478bd9Sstevel@tonic-gate 	initialLoad.flag++;
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate void
clearInitialLoad(void)1207c478bd9Sstevel@tonic-gate db_mindex::clearInitialLoad(void) {
1217c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
1227c478bd9Sstevel@tonic-gate 	if (initialLoad.flag > 0)
1237c478bd9Sstevel@tonic-gate 		initialLoad.flag--;
1247c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1257c478bd9Sstevel@tonic-gate 	else
1267c478bd9Sstevel@tonic-gate 		abort();
1277c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate void
setDbPtr(void * ptr)1317c478bd9Sstevel@tonic-gate db_mindex::setDbPtr(void *ptr) {
1327c478bd9Sstevel@tonic-gate 	dbptr.ptr = ptr;
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate void *
getDbPtr(void)1367c478bd9Sstevel@tonic-gate db_mindex::getDbPtr(void) {
1377c478bd9Sstevel@tonic-gate 	return (dbptr.ptr);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate db_table *
getTable(void)1417c478bd9Sstevel@tonic-gate db_mindex::getTable(void) {
1427c478bd9Sstevel@tonic-gate 	return (table);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
14536e852a1SRaja Andra static void                    setOid(nis_object *obj);
14636e852a1SRaja Andra 
1477c478bd9Sstevel@tonic-gate extern void	db_free_result(db_result *);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate zotypes
updateMappingObj(__nis_table_mapping_t * t,char ** objNameP,bool_t * isMasterP)1507c478bd9Sstevel@tonic-gate updateMappingObj(__nis_table_mapping_t *t, char **objNameP,
1517c478bd9Sstevel@tonic-gate 		bool_t *isMasterP) {
152*8d0852b7SRichard Lowe 	zotypes         type = NIS_BOGUS_OBJ;
153*8d0852b7SRichard Lowe 	char            *objName = 0;
154*8d0852b7SRichard Lowe 	const char	*myself = "updateMappingObj";
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	if (t != 0)
1577c478bd9Sstevel@tonic-gate 		objName = t->objName;
1587c478bd9Sstevel@tonic-gate 	else if (objNameP != 0)
1597c478bd9Sstevel@tonic-gate 		objName = *objNameP;
1607c478bd9Sstevel@tonic-gate 	else
1617c478bd9Sstevel@tonic-gate 		return (NIS_BOGUS_OBJ);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	if (objName != 0) {
1647c478bd9Sstevel@tonic-gate 		db_status	stat;
1657c478bd9Sstevel@tonic-gate 		int		lstat = LDAP_SUCCESS;
1667c478bd9Sstevel@tonic-gate 		nis_object	*o = dbFindObject(objName, &stat);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		/* If not found in the local DB, try LDAP */
1697c478bd9Sstevel@tonic-gate 		if (o == 0) {
1707c478bd9Sstevel@tonic-gate 			if (stat != DB_NOTFOUND) {
1717c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_INFO,
1727c478bd9Sstevel@tonic-gate 					"%s: DB err %d for \"%s\"",
1737c478bd9Sstevel@tonic-gate 					myself, stat, NIL(objName));
1747c478bd9Sstevel@tonic-gate 			}
1757c478bd9Sstevel@tonic-gate 			o = ldapFindObj(t, objName, &lstat);
1767c478bd9Sstevel@tonic-gate 			/* If found, refresh/create the local copy */
1777c478bd9Sstevel@tonic-gate 			if (o != 0) {
1787c478bd9Sstevel@tonic-gate 				db_status	rstat;
1797c478bd9Sstevel@tonic-gate 				rstat = dbRefreshObj(objName, o);
1807c478bd9Sstevel@tonic-gate 				if (rstat != DB_SUCCESS)
1817c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1827c478bd9Sstevel@tonic-gate 					"%s: DB error %d refreshing \"%s\"",
1837c478bd9Sstevel@tonic-gate 					myself, rstat, NIL(objName));
1847c478bd9Sstevel@tonic-gate 			}
1857c478bd9Sstevel@tonic-gate 		}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 		if (o != 0) {
1887c478bd9Sstevel@tonic-gate 			type = o->zo_data.zo_type;
1897c478bd9Sstevel@tonic-gate 			if (objNameP != 0) {
1907c478bd9Sstevel@tonic-gate 				*objNameP = sdup(myself, T, objName);
1917c478bd9Sstevel@tonic-gate 				if (*objNameP == 0) {
1927c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1937c478bd9Sstevel@tonic-gate 				"%s: Unable to copy object name (\"%s\")",
1947c478bd9Sstevel@tonic-gate 						myself, NIL(objName));
1957c478bd9Sstevel@tonic-gate 				}
1967c478bd9Sstevel@tonic-gate 			}
1977c478bd9Sstevel@tonic-gate 			if (t != 0) {
1987c478bd9Sstevel@tonic-gate 				if (!setMappingObjTypeEtc(t, o))
1997c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 			} else {
2027c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
2037c478bd9Sstevel@tonic-gate 			}
2047c478bd9Sstevel@tonic-gate 		} else if (lstat != LDAP_SUCCESS) {
2057c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
2067c478bd9Sstevel@tonic-gate 				"%s: LDAP err %d for \"%s\"",
2077c478bd9Sstevel@tonic-gate 				myself, lstat, NIL(objName));
2087c478bd9Sstevel@tonic-gate 		}
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	return (type);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
mappingFromObj(nis_object * obj,int * statP)2157c478bd9Sstevel@tonic-gate mappingFromObj(nis_object *obj, int *statP) {
2167c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
2177c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
2187c478bd9Sstevel@tonic-gate 	char			*objPath;
219*8d0852b7SRichard Lowe 	const char		*myself = "mappingFromObj";
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	if (obj == 0 || obj->zo_data.zo_type == NIS_ENTRY_OBJ)
2227c478bd9Sstevel@tonic-gate 		return (0);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	/*
2257c478bd9Sstevel@tonic-gate 	 * Convert full object name to the db table path used as
2267c478bd9Sstevel@tonic-gate 	 * key for the mapping hash list.
2277c478bd9Sstevel@tonic-gate 	 */
2287c478bd9Sstevel@tonic-gate 	bp2buf(myself, &b, "%s.%s",
2297c478bd9Sstevel@tonic-gate 		NIL(obj->zo_name), NIL(obj->zo_domain));
2307c478bd9Sstevel@tonic-gate 	objPath = internalTableName(b.buf);
2317c478bd9Sstevel@tonic-gate 	sfree(b.buf);
2327c478bd9Sstevel@tonic-gate 	if (slen(objPath) <= 0) {
2337c478bd9Sstevel@tonic-gate 		if (statP != 0)
2347c478bd9Sstevel@tonic-gate 			*statP = LDAP_OPERATIONS_ERROR;
2357c478bd9Sstevel@tonic-gate 		sfree(objPath);
2367c478bd9Sstevel@tonic-gate 		return (0);
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	t = (__nis_table_mapping_t *)__nis_find_item_mt(objPath,
2407c478bd9Sstevel@tonic-gate 						&ldapMappingList, 0, 0);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	sfree(objPath);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	return (t);
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
selectMapping(db_table * table,nis_object * obj,db_query * qin,bool_t wantWrite,bool_t * asObjP,int * statP)2487c478bd9Sstevel@tonic-gate selectMapping(db_table *table, nis_object *obj, db_query *qin,
2497c478bd9Sstevel@tonic-gate 		bool_t wantWrite, bool_t *asObjP, int *statP) {
2507c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
2517c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
2527c478bd9Sstevel@tonic-gate 	bool_t			doLDAP, asObj;
2537c478bd9Sstevel@tonic-gate 	int			stat = LDAP_SUCCESS;
2547c478bd9Sstevel@tonic-gate 	char			*objPath = 0, buf[MAXPATHLEN+NIS_MAXNAMELEN+1];
255*8d0852b7SRichard Lowe 	const char		*myself = "db_mindex::selectMapping";
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/*
2587c478bd9Sstevel@tonic-gate 	 * If 'table' is NULL, we try to find a mapping for 'obj'.
2597c478bd9Sstevel@tonic-gate 	 * We expect this to happen when our caller wants to write
2607c478bd9Sstevel@tonic-gate 	 * the object from a directory entry to LDAP.
2617c478bd9Sstevel@tonic-gate 	 */
2627c478bd9Sstevel@tonic-gate 	if (table == 0) {
2637c478bd9Sstevel@tonic-gate 		if (asObjP != 0)
2647c478bd9Sstevel@tonic-gate 			*asObjP = TRUE;
2657c478bd9Sstevel@tonic-gate 		if (statP != 0)
2667c478bd9Sstevel@tonic-gate 			*statP = LDAP_SUCCESS;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		t = mappingFromObj(obj, statP);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		if (t == 0)
2717c478bd9Sstevel@tonic-gate 			return (0);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 		/*
2747c478bd9Sstevel@tonic-gate 		 * Should the object type in the mapping be NIS_BOGUS_OBJ,
2757c478bd9Sstevel@tonic-gate 		 * we need to determine what kind of object this is.
2767c478bd9Sstevel@tonic-gate 		 */
2777c478bd9Sstevel@tonic-gate 		if (t->objType == NIS_BOGUS_OBJ) {
2787c478bd9Sstevel@tonic-gate 			t->objType = updateMappingObj(t, 0, 0);
2797c478bd9Sstevel@tonic-gate 			if (t->objType == NIS_BOGUS_OBJ) {
2807c478bd9Sstevel@tonic-gate 				if (statP != 0)
2817c478bd9Sstevel@tonic-gate 					*statP = LDAP_OPERATIONS_ERROR;
2827c478bd9Sstevel@tonic-gate 				return (0);
2837c478bd9Sstevel@tonic-gate 			}
2847c478bd9Sstevel@tonic-gate 		}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 		/*
2877c478bd9Sstevel@tonic-gate 		 * If caller wants a mapping suitable for writing,
2887c478bd9Sstevel@tonic-gate 		 * check that we're the master for this object.
2897c478bd9Sstevel@tonic-gate 		 */
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		return (t);
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/*
2957c478bd9Sstevel@tonic-gate 	 * If the object type for the mapping is NIS_BOGUS_OBJ, then
2967c478bd9Sstevel@tonic-gate 	 * we haven't yet been able to determine what kind of object this
2977c478bd9Sstevel@tonic-gate 	 * is. Try to fix that now.
2987c478bd9Sstevel@tonic-gate 	 */
2997c478bd9Sstevel@tonic-gate 	if (table->mapping.objType == NIS_BOGUS_OBJ) {
3007c478bd9Sstevel@tonic-gate 		table->mapping.objType = updateMappingObj(table->mapping.tm,
3017c478bd9Sstevel@tonic-gate 						&table->mapping.objName,
3027c478bd9Sstevel@tonic-gate 						&table->mapping.isMaster);
3037c478bd9Sstevel@tonic-gate 		table->mapping.expireType = table->mapping.objType;
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	/*
3077c478bd9Sstevel@tonic-gate 	 * Depending on the object type (table->mapping.objType):
3087c478bd9Sstevel@tonic-gate 	 *
3097c478bd9Sstevel@tonic-gate 	 *	table		Use table->mapping.tm to query LDAP
3107c478bd9Sstevel@tonic-gate 	 *			for entries per 'qin'.
3117c478bd9Sstevel@tonic-gate 	 *
3127c478bd9Sstevel@tonic-gate 	 *	directory	Use 'qin' and table->mapping.objName
3137c478bd9Sstevel@tonic-gate 	 *			to retrieve a mapping entry, and then
3147c478bd9Sstevel@tonic-gate 	 *			query LDAP for the corresponding object.
3157c478bd9Sstevel@tonic-gate 	 *			'qin' == NULL means reading/writing the
3167c478bd9Sstevel@tonic-gate 	 *			entire directory object, plus the names
3177c478bd9Sstevel@tonic-gate 	 *			of the directory entries.
3187c478bd9Sstevel@tonic-gate 	 *
3197c478bd9Sstevel@tonic-gate 	 *	bogus		Not mapping this object. However, we may
3207c478bd9Sstevel@tonic-gate 	 *			still be mapping the object 'obj'.
3217c478bd9Sstevel@tonic-gate 	 *
3227c478bd9Sstevel@tonic-gate 	 *	other		Shouldn't happen; illegal.
3237c478bd9Sstevel@tonic-gate 	 */
3247c478bd9Sstevel@tonic-gate 	switch (table->mapping.objType) {
3257c478bd9Sstevel@tonic-gate 	case NIS_TABLE_OBJ:
3267c478bd9Sstevel@tonic-gate 		t = table->mapping.tm;
3277c478bd9Sstevel@tonic-gate 		if (wantWrite)
3287c478bd9Sstevel@tonic-gate 			doLDAP = table->mapping.isMaster &&
3297c478bd9Sstevel@tonic-gate 					table->mapping.toLDAP;
3307c478bd9Sstevel@tonic-gate 		else
3317c478bd9Sstevel@tonic-gate 			doLDAP = table->mapping.fromLDAP;
3327c478bd9Sstevel@tonic-gate 		asObj = FALSE;
3337c478bd9Sstevel@tonic-gate 		break;
3347c478bd9Sstevel@tonic-gate 	case NIS_DIRECTORY_OBJ: {
3357c478bd9Sstevel@tonic-gate 		char		*sub = 0;
3367c478bd9Sstevel@tonic-gate 		int		nqc, len = 0;
3377c478bd9Sstevel@tonic-gate 		db_qcomp	*qc;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 		t = 0;
3407c478bd9Sstevel@tonic-gate 		doLDAP = FALSE;
3417c478bd9Sstevel@tonic-gate 		asObj = TRUE;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 		/*
3447c478bd9Sstevel@tonic-gate 		 * We expect the query to have one component, containing
3457c478bd9Sstevel@tonic-gate 		 * the directory entry name. If there's no query, we want
3467c478bd9Sstevel@tonic-gate 		 * an enumeration of the entries in the directory. They're
3477c478bd9Sstevel@tonic-gate 		 * stored with the XDR:ed directory object in LDAP, so
3487c478bd9Sstevel@tonic-gate 		 * asObj should be TRUE.
3497c478bd9Sstevel@tonic-gate 		 */
3507c478bd9Sstevel@tonic-gate 		if (qin == 0) {
3517c478bd9Sstevel@tonic-gate 			t = table->mapping.tm;
3527c478bd9Sstevel@tonic-gate 			if (wantWrite)
3537c478bd9Sstevel@tonic-gate 				doLDAP = table->mapping.isMaster &&
3547c478bd9Sstevel@tonic-gate 					table->mapping.toLDAP;
3557c478bd9Sstevel@tonic-gate 			else
3567c478bd9Sstevel@tonic-gate 				doLDAP = table->mapping.fromLDAP;
3577c478bd9Sstevel@tonic-gate 			asObj = TRUE;
3587c478bd9Sstevel@tonic-gate 			break;
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		nqc = qin->size();
3627c478bd9Sstevel@tonic-gate 		if (nqc != 1 || (qc = qin->queryloc()) == 0 ||
3637c478bd9Sstevel@tonic-gate 				qc[0].index_value == 0) {
3647c478bd9Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
3657c478bd9Sstevel@tonic-gate 			break;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 		qc[0].index_value->get_value(&sub, &len);
3687c478bd9Sstevel@tonic-gate 		if (sub == 0 || len <= 0) {
3697c478bd9Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
3707c478bd9Sstevel@tonic-gate 			break;
3717c478bd9Sstevel@tonic-gate 		}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 		/* Append directory name to dir entry name */
3747c478bd9Sstevel@tonic-gate 		sbc2buf(myself, sub, len, &b);
3757c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, ".%s", table->mapping.objName);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 		/* Convert to the DB internal name */
3787c478bd9Sstevel@tonic-gate 		objPath = internal_table_name(b.buf, buf);
3797c478bd9Sstevel@tonic-gate 		sfree(b.buf);
3807c478bd9Sstevel@tonic-gate 		if (slen(objPath) <= 0) {
3817c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
3827c478bd9Sstevel@tonic-gate 			break;
3837c478bd9Sstevel@tonic-gate 		}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 		/* Look for the corresponding table mapping */
3867c478bd9Sstevel@tonic-gate 		t = (__nis_table_mapping_t *)__nis_find_item_mt(
3877c478bd9Sstevel@tonic-gate 					objPath, &ldapMappingList, 0, 0);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		if (t == 0)
3907c478bd9Sstevel@tonic-gate 			break;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 		/* Update object mapping information */
3937c478bd9Sstevel@tonic-gate 		if (t->objType == NIS_BOGUS_OBJ)
3947c478bd9Sstevel@tonic-gate 			(void) updateMappingObj(t, 0, 0);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		/*
3977c478bd9Sstevel@tonic-gate 		 * Should check the objectDN's in 't', but leave that to
3987c478bd9Sstevel@tonic-gate 		 * underlying functions.
3997c478bd9Sstevel@tonic-gate 		 */
4007c478bd9Sstevel@tonic-gate 		if (wantWrite)
4017c478bd9Sstevel@tonic-gate 			doLDAP = t->isMaster;
4027c478bd9Sstevel@tonic-gate 		else
4037c478bd9Sstevel@tonic-gate 			doLDAP = TRUE;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		break;
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	case NIS_BOGUS_OBJ:
4087c478bd9Sstevel@tonic-gate 		t = mappingFromObj(obj, statP);
4097c478bd9Sstevel@tonic-gate 		doLDAP = TRUE;
4107c478bd9Sstevel@tonic-gate 		asObj = TRUE;
4117c478bd9Sstevel@tonic-gate 		break;
4127c478bd9Sstevel@tonic-gate 	default:
4137c478bd9Sstevel@tonic-gate 		t = 0;
4147c478bd9Sstevel@tonic-gate 		doLDAP = FALSE;
4157c478bd9Sstevel@tonic-gate 		asObj = TRUE;
4167c478bd9Sstevel@tonic-gate 		break;
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	if (!doLDAP)
4207c478bd9Sstevel@tonic-gate 		t = 0;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	if (asObjP != 0)
4237c478bd9Sstevel@tonic-gate 		*asObjP = asObj;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	if (statP != 0)
4267c478bd9Sstevel@tonic-gate 		*statP = stat;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	return (t);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate  * Replace or remove the table entry identified by 'e'. 'tableName' is
4337c478bd9Sstevel@tonic-gate  * the name of the table (which could be a directory) in which the entry
4347c478bd9Sstevel@tonic-gate  * resides. 'obj' is an un-XDR:ed copy of the object in 'e', optionally
4357c478bd9Sstevel@tonic-gate  * supplied to save re-doing unpacking of the entry object. 'tobj' is
4367c478bd9Sstevel@tonic-gate  * a pointer to the table object; needed for table entries, but not
4377c478bd9Sstevel@tonic-gate  * for directory entries.
4387c478bd9Sstevel@tonic-gate  *
4397c478bd9Sstevel@tonic-gate  * 'ttime' contains the current time, to be supplied for the trans log
4407c478bd9Sstevel@tonic-gate  * entry.
4417c478bd9Sstevel@tonic-gate  *
4427c478bd9Sstevel@tonic-gate  * Returns LDAP_SUCCESS when entry successfully added/modified/deleted,
4437c478bd9Sstevel@tonic-gate  * LDAP_COMPARE_TRUE if an entry to be added/modified was the same as
4447c478bd9Sstevel@tonic-gate  * an already existing one, and a suitable error otherwise.
4457c478bd9Sstevel@tonic-gate  */
4467c478bd9Sstevel@tonic-gate int
updateTableEntry(entry_object * e,int replace,char * tableName,nis_object * obj,nis_object * tobj,uint32_t ttime,int * xid)4477c478bd9Sstevel@tonic-gate db_mindex::updateTableEntry(entry_object *e, int replace, char *tableName,
4487c478bd9Sstevel@tonic-gate 		nis_object *obj, nis_object *tobj, uint32_t ttime,
4497c478bd9Sstevel@tonic-gate 		int *xid) {
4507c478bd9Sstevel@tonic-gate 	int			stat, freeObj = 0;
4517c478bd9Sstevel@tonic-gate 	db_index_entry		*dbie;
4527c478bd9Sstevel@tonic-gate 	long			count = 0;
4537c478bd9Sstevel@tonic-gate 	bool_t			valid = TRUE;
4547c478bd9Sstevel@tonic-gate 	db_result		*dbres;
4557c478bd9Sstevel@tonic-gate 	db_query		*qi;
4567c478bd9Sstevel@tonic-gate 	nis_object		*oldObj = 0;
457*8d0852b7SRichard Lowe 	const char		*myself = "db_mindex::updateTableEntry";
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	if (table == 0 || e == 0)
4607c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	qi = extract_index_values_from_object(e);
4637c478bd9Sstevel@tonic-gate 	if (qi == 0) {
4647c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR,
4657c478bd9Sstevel@tonic-gate 				"%s: Out of memory for query index",
4667c478bd9Sstevel@tonic-gate 				myself);
4677c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	dbie = satisfy_query(qi, &count, &valid, FALSE);
4717c478bd9Sstevel@tonic-gate 	if (dbie != 0 && (count != 1 || !valid)) {
4727c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_INFO,
4737c478bd9Sstevel@tonic-gate 			"%s: count=%d, valid=%s",
4747c478bd9Sstevel@tonic-gate 			myself, count, valid ? "TRUE" : "FALSE");
4757c478bd9Sstevel@tonic-gate 		delete qi;
4767c478bd9Sstevel@tonic-gate 		return (LDAP_OPERATIONS_ERROR);
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	/*
4807c478bd9Sstevel@tonic-gate 	 * Need a copy of the old object in order to log a removal
4817c478bd9Sstevel@tonic-gate 	 * (this is true even if we're modifying an existing entry).
4827c478bd9Sstevel@tonic-gate 	 */
4837c478bd9Sstevel@tonic-gate 	if (dbie != 0) {
4847c478bd9Sstevel@tonic-gate 		oldObj = unmakePseudoEntryObj(
4857c478bd9Sstevel@tonic-gate 				table->get_entry(dbie->getlocation()), tobj);
4867c478bd9Sstevel@tonic-gate 		if (oldObj == 0) {
4877c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
4887c478bd9Sstevel@tonic-gate 	"%s: Error getting object from old pseudo-entry for \"%s\" in \"%s\"",
4897c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
4907c478bd9Sstevel@tonic-gate 					NIL(tableName));
4917c478bd9Sstevel@tonic-gate 			delete qi;
4927c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
4937c478bd9Sstevel@tonic-gate 		}
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (replace) {
4977c478bd9Sstevel@tonic-gate 		/* Need the object from the entry */
4987c478bd9Sstevel@tonic-gate 		if (dbie != 0 && obj == 0) {
4997c478bd9Sstevel@tonic-gate 			obj = unmakePseudoEntryObj(e, tobj);
5007c478bd9Sstevel@tonic-gate 			if (obj == 0) {
5017c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
5027c478bd9Sstevel@tonic-gate 	"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
5037c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
5047c478bd9Sstevel@tonic-gate 					NIL(tableName));
5057c478bd9Sstevel@tonic-gate 				delete qi;
5067c478bd9Sstevel@tonic-gate 				nis_destroy_object(oldObj);
5077c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
5087c478bd9Sstevel@tonic-gate 			}
5097c478bd9Sstevel@tonic-gate 			freeObj = 1;
5107c478bd9Sstevel@tonic-gate 		}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		/* Is the new object a dup of the old ? */
5137c478bd9Sstevel@tonic-gate 		if (dbie != 0 && sameNisPlusObj(oldObj, obj)) {
5147c478bd9Sstevel@tonic-gate 			/* Yes, it's a dup, so just update the timestamp */
5157c478bd9Sstevel@tonic-gate 			table->touchEntry(dbie->getlocation());
5167c478bd9Sstevel@tonic-gate 			delete qi;
5177c478bd9Sstevel@tonic-gate 			if (freeObj)
5187c478bd9Sstevel@tonic-gate 				nis_destroy_object(obj);
5197c478bd9Sstevel@tonic-gate 			nis_destroy_object(oldObj);
5207c478bd9Sstevel@tonic-gate 			return (LDAP_COMPARE_TRUE);
5217c478bd9Sstevel@tonic-gate 		} else {
5227c478bd9Sstevel@tonic-gate 			/*
5237c478bd9Sstevel@tonic-gate 			 * Not a dup, so go ahead and add it. Provided
5247c478bd9Sstevel@tonic-gate 			 * that 'qi' isn't NULL (which we've already
5257c478bd9Sstevel@tonic-gate 			 * checked), DB_ADD(_NOSYNC) does the right
5267c478bd9Sstevel@tonic-gate 			 * thing even if matching entries already
5277c478bd9Sstevel@tonic-gate 			 * exist.
5287c478bd9Sstevel@tonic-gate 			 */
5297c478bd9Sstevel@tonic-gate 			dbres = ((db *)dbptr.ptr)->log_action(DB_ADD_NOSYNC,
5307c478bd9Sstevel@tonic-gate 								qi, e);
5317c478bd9Sstevel@tonic-gate 			if (dbres == 0)
5327c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
5337c478bd9Sstevel@tonic-gate 			else if (dbres->status == DB_SUCCESS)
5347c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
5357c478bd9Sstevel@tonic-gate 			else
5367c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
5377c478bd9Sstevel@tonic-gate 			db_free_result(dbres);
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 	} else {	/* Removing */
5407c478bd9Sstevel@tonic-gate 		/* If the object doesn't exist, we're done */
5417c478bd9Sstevel@tonic-gate 		if (dbie == 0) {
5427c478bd9Sstevel@tonic-gate 			delete qi;
5437c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		dbres = ((db *)dbptr.ptr)->log_action(DB_REMOVE_NOSYNC, qi, 0);
5477c478bd9Sstevel@tonic-gate 		if (dbres == 0)
5487c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
5497c478bd9Sstevel@tonic-gate 		else if (dbres->status == DB_SUCCESS)
5507c478bd9Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
5517c478bd9Sstevel@tonic-gate 		else
5527c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
5537c478bd9Sstevel@tonic-gate 		db_free_result(dbres);
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	/* Log the operation */
5577c478bd9Sstevel@tonic-gate 	if (stat == LDAP_SUCCESS) {
5587c478bd9Sstevel@tonic-gate 		int		ret, numAttrs;
5597c478bd9Sstevel@tonic-gate 		nis_attr	*attr, attrbuf[NIS_MAXCOLUMNS];
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		/* If we haven't begun the transaction yet, do so now */
5627c478bd9Sstevel@tonic-gate 		if (*xid == 0) {
5637c478bd9Sstevel@tonic-gate 			*xid = beginTransaction();
5647c478bd9Sstevel@tonic-gate 			if (*xid == 0) {
5657c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
5667c478bd9Sstevel@tonic-gate 				"%s: Error starting transaction for \"%s\"",
5677c478bd9Sstevel@tonic-gate 					myself, NIL(tableName));
5687c478bd9Sstevel@tonic-gate 				delete qi;
5697c478bd9Sstevel@tonic-gate 				if (oldObj != 0)
5707c478bd9Sstevel@tonic-gate 					nis_destroy_object(oldObj);
5717c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
5727c478bd9Sstevel@tonic-gate 			}
5737c478bd9Sstevel@tonic-gate 		}
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 		if (replace && obj == 0) {
5767c478bd9Sstevel@tonic-gate 			obj = unmakePseudoEntryObj(e, tobj);
5777c478bd9Sstevel@tonic-gate 			if (obj == 0) {
5787c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
5797c478bd9Sstevel@tonic-gate 	"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
5807c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
5817c478bd9Sstevel@tonic-gate 					NIL(tableName));
5827c478bd9Sstevel@tonic-gate 				delete qi;
5837c478bd9Sstevel@tonic-gate 				if (oldObj != 0)
5847c478bd9Sstevel@tonic-gate 					nis_destroy_object(oldObj);
5857c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
5867c478bd9Sstevel@tonic-gate 			}
5877c478bd9Sstevel@tonic-gate 			freeObj = 1;
5887c478bd9Sstevel@tonic-gate 		}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 		/*
5917c478bd9Sstevel@tonic-gate 		 * The log stores nis_attr information, so we need to
5927c478bd9Sstevel@tonic-gate 		 * convert the scheme-query to a nis_attr array.
5937c478bd9Sstevel@tonic-gate 		 */
5947c478bd9Sstevel@tonic-gate 		attr = schemeQuery2nisAttr(qi, attrbuf, scheme,
5957c478bd9Sstevel@tonic-gate 				table->mapping.tm, &numAttrs);
5967c478bd9Sstevel@tonic-gate 		if (attr == 0) {
5977c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
5987c478bd9Sstevel@tonic-gate 	"%s: Error converting index query to nis_attr for \"%s\" in \"%s\"",
5997c478bd9Sstevel@tonic-gate 				myself, NIL(obj->zo_name), NIL(tableName));
6007c478bd9Sstevel@tonic-gate 			if (freeObj)
6017c478bd9Sstevel@tonic-gate 				nis_destroy_object(obj);
6027c478bd9Sstevel@tonic-gate 			if (oldObj != 0)
6037c478bd9Sstevel@tonic-gate 				nis_destroy_object(oldObj);
6047c478bd9Sstevel@tonic-gate 			delete qi;
6057c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
6067c478bd9Sstevel@tonic-gate 		}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 		if (replace) {
6097c478bd9Sstevel@tonic-gate 			/*
6107c478bd9Sstevel@tonic-gate 			 * While the DB can handle a modify (replace)
6117c478bd9Sstevel@tonic-gate 			 * operation, the trans log stores this as a
6127c478bd9Sstevel@tonic-gate 			 * remove followed by an add (which allows
6137c478bd9Sstevel@tonic-gate 			 * backing out the change by removing the new
6147c478bd9Sstevel@tonic-gate 			 * object incarnation, and adding the old one).
6157c478bd9Sstevel@tonic-gate 			 */
6167c478bd9Sstevel@tonic-gate 			if (oldObj != 0)
6177c478bd9Sstevel@tonic-gate 				ret = addUpdate(REM_IBASE, tableName,
6187c478bd9Sstevel@tonic-gate 					numAttrs, attr, oldObj, 0, ttime);
6197c478bd9Sstevel@tonic-gate 			else
6207c478bd9Sstevel@tonic-gate 				ret = 0;
6217c478bd9Sstevel@tonic-gate 			if (ret == 0)
6227c478bd9Sstevel@tonic-gate 				ret = addUpdate(ADD_IBASE, tableName,
6237c478bd9Sstevel@tonic-gate 					numAttrs, attr, obj, 0, ttime);
6247c478bd9Sstevel@tonic-gate 		} else {	/* Removal */
6257c478bd9Sstevel@tonic-gate 			ret = addUpdate(REM_IBASE, tableName, numAttrs, attr,
6267c478bd9Sstevel@tonic-gate 					oldObj, 0, ttime);
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 		if (ret != 0) {
6297c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
6307c478bd9Sstevel@tonic-gate 		"%s: Error adding trans log entry for \"%s\" in \"%s\"",
6317c478bd9Sstevel@tonic-gate 				myself, NIL(obj->zo_name), NIL(tableName));
6327c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
6337c478bd9Sstevel@tonic-gate 		}
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	delete qi;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	if (oldObj != 0)
6397c478bd9Sstevel@tonic-gate 		nis_destroy_object(oldObj);
6407c478bd9Sstevel@tonic-gate 	if (freeObj)
6417c478bd9Sstevel@tonic-gate 		nis_destroy_object(obj);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	return (stat);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate bool_t
touchEntry(entry_object * e)6477c478bd9Sstevel@tonic-gate db_mindex::touchEntry(entry_object *e) {
6487c478bd9Sstevel@tonic-gate 	db_query		*qi;
6497c478bd9Sstevel@tonic-gate 	bool_t			ret;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	if (table == 0 || e == 0)
6527c478bd9Sstevel@tonic-gate 		return (FALSE);
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	qi = extract_index_values_from_object(e);
6557c478bd9Sstevel@tonic-gate 	if (qi == 0)
6567c478bd9Sstevel@tonic-gate 		return (FALSE);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	ret = touchEntry(qi);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	delete qi;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	return (ret);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate bool_t
touchEntry(db_query * q)6667c478bd9Sstevel@tonic-gate db_mindex::touchEntry(db_query *q) {
6677c478bd9Sstevel@tonic-gate 	db_index_entry		*dbie;
6687c478bd9Sstevel@tonic-gate 	long			count;
6697c478bd9Sstevel@tonic-gate 	bool_t			valid;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	dbie = satisfy_query(q, &count, &valid, FALSE);
6727c478bd9Sstevel@tonic-gate 	if (dbie != 0 && count == 1 && valid)
6737c478bd9Sstevel@tonic-gate 		table->touchEntry(dbie->getlocation());
6747c478bd9Sstevel@tonic-gate 	else
6757c478bd9Sstevel@tonic-gate 		return (FALSE);
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	return (TRUE);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * Compose an object name from column zero of 'e' and 't->objName',
6827c478bd9Sstevel@tonic-gate  * and return the mapping for that object, if any. Also set '*name'
6837c478bd9Sstevel@tonic-gate  * to point to the dir entry name in 'e'. Note that this is a pointer
6847c478bd9Sstevel@tonic-gate  * to existing data, and shouldn't be freed other than as part of
6857c478bd9Sstevel@tonic-gate  * freeing 'e'.
6867c478bd9Sstevel@tonic-gate  */
6877c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
findDirEntryMapping(__nis_table_mapping_t * t,entry_object * e,char ** name)6887c478bd9Sstevel@tonic-gate findDirEntryMapping(__nis_table_mapping_t *t, entry_object *e, char **name) {
6897c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*x;
6907c478bd9Sstevel@tonic-gate 	char			*entryName;
691*8d0852b7SRichard Lowe 	const char		*myself = "findDirEntryMapping";
6927c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (e == 0 || e->en_cols.en_cols_len != 2 ||
6957c478bd9Sstevel@tonic-gate 			e->en_cols.en_cols_val == 0)
6967c478bd9Sstevel@tonic-gate 		return (0);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	entryName = e->en_cols.en_cols_val[1].ec_value.ec_value_val;
6997c478bd9Sstevel@tonic-gate 	if (name != 0)
7007c478bd9Sstevel@tonic-gate 		*name = entryName;
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	if (t == 0 || entryName == 0 || t->objName == 0)
7037c478bd9Sstevel@tonic-gate 		return (0);
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	bp2buf(myself, &b, "%s.%s", entryName, t->objName);
7067c478bd9Sstevel@tonic-gate 	if (b.len == 0 || b.buf == 0)
7077c478bd9Sstevel@tonic-gate 		return (0);
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	x = (__nis_table_mapping_t *)__nis_find_item_mt(b.buf,
7107c478bd9Sstevel@tonic-gate 						&ldapMappingList, 0, 0);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	sfree(b.buf);
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	return (x);
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate  * Query LDAP per the supplied (scheme-) query 'qin'. If 'doAsynch' is
7197c478bd9Sstevel@tonic-gate  * set, and the query is an enumeration (qin == 0), the query will be
7207c478bd9Sstevel@tonic-gate  * performed in a detached thread, and complete asynchronously. In this
7217c478bd9Sstevel@tonic-gate  * case, the return status reflects the setup and launch of the
7227c478bd9Sstevel@tonic-gate  * detached thread; the query will complete asynchronously.
7237c478bd9Sstevel@tonic-gate  *
7247c478bd9Sstevel@tonic-gate  * Returns an appropriate LDAP status code.
7257c478bd9Sstevel@tonic-gate  */
7267c478bd9Sstevel@tonic-gate int
queryLDAP(db_query * qin,char * dbId,int doAsynch)7277c478bd9Sstevel@tonic-gate db_mindex::queryLDAP(db_query *qin, char *dbId, int doAsynch) {
7287c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
7297c478bd9Sstevel@tonic-gate 	int			i, na, nq = 0, stat, stat2, numAttrs, ret;
7307c478bd9Sstevel@tonic-gate 	int			xid = 0;
7317c478bd9Sstevel@tonic-gate 	long			numEa;
7327c478bd9Sstevel@tonic-gate 	bool_t			asObj, doEnum;
7337c478bd9Sstevel@tonic-gate 	db_query		*q;
7347c478bd9Sstevel@tonic-gate 	entry_object		**ea;
7357c478bd9Sstevel@tonic-gate 	nis_attr		attr;
7367c478bd9Sstevel@tonic-gate 	nis_object		*dirObj;
7377c478bd9Sstevel@tonic-gate 	db_status		dstat;
738*8d0852b7SRichard Lowe 	const char		*myself = "db_mindex::queryLDAP";
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
7417c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	/*
7447c478bd9Sstevel@tonic-gate 	 * Instances from the deferred dictionary shouldn't change,
7457c478bd9Sstevel@tonic-gate 	 * there's no point in querying LDAP.
7467c478bd9Sstevel@tonic-gate 	 */
7477c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
7487c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, FALSE, &asObj, &stat);
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	if (t == 0)
7537c478bd9Sstevel@tonic-gate 		return (stat);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
7567c478bd9Sstevel@tonic-gate 	printf("%s: %s (%s)\n",
7577c478bd9Sstevel@tonic-gate 		myself, NIL(t->objName), (asObj ? "object" : "entry"));
7587c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if (qin != NULL) {
7617c478bd9Sstevel@tonic-gate 		q = schemeQuery2Query(qin, scheme);
7627c478bd9Sstevel@tonic-gate 		if (q == 0)
7637c478bd9Sstevel@tonic-gate 			return (LDAP_PARAM_ERROR);
7647c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
7657c478bd9Sstevel@tonic-gate 		q->print();
7667c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
7677c478bd9Sstevel@tonic-gate 	} else {
7687c478bd9Sstevel@tonic-gate 		q = 0;
7697c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
7707c478bd9Sstevel@tonic-gate 		printf("\tenumerating %s%s%s\n",
7717c478bd9Sstevel@tonic-gate 			dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
7727c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
7737c478bd9Sstevel@tonic-gate 	}
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	/*
7767c478bd9Sstevel@tonic-gate 	 * Do we have any active mappings for this particular query and
7777c478bd9Sstevel@tonic-gate 	 * dbId ?  If not, we're done.
7787c478bd9Sstevel@tonic-gate 	 *
7797c478bd9Sstevel@tonic-gate 	 * Note that we don't care about the return value from
7807c478bd9Sstevel@tonic-gate 	 * selectTableMapping(), just wheter or not there are
7817c478bd9Sstevel@tonic-gate 	 * any valid mappings.
7827c478bd9Sstevel@tonic-gate 	 */
7837c478bd9Sstevel@tonic-gate 	i = 0;
7847c478bd9Sstevel@tonic-gate 	sfree(selectTableMapping(t, q, 0, asObj, dbId, &i));
7857c478bd9Sstevel@tonic-gate 	if (i <= 0) {
7867c478bd9Sstevel@tonic-gate 		freeQuery(q);
7877c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
7887c478bd9Sstevel@tonic-gate 	}
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	/* Is the object a directory ? */
7917c478bd9Sstevel@tonic-gate 	if (asObj) {
7927c478bd9Sstevel@tonic-gate 		nis_object	*o;
7937c478bd9Sstevel@tonic-gate 		entry_object	*e, eo;
7947c478bd9Sstevel@tonic-gate 		entry_col	ec[2];
7957c478bd9Sstevel@tonic-gate 		int		nea;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 		stat = objFromLDAP(t, &o, &ea, &nea);
7987c478bd9Sstevel@tonic-gate 		numEa = nea;
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 		if (stat == LDAP_NO_SUCH_OBJECT) {
8017c478bd9Sstevel@tonic-gate 			/* Positive failure; remove the object */
8027c478bd9Sstevel@tonic-gate 			dstat = dbDeleteObj(t->objName);
8037c478bd9Sstevel@tonic-gate 			if (dstat == DB_SUCCESS || dstat == DB_NOTFOUND) {
8047c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
8057c478bd9Sstevel@tonic-gate 			} else {
8067c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
8077c478bd9Sstevel@tonic-gate 					"%s: DB error %d deleting \"%s\"",
8087c478bd9Sstevel@tonic-gate 					myself, dstat, NIL(t->objName));
8097c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
8107c478bd9Sstevel@tonic-gate 			}
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 			freeQuery(q);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 			return (stat);
8157c478bd9Sstevel@tonic-gate 		} else if (stat != LDAP_SUCCESS) {
8167c478bd9Sstevel@tonic-gate 			freeQuery(q);
8177c478bd9Sstevel@tonic-gate 			return (stat);
8187c478bd9Sstevel@tonic-gate 		} else if (o == 0) {
8197c478bd9Sstevel@tonic-gate 			/* OK; this entry just isn't mapped */
8207c478bd9Sstevel@tonic-gate 			freeQuery(q);
8217c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
8227c478bd9Sstevel@tonic-gate 		}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 		if (q != 0) {
8257c478bd9Sstevel@tonic-gate 			/*
8267c478bd9Sstevel@tonic-gate 			 * We're updating one particular entry (described
8277c478bd9Sstevel@tonic-gate 			 * by 't') in the directory 'table->mapping.tm'.
8287c478bd9Sstevel@tonic-gate 			 */
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 			setOid(o);
8317c478bd9Sstevel@tonic-gate 			dstat = dbRefreshObj(t->objName, o);
8327c478bd9Sstevel@tonic-gate 			if (dstat == DB_SUCCESS) {
8337c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
8347c478bd9Sstevel@tonic-gate 			} else {
8357c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
8367c478bd9Sstevel@tonic-gate 			"%s: DB error %d updating \"%s\" in \"%s\"",
8377c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName),
8387c478bd9Sstevel@tonic-gate 					NIL(table->mapping.tm->objName));
8397c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
8407c478bd9Sstevel@tonic-gate 			}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 			freeEntryObjArray(ea, numEa);
8437c478bd9Sstevel@tonic-gate 			freeQuery(q);
8447c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 			return (stat);
8477c478bd9Sstevel@tonic-gate 		}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 		dirObj = o;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 		/*
8527c478bd9Sstevel@tonic-gate 		 * q == 0, so we're enumerating. Update the list of
8537c478bd9Sstevel@tonic-gate 		 * directory entries.
8547c478bd9Sstevel@tonic-gate 		 */
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 		/*
8577c478bd9Sstevel@tonic-gate 		 * Need to disable write-through to LDAP, for which we need
8587c478bd9Sstevel@tonic-gate 		 * a lock on our db_mindex ('this'); we're also updating the
8597c478bd9Sstevel@tonic-gate 		 * table, so we need a write lock on that as well.
8607c478bd9Sstevel@tonic-gate 		 */
8617c478bd9Sstevel@tonic-gate 		WRITELOCKNR(this, stat, "w db_mindex::queryLDAP");
8627c478bd9Sstevel@tonic-gate 		if (stat == 0) {
8637c478bd9Sstevel@tonic-gate 			WRITELOCKNR(table, stat2,
8647c478bd9Sstevel@tonic-gate 				"table w db_mindex::queryLDAP");
8657c478bd9Sstevel@tonic-gate 		}
8667c478bd9Sstevel@tonic-gate 		if (stat != 0 || stat2 != 0) {
8677c478bd9Sstevel@tonic-gate 			nis_destroy_object(dirObj);
8687c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
8697c478bd9Sstevel@tonic-gate 				"%s: lock error %d", myself,
8707c478bd9Sstevel@tonic-gate 				stat != 0 ? stat : stat2);
8717c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
8727c478bd9Sstevel@tonic-gate 		}
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 		setNoWriteThrough();
8757c478bd9Sstevel@tonic-gate 		setNoLDAPquery();
8767c478bd9Sstevel@tonic-gate 		table->setEnumMode(0);
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 		for (i = 0, na = 0; i < numEa; i++) {
8797c478bd9Sstevel@tonic-gate 			int			st;
8807c478bd9Sstevel@tonic-gate 			__nis_table_mapping_t	*x;
8817c478bd9Sstevel@tonic-gate 			char			*name = 0;
8827c478bd9Sstevel@tonic-gate 			entry_obj		*e;
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 			if (ea[i] == 0)
8857c478bd9Sstevel@tonic-gate 				continue;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 			/*
8887c478bd9Sstevel@tonic-gate 			 * We've got a list of dir entries. In the general,
8897c478bd9Sstevel@tonic-gate 			 * case, some are new, and some already exist.
8907c478bd9Sstevel@tonic-gate 			 * We definitely want to add the new ones, and to
8917c478bd9Sstevel@tonic-gate 			 * that end, we need a copy of the object for the
8927c478bd9Sstevel@tonic-gate 			 * entry. By definition, if an entry is new, we
8937c478bd9Sstevel@tonic-gate 			 * don't yet have a copy of the object for it, so
8947c478bd9Sstevel@tonic-gate 			 * it's LDAP or nothing.
8957c478bd9Sstevel@tonic-gate 			 *
8967c478bd9Sstevel@tonic-gate 			 * If the entry already exists, try to update the
8977c478bd9Sstevel@tonic-gate 			 * entry object. In this case, we again only need
8987c478bd9Sstevel@tonic-gate 			 * to look in LDAP for the object; if there already
8997c478bd9Sstevel@tonic-gate 			 * is one in the DB, it's in the dir entry which we
9007c478bd9Sstevel@tonic-gate 			 * want to update.
9017c478bd9Sstevel@tonic-gate 			 *
9027c478bd9Sstevel@tonic-gate 			 * So, whether adding or replacing, try to get the
9037c478bd9Sstevel@tonic-gate 			 * object from LDAP.
9047c478bd9Sstevel@tonic-gate 			 *
9057c478bd9Sstevel@tonic-gate 			 * If we can't get a copy of the object, there's not
9067c478bd9Sstevel@tonic-gate 			 * much point in adding or updating (since a dir
9077c478bd9Sstevel@tonic-gate 			 * entry just consists of the entry object and name),
9087c478bd9Sstevel@tonic-gate 			 * so we continue to the next entry.
9097c478bd9Sstevel@tonic-gate 			 *
9107c478bd9Sstevel@tonic-gate 			 * However, in that case, we do need to touch the
9117c478bd9Sstevel@tonic-gate 			 * dir entry; otherwise, it will be removed later
9127c478bd9Sstevel@tonic-gate 			 * on.
9137c478bd9Sstevel@tonic-gate 			 */
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 			x = findDirEntryMapping(t, ea[i], &name);
9167c478bd9Sstevel@tonic-gate 			o = 0;
9177c478bd9Sstevel@tonic-gate 			if (x == 0 || (st = objFromLDAP(x, &o, 0, 0)) !=
9187c478bd9Sstevel@tonic-gate 					LDAP_SUCCESS) {
9197c478bd9Sstevel@tonic-gate 				if (x != 0)
9207c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9217c478bd9Sstevel@tonic-gate 			"%s: Unable to obtain object for \"%s\" in \"%s\": %s",
9227c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName),
9237c478bd9Sstevel@tonic-gate 						ldap_err2string(st));
9247c478bd9Sstevel@tonic-gate 				if (o != 0)
9257c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
9267c478bd9Sstevel@tonic-gate 				if (!touchEntry(ea[i])) {
9277c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9287c478bd9Sstevel@tonic-gate 			"%s: Inconsistency: LDAP-derived directory \"%s\" "
9297c478bd9Sstevel@tonic-gate 			"contains entry \"%s\", which is unknown locally, "
9307c478bd9Sstevel@tonic-gate 			"and has no LDAP mapping",
9317c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName),
9327c478bd9Sstevel@tonic-gate 						NIL(name));
9337c478bd9Sstevel@tonic-gate 				}
9347c478bd9Sstevel@tonic-gate 				continue;
9357c478bd9Sstevel@tonic-gate 			}
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 			if (ea[i]->en_cols.en_cols_len != 2 ||
9387c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val == 0 ||
9397c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val[0].
9407c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val != 0 ||
9417c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val[0].
9427c478bd9Sstevel@tonic-gate 					ec_value.ec_value_len != 0) {
9437c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9447c478bd9Sstevel@tonic-gate 			"%s: Illegal entry_obj col 0 for \"%s\" in \"%s\"",
9457c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName));
9467c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
9477c478bd9Sstevel@tonic-gate 				touchEntry(ea[i]);
9487c478bd9Sstevel@tonic-gate 				continue;
9497c478bd9Sstevel@tonic-gate 			}
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 			setOid(o);
9527c478bd9Sstevel@tonic-gate 			e = makePseudoEntryObj(o, ea[i], 0);
9537c478bd9Sstevel@tonic-gate 			if (e == 0) {
9547c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9557c478bd9Sstevel@tonic-gate 	"%s: Unable to create pseudo entry object for \"%s\" in \"%s\"",
9567c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName));
9577c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
9587c478bd9Sstevel@tonic-gate 				touchEntry(ea[i]);
9597c478bd9Sstevel@tonic-gate 				continue;
9607c478bd9Sstevel@tonic-gate 			}
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 			st = updateTableEntry(e, 1, t->objName, o, 0,
9637c478bd9Sstevel@tonic-gate 						o->zo_oid.mtime, &xid);
9647c478bd9Sstevel@tonic-gate 			if (st == LDAP_SUCCESS) {
9657c478bd9Sstevel@tonic-gate 				na++;
9667c478bd9Sstevel@tonic-gate 			} else if (st == LDAP_COMPARE_TRUE) {
9677c478bd9Sstevel@tonic-gate 				/* OK, same as existing entry */
9687c478bd9Sstevel@tonic-gate 				st = LDAP_SUCCESS;
9697c478bd9Sstevel@tonic-gate 			} else {
9707c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
9717c478bd9Sstevel@tonic-gate 		"%s: Error updating directory entry for \"%s\" in \"%s\": %s",
9727c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName),
9737c478bd9Sstevel@tonic-gate 					ldap_err2string(st));
9747c478bd9Sstevel@tonic-gate 				if (stat == LDAP_SUCCESS)
9757c478bd9Sstevel@tonic-gate 					stat = st;
9767c478bd9Sstevel@tonic-gate 			}
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 			/* Free the XDR buffer */
9797c478bd9Sstevel@tonic-gate 			sfree(e->en_cols.en_cols_val[0].
9807c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val);
9817c478bd9Sstevel@tonic-gate 			/* Restore ea[i] */
9827c478bd9Sstevel@tonic-gate 			ea[i]->en_cols.en_cols_val[0].
9837c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val = 0;
9847c478bd9Sstevel@tonic-gate 			ea[i]->en_cols.en_cols_val[0].
9857c478bd9Sstevel@tonic-gate 					ec_value.ec_value_len = 0;
9867c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
9877c478bd9Sstevel@tonic-gate 		}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 		freeEntryObjArray(ea, numEa);
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 		/* Get list of entries to remove */
9927c478bd9Sstevel@tonic-gate 		ea = table->endEnumMode(&numEa);
9937c478bd9Sstevel@tonic-gate 		if (ea != 0) {
9947c478bd9Sstevel@tonic-gate 			uint32_t	nowt = time(0);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 			for (i = 0; i < numEa; i++) {
9977c478bd9Sstevel@tonic-gate 				int	st;
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 				if (ea[i] == 0)
10007c478bd9Sstevel@tonic-gate 					continue;
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 				st = updateTableEntry(ea[i], 0, t->objName, 0,
10037c478bd9Sstevel@tonic-gate 							0, nowt, &xid);
10047c478bd9Sstevel@tonic-gate 				if (st == LDAP_SUCCESS) {
10057c478bd9Sstevel@tonic-gate 					na++;
10067c478bd9Sstevel@tonic-gate 				} else {
10077c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
10087c478bd9Sstevel@tonic-gate 			"%s: Error removing directory entry for \"%s\": %s",
10097c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName),
10107c478bd9Sstevel@tonic-gate 						ldap_err2string(st));
10117c478bd9Sstevel@tonic-gate 					if (stat == LDAP_SUCCESS)
10127c478bd9Sstevel@tonic-gate 						stat = st;
10137c478bd9Sstevel@tonic-gate 				}
10147c478bd9Sstevel@tonic-gate 			}
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 		if (stat == LDAP_SUCCESS) {
10187c478bd9Sstevel@tonic-gate 			struct timeval	now;
10197c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&now, 0);
10207c478bd9Sstevel@tonic-gate 			table->mapping.enumExpire = now.tv_sec +
10217c478bd9Sstevel@tonic-gate 				table->mapping.ttl;
10227c478bd9Sstevel@tonic-gate 		}
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 		if (na > 0)
10257c478bd9Sstevel@tonic-gate 			(void) ((db *)dbptr.ptr)->sync_log();
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 		if (xid != 0 && na > 0 && stat == LDAP_SUCCESS) {
10287c478bd9Sstevel@tonic-gate 			ret = endTransaction(xid, dirObj);
10297c478bd9Sstevel@tonic-gate 			if (ret != 0) {
10307c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
10317c478bd9Sstevel@tonic-gate 				"%s: Error ending transaction for \"%s\"",
10327c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
10337c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
10347c478bd9Sstevel@tonic-gate 			}
10357c478bd9Sstevel@tonic-gate 		} else if (xid != 0) {
10367c478bd9Sstevel@tonic-gate 			ret = abort_transaction(xid);
10377c478bd9Sstevel@tonic-gate 			if (ret != 0) {
10387c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
10397c478bd9Sstevel@tonic-gate 				"%s: Error aborting transaction for \"%s\"",
10407c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
10417c478bd9Sstevel@tonic-gate 			}
10427c478bd9Sstevel@tonic-gate 		}
10437c478bd9Sstevel@tonic-gate 		nis_destroy_object(dirObj);
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 		sfree(ea);
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		clearNoLDAPquery();
10487c478bd9Sstevel@tonic-gate 		clearNoWriteThrough();
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 		WRITEUNLOCK2(table, this,
10517c478bd9Sstevel@tonic-gate 			stat, stat,
10527c478bd9Sstevel@tonic-gate 			"table wu db_mindex::queryLDAP",
10537c478bd9Sstevel@tonic-gate 			"wu db_mindex::queryLDAP");
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 		return (stat);
10567c478bd9Sstevel@tonic-gate 	}
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	/*
10597c478bd9Sstevel@tonic-gate 	 * In order to ping replicas, if any, we need to find the
10607c478bd9Sstevel@tonic-gate 	 * directory containing the table to be updated. If we
10617c478bd9Sstevel@tonic-gate 	 * can't find the directory object, we're sunk, so let's
10627c478bd9Sstevel@tonic-gate 	 * start with that.
10637c478bd9Sstevel@tonic-gate 	 */
10647c478bd9Sstevel@tonic-gate 	if (t->isMaster) {
10657c478bd9Sstevel@tonic-gate 		dirObj = findObj(t->obj->zo_domain, &dstat, &stat);
10667c478bd9Sstevel@tonic-gate 		if (dirObj == 0) {
10677c478bd9Sstevel@tonic-gate 			if (stat == LDAP_SUCCESS)
10687c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
10697c478bd9Sstevel@tonic-gate 			return (stat);
10707c478bd9Sstevel@tonic-gate 		}
10717c478bd9Sstevel@tonic-gate 	} else {
10727c478bd9Sstevel@tonic-gate 		dirObj = 0;
10737c478bd9Sstevel@tonic-gate 	}
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 	stat = entriesFromLDAP(t, qin, q, dbId, dirObj, doAsynch);
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	return (stat);
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate extern db	*tableDB(char *);
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate /*
10837c478bd9Sstevel@tonic-gate  * Remove the LDAP entry/entries corresponding to 'qin'/'obj'.
10847c478bd9Sstevel@tonic-gate  */
10857c478bd9Sstevel@tonic-gate int
removeLDAP(db_query * qin,nis_object * obj)10867c478bd9Sstevel@tonic-gate db_mindex::removeLDAP(db_query *qin, nis_object *obj) {
10877c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
10887c478bd9Sstevel@tonic-gate 	db_query		*q;
10897c478bd9Sstevel@tonic-gate 	bool_t			asObj;
10907c478bd9Sstevel@tonic-gate 	int			stat;
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
10937c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	/* Instances from the deferred dictionary should not update LDAP */
10967c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
10977c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
11007c478bd9Sstevel@tonic-gate 	if (t == 0 && stat != LDAP_SUCCESS)
11017c478bd9Sstevel@tonic-gate 		return (stat);
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
11047c478bd9Sstevel@tonic-gate 	if (t != 0)
11057c478bd9Sstevel@tonic-gate 		printf("removeLDAP: %s\n", NIL(t->objName));
11067c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 	if (qin != NULL) {
11097c478bd9Sstevel@tonic-gate 		if (asObj) {
11107c478bd9Sstevel@tonic-gate 			/*
11117c478bd9Sstevel@tonic-gate 			 * selectMapping() gave us the mapping for the
11127c478bd9Sstevel@tonic-gate 			 * directory entry. However, if 't' is NULL, this
11137c478bd9Sstevel@tonic-gate 			 * could be due to the directory itself not being
11147c478bd9Sstevel@tonic-gate 			 * mapped, in which case we must obtain the mapping
11157c478bd9Sstevel@tonic-gate 			 * info from 'obj'.
11167c478bd9Sstevel@tonic-gate 			 */
11177c478bd9Sstevel@tonic-gate 			if (t == 0) {
11187c478bd9Sstevel@tonic-gate 				t = selectMapping(0, obj, 0, TRUE, &asObj,
11197c478bd9Sstevel@tonic-gate 						&stat);
11207c478bd9Sstevel@tonic-gate 				if (t == 0 && stat != LDAP_SUCCESS)
11217c478bd9Sstevel@tonic-gate 					return (stat);
11227c478bd9Sstevel@tonic-gate 			}
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 			if (t != 0) {
11257c478bd9Sstevel@tonic-gate 				stat = deleteLDAPobj(t);
11267c478bd9Sstevel@tonic-gate 				/*
11277c478bd9Sstevel@tonic-gate 				 * If we were successful, update the object
11287c478bd9Sstevel@tonic-gate 				 * stored with the mapping.
11297c478bd9Sstevel@tonic-gate 				 */
11307c478bd9Sstevel@tonic-gate 				if (stat == LDAP_SUCCESS)
11317c478bd9Sstevel@tonic-gate 					(void) replaceMappingObj(t, 0);
11327c478bd9Sstevel@tonic-gate 				else
11337c478bd9Sstevel@tonic-gate 					return (stat);
11347c478bd9Sstevel@tonic-gate 			}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 			/*
11377c478bd9Sstevel@tonic-gate 			 * Since it's a directory entry we've removed, we also
11387c478bd9Sstevel@tonic-gate 			 * need to update the directory object itself.
11397c478bd9Sstevel@tonic-gate 			 */
11407c478bd9Sstevel@tonic-gate 			stat = storeLDAP(0, 0, 0, 0, 0);
11417c478bd9Sstevel@tonic-gate 		} else {
11427c478bd9Sstevel@tonic-gate 			q = schemeQuery2Query(qin, scheme);
11437c478bd9Sstevel@tonic-gate 			if (q == 0)
11447c478bd9Sstevel@tonic-gate 				return (LDAP_PARAM_ERROR);
11457c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
11467c478bd9Sstevel@tonic-gate 			q->print();
11477c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
11487c478bd9Sstevel@tonic-gate 			stat = mapToLDAP(t, 1, &q, 0, 0, 0, 0);
11497c478bd9Sstevel@tonic-gate 			freeQuery(q);
11507c478bd9Sstevel@tonic-gate 		}
11517c478bd9Sstevel@tonic-gate 	} else {
11527c478bd9Sstevel@tonic-gate 		/*
11537c478bd9Sstevel@tonic-gate 		 * This isn't the way to remove the LDAP entries
11547c478bd9Sstevel@tonic-gate 		 * corresponding to the entire table.
11557c478bd9Sstevel@tonic-gate 		 */
11567c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
11577c478bd9Sstevel@tonic-gate 		abort();
11587c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
11597c478bd9Sstevel@tonic-gate 		stat = LDAP_PARAM_ERROR;
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	return (stat);
11637c478bd9Sstevel@tonic-gate }
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate /*
11667c478bd9Sstevel@tonic-gate  * Helper function for storeLDAP() which handles updates for objects
11677c478bd9Sstevel@tonic-gate  * other than table entries.
11687c478bd9Sstevel@tonic-gate  */
11697c478bd9Sstevel@tonic-gate int
storeObjLDAP(__nis_table_mapping_t * t,nis_object * o)11707c478bd9Sstevel@tonic-gate db_mindex::storeObjLDAP(__nis_table_mapping_t *t, nis_object *o) {
11717c478bd9Sstevel@tonic-gate 	int		stat, assigned = 0;
11727c478bd9Sstevel@tonic-gate 	entry_object	**ea;
11737c478bd9Sstevel@tonic-gate 	int		numEa, doUnlock = 0;
11747c478bd9Sstevel@tonic-gate 	db		*dbase = 0;
11757c478bd9Sstevel@tonic-gate 	db_mindex	*dbm = 0;
1176*8d0852b7SRichard Lowe 	const char	*myself = "db_mindex::storeObjLDAP";
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	if (t == 0 || o == 0)
11797c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	/*
11827c478bd9Sstevel@tonic-gate 	 * If the object to be stored is anything other than a
11837c478bd9Sstevel@tonic-gate 	 * directory, we can just go ahead and write it to LDAP.
11847c478bd9Sstevel@tonic-gate 	 * A directory object, however, also needs a directory
11857c478bd9Sstevel@tonic-gate 	 * entry list, so we should to get hold of the db_table
11867c478bd9Sstevel@tonic-gate 	 * that goes with the directory.
11877c478bd9Sstevel@tonic-gate 	 */
11887c478bd9Sstevel@tonic-gate 	if (o->zo_data.zo_type == NIS_DIRECTORY_OBJ) {
11897c478bd9Sstevel@tonic-gate 		dbase = tableDB(t->objName);
11907c478bd9Sstevel@tonic-gate 		if (dbase != 0)
11917c478bd9Sstevel@tonic-gate 			dbm = dbase->mindex();
11927c478bd9Sstevel@tonic-gate 		if (dbase == 0 || dbm == 0 || dbm->table == 0) {
11937c478bd9Sstevel@tonic-gate 			/* By definition, no dir entries */
11947c478bd9Sstevel@tonic-gate 			ea = 0;
11957c478bd9Sstevel@tonic-gate 			numEa = 0;
11967c478bd9Sstevel@tonic-gate 			dbase = 0;
11977c478bd9Sstevel@tonic-gate 		} else {
11987c478bd9Sstevel@tonic-gate 			entry_object	**tea;
11997c478bd9Sstevel@tonic-gate 			long		i, ntea;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 			/*
12027c478bd9Sstevel@tonic-gate 			 * Read-lock the table so that 'tab'
12037c478bd9Sstevel@tonic-gate 			 * doesn't change while we're using it.
12047c478bd9Sstevel@tonic-gate 			 */
12057c478bd9Sstevel@tonic-gate 			READLOCK(dbm->table, LDAP_OPERATIONS_ERROR,
12067c478bd9Sstevel@tonic-gate 					"r table db_mindex::storeLDAP");
12077c478bd9Sstevel@tonic-gate 			doUnlock = 1;
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 			tea = dbm->table->gettab();
12107c478bd9Sstevel@tonic-gate 			ntea = dbm->table->getsize();
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 			/*
12137c478bd9Sstevel@tonic-gate 			 * There may be empty slots in the table 'tab'
12147c478bd9Sstevel@tonic-gate 			 * array, so get rid of those.
12157c478bd9Sstevel@tonic-gate 			 */
12167c478bd9Sstevel@tonic-gate 			if (tea != 0 && ntea > 0) {
12177c478bd9Sstevel@tonic-gate 				ea = (entry_object **)am(myself,
12187c478bd9Sstevel@tonic-gate 						ntea * sizeof (ea[0]));
12197c478bd9Sstevel@tonic-gate 				if (ea == 0) {
12207c478bd9Sstevel@tonic-gate 					READUNLOCK(dbm->table, LDAP_NO_MEMORY,
12217c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
12227c478bd9Sstevel@tonic-gate 					return (LDAP_NO_MEMORY);
12237c478bd9Sstevel@tonic-gate 				}
12247c478bd9Sstevel@tonic-gate 				for (i = 0, numEa = 0; i < ntea; i++) {
12257c478bd9Sstevel@tonic-gate 					if (tea[i] != 0) {
12267c478bd9Sstevel@tonic-gate 						ea[numEa] = tea[i];
12277c478bd9Sstevel@tonic-gate 						numEa++;
12287c478bd9Sstevel@tonic-gate 					}
12297c478bd9Sstevel@tonic-gate 				}
12307c478bd9Sstevel@tonic-gate 				if (numEa == 0) {
12317c478bd9Sstevel@tonic-gate 					/* No non-empty slots */
12327c478bd9Sstevel@tonic-gate 					sfree(ea);
12337c478bd9Sstevel@tonic-gate 					ea = 0;
12347c478bd9Sstevel@tonic-gate 					READUNLOCK(dbm->table,
12357c478bd9Sstevel@tonic-gate 						LDAP_OPERATIONS_ERROR,
12367c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
12377c478bd9Sstevel@tonic-gate 					doUnlock = 0;
12387c478bd9Sstevel@tonic-gate 				}
12397c478bd9Sstevel@tonic-gate 			} else {
12407c478bd9Sstevel@tonic-gate 				ea = 0;
12417c478bd9Sstevel@tonic-gate 				numEa = 0;
12427c478bd9Sstevel@tonic-gate 				READUNLOCK(dbm->table,
12437c478bd9Sstevel@tonic-gate 					LDAP_OPERATIONS_ERROR,
12447c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
12457c478bd9Sstevel@tonic-gate 				doUnlock = 0;
12467c478bd9Sstevel@tonic-gate 			}
12477c478bd9Sstevel@tonic-gate 		}
12487c478bd9Sstevel@tonic-gate 	} else {
12497c478bd9Sstevel@tonic-gate 		ea = 0;
12507c478bd9Sstevel@tonic-gate 		numEa = 0;
12517c478bd9Sstevel@tonic-gate 	}
12527c478bd9Sstevel@tonic-gate 
12537c478bd9Sstevel@tonic-gate 	stat = objToLDAP(t, o, ea, numEa);
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	if (ea != 0)
12567c478bd9Sstevel@tonic-gate 		sfree(ea);
12577c478bd9Sstevel@tonic-gate 	if (doUnlock) {
12587c478bd9Sstevel@tonic-gate 		READUNLOCK(dbm->table, stat,
12597c478bd9Sstevel@tonic-gate 				"ru table db_mindex::storeLDAP");
12607c478bd9Sstevel@tonic-gate 	}
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	return (stat);
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate /*
12677c478bd9Sstevel@tonic-gate  * Store data specified by the index-query 'qin' to LDAP. If 'obj' is
12687c478bd9Sstevel@tonic-gate  * non-null, it's a pointer to the pseudo-entry object corresponding to
12697c478bd9Sstevel@tonic-gate  * 'qin'. As a short-cut/convenience, the caller can instead supply
12707c478bd9Sstevel@tonic-gate  * the actual nis_object 'o'; if 'o' is NULL, it's derived from 'obj'.
12717c478bd9Sstevel@tonic-gate  *
12727c478bd9Sstevel@tonic-gate  * 'oldObj' is used for table entries if the store operation is
12737c478bd9Sstevel@tonic-gate  * an update, and the corresponding NIS+ operation was a delete followed
12747c478bd9Sstevel@tonic-gate  * by an add. In this case, oldObj contains the pre-delete incarnation of
12757c478bd9Sstevel@tonic-gate  * the entry object to be modified.
12767c478bd9Sstevel@tonic-gate  *
12777c478bd9Sstevel@tonic-gate  * The 'dbId' string is used to select one dbId for mapping chains
12787c478bd9Sstevel@tonic-gate  * that contain more than one.
12797c478bd9Sstevel@tonic-gate  *
12807c478bd9Sstevel@tonic-gate  * Returns an LDAP status code.
12817c478bd9Sstevel@tonic-gate  */
12827c478bd9Sstevel@tonic-gate int
storeLDAP(db_query * qin,entry_object * obj,nis_object * o,entry_obj * oldObj,char * dbId)12837c478bd9Sstevel@tonic-gate db_mindex::storeLDAP(db_query *qin, entry_object *obj, nis_object *o,
12847c478bd9Sstevel@tonic-gate 			entry_obj *oldObj, char *dbId) {
12857c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
12867c478bd9Sstevel@tonic-gate 	bool_t			asObj;
12877c478bd9Sstevel@tonic-gate 	db_query		*q, *qo, **qa;
12887c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv = 0;
12897c478bd9Sstevel@tonic-gate 	int			stat;
1290*8d0852b7SRichard Lowe 	const char		*myself = "db_mindex::storeLDAP";
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
12937c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	/* Instances from the deferred dictionary should not update LDAP */
12967c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
12977c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
13007c478bd9Sstevel@tonic-gate 	if (t == 0 && stat != LDAP_SUCCESS)
13017c478bd9Sstevel@tonic-gate 		return (stat);
13027c478bd9Sstevel@tonic-gate 
13037c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
13047c478bd9Sstevel@tonic-gate 	if (t != 0)
13057c478bd9Sstevel@tonic-gate 		printf("storeLDAP: %s%s%s\n",
13067c478bd9Sstevel@tonic-gate 			dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
13077c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	/*
13107c478bd9Sstevel@tonic-gate 	 * selectMapping() didn't have the object to look at, so we
13117c478bd9Sstevel@tonic-gate 	 * must check if this is a directory entry or not.
13127c478bd9Sstevel@tonic-gate 	 */
13137c478bd9Sstevel@tonic-gate 	if (asObj) {
13147c478bd9Sstevel@tonic-gate 		if (o != 0) {
13157c478bd9Sstevel@tonic-gate 			if (o->zo_data.zo_type == NIS_ENTRY_OBJ)
13167c478bd9Sstevel@tonic-gate 				asObj = FALSE;
13177c478bd9Sstevel@tonic-gate 		} else if (obj != 0) {
13187c478bd9Sstevel@tonic-gate 			if (obj->en_type == 0 ||
13197c478bd9Sstevel@tonic-gate 				strcmp(obj->en_type, "IN_DIRECTORY") != 0)
13207c478bd9Sstevel@tonic-gate 				asObj = FALSE;
13217c478bd9Sstevel@tonic-gate 		}
13227c478bd9Sstevel@tonic-gate 	}
13237c478bd9Sstevel@tonic-gate 
13247c478bd9Sstevel@tonic-gate 	if (asObj) {
13257c478bd9Sstevel@tonic-gate 		bool_t		freeO = FALSE;
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 		/*
13287c478bd9Sstevel@tonic-gate 		 * If we don't have a mapping, that's probably because
13297c478bd9Sstevel@tonic-gate 		 * the directory (represented by 'this') isn't mapped.
13307c478bd9Sstevel@tonic-gate 		 * Try to get a mapping from 'o' or 'obj'.
13317c478bd9Sstevel@tonic-gate 		 */
13327c478bd9Sstevel@tonic-gate 		if (t == 0) {
13337c478bd9Sstevel@tonic-gate 			if (o == 0 && obj != 0) {
13347c478bd9Sstevel@tonic-gate 				o = unmakePseudoEntryObj(obj, 0);
13357c478bd9Sstevel@tonic-gate 				if (o == 0)
13367c478bd9Sstevel@tonic-gate 					return (LDAP_OPERATIONS_ERROR);
13377c478bd9Sstevel@tonic-gate 				freeO = TRUE;
13387c478bd9Sstevel@tonic-gate 			}
13397c478bd9Sstevel@tonic-gate 			if (o != 0) {
13407c478bd9Sstevel@tonic-gate 				t = selectMapping(0, o, 0, TRUE, &asObj, &stat);
13417c478bd9Sstevel@tonic-gate 				if (t == 0) {
13427c478bd9Sstevel@tonic-gate 					if (freeO)
13437c478bd9Sstevel@tonic-gate 						nis_destroy_object(o);
13447c478bd9Sstevel@tonic-gate 					return (stat);
13457c478bd9Sstevel@tonic-gate 				}
13467c478bd9Sstevel@tonic-gate 			}
13477c478bd9Sstevel@tonic-gate 		}
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 		/*
13507c478bd9Sstevel@tonic-gate 		 * If we found a mapping for the 'table' in this db_mindex,
13517c478bd9Sstevel@tonic-gate 		 * store the object.
13527c478bd9Sstevel@tonic-gate 		 */
13537c478bd9Sstevel@tonic-gate 		if (t != 0) {
13547c478bd9Sstevel@tonic-gate 			if (o == 0) {
13557c478bd9Sstevel@tonic-gate 				if (obj != 0) {
13567c478bd9Sstevel@tonic-gate 					o = unmakePseudoEntryObj(obj, 0);
13577c478bd9Sstevel@tonic-gate 					freeO = TRUE;
13587c478bd9Sstevel@tonic-gate 				} else {
13597c478bd9Sstevel@tonic-gate 					db_status	dstat;
13607c478bd9Sstevel@tonic-gate 
13617c478bd9Sstevel@tonic-gate 					o = dbFindObject(t->objName, &dstat);
13627c478bd9Sstevel@tonic-gate 					if (o == 0)
13637c478bd9Sstevel@tonic-gate 						logmsg(MSG_NOTIMECHECK, LOG_ERR,
13647c478bd9Sstevel@tonic-gate 					"%s: DB error %d finding \"%s\"",
13657c478bd9Sstevel@tonic-gate 							myself,
13667c478bd9Sstevel@tonic-gate 							NIL(t->objName));
13677c478bd9Sstevel@tonic-gate 					freeO = TRUE;
13687c478bd9Sstevel@tonic-gate 				}
13697c478bd9Sstevel@tonic-gate 			}
13707c478bd9Sstevel@tonic-gate 			if (o == 0)
13717c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 			stat = storeObjLDAP(t, o);
13747c478bd9Sstevel@tonic-gate 
13757c478bd9Sstevel@tonic-gate 			/*
13767c478bd9Sstevel@tonic-gate 			 * Store the object with the mapping. If 'o' was
13777c478bd9Sstevel@tonic-gate 			 * supplied by the caller, we first need to make
13787c478bd9Sstevel@tonic-gate 			 * a copy.
13797c478bd9Sstevel@tonic-gate 			 */
13807c478bd9Sstevel@tonic-gate 			if (!freeO) {
13817c478bd9Sstevel@tonic-gate 				o = nis_clone_object(o, 0);
13827c478bd9Sstevel@tonic-gate 				if (o == 0)
13837c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
13847c478bd9Sstevel@tonic-gate 			"%s: Unable to refresh mapping object for \"%s\"",
13857c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName));
13867c478bd9Sstevel@tonic-gate 			}
13877c478bd9Sstevel@tonic-gate 			if (o != 0) {
13887c478bd9Sstevel@tonic-gate 				if (!replaceMappingObj(t, o))
13897c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
13907c478bd9Sstevel@tonic-gate 			}
13917c478bd9Sstevel@tonic-gate 
13927c478bd9Sstevel@tonic-gate 			/*
13937c478bd9Sstevel@tonic-gate 			 * Object now either destroyed or stored in 't'.
13947c478bd9Sstevel@tonic-gate 			 * Set pointer to NULL in order to avoid freeing
13957c478bd9Sstevel@tonic-gate 			 * it below.
13967c478bd9Sstevel@tonic-gate 			 */
13977c478bd9Sstevel@tonic-gate 			o = 0;
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 			if (stat != LDAP_SUCCESS)
14007c478bd9Sstevel@tonic-gate 				return (stat);
14017c478bd9Sstevel@tonic-gate 		}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 		if (freeO && o != 0) {
14047c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
14057c478bd9Sstevel@tonic-gate 			o = 0;
14067c478bd9Sstevel@tonic-gate 		}
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 		/*
14097c478bd9Sstevel@tonic-gate 		 * If the entry object 'obj' has the type "IN_DIRECTORY",
14107c478bd9Sstevel@tonic-gate 		 * then it's a directory entry, and we should check if
14117c478bd9Sstevel@tonic-gate 		 * the directory is mapped to LDAP, and update the dir
14127c478bd9Sstevel@tonic-gate 		 * entry list accordingly.
14137c478bd9Sstevel@tonic-gate 		 */
14147c478bd9Sstevel@tonic-gate 		if (obj == 0 || obj->en_type == 0 ||
14157c478bd9Sstevel@tonic-gate 				strcmp(obj->en_type, "IN_DIRECTORY") != 0)
14167c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 		/* Does it have a mapping  ? */
14197c478bd9Sstevel@tonic-gate 		t = selectMapping(table, 0, 0, TRUE, &asObj, &stat);
14207c478bd9Sstevel@tonic-gate 		if (t == 0)
14217c478bd9Sstevel@tonic-gate 			return (stat);
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate 		stat = storeObjLDAP(t, t->obj);
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 		return (stat);
14267c478bd9Sstevel@tonic-gate 	}
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate 	/* Store table entries. If we don't have a mapping, we're done. */
14297c478bd9Sstevel@tonic-gate 	if (t == 0)
14307c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 	if (qin != NULL && obj != NULL) {
14337c478bd9Sstevel@tonic-gate 		db_index_entry	*dbie;
14347c478bd9Sstevel@tonic-gate 		int		i, size, nq = 0;
14357c478bd9Sstevel@tonic-gate 		long		l, count;
14367c478bd9Sstevel@tonic-gate 		bool_t		valid;
14377c478bd9Sstevel@tonic-gate 		db_query	qbuf, **qold;
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate 		rv = (__nis_rule_value_t *)am(myself, sizeof (*rv));
14407c478bd9Sstevel@tonic-gate 		qa = (db_query **)am(myself, sizeof (qa[0]));
14417c478bd9Sstevel@tonic-gate 		if (oldObj != 0) {
14427c478bd9Sstevel@tonic-gate 			/*
14437c478bd9Sstevel@tonic-gate 			 * Note that only qold[0] is a unique query pointer.
14447c478bd9Sstevel@tonic-gate 			 * All the other qold[i]'s are copies of qa[i].
14457c478bd9Sstevel@tonic-gate 			 * Hence, we only free qold[0], as well as qold
14467c478bd9Sstevel@tonic-gate 			 * itself.
14477c478bd9Sstevel@tonic-gate 			 */
14487c478bd9Sstevel@tonic-gate 			qold = (db_query **)am(myself, sizeof (qold[0]));
14497c478bd9Sstevel@tonic-gate 		} else {
14507c478bd9Sstevel@tonic-gate 			qold = 0;
14517c478bd9Sstevel@tonic-gate 		}
14527c478bd9Sstevel@tonic-gate 		if (rv == 0 || qa == 0 || (oldObj != 0 && qold == 0)) {
14537c478bd9Sstevel@tonic-gate 			sfree(rv);
14547c478bd9Sstevel@tonic-gate 			sfree(qa);
14557c478bd9Sstevel@tonic-gate 			sfree(qold);
14567c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
14577c478bd9Sstevel@tonic-gate 		}
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 		q = schemeQuery2Query(qin, scheme);
14607c478bd9Sstevel@tonic-gate 		if (q == 0) {
14617c478bd9Sstevel@tonic-gate 			sfree(rv);
14627c478bd9Sstevel@tonic-gate 			sfree(qa);
14637c478bd9Sstevel@tonic-gate 			return (LDAP_PARAM_ERROR);
14647c478bd9Sstevel@tonic-gate 		}
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 		qa[0] = pseudoEntryObj2Query(obj, t->obj, &rv[0]);
14677c478bd9Sstevel@tonic-gate 		if (qa[0] == 0) {
14687c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
14697c478bd9Sstevel@tonic-gate "%s: Unable to obtain query representation of new entry object for \"%s\"",
14707c478bd9Sstevel@tonic-gate 				myself, NIL(t->dbId));
14717c478bd9Sstevel@tonic-gate 			freeQuery(q);
14727c478bd9Sstevel@tonic-gate 			sfree(rv);
14737c478bd9Sstevel@tonic-gate 			sfree(qa);
14747c478bd9Sstevel@tonic-gate 			sfree(qold);
14757c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
14767c478bd9Sstevel@tonic-gate 		}
14777c478bd9Sstevel@tonic-gate 		if (oldObj != 0) {
14787c478bd9Sstevel@tonic-gate 			qold[0] = pseudoEntryObj2Query(oldObj, t->obj, 0);
14797c478bd9Sstevel@tonic-gate 			if (qold[0] == 0) {
14807c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
14817c478bd9Sstevel@tonic-gate "%s: Unable to obtain query representation of old entry object for \"%s\"",
14827c478bd9Sstevel@tonic-gate 					myself, NIL(t->dbId));
14837c478bd9Sstevel@tonic-gate 				freeQueries(qa, 1);
14847c478bd9Sstevel@tonic-gate 				freeQuery(q);
14857c478bd9Sstevel@tonic-gate 				sfree(rv);
14867c478bd9Sstevel@tonic-gate 				sfree(qa);
14877c478bd9Sstevel@tonic-gate 				sfree(qold);
14887c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
14897c478bd9Sstevel@tonic-gate 			}
14907c478bd9Sstevel@tonic-gate 		}
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 		nq++;
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 		/*
14957c478bd9Sstevel@tonic-gate 		 * In order to support many-to-one NIS+ to LDAP mapping,
14967c478bd9Sstevel@tonic-gate 		 * we need to find all possible matches in the NIS+ DB,
14977c478bd9Sstevel@tonic-gate 		 * and then merge to produce a single update. mapToLDAP()
14987c478bd9Sstevel@tonic-gate 		 * takes care of the merging, so our job is to collect
14997c478bd9Sstevel@tonic-gate 		 * the matches. Worst case is that we need to search
15007c478bd9Sstevel@tonic-gate 		 * individually for each component in 'qin', so that's
15017c478bd9Sstevel@tonic-gate 		 * what we'll do.
15027c478bd9Sstevel@tonic-gate 		 *
15037c478bd9Sstevel@tonic-gate 		 * mapToLDAP() has a mode that only performs an update
15047c478bd9Sstevel@tonic-gate 		 * for the first DN, and that's what we want. In order
15057c478bd9Sstevel@tonic-gate 		 * to make sure that it's the correct DN, we leave the
15067c478bd9Sstevel@tonic-gate 		 * original query as the first one passed to mapToLDAP().
15077c478bd9Sstevel@tonic-gate 		 */
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 		size = qin->size();
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate 		/* For each component of 'qin' */
15127c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
15137c478bd9Sstevel@tonic-gate 			db_query		*qc, **qat, **qoldt;
15147c478bd9Sstevel@tonic-gate 			long			j;
15157c478bd9Sstevel@tonic-gate 			__nis_rule_value_t	*rvt;
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate 			qc = queryFromComponent(qin, i, &qbuf);
15187c478bd9Sstevel@tonic-gate 			if (qc == 0)
15197c478bd9Sstevel@tonic-gate 				continue;
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 			dbie = satisfy_query_dbonly(qc, &count, FALSE, &valid);
15227c478bd9Sstevel@tonic-gate 			if (dbie == 0 || !valid || count <= 0)
15237c478bd9Sstevel@tonic-gate 				continue;
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 			rvt = (__nis_rule_value_t *)realloc(rv,
15267c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (rv[0]));
15277c478bd9Sstevel@tonic-gate 			qat = (db_query **)realloc(qa,
15287c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (qa[0]));
15297c478bd9Sstevel@tonic-gate 			if (qold != 0)
15307c478bd9Sstevel@tonic-gate 				qoldt = (db_query **)realloc(qold,
15317c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (qold[0]));
15327c478bd9Sstevel@tonic-gate 			if (rvt == 0 || qat == 0 || (qold != 0 && qoldt == 0)) {
15337c478bd9Sstevel@tonic-gate 				if (qat == 0)
15347c478bd9Sstevel@tonic-gate 					freeQueries(qa, nq);
15357c478bd9Sstevel@tonic-gate 				else
15367c478bd9Sstevel@tonic-gate 					freeQueries(qat, nq);
15377c478bd9Sstevel@tonic-gate 				if (rvt == 0)
15387c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nq);
15397c478bd9Sstevel@tonic-gate 				else
15407c478bd9Sstevel@tonic-gate 					freeRuleValue(rvt, nq);
15417c478bd9Sstevel@tonic-gate 				if (qold != 0) {
15427c478bd9Sstevel@tonic-gate 					if (qoldt == 0)
15437c478bd9Sstevel@tonic-gate 						freeQueries(qold, 1);
15447c478bd9Sstevel@tonic-gate 					else
15457c478bd9Sstevel@tonic-gate 						freeQueries(qoldt, 1);
15467c478bd9Sstevel@tonic-gate 				}
15477c478bd9Sstevel@tonic-gate 				freeQuery(q);
15487c478bd9Sstevel@tonic-gate 				(void) memset(&qbuf, 0, sizeof (qbuf));
15497c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOMEM, LOG_ERR,
15507c478bd9Sstevel@tonic-gate 					"%s: realloc(%d) failed",
15517c478bd9Sstevel@tonic-gate 					myself, (nq+count) * sizeof (void *));
15527c478bd9Sstevel@tonic-gate 				return (LDAP_NO_MEMORY);
15537c478bd9Sstevel@tonic-gate 			}
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 			rv = rvt;
15567c478bd9Sstevel@tonic-gate 			qa = qat;
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 			(void) memset(&rv[nq], 0, count * sizeof (rv[0]));
15597c478bd9Sstevel@tonic-gate 			(void) memset(&qa[nq], 0, count * sizeof (qa[0]));
15607c478bd9Sstevel@tonic-gate 			if (qold != 0) {
15617c478bd9Sstevel@tonic-gate 				qold = qoldt;
15627c478bd9Sstevel@tonic-gate 				(void) memset(&qold[nq], 0,
15637c478bd9Sstevel@tonic-gate 						count * sizeof (qold[0]));
15647c478bd9Sstevel@tonic-gate 			}
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 			for (j = 0; j < count; j++) {
15677c478bd9Sstevel@tonic-gate 				qa[nq] = pseudoEntryObj2Query(
15687c478bd9Sstevel@tonic-gate 					table->get_entry(dbie->getlocation()),
15697c478bd9Sstevel@tonic-gate 							t->obj, &rv[nq]);
15707c478bd9Sstevel@tonic-gate 				if (qa[nq] == 0) {
15717c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
15727c478bd9Sstevel@tonic-gate 			"%s: Could not create query from entry obj for \"%s\"",
15737c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName));
15747c478bd9Sstevel@tonic-gate 					freeQueries(qa, nq);
15757c478bd9Sstevel@tonic-gate 					freeQueries(qold, 1);
15767c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nq);
15777c478bd9Sstevel@tonic-gate 					freeQuery(q);
15787c478bd9Sstevel@tonic-gate 					(void) memset(&qbuf, 0, sizeof (qbuf));
15797c478bd9Sstevel@tonic-gate 					return (LDAP_PARAM_ERROR);
15807c478bd9Sstevel@tonic-gate 				}
15817c478bd9Sstevel@tonic-gate 				if (qold != 0)
15827c478bd9Sstevel@tonic-gate 					qold[nq] = qa[nq];
15837c478bd9Sstevel@tonic-gate 				nq++;
15847c478bd9Sstevel@tonic-gate 				dbie = dbie->getnextresult();
15857c478bd9Sstevel@tonic-gate 				if (dbie == 0)
15867c478bd9Sstevel@tonic-gate 					break;
15877c478bd9Sstevel@tonic-gate 			}
15887c478bd9Sstevel@tonic-gate 		}
15897c478bd9Sstevel@tonic-gate 
15907c478bd9Sstevel@tonic-gate 		stat = mapToLDAP(t, nq, (qold != 0 ? qold : qa), qa, rv, 1,
15917c478bd9Sstevel@tonic-gate 				dbId);
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate 		freeQueries(qa, nq);
15947c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, nq);
15957c478bd9Sstevel@tonic-gate 		freeQuery(q);
15967c478bd9Sstevel@tonic-gate 		freeQueries(qold, 1);
15977c478bd9Sstevel@tonic-gate 		(void) memset(&qbuf, 0, sizeof (qbuf));
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate 	} else if (qin == 0 && obj == 0 && t->objType == NIS_TABLE_OBJ) {
16007c478bd9Sstevel@tonic-gate 		long			i, j, ntab;
16017c478bd9Sstevel@tonic-gate 		entry_object		**tab;
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 		READLOCK(table, LDAP_OPERATIONS_ERROR,
16047c478bd9Sstevel@tonic-gate 				"r table db_mindex::storeLDAP");
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 		tab = table->gettab();
16077c478bd9Sstevel@tonic-gate 		ntab = table->getsize();
16087c478bd9Sstevel@tonic-gate 		if (tab == 0 || ntab <= 0) {
16097c478bd9Sstevel@tonic-gate 			READUNLOCK(table, LDAP_OPERATIONS_ERROR,
16107c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
16117c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
16127c478bd9Sstevel@tonic-gate 		}
16137c478bd9Sstevel@tonic-gate 
16147c478bd9Sstevel@tonic-gate 		qa = (db_query **)am(myself, ntab * sizeof (qa[0]));
16157c478bd9Sstevel@tonic-gate 		rv = (__nis_rule_value_t *)am(myself, ntab * sizeof (rv[0]));
16167c478bd9Sstevel@tonic-gate 		if (qa == 0 || rv == 0) {
16177c478bd9Sstevel@tonic-gate 			sfree(qa);
16187c478bd9Sstevel@tonic-gate 			sfree(rv);
16197c478bd9Sstevel@tonic-gate 			READUNLOCK(table, LDAP_OPERATIONS_ERROR,
16207c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
16217c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
16227c478bd9Sstevel@tonic-gate 		}
16237c478bd9Sstevel@tonic-gate 
16247c478bd9Sstevel@tonic-gate 		for (i = 0; i < ntab; i++) {
16257c478bd9Sstevel@tonic-gate 			if (tab[i] == 0)
16267c478bd9Sstevel@tonic-gate 				continue;
16277c478bd9Sstevel@tonic-gate 
16287c478bd9Sstevel@tonic-gate 			qa[i] = pseudoEntryObj2Query(tab[i], t->obj, &rv[i]);
16297c478bd9Sstevel@tonic-gate 			if (qa[i] == 0) {
16307c478bd9Sstevel@tonic-gate 				freeQueries(qa, i);
16317c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, i);
16327c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
16337c478bd9Sstevel@tonic-gate 			"%s: Could not create query from entry for \"%s\"",
16347c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
16357c478bd9Sstevel@tonic-gate 				READUNLOCK(table, LDAP_OPERATIONS_ERROR,
16367c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
16377c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
16387c478bd9Sstevel@tonic-gate 			}
16397c478bd9Sstevel@tonic-gate 		}
16407c478bd9Sstevel@tonic-gate 
16417c478bd9Sstevel@tonic-gate 		stat = mapToLDAP(t, ntab, qa, qa, rv, 0, dbId);
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 		freeQueries(qa, ntab);
16447c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, ntab);
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate 		if (stat == LDAP_SUCCESS) {
16477c478bd9Sstevel@tonic-gate 			struct timeval  now;
16487c478bd9Sstevel@tonic-gate 			int		lstat, lck = 1;
16497c478bd9Sstevel@tonic-gate 			/*
16507c478bd9Sstevel@tonic-gate 			 * Since we've just successfully uploaded everthing
16517c478bd9Sstevel@tonic-gate 			 * in this table, we now consider our local copy
16527c478bd9Sstevel@tonic-gate 			 * up-to-date as well.
16537c478bd9Sstevel@tonic-gate 			 */
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&now, 0);
16567c478bd9Sstevel@tonic-gate 			WRITELOCKNR(table, lstat,
16577c478bd9Sstevel@tonic-gate 				"w table db_mindex::storeLDAP");
16587c478bd9Sstevel@tonic-gate 			if (lstat == 0) {
16597c478bd9Sstevel@tonic-gate 				table->mapping.enumExpire = now.tv_sec +
16607c478bd9Sstevel@tonic-gate 					table->mapping.ttl;
16617c478bd9Sstevel@tonic-gate 				lck = 0;
16627c478bd9Sstevel@tonic-gate 				WRITEUNLOCKNR(table, lstat,
16637c478bd9Sstevel@tonic-gate 					"wu table db_mindex::storeLDAP");
16647c478bd9Sstevel@tonic-gate 			}
16657c478bd9Sstevel@tonic-gate 			if (lstat != 0) {
16667c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
16677c478bd9Sstevel@tonic-gate 					"%s: %sock error %d for \"%s\"%s",
16687c478bd9Sstevel@tonic-gate 					myself, lck?"L":"Unl", lstat,
16697c478bd9Sstevel@tonic-gate 					NIL(t->objName),
16707c478bd9Sstevel@tonic-gate 					lck ?
16717c478bd9Sstevel@tonic-gate 				"; unable to update enumeration expiration":
16727c478bd9Sstevel@tonic-gate 				"");
16737c478bd9Sstevel@tonic-gate 			}
16747c478bd9Sstevel@tonic-gate 		}
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 		READUNLOCK(table, stat,
16777c478bd9Sstevel@tonic-gate 				"ru table db_mindex::storeLDAP");
16787c478bd9Sstevel@tonic-gate 	}
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	return (stat);
16817c478bd9Sstevel@tonic-gate }
168236e852a1SRaja Andra /*
168336e852a1SRaja Andra  * Sets the oid (i.e., the creation and modification times) for the
168436e852a1SRaja Andra  * specified object. In order to avoid retrieving the old incarnation
168536e852a1SRaja Andra  * (if any) from the DB first, we're punting and setting both mtime
168636e852a1SRaja Andra  * and ctime to the current time.
168736e852a1SRaja Andra  */
168836e852a1SRaja Andra static void
setOid(nis_object * obj)168936e852a1SRaja Andra setOid(nis_object *obj) {
169036e852a1SRaja Andra         if (obj != 0) {
169136e852a1SRaja Andra                 obj->zo_oid.ctime = obj->zo_oid.mtime = time(0);
169236e852a1SRaja Andra         }
169336e852a1SRaja Andra }
1694