shim.c revision 2
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * DESCRIPTION: Contains the top level shim hook functions. These must have 2N/A * identical interfaces to the equivalent standard dbm calls. 2N/A * Unfortunately many of these will do a copy of a datum structure 2N/A * on return. This is a side effect of the original DBM function 2N/A * being written to pass structures rather than pointers. 2N/A * dbm_nextkey() of dbm_firstkey() cannot be passed to dbm_store(). 2N/A * When the store occurs dbm's internal memory get's reorganized 2N/A * and the static strings pointed to by the key are destroyed. The 2N/A * data is then stored in the wrong place. We attempt to get round 2N/A * this by dbm_firstkey() and dbm_nextkey() making a copy of the 2N/A * key data in malloced memory. This is freed when map_ctrl is 2N/A * Set if in N2L mode and we want to use the new 2N/A * lock mapping mechanism 2N/A/* Number of times to try to update a map before giving up */ 2N/A/* #define MAX_UPDATE_ATTEMPTS 3 */ 2N/A * FUNCTION: shim_dbm_close(); 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A * FUNCTION: shim_dbm_delete(); 2N/A * DESCRIPTION: This function is currently unused but is present so that the 2N/A * set of shim_dbm_xxx() interfaces is complete if required in 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Delete from and ttl map. Not a huge disaster if it fails. */ 2N/A * FUNCTION: shim_dbm_fetch() 2N/A * DESCRIPTION: N2L function used to handle 'normal' dbm_fetch() operations. 2N/A * INPUTS: First two identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Update thinks we should return something */ 2N/A /* Non yptol mode do a normal fetch */ 2N/A * FUNCTION: shim_dbm_fetch_noupdate() 2N/A * DESCRIPTION: A special version of shim_dbm_fetch() that never checks TTLs 2N/A * or updates entries. 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Get the map control block */ 2N/A /* Not updating so no need to lock */ 2N/A * FUNCTION: shim_dbm_firstkey() 2N/A * DESCRIPTION: Get firstkey in an enumeration. If the map is out of date then 2N/A * this is the time to scan it and see if any new entries have been 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A * Due to the limitations in the hashing algorithm ypxfrd 2N/A * may end up waiting on the wrong update. It must thus loop 2N/A * until the right map has been updated. 2N/A * Ideally ypxfr should wait for the map update 2N/A * to complete i.e. pass ypxfrd_flag into 2N/A * update_map_if_required(). This cannot be done 2N/A * because if there is a large map update the client 2N/A * side, ypxfr, can time out while waiting. 2N/A * Because ypxfrd does weird things with DBMs 2N/A * internal structures it's a good idea to 2N/A * reopen here. (Code that uses the real DBM 2N/A * API appears not to need this.) 2N/A * This should not be necessary all we have 2N/A * done is 'mv' the new file over the old one. 2N/A * Open handles should get the old data but if 2N/A * these lines are removed the first ypxfrd 2N/A * read access fail with bad file handle. 2N/A * NOTE : If we don't wait, because of the 2N/A * ypxfr timeout problem, there is no point 2N/A "Could not reopen DBM files");
2N/A /* For daemons that don't wait just try once */ 2N/A /* Move key data out of static memory. See NOTE in file header above */ 2N/A * FUNCTION: shim_dbm_nextkey() 2N/A * DESCRIPTION: Get next key in an enumeration. Since updating an entry would 2N/A * invalidate the enumeration we never do it. 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Move key data out of static memory. See NOTE in file header above */ 2N/A * FUNCTION: shim_dbm_do_nextkey() 2N/A * DESCRIPTION: Get next key in an enumeration. Since updating an entry would 2N/A * invalidate the enumeration we never do it. 2N/A * NOTE : dbm_do_nextkey is not a documented or legal DBM API. 2N/A * Despite this the existing NIS code calls it. One gross hack 2N/A * deserves another so we have this extra shim function to handle 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Move key data out of static memory. See NOTE in file header above */ 2N/A * FUNCTION: shim_dbm_open() 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Find or create map_ctrl for this map */ 2N/A /* Remember flags and mode in case we have to reopen */ 2N/A * This is a good place to check that the 2N/A * equivalent old style map file has not been 2N/A /* Open entries map */ 2N/A /* If we were not successful unravel what we have done so far */ 2N/A /* Return map_ctrl pointer as a DBM *. To the outside world it is */ 2N/A * FUNCTION: shim_dbm_store() 2N/A * DESCRIPTION: Shim for dbm_store. 2N/A * In N2L mode if we are asked to store in DBM_INSERT mode 2N/A * then first an attempt is made to write to the DIT (in the same 2N/A * mode). If this is successful then the value is forced into DBM 2N/A * using DBM_REPLACE. This is because the DIT is authoritative. 2N/A * The success of failure of an 'insert' is determined by the 2N/A * presence or otherwise of an entry in the DIT not DBM. 2N/A * INPUTS: Identical to equivalent dbm call. 2N/A * OUTPUTS: Identical to equivalent dbm call. 2N/A /* Write to the DIT before doing anything else */ 2N/A * FUNCTION : shim_exit() 2N/A * DESCRIPTION: Intercepts exit() calls made by N2L compatible NIS components. 2N/A * This is required because any call to the shim_dbm... series 2N/A * of functions may have started an update thread. If the process 2N/A * exits normally then this thread may be killed before it can 2N/A * complete its work. We thus wait here for the thread to complete. 2N/A * GIVEN : Same arg as exit() 2N/A * FUNCTION : init_yptol_flag() 2N/A * DESCRIPTION: Initializes two flags these are similar but their function is 2N/A * yp2ldap tells the mapping system if it is to work in NIS or 2N/A * NIS+(obsolete) mode. For N2L this is always set to NIS mode. 2N/A * yptol tells the shim if it is to work in N2L or traditional 2N/A * NIS mode. For N2L this is turned on if the N2L mapping file 2N/A * is found to be present. In NIS+(obsolete) mode it is 2N/A * yp2ldap is used to switch appropriate code in the 2N/A * common libnisdb library used by rpc.nisd(obsolete) and ypserv. 2N/A * Use the new lock mapping mechanism 2N/A * FUNCTION : set_yxfrd_flag() 2N/A * FUNCTION : check_old_map_date() 2N/A * DESCRIPTION: Checks that an old style map has not been updated. If it has 2N/A * then ypmake has probably erroneously been run and an error is 2N/A * GIVEN : A map_ctrl containing details of the NEW STYLE map. 2N/A /* Get date of last update */ 2N/A * No problem. We have a new style map but no old style map 2N/A * this will occur if the original data came from native LDAP 2N/A /* Set up datum with key for recorded old map update time */ 2N/A * Because dptr may not be int aligned need to build an int 2N/A * out of what it points to or will get a bus error. 2N/A /* Do the comparison */ 2N/A /* All is well, has not been updated */ 2N/A /* If we get here the file has been updated */ 2N/A "Caution. ypmake may have been run in N2L " 2N/A "mode. This will NOT initiate a NIS map push. In " 2N/A "this mode pushes should be initiated with yppush");
2N/A * If we get here then either the file was updated or there was not 2N/A * a valid old map date (no problem, maybe this is the first time we 2N/A * checked). In either case the old map date entry must be update. 2N/A * FUNCTION : init_lock_system() 2N/A * DESCRIPTION: Initializes all the systems related to map locking. This must 2N/A * be called before any access to the shim functions. 2N/A * GIVEN : A flag indicating if we are being called from ypserv, which does 2N/A * not wait for map updates to complete, or other NIS components 2N/A * RETURNS : TRUE = Everything worked 2N/A * FALSE = There were problems 2N/A /* Remember what called us */ 2N/A * Remember PID of process which called us. This enables update threads 2N/A * created by YP children to be handled differently to those created 2N/A /* Init map locks */ 2N/A "Failed to init process synchronization");
2N/A /* If we are in yptol mode set flag indicating the fact */ 2N/A * If boot random number system. For now go for reproducible 2N/A * If not N2L mode then no error but do not bother initializing update 2N/A "Failed to init update synchronization");