xref: /onnv-gate/usr/src/lib/libnisdb/yptol/map_ctrl.c (revision 2189:bbaf8c7f3afd)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2189Ssdussud  * Common Development and Distribution License (the "License").
6*2189Ssdussud  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2189Ssdussud  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * DESCRIPTION:	Contains functions relating to the creation and manipulation
300Sstevel@tonic-gate  *		of map_ctrl structures. These are used to hold information
310Sstevel@tonic-gate  *		specific to one NIS map.
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  *		Because each of these contains a significant amount of state
340Sstevel@tonic-gate  *		information about an individual map they are created (on the
350Sstevel@tonic-gate  *		heap) when a map is opened and destroyed when it is closed.
360Sstevel@tonic-gate  *		The overhead of doing this is less than maintaining a pool
370Sstevel@tonic-gate  *		of map_ctrls.
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  *		If two processes access the same map two map_ctrls will be
400Sstevel@tonic-gate  *		created with similar contents (but differing DBM pointers).
410Sstevel@tonic-gate  *		Both will have the same hash value so when one is locked
420Sstevel@tonic-gate  *		access to the other will also be prevented.
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #include <unistd.h>
46*2189Ssdussud #include <stdlib.h>
470Sstevel@tonic-gate #include <syslog.h>
480Sstevel@tonic-gate #include <ndbm.h>
490Sstevel@tonic-gate #include <string.h>
50*2189Ssdussud #include <sys/param.h>
510Sstevel@tonic-gate #include "ypsym.h"
520Sstevel@tonic-gate #include "ypdefs.h"
530Sstevel@tonic-gate #include "shim.h"
540Sstevel@tonic-gate #include "yptol.h"
550Sstevel@tonic-gate #include "../ldap_util.h"
560Sstevel@tonic-gate 
57*2189Ssdussud extern int hash(char *s);
58*2189Ssdussud extern bool_t add_map_domain_to_list(char *domain, char ***map_list);
59*2189Ssdussud 
60*2189Ssdussud /*
61*2189Ssdussud  * Static variables for locking mechanism in
62*2189Ssdussud  * N2L mode.
63*2189Ssdussud  *  map_id_list: hash table for map lists
64*2189Ssdussud  *  max_map: max number of maps in map_id_list
65*2189Ssdussud  *      it is also used as the map ID for
66*2189Ssdussud  *      unknown maps, see get_map_id()
67*2189Ssdussud  *      in usr/src/cmd/ypcmd/shared/lockmap.c
68*2189Ssdussud  */
69*2189Ssdussud static map_id_elt_t *map_id_list[MAXHASH];
70*2189Ssdussud static int max_map = 0;
71*2189Ssdussud 
720Sstevel@tonic-gate /* Switch on parts of ypdefs.h */
730Sstevel@tonic-gate USE_DBM
74*2189Ssdussud USE_YPDBPATH
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * FUNCTION: 	create_map_ctrl();
780Sstevel@tonic-gate  *
790Sstevel@tonic-gate  * DESCRIPTION: Create and a new map_ctrl in a non opened state.
800Sstevel@tonic-gate  *
810Sstevel@tonic-gate  * INPUTS:	Fully qualified map name
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * OUTPUTS:	Pointer to map_ctrl
840Sstevel@tonic-gate  *		NULL on failure.
850Sstevel@tonic-gate  *
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate map_ctrl *
880Sstevel@tonic-gate create_map_ctrl(char *name)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate 	char *myself = "create_map_ctrl";
910Sstevel@tonic-gate 	map_ctrl *map;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	map = (map_ctrl *)am(myself, sizeof (map_ctrl));
940Sstevel@tonic-gate 	if (NULL == map) {
950Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR, "Could not alloc map_ctrl");
960Sstevel@tonic-gate 		return (NULL);
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	/* Clear new map (in case we have to free it) */
1000Sstevel@tonic-gate 	map->entries = NULL;
1010Sstevel@tonic-gate 	map->hash_val = 0;
1020Sstevel@tonic-gate 	map->map_name = NULL;
1030Sstevel@tonic-gate 	map->domain = NULL;
1040Sstevel@tonic-gate 	map->map_path = NULL;
1050Sstevel@tonic-gate 	map->ttl = NULL;
1060Sstevel@tonic-gate 	map->ttl_path = NULL;
1070Sstevel@tonic-gate 	map->trad_map_path = NULL;
1080Sstevel@tonic-gate 	map->key_data.dptr = NULL;
1090Sstevel@tonic-gate 	map->open_mode = 0;
1100Sstevel@tonic-gate 	map->open_flags = 0;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	/*
1130Sstevel@tonic-gate 	 * Initialize the fields of the map_ctrl. By doing this once here we
1140Sstevel@tonic-gate 	 * can save a lot of work as map entries are accessed.
1150Sstevel@tonic-gate 	 */
1160Sstevel@tonic-gate 	if (SUCCESS != map_ctrl_init(map, name)) {
1170Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
1180Sstevel@tonic-gate 				"Could not initialize map_ctrl for %s", name);
1190Sstevel@tonic-gate 		free_map_ctrl(map);
1200Sstevel@tonic-gate 		return (NULL);
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	return (map);
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate  * FUNCTION :	map_ctrl_init()
1280Sstevel@tonic-gate  *
1290Sstevel@tonic-gate  * DESCRIPTION:	Initializes the fields of a map_ctrl structure.
1300Sstevel@tonic-gate  *
1310Sstevel@tonic-gate  *		By doing this once (when the map_ctrl is created) we avoid
1320Sstevel@tonic-gate  *		numerous other function having to repeat this string
1330Sstevel@tonic-gate  *		manipulation.
1340Sstevel@tonic-gate  *
1350Sstevel@tonic-gate  * GIVEN :	Pointer to the structure
1360Sstevel@tonic-gate  *		Fully qualified name of the map
1370Sstevel@tonic-gate  *
1380Sstevel@tonic-gate  * RETURNS :	SUCCESS = map_ctrl fully set up.
1390Sstevel@tonic-gate  *		FAILURE = map_ctrl not set up CALLER MUST FREE.
1400Sstevel@tonic-gate  */
1410Sstevel@tonic-gate suc_code
1420Sstevel@tonic-gate map_ctrl_init(map_ctrl *map, char *name)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate 	char *myself = "map_ctrl_init";
1450Sstevel@tonic-gate 	char *p, *q;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	/* Save map path for future reference */
1480Sstevel@tonic-gate 	map->map_path = (char *)strdup(name);
1490Sstevel@tonic-gate 	if (NULL ==  map->map_path) {
1500Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR,
1510Sstevel@tonic-gate 				"Could not duplicate map path %s", map);
1520Sstevel@tonic-gate 		return (FAILURE);
1530Sstevel@tonic-gate 	}
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	/* Work out map's unqualified name from path */
1560Sstevel@tonic-gate 	p = strrchr(name, SEP_CHAR);
1570Sstevel@tonic-gate 	if (NULL == p) {
1580Sstevel@tonic-gate 		/* Must be at least a domain and name */
1590Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
1600Sstevel@tonic-gate 			"Could not find separator in map path %s", map);
1610Sstevel@tonic-gate 		return (FAILURE);
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 	q = p + 1;
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* Check for and remove N2L prefix */
1660Sstevel@tonic-gate 	if (yptol_mode) {
1670Sstevel@tonic-gate 		/*
1680Sstevel@tonic-gate 		 * Check for and remove N2L prefix. If not found not a problem
1690Sstevel@tonic-gate 		 * we open some old style maps during DIT initialization.
1700Sstevel@tonic-gate 		 */
1710Sstevel@tonic-gate 		if (0 == strncmp(q, NTOL_PREFIX, strlen(NTOL_PREFIX)))
1720Sstevel@tonic-gate 			q += strlen(NTOL_PREFIX);
1730Sstevel@tonic-gate 	} else {
1740Sstevel@tonic-gate 		if (0 == strncmp(q, NTOL_PREFIX, strlen(NTOL_PREFIX)))
1750Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
1760Sstevel@tonic-gate 				"Working in non N2L mode and path %s "
1770Sstevel@tonic-gate 				"contains N2L prefix", name);
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	/* Save unqualified map name */
1810Sstevel@tonic-gate 	map->map_name = strdup(q);
1820Sstevel@tonic-gate 	if (NULL == map->map_name) {
1830Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR,
1840Sstevel@tonic-gate 				"Could not duplicate map name %s", q);
1850Sstevel@tonic-gate 		return (FAILURE);
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/* Work out map's domain name from path */
1890Sstevel@tonic-gate 	for (q = p-1; (SEP_CHAR != *q) && (q > name); q--);
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	if (q <= name) {
1920Sstevel@tonic-gate 		/* Didn't find separator */
1930Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
1940Sstevel@tonic-gate 				"Could not find domain in map path %s", name);
1950Sstevel@tonic-gate 		return (FAILURE);
1960Sstevel@tonic-gate 	}
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	map->domain = (char *)am(myself, p - q);
1990Sstevel@tonic-gate 	if (NULL == map->domain) {
2000Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR,
2010Sstevel@tonic-gate 			"Could not alloc memory for domain in path %s", name);
2020Sstevel@tonic-gate 		return (FAILURE);
2030Sstevel@tonic-gate 	}
204*2189Ssdussud 	(void) strncpy(map->domain, q + 1, p-q-1);
2050Sstevel@tonic-gate 	map->domain[p-q-1] = '\0';
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/* Work out extra names required by N2L */
2080Sstevel@tonic-gate 	if (yptol_mode) {
2090Sstevel@tonic-gate 		/*
2100Sstevel@tonic-gate 		 * Work out what old style NIS path would have been. This is
2110Sstevel@tonic-gate 		 * used to check for date of DBM file so add the DBM
2120Sstevel@tonic-gate 		 * extension.
2130Sstevel@tonic-gate 		 */
2140Sstevel@tonic-gate 		map->trad_map_path = (char *)am(myself, strlen(map->map_name) +
2150Sstevel@tonic-gate 					+ strlen(dbm_pag) + (p - name) + 2);
2160Sstevel@tonic-gate 		if (NULL == map->trad_map_path) {
2170Sstevel@tonic-gate 			logmsg(MSG_NOMEM, LOG_ERR,
2180Sstevel@tonic-gate 				"Could not alocate memory for "
2190Sstevel@tonic-gate 				"traditional map path derived from %s", name);
2200Sstevel@tonic-gate 			return (FAILURE);
2210Sstevel@tonic-gate 		}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 		strncpy(map->trad_map_path, name, p - name + 1);
2240Sstevel@tonic-gate 		map->trad_map_path[p - name + 1] = '\0';
2250Sstevel@tonic-gate 		strcat(map->trad_map_path, map->map_name);
2260Sstevel@tonic-gate 		strcat(map->trad_map_path, dbm_pag);
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 		/* Generate qualified TTL file name */
2290Sstevel@tonic-gate 		map->ttl_path = (char *)am(myself, strlen(map->map_path) +
2300Sstevel@tonic-gate 						strlen(TTL_POSTFIX) + 1);
2310Sstevel@tonic-gate 		if (NULL == map->ttl_path) {
2320Sstevel@tonic-gate 			logmsg(MSG_NOMEM, LOG_ERR,
2330Sstevel@tonic-gate 				"Could not alocate memory for "
2340Sstevel@tonic-gate 				"ttl path derived from %s", name);
2350Sstevel@tonic-gate 			return (FAILURE);
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 		strcpy(map->ttl_path, map->map_path);
2390Sstevel@tonic-gate 		strcat(map->ttl_path, TTL_POSTFIX);
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	/* Work out hash value */
2430Sstevel@tonic-gate 	map->hash_val = hash(name);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	/* Set up magic number */
2460Sstevel@tonic-gate 	map->magic = MAP_MAGIC;
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	/* Null out pointers */
2490Sstevel@tonic-gate 	map->entries = NULL;
2500Sstevel@tonic-gate 	map->ttl = NULL;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	/* No key data yet */
2530Sstevel@tonic-gate 	map->key_data.dptr = NULL;
2540Sstevel@tonic-gate 	map->key_data.dsize = 0;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	return (SUCCESS);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate /*
2600Sstevel@tonic-gate  * FUNCTION: 	get_map_crtl();
2610Sstevel@tonic-gate  *
2620Sstevel@tonic-gate  * DESCRIPTION: Find an existing map_ctrl for a map of a given DBM * (i.e.
2630Sstevel@tonic-gate  *		handle) . If none exists return an error.
2640Sstevel@tonic-gate  *
2650Sstevel@tonic-gate  * INPUTS:	Map handle
2660Sstevel@tonic-gate  *
2670Sstevel@tonic-gate  * OUTPUTS:	Pointer to map_ctrl
2680Sstevel@tonic-gate  *		NULL on failure.
2690Sstevel@tonic-gate  *
2700Sstevel@tonic-gate  */
2710Sstevel@tonic-gate map_ctrl *
2720Sstevel@tonic-gate get_map_ctrl(DBM *db)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate 	/* Check that this really is a map_ctrl not a DBM */
2750Sstevel@tonic-gate 	if (((map_ctrl *)db)->magic != MAP_MAGIC) {
2760Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
2770Sstevel@tonic-gate 				"SHIM called with DBM ptr not map_crtl ptr");
2780Sstevel@tonic-gate 		return (NULL);
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	/* Since this is an opaque pointer just cast it */
2820Sstevel@tonic-gate 	return ((map_ctrl *)db);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate  * FUNCTION:	dup_map_ctrl()
2870Sstevel@tonic-gate  *
2880Sstevel@tonic-gate  * DESCRIPTION:	Duplicates a map_ctrl structure
2890Sstevel@tonic-gate  *
2900Sstevel@tonic-gate  * GIVEN :	Map_ctrl to duplicate
2910Sstevel@tonic-gate  *
2920Sstevel@tonic-gate  * RETURNS :	Pointer to a new malloced map_ctrl. CALLER MUST FREE
2930Sstevel@tonic-gate  *		NULL on failure.
2940Sstevel@tonic-gate  */
2950Sstevel@tonic-gate map_ctrl *
2960Sstevel@tonic-gate dup_map_ctrl(map_ctrl *old_map)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate 	map_ctrl *new_map;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	/*
3010Sstevel@tonic-gate 	 * Could save a little bit of time by duplicating the static parts
3020Sstevel@tonic-gate 	 * of the old map but on balance it is cleaner to just make a new one
3030Sstevel@tonic-gate 	 * from scratch
3040Sstevel@tonic-gate 	 */
3050Sstevel@tonic-gate 	new_map = create_map_ctrl(old_map->map_path);
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	if (NULL == new_map)
3080Sstevel@tonic-gate 		return (NULL);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	/* If old map had open handles duplicate them */
3110Sstevel@tonic-gate 	if (NULL != old_map->entries) {
3120Sstevel@tonic-gate 		new_map->open_flags = old_map->open_flags;
3130Sstevel@tonic-gate 		new_map->open_mode = old_map->open_mode;
3140Sstevel@tonic-gate 		if (FAILURE == open_yptol_files(new_map)) {
3150Sstevel@tonic-gate 			free_map_ctrl(new_map);
3160Sstevel@tonic-gate 			return (NULL);
3170Sstevel@tonic-gate 		}
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	return (new_map);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate /*
3240Sstevel@tonic-gate  * FUNCTION: 	free_map_crtl();
3250Sstevel@tonic-gate  *
3260Sstevel@tonic-gate  * DESCRIPTION: Free contents of a map_ctr structure and closed any open
3270Sstevel@tonic-gate  *		DBM files.
3280Sstevel@tonic-gate  *
3290Sstevel@tonic-gate  * INPUTS:	Pointer to pointer to a map_ctrl.
3300Sstevel@tonic-gate  *
3310Sstevel@tonic-gate  * OUTPUTS:	Nothing
3320Sstevel@tonic-gate  *
3330Sstevel@tonic-gate  */
3340Sstevel@tonic-gate void
3350Sstevel@tonic-gate free_map_ctrl(map_ctrl *map)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (NULL != map->entries) {
3390Sstevel@tonic-gate 		dbm_close(map->entries);
3400Sstevel@tonic-gate 		map->entries = NULL;
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	if (NULL != map->map_name) {
3440Sstevel@tonic-gate 		sfree(map->map_name);
3450Sstevel@tonic-gate 		map->map_name = NULL;
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	if (NULL != map->map_path) {
3490Sstevel@tonic-gate 		sfree(map->map_path);
3500Sstevel@tonic-gate 		map->map_path = NULL;
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	if (NULL != map->domain) {
3540Sstevel@tonic-gate 		sfree(map->domain);
3550Sstevel@tonic-gate 		map->domain = NULL;
3560Sstevel@tonic-gate 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	if (yptol_mode) {
3590Sstevel@tonic-gate 		if (NULL != map->ttl) {
3600Sstevel@tonic-gate 			dbm_close(map->ttl);
3610Sstevel@tonic-gate 			map->ttl = NULL;
3620Sstevel@tonic-gate 		}
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 		if (NULL != map->trad_map_path) {
3650Sstevel@tonic-gate 			sfree(map->trad_map_path);
3660Sstevel@tonic-gate 			map->trad_map_path = NULL;
3670Sstevel@tonic-gate 		}
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 		if (NULL != map->ttl_path) {
3700Sstevel@tonic-gate 			sfree(map->ttl_path);
3710Sstevel@tonic-gate 			map->ttl_path = NULL;
3720Sstevel@tonic-gate 		}
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 		if (NULL != map->key_data.dptr) {
3750Sstevel@tonic-gate 			sfree(map->key_data.dptr);
3760Sstevel@tonic-gate 			map->key_data.dptr = NULL;
3770Sstevel@tonic-gate 			map->key_data.dsize = 0;
3780Sstevel@tonic-gate 		}
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	map->magic = 0;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	/* Since map_ctrls are now always in malloced memory */
3840Sstevel@tonic-gate 	sfree(map);
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate  * FUNCTION :	get_map_name()
3900Sstevel@tonic-gate  *
3910Sstevel@tonic-gate  * DESCRIPTION:	Get the name of a map from its map_ctrl. This could be done
3920Sstevel@tonic-gate  *		as a simple dereference but this function hides the internal
3930Sstevel@tonic-gate  *		implementation of map_ctrl from higher layers.
3940Sstevel@tonic-gate  *
3950Sstevel@tonic-gate  * GIVEN :	A map_ctrl pointer
3960Sstevel@tonic-gate  *
3970Sstevel@tonic-gate  * RETURNS :	A pointer to the map_ctrl. Higher levels treat this as an
3980Sstevel@tonic-gate  *		opaque DBM pointer.
3990Sstevel@tonic-gate  *		NULL on failure.
4000Sstevel@tonic-gate  */
4010Sstevel@tonic-gate char *
4020Sstevel@tonic-gate get_map_name(DBM *db)
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate 	map_ctrl *map = (map_ctrl *)db;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	if (NULL == map)
4070Sstevel@tonic-gate 		return (NULL);
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	return (map->map_name);
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate /*
4130Sstevel@tonic-gate  * FUNCTION :	set_key_data()
4140Sstevel@tonic-gate  *
4150Sstevel@tonic-gate  * DESCRIPTION:	Sets up the key data freeing any that already exists.
4160Sstevel@tonic-gate  *
4170Sstevel@tonic-gate  * GIVEN :	Pointer to the map_ctrl to set up.
4180Sstevel@tonic-gate  *		Datum containing the key. The dptr of this will be set to
4190Sstevel@tonic-gate  *		point to the key data.
4200Sstevel@tonic-gate  *
4210Sstevel@tonic-gate  * RETURNS :	Nothing
4220Sstevel@tonic-gate  */
4230Sstevel@tonic-gate void
4240Sstevel@tonic-gate set_key_data(map_ctrl *map, datum *data)
4250Sstevel@tonic-gate {
4260Sstevel@tonic-gate 	char *myself = "set_key_data";
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	/*
4290Sstevel@tonic-gate 	 * Free up any existing key data. Because each dbm file can only have
4300Sstevel@tonic-gate 	 * one enumeration going at a time this is safe.
4310Sstevel@tonic-gate 	 */
4320Sstevel@tonic-gate 	if (NULL != map->key_data.dptr) {
4330Sstevel@tonic-gate 		sfree(map->key_data.dptr);
4340Sstevel@tonic-gate 		map->key_data.dptr = NULL;
4350Sstevel@tonic-gate 		map->key_data.dsize = 0;
4360Sstevel@tonic-gate 	}
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	/* If nothing in key just return */
4390Sstevel@tonic-gate 	if (NULL == data->dptr)
4400Sstevel@tonic-gate 		return;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/* Something is in the key so must duplicate out of static memory */
4430Sstevel@tonic-gate 	map->key_data.dptr = (char *)am(myself, data->dsize);
4440Sstevel@tonic-gate 	if (NULL == map->key_data.dptr) {
4450Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR, "Cannot alloc memory for key data");
4460Sstevel@tonic-gate 	} else {
4470Sstevel@tonic-gate 		memcpy(map->key_data.dptr, data->dptr, data->dsize);
4480Sstevel@tonic-gate 		map->key_data.dsize = data->dsize;
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	/* Set datum to point to malloced version of the data */
4520Sstevel@tonic-gate 	data->dptr = map->key_data.dptr;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	return;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate /*
4590Sstevel@tonic-gate  * FUNCTION :	open_yptol_files()
4600Sstevel@tonic-gate  *
4610Sstevel@tonic-gate  * DESCRIPTION:	Opens both yptol files for a map. This is called both when a
4620Sstevel@tonic-gate  *		map is opened and when it is reopened as a result of an update
4630Sstevel@tonic-gate  *		operation. Must be called with map locked.
4640Sstevel@tonic-gate  *
4650Sstevel@tonic-gate  * GIVEN :	Initialized map_ctrl
4660Sstevel@tonic-gate  *
4670Sstevel@tonic-gate  * RETURNS :	SUCCESS = Maps opened
4680Sstevel@tonic-gate  *		FAILURE = Maps not opened (and mess tidied up)
4690Sstevel@tonic-gate  */
4700Sstevel@tonic-gate suc_code
4710Sstevel@tonic-gate open_yptol_files(map_ctrl *map)
4720Sstevel@tonic-gate {
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/* Open entries map */
4750Sstevel@tonic-gate 	map->entries = dbm_open(map->map_path, map->open_flags, map->open_mode);
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	if (NULL == map->entries) {
4780Sstevel@tonic-gate 		/* Maybe we were asked to open a non-existent map. No problem */
4790Sstevel@tonic-gate 		return (FAILURE);
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	if (yptol_mode) {
4830Sstevel@tonic-gate 		/* Open TTLs map. Must always be writable */
4840Sstevel@tonic-gate 		map->ttl = dbm_open(map->ttl_path, O_RDWR | O_CREAT, 0644);
4850Sstevel@tonic-gate 		if (NULL == map->ttl) {
4860Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
4870Sstevel@tonic-gate 				"Cannot open TTL file %s", map->ttl_path);
4880Sstevel@tonic-gate 			dbm_close(map->entries);
4890Sstevel@tonic-gate 			map->entries = NULL;
4900Sstevel@tonic-gate 			return (FAILURE);
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	return (SUCCESS);
4950Sstevel@tonic-gate }
496*2189Ssdussud 
497*2189Ssdussud /*
498*2189Ssdussud  * FUNCTION :   insert_map_in_list()
499*2189Ssdussud  *
500*2189Ssdussud  * DESCRIPTION:	add a map in map_id_list[]
501*2189Ssdussud  *
502*2189Ssdussud  * GIVEN :      map name
503*2189Ssdussud  *              map unique ID
504*2189Ssdussud  *
505*2189Ssdussud  * RETURNS :	SUCCESS = map added
506*2189Ssdussud  *		FAILURE = map not added
507*2189Ssdussud  */
508*2189Ssdussud suc_code
509*2189Ssdussud insert_map_in_list(char *map_name, int unique_value)
510*2189Ssdussud {
511*2189Ssdussud 	int index;
512*2189Ssdussud 	bool_t yptol_nl_sav = yptol_newlock;
513*2189Ssdussud 	map_id_elt_t *new_elt;
514*2189Ssdussud 
515*2189Ssdussud 	/*
516*2189Ssdussud 	 * Index in the hash table is computed from the original
517*2189Ssdussud 	 * hash function: make sure yptol_newlock is set to false.
518*2189Ssdussud 	 */
519*2189Ssdussud 	yptol_newlock = FALSE;
520*2189Ssdussud 	index = hash(map_name);
521*2189Ssdussud 	yptol_newlock = yptol_nl_sav;
522*2189Ssdussud 
523*2189Ssdussud 	new_elt = (map_id_elt_t *)calloc(1, sizeof (map_id_elt_t));
524*2189Ssdussud 	if (new_elt == NULL) {
525*2189Ssdussud 		return (FAILURE);
526*2189Ssdussud 	}
527*2189Ssdussud 	new_elt->map_name = strdup(map_name);
528*2189Ssdussud 	if (new_elt->map_name == NULL) { /* strdup() failed */
529*2189Ssdussud 		return (FAILURE);
530*2189Ssdussud 	}
531*2189Ssdussud 	new_elt->map_id = unique_value;
532*2189Ssdussud 
533*2189Ssdussud 	if (map_id_list[index] == NULL) {
534*2189Ssdussud 		new_elt->next = NULL;
535*2189Ssdussud 	} else {
536*2189Ssdussud 		new_elt->next = map_id_list[index];
537*2189Ssdussud 	}
538*2189Ssdussud 	/* insert at begining */
539*2189Ssdussud 	map_id_list[index] = new_elt;
540*2189Ssdussud 
541*2189Ssdussud 	return (SUCCESS);
542*2189Ssdussud }
543*2189Ssdussud 
544*2189Ssdussud #ifdef NISDB_LDAP_DEBUG
545*2189Ssdussud /*
546*2189Ssdussud  * FUNCTION :   dump_map_id_list()
547*2189Ssdussud  *
548*2189Ssdussud  * DESCRIPTION:	display max_map and dump map_id_list[]
549*2189Ssdussud  *		not called, here for debug convenience only
550*2189Ssdussud  *
551*2189Ssdussud  * GIVEN :      nothing
552*2189Ssdussud  *
553*2189Ssdussud  * RETURNS :	nothing
554*2189Ssdussud  */
555*2189Ssdussud void
556*2189Ssdussud dump_map_id_list()
557*2189Ssdussud {
558*2189Ssdussud 	int i;
559*2189Ssdussud 	map_id_elt_t *cur_elt;
560*2189Ssdussud 
561*2189Ssdussud 	logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
562*2189Ssdussud 		"dump_map_id_list: max_map is: %d, dumping map_idlist ...",
563*2189Ssdussud 		max_map);
564*2189Ssdussud 
565*2189Ssdussud 	for (i = 0; i < MAXHASH; i++) {
566*2189Ssdussud 		if (map_id_list[i] == NULL) {
567*2189Ssdussud 			logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
568*2189Ssdussud 				"no map for index %d", i);
569*2189Ssdussud 		} else {
570*2189Ssdussud 			logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
571*2189Ssdussud 				"index %d has the following maps", i);
572*2189Ssdussud 			cur_elt = map_id_list[i];
573*2189Ssdussud 			do {
574*2189Ssdussud 				logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
575*2189Ssdussud 					"%s, unique id: %d",
576*2189Ssdussud 					cur_elt->map_name,
577*2189Ssdussud 					cur_elt->map_id);
578*2189Ssdussud 				cur_elt = cur_elt->next;
579*2189Ssdussud 			} while (cur_elt != NULL);
580*2189Ssdussud 		}
581*2189Ssdussud 	}
582*2189Ssdussud }
583*2189Ssdussud #endif
584*2189Ssdussud 
585*2189Ssdussud /*
586*2189Ssdussud  * FUNCTION :   free_map_id_list()
587*2189Ssdussud  *
588*2189Ssdussud  * DESCRIPTION:	free all previously allocated elements of map_id_list[]
589*2189Ssdussud  *		reset max_map to 0
590*2189Ssdussud  *
591*2189Ssdussud  * GIVEN :      nothing
592*2189Ssdussud  *
593*2189Ssdussud  * RETURNS :	nothing
594*2189Ssdussud  */
595*2189Ssdussud void
596*2189Ssdussud free_map_id_list()
597*2189Ssdussud {
598*2189Ssdussud 	int i;
599*2189Ssdussud 	map_id_elt_t *cur_elt, *next_elt;
600*2189Ssdussud 
601*2189Ssdussud 	for (i = 0; i < MAXHASH; i++) {
602*2189Ssdussud 		if (map_id_list[i] != NULL) {
603*2189Ssdussud 			cur_elt = map_id_list[i];
604*2189Ssdussud 			do {
605*2189Ssdussud 				next_elt = cur_elt->next;
606*2189Ssdussud 				if (cur_elt->map_name)
607*2189Ssdussud 					sfree(cur_elt->map_name);
608*2189Ssdussud 				sfree(cur_elt);
609*2189Ssdussud 				cur_elt = next_elt;
610*2189Ssdussud 			} while (cur_elt != NULL);
611*2189Ssdussud 			map_id_list[i] = NULL;
612*2189Ssdussud 		}
613*2189Ssdussud 	}
614*2189Ssdussud 	max_map = 0;
615*2189Ssdussud }
616*2189Ssdussud 
617*2189Ssdussud /*
618*2189Ssdussud  * FUNCTION :   map_id_list_init()
619*2189Ssdussud  *
620*2189Ssdussud  * DESCRIPTION:	initializes map_id_list[] and max_map
621*2189Ssdussud  *
622*2189Ssdussud  * GIVEN :      nothing
623*2189Ssdussud  *
624*2189Ssdussud  * RETURNS :	 0 if OK
625*2189Ssdussud  *		-1 if failure
626*2189Ssdussud  */
627*2189Ssdussud int
628*2189Ssdussud map_id_list_init()
629*2189Ssdussud {
630*2189Ssdussud 	char **domain_list, **map_list = NULL;
631*2189Ssdussud 	int domain_num;
632*2189Ssdussud 	int i, j;
633*2189Ssdussud 	char *myself = "map_id_list_init";
634*2189Ssdussud 	char mapbuf[MAXPATHLEN];
635*2189Ssdussud 	int mapbuf_len = sizeof (mapbuf);
636*2189Ssdussud 	int map_name_len;
637*2189Ssdussud 	int seqnum = 0;
638*2189Ssdussud 	int rc = 0;
639*2189Ssdussud 
640*2189Ssdussud 	for (i = 0; i < MAXHASH; i++) {
641*2189Ssdussud 		map_id_list[i] = NULL;
642*2189Ssdussud 	}
643*2189Ssdussud 
644*2189Ssdussud 	domain_num = get_mapping_domain_list(&domain_list);
645*2189Ssdussud 	for (i = 0; i < domain_num; i++) {
646*2189Ssdussud 		if (map_list) {
647*2189Ssdussud 			free_map_list(map_list);
648*2189Ssdussud 			map_list = NULL;
649*2189Ssdussud 		}
650*2189Ssdussud 
651*2189Ssdussud 		/* get map list from mapping file */
652*2189Ssdussud 		map_list = get_mapping_map_list(domain_list[i]);
653*2189Ssdussud 		if (map_list == NULL) {
654*2189Ssdussud 			/* no map for this domain in mapping file */
655*2189Ssdussud 			logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
656*2189Ssdussud 			    "%s: get_mapping_map_list()"
657*2189Ssdussud 			    " found no map for domain %s",
658*2189Ssdussud 			    myself, domain_list[i]);
659*2189Ssdussud 		}
660*2189Ssdussud 
661*2189Ssdussud 		/* add maps from /var/yp/<domain> */
662*2189Ssdussud 		if (add_map_domain_to_list(domain_list[i], &map_list) ==
663*2189Ssdussud 		    FALSE) {
664*2189Ssdussud 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
665*2189Ssdussud 			    "%s: add_map_domain_to_list() failed", myself);
666*2189Ssdussud 			free_map_id_list();
667*2189Ssdussud 			if (map_list) free_map_list(map_list);
668*2189Ssdussud 			return (-1);
669*2189Ssdussud 		}
670*2189Ssdussud 
671*2189Ssdussud 		if (map_list == NULL || map_list[0] == NULL) {
672*2189Ssdussud 			logmsg(MSG_NOTIMECHECK, LOG_DEBUG,
673*2189Ssdussud 			    "%s: no map in domain %s",
674*2189Ssdussud 			    myself, domain_list[i]);
675*2189Ssdussud 			continue;
676*2189Ssdussud 		}
677*2189Ssdussud 
678*2189Ssdussud 		for (j = 0; map_list[j] != NULL; j++) {
679*2189Ssdussud 			/* build long name */
680*2189Ssdussud 			map_name_len = ypdbpath_sz + 1 +
681*2189Ssdussud 					strlen(domain_list[i]) + 1 +
682*2189Ssdussud 					strlen(NTOL_PREFIX) +
683*2189Ssdussud 					strlen(map_list[j]) + 1;
684*2189Ssdussud 			if (map_name_len > mapbuf_len) {
685*2189Ssdussud 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
686*2189Ssdussud 				    "%s: map name too long for %s",
687*2189Ssdussud 				    " in domain %s", myself, map_list[j],
688*2189Ssdussud 				    domain_list[i]);
689*2189Ssdussud 				free_map_id_list();
690*2189Ssdussud 				if (map_list) free_map_list(map_list);
691*2189Ssdussud 				return (-1);
692*2189Ssdussud 			}
693*2189Ssdussud 			(void) memset(mapbuf, 0, mapbuf_len);
694*2189Ssdussud 			(void) snprintf(mapbuf, map_name_len, "%s%c%s%c%s%s",
695*2189Ssdussud 				ypdbpath, SEP_CHAR, domain_list[i], SEP_CHAR,
696*2189Ssdussud 				NTOL_PREFIX, map_list[j]);
697*2189Ssdussud 
698*2189Ssdussud 			if (insert_map_in_list(mapbuf, seqnum)
699*2189Ssdussud 				    == FAILURE) {
700*2189Ssdussud 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
701*2189Ssdussud 				    "%s: failed to insert map %s",
702*2189Ssdussud 				    " in domain %s", myself, map_list[j]);
703*2189Ssdussud 				free_map_id_list();
704*2189Ssdussud 				if (map_list) free_map_list(map_list);
705*2189Ssdussud 				return (-1);
706*2189Ssdussud 			}
707*2189Ssdussud 			seqnum++;
708*2189Ssdussud 		}
709*2189Ssdussud 	}
710*2189Ssdussud 
711*2189Ssdussud 	max_map = seqnum;
712*2189Ssdussud 
713*2189Ssdussud #ifdef NISDB_LDAP_DEBUG
714*2189Ssdussud 	dump_map_id_list();
715*2189Ssdussud #endif
716*2189Ssdussud 
717*2189Ssdussud 	/*
718*2189Ssdussud 	 * If more maps than allocated spaces in shared memory, that's a failure
719*2189Ssdussud 	 * probably need to free previously allocated memory if failure,
720*2189Ssdussud 	 * before returning.
721*2189Ssdussud 	 */
722*2189Ssdussud 	if (max_map > MAXHASH) {
723*2189Ssdussud 		rc = -1;
724*2189Ssdussud 		logmsg(MSG_NOTIMECHECK, LOG_ERR,
725*2189Ssdussud 		    "%s: too many maps (%d)",
726*2189Ssdussud 		    myself, max_map);
727*2189Ssdussud 		free_map_id_list();
728*2189Ssdussud 	}
729*2189Ssdussud 	if (map_list) free_map_list(map_list);
730*2189Ssdussud 	return (rc);
731*2189Ssdussud }
732*2189Ssdussud 
733*2189Ssdussud /*
734*2189Ssdussud  * FUNCTION :   get_list_max()
735*2189Ssdussud  *
736*2189Ssdussud  * DESCRIPTION: return references to static variables map_id_list
737*2189Ssdussud  *              and max_map;
738*2189Ssdussud  *
739*2189Ssdussud  * GIVEN :      address for referencing map_id_list
740*2189Ssdussud  *              address for referencing max_map
741*2189Ssdussud  *
742*2189Ssdussud  * RETURNS :    nothing
743*2189Ssdussud  */
744*2189Ssdussud void
745*2189Ssdussud get_list_max(map_id_elt_t ***list, int *max)
746*2189Ssdussud {
747*2189Ssdussud 	*list = map_id_list;
748*2189Ssdussud 	*max = max_map;
749*2189Ssdussud }
750