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