|
|
| Author: | Doug Leavitt <doug.leavitt@sun.com> |
|---|---|
| Version: | DRAFT 0.5 |
| Date: | 2008-03-05 |
Contents
This document specifies the historical (previously undocumented) finder API interfaces and the NSS2 extensions to those APIs as they as part of the following projects:
PSARC/2008/035 - Sparks foreign backend support
PSARC/2007/694 - Duckwater: Simplified name services management
The initial delivery of Sparks: PSARC/2005/133 made no modifications to these APIs.
The versioning and finder interfaces are currently classified as:
Project Private and Committed Private
Because the other nss policy engine to backend interfaces are currently classified in this manner. See PSARC/2005/133.
However, these interfaces are currently treated as:
Volatile
because the new development is being pursued via OpenSolaris.
One of the goals of the Sparks and Duckwater efforts are to document all the name service switch interfaces and eventually expose the interfaces first as volatile, and eventually Committed at some point in the future.
The name service switch interfaces have been private [and mostly undocumented] since their development. While the private status of the interfaces has been restated multiple times, and explicitly documented as private as far back as 1994, this has not prevented uncontracted API usage outside the ON consolidation and unsupported usage by third parties.
This is a well known problem that has been partly responsible for the lack of evolution of these APIs, until the initial delivery of the Sparks project [PSARC/2005/133], in snv_50.
This document is one step towards rectifying this problem.
Currently, it is unclear how many nsswitch backends making use of the uncontracted/unsupported APIs actually exist. Realistically the number of "foreign" nsswitch backends is probably more than 10.
Prior to PSARC/2005/133, the only known documentation for the name service switch is PSARC/1991/018, which briefly discusses the switch at a very high level, and does not document any specific internal interfaces.
Followup ARC cases make it clearer, that these interfaces are all considered project private. See PSARC/2005/133 for a more detailed analysis of prior work.
The sparks effort currently preserves backwards compatibility by keeping the old, backwards compatible, nsswitch interface code in it's original libc location. The new redesigned nsswitch is located in nscd. As discussed in PSARC/2005/133, the public APIs send requests to the new nsswitch which in turn can return a request back to the libc nsswitch via the TRYLOCAL protocol, if the new switch determines that the request must be executed by the old nsswitch to preserve backwards compatibility.
The PSARC/2005/133 delivery preserves compatibility and stability between the old and new interfaces, through 2 means:
PSARC/2005/133 created 2 classes of backends with this behavior.
The first class of backends are pre PSARC/2005/133 backends. These are any backend that has not been updated to behave with the new name service switch engine in nscd, and subsequent versionable changes. These backends are considered 'foreign' to the new name service switch engine. The new name service switch engine returns requests that need to use a foreign backend to the original (obsolete) libc name service switch for local processing on the client. Databases using an old style backend are generally not cached.
The second class of backends are backends that have been updated to support the new interfaces. Nscd has a built in knowledge of a core set of backends that are delivered in unison with nscd and must always adhere to all the current latest nsswitch specifications. In PSARC 2005/133, these backends are the backends delivered with nscd in the ON consolidation.
PSARC/2005/133 introduced the notion of new extended APIs, but failed to also introduce a versioning model.
PSARC/2005/133 used this new model to introduce at least one project private API, in the nss_dns backend to return DNS lookups with associated timeout values from the resolver. Something impossible in the interfaces prior to PSARC/2005/133.
Prior to PSARC 2005/133, changes in backend behavior required physical changes to the project private C structures and #defines in nss header files and accompanying recompilation of all components that depended upon those header files.
Prior to PSARC/2008/035 the name service switch has no versioning capability and no way to differentiate (except with explicit knowledge) what backend has or has not been updated to at least PSARC/2005/133 specifications.
PSARC/2008/035 introduces a method to distinguish unversioned (pre PSARC/2005/133) and versioned (PSARC/2005/133 or later) libraries.
The purpose of this change is to allow nscd to distinguish between foreign backends that have been updated to PSARC/2005/133 specifications and foreign backends that have not been updated. Foreign backends that are updated to PSARC/2008/035 can be used by nscd and therefore caching of data from those backends can occur.
This project introduces minimal versioning support. That is, the ability to distinguish between pre PSARC/2005/133 and post PSARC/2005/133 backends.
This project defines a versioned backend to have, at a minimum, an externally defined version global symbol [dlsym retrievable] whose name is in the form:
_nss_[backend-name]_version
where backend-name corresponds to the backend name used in nsswitch.conf as in:
_nss_nis_version, _nss_files_version
The contents of the variable are treated as a castable (void *) pointer in the native pointer size for the compiled library.
Existence of the symbol in a nsswitch backend with a value of NULL implies that the backend is in compliance with the specifications of PSARC/2005/133.
If this NULL valued symbol exists, nscd will treat the nsswitch backend as eligible for being dlopen'd and used per PSARC/2005/133 specifications. The results from lookups from a backend will be cached along with other lookup results as applicable.
PSARC/2007/694 extends PSARC/2008/035 with the introduction of new finder functions and extensible versioning data provided by each updated nss backend.
This extensible model enables the name service switch projects to add new backend interfaces including configuration and management interfaces. Prior to this effort, the pre PSARC/2005/133 project private finder APIs only lookup pre NSS2 style interfaces.
The extended finder APIs are the interfaces used to detect and extract the new interfaces and options for use by updated applications and nscd.
In PSARC/2007/694, the Duckwater project defines new backend APIs, and options that the Duckwater management tools use to manage naming configuration auto detection, setup, verification etc.
These finder APIs will also allow future Sparks, Duckwater and other projects the flexible ability to easily add and extend backend APIs moving forward.
the pre Sparks name service switch has no concept of versioning.
The finder APIs in NSS are rudimentary APIs that perform simple dlopen/dlsym lookups for function APIs called constructors.
These NSS (pre Sparks) constructor functions, when called, return a project private pointer to a fixed size structure of function pointers for a given set of NSS interfaces. These pointers are then used in undocumented project private behaviors to process backend lookups. Prior to PSARC/2005/133 usage was inconsistent and undocumented. the finder APIs were also undocumented.
The constructor names, function APIs and values are all considered project private APIs.
By it's nature, any API change, addition, or other requires multiple header changes and recompilation of libc, all the nsswitch backends, nscd and any other component that depends on these hard coded interfaces.
This is made worse, by the fact that the project private headers (nss_common.h, nss_dbdefs.h) were publicly exposed in /usr/include and third parties have chosen to become dependent on them.
As a result these interfaces have been left virtually unenhanced for years, resulting in significant lack of functionality enhancements, such as put XbyY.
More NSS details to be provided below.
The NSS2 finder APIs keep the NSS APIs in their backwards compatible behavior, but extend the finder structure to include new APIs that look for a versioning symbol, and then process that symbol as appropriate.
A backend that supports NSS2 versioning compiles, at a minimum with PSARC/2005/133 and PSARC/2008/035 with the further addition that the version symbol defined in PSARC/2008/035 is not NULL, but instead points to a nss_version structure as described below.
The version structure is the structure pointed to by the versioning symbol in all post PSARC/2008/035 backends. The purpose of the versioning structure is to specify the version number of the library and to specify the APIs supported by the backend plus and backend options that may exist.
The structures are intended to be extensible over time. The contents of the structures include variable length lists of APIs and options, both of which can be extended over time.
The intent is to provide a easy to manage, extensible C interface to nss2 backends that is upwards compatible with nss.
The version structure proposed by the ARC case looks like:
/* Currently supported backend version(s) */
#ifndef NSS_VERSION_2_1
#define NSS_VERSION_2_1 0x00020001
#endif
/* Current backend version */
#ifndef NSS_VERSION
#define NSS_VERSION NSS_VERSION_2_1
#endif
/* internal nss_version signal markers for unversioned or foreign backends */
#define NSS_NOVERSION 0x00020000 /* Supports PSARC/2008/035 */
#define NSS_FOREIGN 0xFFFFFFFF /* Unversioned pre PSARC/2005/133 BE */
/*
* NSS version 2 version structure
* This is the structure pointed to by the dlsym accessible version variable.
* _nss_[backend-name]_version
*
* nss_v_version - version supported by the backend.
* nss_v_sz - sizeof nss_version structure
* nss_v_api - list [array] of APIs supported by the backend
* nss_v_api_cnt - API list count
* nss_v_api_flags - NSS_VERSION_SORTED or 0
* nss_v_opt - list [array] of version options supported in the backend
* nss_v_opt_cnt - option list count
* nss_v_opt_flags - NSS_VERSION_SORTED or 0
*/
/* set if API/option names are in ascii sorted order [search] */
#define NSS_VERSION_SORTED 0x1
/* internal flag set if backend api is alloc'd - for V2 compatibility */
#define NSS_ITEM_ALLOCED 0x80000000
struct nss_version {
nssuint_t nss_v_version; /* backend version */
nssuint_t nss_v_sz; /* sizeof struct */
nss_backend_api_t *nss_v_api; /* API array */
nssuint_t nss_v_api_cnt; /* API count */
nssuint_t nss_v_api_flags;
nss_backend_opt_t *nss_v_opt; /* option array */
nssuint_t nss_v_opt_cnt; /* option count */
nssuint_t nss_v_opt_flags;
};
typedef struct nss_version nss_version_t;
The following #define values help determine a backend version
The API structure is created as a list of APIs supported in a particular backend.
/*
* NSS version 2 backend API array item
* This structure is used to define support for a single API in a nss2 backend.
* be_api_name - nss2 (dlsym equivalent) search name
* be_api_flags - API option flags
* be_api_func - pointer to API
* be_api_constr - pointer to [optional] API constructor/init function
*/
struct nss_backend_api {
char *be_api_name; /* API name */
nssuint_t be_api_version; /* API version */
nssuint_t be_api_flags; /* support flags */
nss_backend_nop_t be_api_func; /* API */
nss_backend_nop_t be_api_constr; /* constructor [opt] */
nss_backend_nop_t be_api_destr; /* destructor [opt] */
nssuint_t be_api_reserved; /* reserved field */
};
typedef struct nss_backend_api nss_backend_api_t;
/*
* nss_backend_api_t helper macros
* NSS_API_ENTRY_V1 - creates a V1 entry in a api list.
* cname = V1 constructor function name
* NSS_API_ENTRY_V2 - creates a V2 entry in a api list.
* func = V2 function name
* flag = API flags or 0
* cname = address of [optional] constructor name
* dname = address of [optional] destructor name
*/
#ifndef NSS_APIENTRY_V1
#define NSS_APIENTRY_V1(cname) \
{ #cname, 0, 0, (nss_backend_nop_t)NULL, \
(nss_backend_nop_t)&cname, (nss_backend_nop_t)NULL, 0 }
#endif
#ifndef NSS_APIENTRY_V2
#define NSS_APIENTRY_V2(func, flag, cname, dname) \
{ #func, NSS_VERSION, flag, (nss_backend_nop_t)&func, \
(nss_backend_nop_t)cname, (nss_backend_nop_t)dname, 0 }
#endif
The option structure is created as a list of options supported in a particular backend. Options may be generic across backends, or backend specific.
/*
* NSS version 2 backend option array item
* This structure is used to define support for a nss2 backend option.
* This is to allow extensibility within a version by defining optional
* support in a backend beyond APIs.
*
* This structure specifies support for a single API in the nss2 backend
* be_opt_name - supported backend option name
* be_opt_flags - flags applicable to this option
* NSS_FINDER_WRITABLE this option is writable (not const)
* be_opt_string - field for options with string type value(s)
* be_opt_int - field for options with int type value(s)
*/
struct nss_backend_opt {
char *be_opt_name; /* option name */
nssuint_t be_opt_flags; /* support flags */
char *be_opt_string; /* string value(s) */
nssuint_t be_opt_int; /* int/flag value(s) */
nssuint_t be_opt_reserved; /* reserved field */
};
typedef struct nss_backend_opt nss_backend_opt_t;
The purposes of the finder functions are as follows:
11. foreign (pre-sparks PSARC/2005/133)
11. lists of backends matching certain search criteria This is the scan feature
/*
* FINDER flag options
*
* NSS_FINDER_VCHK version check library (temp opens dyn lib)
* NSS_FINDER_OPEN open (keep open) dyn lib
* NSS_FINDER_CLOSE close dyn lib (OPEN/CLOSE mutually exclusive)
* NSS_FINDER_DELETE TBD
* NSS_FINDER_V1API process (scan/lookup) V1API
* NSS_FINDER_EXTENSION process (scan/lookup) extension API
* NSS_FINDER_WRITABLE dyn lib options are writable (not const)
*/
#define NSS_FINDER_VCHK 0x00000001
#define NSS_FINDER_OPEN 0x00000002
#define NSS_FINDER_CLOSE 0x00000004
#define NSS_FINDER_DELETE 0x00000008
#define NSS_FINDER_V1API 0x00000010
#define NSS_FINDER_EXTENSION 0x00000020
#define NSS_FINDER_WRITABLE 0x00000040
struct nss_backend_finder {
/* NSS version 1 finder operations */
#if defined(__STDC__)
nss_backend_constr_t (*lookup)
(void *lkp_priv, const char *, const char *, void **del_privp);
void (*delete)
(void *del_priv, nss_backend_constr_t);
#else
nss_backend_constr_t (*lookup)();
void (*delete)();
#endif
struct nss_backend_finder *next;
void *lookup_priv;
/* NSS version 2 finder operations */
#if defined(__STDC__)
nss_status_t (*scan_ext)
(const char *db_name, const char *src_name,
nssuint_t flags, nss_backend_src_t ***be_list,
uint32_t *count, void **finder_priv);
nss_status_t (*lookup_ext)
(const char *db_name, const char *src_name,
const char *op_name, const char *key_name,
nssuint_t flags, nss_backend_api_t ***api_list,
uint32_t *count, void **finder_priv);
nss_status_t (*query_ext)
(const char *db_name, const char *src_name,
const char *opt_name,
nssuint_t flags, nss_backend_opt_t ***opt_list,
uint32_t *count, void **finder_priv);
void (*free_ext)
(nss_backend_src_t ***be_list, uint32_t *be_cnt,
nss_backend_api_t ***api_list, uint32_t *api_cnt,
nss_backend_opt_t ***opt_list, uint32_t *opt_cnt,
void **finder_priv);
void (*delete_ext)(void **finder_priv);
#else
nss_status_t (*scan_ext)();
nss_status_t (*lookup_ext)();
nss_status_t (*query_ext)();
void (*free_ext)();
void (*delete_ext)();
#endif
};
typedef struct nss_backend_finder nss_backend_finder_t;
extern nss_backend_finder_t *nss_default_finders;
nss_default_finders is a symbol exposed by libc. This symbol points to the nss_backend_finder_t structure. This structure is the list of pointers to the nss finder function interfaces.
The contents of the structure are currently considered project private. Prior to PSARC 2007/694, The old structure definition is as follows:
struct nss_backend_finder {
/* NSS version 1 finder operations */
#if defined(__STDC__)
nss_backend_constr_t (*lookup)
(void *lkp_priv, const char *, const char *, void **del_privp);
void (*delete)
(void *del_priv, nss_backend_constr_t);
#else
nss_backend_constr_t (*lookup)();
void (*delete)();
#endif
struct nss_backend_finder *next;
void *lookup_priv;
};
The original name service switch provided a lookup finder API that searched for a specific API by database and named backend.
Additionally there is a cleanup/delete API.
The version 1 lookup API returns a pointer to a constructor function for the backend, or NULL if it can not find the backend. The switch engine caches these function pointers; when it needs to perform a backend lookup. The switch calls the constructor function, which returns a pointer to a new instance of the backend, properly initialized or NULL.
The nsswitch engine then uses a hardwired function array indexed by defines in nss_dbdefs.h and nss_backend_t to call the appropriate API in version 1 format. See PSARC/2005/133 for further details.
This behavior is considered stable but obsolete. The array indexes, databases and version 1 definitions related to these finder definitions array indices and other internal behaviors and the associated backend API behaviors are considered stable/standard and obsolete.
The nss version 1 finder interfaces are:
lookup(void *dummy, const char *db_name, const char *src_name,
void **delete_privp)
delete(void *delete_priv, nss_backend_constr_t dummy)
Where:
The following rules apply to these APIs:
nss_backend & nss_backend_t are the hardcoded v1 structures of function pointers used to define the function indices for the various get operations on a per DB basis. Offsets are hardcoded index values defined in nss_dbdefs.h
These structures are considered stable but obsolete as of PSARC/2005/133. New sizes, indices or behaviors post PSARC/2005/133 are not permitted.
The NSS_DBOP_* macros define the indices for the various db behaviors for v1 structure use.
For nsswitch version 2 interfaces, nss_backend_t is considered a backend private pointer and is required to be treated as a void pointer by the frontend.
The version2 APIs use and return data structures defined by the versioning specification.
Additionally, the version2 finder APIs track scanned and open nss backends using the following nss_backend_src structure.
/*
* NSS version 2
* nss_backend_src in memory representation of a found backend library
* This data is returned from the extended scan API.
* be_src_dlh - dlhandle [if the source has been dlopened, NULL if not]
* be_src_name - backend name used in nsswitch.conf
* be_src_lib - backend library name nss_[backend].so.1
* be_src_path - backend library directory path (if opened)
* be_src_verp - backend's version structure ptr/NULL
* be_src_version - backend's version number/NSS_FOREIGN/NSS_NOVERSION
* be_src_mtim - opened libraries mtime timestamp
*/
struct nss_backend_src {
void *be_src_dlh;
char *be_src_name;
char *be_src_lib;
char *be_src_path;
nss_version_t *be_src_verp;
nssuint_t be_src_version;
timestruc_t be_src_mtim;
};
typedef struct nss_backend_src nss_backend_src_t;
These interfaces are considered project private. The purpose of the structure is to list and manage the internal state of open or closed nss backends.
Version 2 adds 5 new extended finder functions.
free_ext - frees memory from previously returned scan/lookup/query delete_ext - closes opened backend(s) from previous *_ext requests
nss_status_t (*scan_ext)
(const char *db_name, const char *src_name,
nssuint_t flags, nss_backend_src_t ***be_list,
uint32_t *count, void **finder_priv);
scan_ext scans library paths and [optionally] dlopens backends to determine the versioning information of the nsswitch library
If libraries are opened, they are opened in RTLD_LAZY mode to reduce dependency loading
Arguments:
The scan API returns the list of found backends. The data is considered read only. The be_list and count may be passed back through repeated scan_ext calls, if the caller wants to add non-duplicate new entries to the current list.
A NULL db_name is a wildcard allowing the scan operation to report for any database. A NULL src_name is a wildcard allowing the scan operation to report for any source.
If the be_list and count pointers are NULL, then the scanning occurs but no results are returned. This is to allow for opening and version checking side effects only.
Flags:
nss_status_t (*lookup_ext)
(const char *db_name, const char *src_name,
const char *op_name, const char *key_name,
nssuint_t flags, nss_backend_api_t ***api_list,
uint32_t *count, void **finder_priv);
As needed, the lookup_ext API performs a scan_ext on the library paths, dlopening the required backends (NSS_FINDER_OPEN) , and determining the versioning information of the nsswitch library. If the library has been previously opened by a scan or earlier lookup operation, the existing open will be shared. The function then performs the lookup function using the new API formats, and versioning control information.
The lookup API returns the list of found APIs. The data is considered direct read-only pointers into the applicable backend library. The api_list and count may be passed back through repeated lookup_ext calls, if the caller wants to add non-duplicate new entries to the current list.
A NULL db_name is a wildcard allowing the lookup operation to report for any database. A NULL src_name is a wildcard allowing the lookup operation to report for any source.
If the api_list and count or finder_priv pointers are NULL, then the lookup fails with a EINVAL errno.
Flags:
nss_status_t (*query_ext)
(const char *db_name, const char *src_name,
const char *opt_name,
nssuint_t flags, nss_backend_opt_t ***opt_list,
uint32_t *count, void **finder_priv);
As needed, the query_ext API performs a scan_ext on the library paths, dlopening the required backends (NSS_FINDER_OPEN) , and determining the versioning information of the nsswitch library. If the library has been previously opened by a scan or earlier lookup operation, the existing open will be shared. The function then performs the query function returning and nss2 options information.
The query API returns the list of found options. The data is considered direct read-only pointers into the applicable backend library. The opt_list and count may be passed back through repeated lookup_ext calls, if the caller wants to add non-duplicate new entries to the current list.
A NULL db_name is a wildcard allowing the lookup operation to report for any database. A NULL src_name is a wildcard allowing the lookup operation to report for any source.
If the api_list and count or finder_priv pointers are NULL, then the query fails with a EINVAL errno.
Only version 2 backends with versioning information are queried. All other backends are ignored.
Specific options may be enabled as read/write. See the versioning section on options for details.
Flags:
void (*free_ext)
(nss_backend_src_t ***be_list, uint32_t *be_cnt,
nss_backend_api_t ***api_list, uint32_t *api_cnt,
nss_backend_opt_t ***opt_list, uint32_t *opt_cnt,
void **finder_priv);
This API frees one or more lists.
If be_list and be_cnt are non NULL, this API will free the be_list. be_cnt is assumed to the appropriate length.
If api_list and api_cnt are non NULL, this API will free the api_list. api_cnt is assumed to the appropriate length.
If opt_list and opt_cnt are non NULL, this API will free the opt_list. opt_cnt is assumed to the appropriate length.
finder_priv is currently ignored.
void (*delete_ext)(void **finder_priv);
This API frees the finder_priv data, and closes any unclosed backends. One the delete_ext API is called any copies or references to any internal nss backend details is invalid.
This section defines the symbol name formats as defined by PSARC/2007/694 and previous.
Are of the form:
_nss_[src_name]_version
Are of the form:
nss_[src_name].so.1
Are of the form:
_nss_[src_name]_[db_name]_constr
Are of the form:
_nss_[op_name]_[src_name]_[db_name]_[key]
Are of the form:
_nss_[src_name]_[db_name]_opt_[opt_name]
Are of the form:
_nss_[src_name]_[ext_name]_[extop_name]
Terms of Use
|
Privacy
|
Trademarks
|
Copyright Policy
|
Site Guidelines
|
Site Map
|
Help
Your use of this web site or any of its content or software indicates your agreement to be bound by these Terms of Use.
© 2012, Oracle Corporation and/or its affiliates.