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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*a87701e9SGary Mills * Copyright 2015 Gary Mills 247c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * DESCRIPTION: Contains the map update thread and related code. 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <syslog.h> 347c478bd9Sstevel@tonic-gate #include <ndbm.h> 357c478bd9Sstevel@tonic-gate #include <thread.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <strings.h> 387c478bd9Sstevel@tonic-gate #include "ypsym.h" 397c478bd9Sstevel@tonic-gate #include "ypdefs.h" 407c478bd9Sstevel@tonic-gate #include "shim.h" 417c478bd9Sstevel@tonic-gate #include "yptol.h" 427c478bd9Sstevel@tonic-gate #include "../ldap_util.h" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* Enable standard YP code features defined in ypdefs.h */ 457c478bd9Sstevel@tonic-gate USE_YP_PREFIX 467c478bd9Sstevel@tonic-gate USE_YP_MASTER_NAME 477c478bd9Sstevel@tonic-gate USE_YP_LAST_MODIFIED 487c478bd9Sstevel@tonic-gate USE_YP_INPUT_FILE 497c478bd9Sstevel@tonic-gate USE_YP_OUTPUT_NAME 507c478bd9Sstevel@tonic-gate USE_YP_DOMAIN_NAME 517c478bd9Sstevel@tonic-gate USE_YP_SECURE 527c478bd9Sstevel@tonic-gate USE_YP_INTERDOMAIN 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * Decs 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate suc_code update_from_dit(map_ctrl *, datum *); 587c478bd9Sstevel@tonic-gate void * update_thread(void *); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * Globals 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate extern pid_t parent_pid; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * FUNCTION: update_entry_if_required() 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * DESCRIPTION: Determines if an entry is to be updated and if it is does the 697c478bd9Sstevel@tonic-gate * update. 707c478bd9Sstevel@tonic-gate * 717c478bd9Sstevel@tonic-gate * GIVEN : Pointer to the open map ctrl 727c478bd9Sstevel@tonic-gate * Pointer to the entry key 737c478bd9Sstevel@tonic-gate * 747c478bd9Sstevel@tonic-gate * RETURNS : SUCCESS = Entry is in a state to be returned to the client 757c478bd9Sstevel@tonic-gate * i.e. either got updated, did not need to be updated or we are 767c478bd9Sstevel@tonic-gate * in a mode where it is acceptable to return out of date 777c478bd9Sstevel@tonic-gate * information. 787c478bd9Sstevel@tonic-gate * FAILURE = Entry need an update but it could not be done. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate suc_code 817c478bd9Sstevel@tonic-gate update_entry_if_required(map_ctrl *map, datum *key) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* Only update individual entries if entire map is */ 857c478bd9Sstevel@tonic-gate /* not being updated */ 867c478bd9Sstevel@tonic-gate if (is_map_updating(map)) 877c478bd9Sstevel@tonic-gate return (SUCCESS); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * If we are being asked for the order then need to check if 917c478bd9Sstevel@tonic-gate * the map is in need of an update. If it is then fake a 927c478bd9Sstevel@tonic-gate * recent order. The client will then read the map, using 937c478bd9Sstevel@tonic-gate * dbm_firstkey and this will do the update. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate if (0 == strncmp(key->dptr, yp_last_modified, yp_last_modified_sz)) { 967c478bd9Sstevel@tonic-gate if (has_map_expired(map)) 977c478bd9Sstevel@tonic-gate update_timestamp(map->entries); 987c478bd9Sstevel@tonic-gate return (SUCCESS); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* Never update special keys. Have no TTLs */ 1027c478bd9Sstevel@tonic-gate if (is_special_key(key)) 1037c478bd9Sstevel@tonic-gate return (SUCCESS); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate if (!has_entry_expired(map, key)) 1067c478bd9Sstevel@tonic-gate /* Didn't need an update */ 1077c478bd9Sstevel@tonic-gate return (SUCCESS); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* Do the update */ 1107c478bd9Sstevel@tonic-gate return (update_from_dit(map, key)); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * FUNCTION: update_from_dit() 1157c478bd9Sstevel@tonic-gate * 1167c478bd9Sstevel@tonic-gate * DESCRIPTION: Called to update an entry from the DIT 1177c478bd9Sstevel@tonic-gate * 1187c478bd9Sstevel@tonic-gate * INPUTS: Map control structure for an open map 1197c478bd9Sstevel@tonic-gate * Entry key 1207c478bd9Sstevel@tonic-gate * 1217c478bd9Sstevel@tonic-gate * OUTPUTS: SUCCESS = Update complete or we are in a mode where it is 1227c478bd9Sstevel@tonic-gate * acceptable to return out of date information. 1237c478bd9Sstevel@tonic-gate * FAILURE = Update failed 1247c478bd9Sstevel@tonic-gate * 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate suc_code 1277c478bd9Sstevel@tonic-gate update_from_dit(map_ctrl *map, datum *key) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate datum dat; 1307c478bd9Sstevel@tonic-gate int ret; 1317c478bd9Sstevel@tonic-gate suc_code res; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Netgroup maps are a special case we cannot update just one entry so 1357c478bd9Sstevel@tonic-gate * update the entire map instead. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate if ((0 == strcmp(map->map_name, NETGROUP_BYHOST)) || 1387c478bd9Sstevel@tonic-gate (0 == strcmp(map->map_name, NETGROUP_BYUSER))) { 1397c478bd9Sstevel@tonic-gate return (update_map_if_required(map, FALSE)); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* Read entry from the DIT */ 1437c478bd9Sstevel@tonic-gate ret = read_from_dit(map->map_name, map->domain, key, &dat); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* Check that we got something */ 1467c478bd9Sstevel@tonic-gate if (NULL == dat.dptr) { 1477c478bd9Sstevel@tonic-gate if (0 == ret) { 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * In a mode where it is acceptable to return out of 1507c478bd9Sstevel@tonic-gate * date information. 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 1537c478bd9Sstevel@tonic-gate "LDAP inaccessible returning old information"); 1547c478bd9Sstevel@tonic-gate return (SUCCESS); 1557c478bd9Sstevel@tonic-gate } else { 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * In a mode where it is not acceptable to return out 1587c478bd9Sstevel@tonic-gate * of date information. 1597c478bd9Sstevel@tonic-gate * 1607c478bd9Sstevel@tonic-gate * If the error positviely indicates that there is no 1617c478bd9Sstevel@tonic-gate * such entry delete it. For errors where object may 1627c478bd9Sstevel@tonic-gate * still exist in the DIT leave it. 1637c478bd9Sstevel@tonic-gate */ 1647c478bd9Sstevel@tonic-gate if (MAP_NO_MATCHING_KEY == ret) { 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Don't log errors. If the entry was not 1677c478bd9Sstevel@tonic-gate * already present then no problem. The user 1687c478bd9Sstevel@tonic-gate * just asked us for a non existant entry. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate dbm_delete(map->entries, *key); 1717c478bd9Sstevel@tonic-gate dbm_delete(map->ttl, *key); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate return (FAILURE); 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* Write it to DBM */ 1787c478bd9Sstevel@tonic-gate res = dbm_store(map->entries, *key, dat, DBM_REPLACE); 1797c478bd9Sstevel@tonic-gate sfree(dat.dptr); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate if (SUCCESS != res) 1827c478bd9Sstevel@tonic-gate return (FAILURE); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* Update TTL */ 1857c478bd9Sstevel@tonic-gate update_entry_ttl(map, key, TTL_RUNNING); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate return (SUCCESS); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * FUNCTION: update_map_if_required() 1927c478bd9Sstevel@tonic-gate * 1937c478bd9Sstevel@tonic-gate * DESCRIPTION: Called to update an entire map if it is out of date. Map ctrl 1947c478bd9Sstevel@tonic-gate * must be locked before this is called. This handles checking if 1957c478bd9Sstevel@tonic-gate * the map is already being updated. It is important that this is 1967c478bd9Sstevel@tonic-gate * done atomically with obtaining the maps update lock. 1977c478bd9Sstevel@tonic-gate * 1987c478bd9Sstevel@tonic-gate * INPUTS: Map control structure for an open map 1997c478bd9Sstevel@tonic-gate * Flag indication if we should wait for completion 2007c478bd9Sstevel@tonic-gate * 2017c478bd9Sstevel@tonic-gate * OUTPUTS: SUCCESS = Map update initiated 2027c478bd9Sstevel@tonic-gate * FAILURE = Map update not initiated 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate suc_code 2057c478bd9Sstevel@tonic-gate update_map_if_required(map_ctrl *map, bool_t wait) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate thread_t tid; 2087c478bd9Sstevel@tonic-gate map_ctrl *new_map; 2097c478bd9Sstevel@tonic-gate suc_code res; 2107c478bd9Sstevel@tonic-gate long flags; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate if (wait) { 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * Actually get the lock 2157c478bd9Sstevel@tonic-gate * 2167c478bd9Sstevel@tonic-gate * May block so unlock map_ctrl while it is done 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate unlock_map_ctrl(map); 2197c478bd9Sstevel@tonic-gate res = lock_map_update(map); 2207c478bd9Sstevel@tonic-gate lock_map_ctrl(map); 2217c478bd9Sstevel@tonic-gate if (SUCCESS != res) { 2227c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 2237c478bd9Sstevel@tonic-gate "Could not lock map %s for update", 2247c478bd9Sstevel@tonic-gate map->map_name); 2257c478bd9Sstevel@tonic-gate return (FAILURE); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate } else { 2287c478bd9Sstevel@tonic-gate /* If not waiting try to get the lock */ 2297c478bd9Sstevel@tonic-gate switch (try_lock_map_update(map)) { 2307c478bd9Sstevel@tonic-gate case 0: 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * We got the lock. Continue to start an update. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate case EBUSY: 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * Some one else got the lock. OK they are 2397c478bd9Sstevel@tonic-gate * doing the update so we can just return. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate return (SUCCESS); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate default: 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * Some serious problem with lock. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate return (FAILURE); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * If we get here are holding the update lock. Make a final check that 2537c478bd9Sstevel@tonic-gate * nobody beat us to the map update while we were getting it. 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate if (!has_map_expired(map)) { 2567c478bd9Sstevel@tonic-gate /* A big waste of time. Somebody else did the update */ 2577c478bd9Sstevel@tonic-gate unlock_map_update(map); 2587c478bd9Sstevel@tonic-gate return (SUCCESS); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * We got the lock and nobody beat us to doing the update. Start our 2637c478bd9Sstevel@tonic-gate * own update. 2647c478bd9Sstevel@tonic-gate * 2657c478bd9Sstevel@tonic-gate * Thread will free the update lock when update is complete. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * Make a copy of the map_ctrl structure so the update thread has an 2717c478bd9Sstevel@tonic-gate * independent version to work with. Note: Must not be on stack. 2727c478bd9Sstevel@tonic-gate * 2737c478bd9Sstevel@tonic-gate * On exit the update thread must free this. 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate new_map = dup_map_ctrl(map); 2767c478bd9Sstevel@tonic-gate if (NULL == new_map) { 2777c478bd9Sstevel@tonic-gate unlock_map_update(map); 2787c478bd9Sstevel@tonic-gate return (FAILURE); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * While thread is running unlock map so other processes can 2837c478bd9Sstevel@tonic-gate * execute non update related accesses 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate unlock_map_ctrl(map); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate flags = THR_BOUND | THR_NEW_LWP; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * If we are not going to thr_join then need to create detached. 2917c478bd9Sstevel@tonic-gate * This prevents a zombie being left when nobody joins us. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate if (!wait && (getpid() == parent_pid)) 2947c478bd9Sstevel@tonic-gate flags |= THR_DETACHED; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* Kick off update thread */ 2977c478bd9Sstevel@tonic-gate if (0 != thr_create(NULL, NULL, update_thread, new_map, 2987c478bd9Sstevel@tonic-gate flags, &tid)) { 2997c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3007c478bd9Sstevel@tonic-gate "Could not create NIS update thread"); 3017c478bd9Sstevel@tonic-gate free_map_ctrl(new_map); 3027c478bd9Sstevel@tonic-gate unlock_map_update(map); 3037c478bd9Sstevel@tonic-gate if (SUCCESS != lock_map_ctrl(map)) 3047c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3057c478bd9Sstevel@tonic-gate "Could not acquire update lock for %s", map->map_name); 3067c478bd9Sstevel@tonic-gate return (FAILURE); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (wait) { 3107c478bd9Sstevel@tonic-gate /* May block but no problem map_ctrl is already unlocked. */ 3117c478bd9Sstevel@tonic-gate thr_join(tid, NULL, NULL); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* Re acquire lock */ 3157c478bd9Sstevel@tonic-gate if (1 != lock_map_ctrl(map)) { 3167c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 3177c478bd9Sstevel@tonic-gate "Could not re-acquire lock for %s", map->map_name); 3187c478bd9Sstevel@tonic-gate return (FAILURE); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate return (SUCCESS); 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * FUNCTION: update_thread() 3267c478bd9Sstevel@tonic-gate * 3277c478bd9Sstevel@tonic-gate * DESCRIPTION: The update thread this is called to update an entire NIS map. 3287c478bd9Sstevel@tonic-gate * if several NIS maps are found to be out of date several 3297c478bd9Sstevel@tonic-gate * instances of this may be running at the same time. 3307c478bd9Sstevel@tonic-gate * 3317c478bd9Sstevel@tonic-gate * Since we are using a duplicate map_ctrl we do not have to lock 3327c478bd9Sstevel@tonic-gate * it. If we did would end up using the same mutex as the parent 3337c478bd9Sstevel@tonic-gate * map ctrl an possibly deadlocking. 3347c478bd9Sstevel@tonic-gate * 3357c478bd9Sstevel@tonic-gate * INPUTS: Map handle (because we need access to name and lock) 3367c478bd9Sstevel@tonic-gate * 3377c478bd9Sstevel@tonic-gate * OUTPUTS: None exits when finished. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate void * 3417c478bd9Sstevel@tonic-gate update_thread(void *arg) 3427c478bd9Sstevel@tonic-gate { 3437c478bd9Sstevel@tonic-gate void *ret = (void *)-1; 3447c478bd9Sstevel@tonic-gate map_ctrl *map; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* Cast argument pointer to correct type */ 3477c478bd9Sstevel@tonic-gate map = (map_ctrl *)arg; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* Actually do the work */ 3507c478bd9Sstevel@tonic-gate if (SUCCESS == update_map_from_dit(map, FALSE)) 3517c478bd9Sstevel@tonic-gate ret = 0; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* Update complete or failed */ 3547c478bd9Sstevel@tonic-gate unlock_map_update(map); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* Free up duplicate copy of the map_ctrl */ 3577c478bd9Sstevel@tonic-gate free_map_ctrl(map); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate thr_exit(ret); 360*a87701e9SGary Mills 361*a87701e9SGary Mills return (NULL); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * FUNCTION : is_special_key() 3667c478bd9Sstevel@tonic-gate * 3677c478bd9Sstevel@tonic-gate * DESCRIPTION: Works out if a given key is one of the special ones. We just 3687c478bd9Sstevel@tonic-gate * check for the "YP_" prefix. This is not 100% safe but if 3697c478bd9Sstevel@tonic-gate * valid keys with a "YP_" prefix exist in the DIT then a lot of 3707c478bd9Sstevel@tonic-gate * other parts of NIS wont work. 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate bool_t 3737c478bd9Sstevel@tonic-gate is_special_key(datum *key) 3747c478bd9Sstevel@tonic-gate { 3757c478bd9Sstevel@tonic-gate if (0 == strncmp(key->dptr, yp_prefix, yp_prefix_sz)) 3767c478bd9Sstevel@tonic-gate return (TRUE); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate return (FALSE); 3797c478bd9Sstevel@tonic-gate } 380