Novell is now a part of Micro Focus

Accessing and Modifying Information in the NDS Database

Articles and Tips: article

KARL BUNNELL
Software Engineer
Novell Consulting Services

01 Oct 1997


Introduction

This article is the second in a series of articles on NDS development. The first article, "Getting Started with NDS Development" appeared in the September 1997 issue of Novell Developer Notes.

Novell Directory Services is a database of object names and corresponding attribute values. The API interface for accessing and modifying these objects is very similar to the Directory Access Protocol (DAP) defined by x.500. This interface allows the developer to perform any of the standard database operations such as read, list, search, compare and modify. The following table illustrates the mapping between the x.500 DAP function definition and the NDS implementation. Click on the Novell NDS API function name to obtain specific information and sample code for each.


x.500 DAP
NDS Function

Read

NWDSRead()

Compare

NWDSCompare()

List

NWDSList()

Search

NWDSSearch()

AddEntry

NWDSAddObject()

RemoveEntry

NWDSRemoveObject()

ModifyEntry

NWDSModifyObject()

ModifyRDN

NWDSModifyRDN

Novell Directory Services Read Operation

The Read Operation is executed by calling NWDSRead(). This function is used to read attribute names and values from the supplied NDS object. NWDSRead() accepts input parameters that define the criteria for the data returned. This criteria can be defined as follows:

  • All Attribute Names

  • Specific Attribute Names

  • All Attribute Names And Values

  • Specific Attribute Names And Values

NWDSRead() Function Prototype

NWDSCCODE N_API NWDSRead   (



    NWDSContextHandle   context,



    pnstr8              object,



    nuint32             infoType,



    nbool8              allAttrs,



    pBuf_T              attrNames,



    pnint32             iterationHandle,



    pBuf_T              objectInfo);

Let's take a closer look at these parameters.


Parameter
Description

context

The context handle governs the behavior of the read operation.

object

This is the target NDS object for the read operation. The combination of the object namepassed as this parameter and the context variable DCK_NAME_CONTEXT determine thefull path to the object.

infoType

This parameter determines whether just attribute names or attribute names and values arereturned. Following are the MACRO defines for the available options for this parameter:

DS_ATTRIBUTE_NAMES: Only attribute names will be returned.

DS_ATTRIBUTE_VALUES: Attribute names and attribute values will be returned.

allAttrs

This parameter determines whether all attributes should be returned or only thosespecified in an input buffer. The available options for this parameter are:

TRUE: All attributes will be returned.

FALSE: Only those attributes specified in the attrNames input buffer will be returned.

attrNames

The value of this parameter depends on the value of allAttrs. If allAttrs is set to TRUE, thevalue of this parameter should be set to NULL. If allAttrs is set to FALSE, the value of thisparameter should be a pointer to the input buffer that defines the specific attributes thatshould be returned by the read operation.

iterationHandle

This handle governs the flow control between the Directory Server Agent (NDS Server) andthe requesting application. The DSA will only send data in chunks application outputbuffer can accommodate.

objectInfo

This is the output buffer where the results of the read operation will be placed. Rememberthat if the iterationHandle is not set to -1 after the initial call the NWDSRead(), thisfunction must be called again to read the next iteration of data from the DSA.

The Novell SDK defines some addition read operation functions that are extensions to the standard read operation. The names of these functions are as follows:


Function Name
Description

v

This function is identical to NWDSRead() with exception of a time filter parameter whichallows the read operation to further discriminate the data that is returned. The time filter isspecified in UTC time. Only objects that have been modified since the specified time filterare returned.

NWDSReadObjectInfo()

This function returns information about an NDS object that is not available by using NWDSRead() to return attribute information. This function returns the full distinguished name of the object and a structure of type Object_Info_T.

typedef struct {



       nuint32 objectFlags;



       nuint32 subordinateCount;



       time_t  modificationTime;



       nstr8 baseClass[MAX_SCHEMA_NAME_BYTES + 2];



       } Object_Info_T;

Field
Description

objectFlags

The object flags provide additional information about the object type. The possible valuesfor this field are as follows:

DS_ALIAS_ENTRY

DS_PARTITION_ROOT

DS_CONTAINER_ENTRY

subordinateCount

This field returns the number of subordinates of the target object.

modificationTime

This field returns the modification time stamp for the object. This value is in UTC.

baseClass

This fields returns the NDS schema base class of the object.

Novell Directory Services List Operation

The list operation returns the names of the immediate subordinates for the specified entry. No attribute names or values are returned.

NWDSList() Function Prototype

NWDSCCODE N_API NWDSList(



        NWDSContextHandle       context,



        pnstr8              object,



        pnint32             iterationHandle,



        pBuf_T              subordinates);

Let's examine these parameters:


Parameter
Description

context

The context handle governs the behavior of the read operation.

object

This is the target object for the list operation. The value for this parameter must be a container object. The subordinates of the specified object will be returned.

iterationHandle

This handle governs the flow control between the Directory Server Agent (NDS Server) and the requesting application. The DSA will only send data in chunks application output buffer can accommodate.

subordinates

This is the output buffer where the results of the list operation will be placed.Remember that if the iterationHandle is not set to -1 after the initial call toNWDSList(), this function must be called again to read the next iteration ofdata from the DSA.

The Novell NetWare SDK adds some extensions to the NWDSList() API to provide additional functionality or additional filtering capability. These list operation extensions are as follows:


Extension
Description

NWDSListByClassAndName()

This function lists a Directory object's immediate subordinates, restricting the list to subordinate objects matching a specified object class and/or name.

NWDSListContainers()

This function lists only the containers beneath the specified "starting object."

NWDSExtSyncList()

This function is identical to NWDSList() with the additional capability of specifying a time filter parameter which allows the list operation to further discriminate the data that is returned. The time filter is specified in UTC time. Only objects that have been modified since the specified time filter are returned. This function also allows a class name filter to be specified so only objects of the specified schema class are returned.

Novell Directory Services Compare Operation

The compare operation is used to compare an object's attribute value to a specified value. This is a very convenient mechanism to quickly determine whether an attribute value is equal to a specified value without actually reading the value from the target object. For example, if the status of a service registered with NDS is stored in an NDS attribute on the service object (such as a print server), a requesting client could simply test the value of the "status" attribute against "UP." If the match was successful, the client would be cleared to make a connection.

NWDSCompare() Function Prototype

NWDSCCODE N_API NWDSCompare(



            NWDSContextHandle       context,



            pnstr8              objectName,



            pBuf_T              buf,



            pnbool8             matched);

Let's take a closer look at these parameters:


Parameter
Description

context

The context handle governs the behavior of the compare operation.

object

This is the target object for the compare operation.

buf

This is the input buffer that identifies the attribute name and value to compare.

matched

This parameter returns TRUE if the match is successful, otherwise, it returns FALSE.

Novell Directory Services Add Object Operation

The Novell Directory Services add operation is implemented by the function NWDSAddObject(). This function is used to add an object to the Novell Directory Services database. Values for the mandatory attributes defined for the object class to be added must be provided in the input buffer upon calling this function, otherwise, the function will fail.

NWDSAddObject() Function Prototype

NWDSCCODE N_API NWDSAddObject(



            NWDSContextHandle       context,



            pnstr8              objectName,



            pnint32             iterationHandle,



            nbool8              more,



            pBuf_T              objectInfo);

Let's make a closer inspection of these parameters:


Parameter
Description

context

The context handle governs the behavior of the add operation.

objectName

This identifies the name of the object to be added. Remember that by default, the combination of the object name passed as this parameter and the context variable DCK_NAME_CONTEXT determine the full path to the object

iterationHandle

This parameter is reserved and should be set to NULL.

objectInfo

This parameter is a pointer to an input buffer that contains the attribute names and valuesfor the mandatory and optional attributes of the class to be added.

Novell Directory Services Modify Object Operation

The modify operation is implemented by the NWDSModifyObject() function. This operation is used to modify optional attribute values or add new optional attribute values to an existing object. The mandatory attribute values must be added upon creation of the object by NWDSAddObject().

NWDSModifyObject() Function Prototype

NWDSCCODE N_API NWDSModifyObject(



            NWDSContextHandle       context,



            pnstr8              objectName,



            pnint32             iterationHandle,



            nbool8              more,



            pBuf_T              changes);

Let's take a closer look at these parameters.


Parameter
Description

context

The context handle governs the behavior of the modify operation.

objectName

This identifies the name of the object to be modified. Remember that by default, the combination of the object name passed as this parameter and the context variable DCK_NAME_CONTEXT determine the full path to the object.

iterationHandle

This parameter is reserved and should be set to NULL.

more

This parameter is reserved and should be set to zero

objectInfo

This parameter is a pointer to an input buffer that contains the attribute names and values for the optional attributes of the class to be modified.

NWDSModifyObject() accepts a pointer to an input buffer wherein the attribute names and values to be added or modified reside. Following is a list of valid modification operations for NDS attributes:

  • DS_ADD_ATTRIBUTE 0x00 - Add first value of attribute, error if it already exists.

  • DS_REMOVE_ATTRIBUTE 0x01 - Remove all values, error if attribute does not exist.

  • DS_ADD_VALUE 0x02 - Add first or additional value, error if duplicate.

  • DS_REMOVE_VALUE 0x03 - Remove a value, error if it does not exist

  • DS_ADDITIONAL_VALUE 0x04 - Add additional value, error if duplicate or first.

  • DS_OVERWRITE_VALUE 0x05 - Add first or additional value, overwrite if duplicate.

  • DS_CLEAR_ATTRIBUTE 0x06 - Remove all values, no error if attribute does not exist.

  • DS_CLEAR_VALUE 0x07 - Remove value, no error if value does not exist.

Novell Directory Services Remove Object Operation

The remove object operation is implemented by the function NWDSRemoveObject(). This function is used to remove an object from the NDS database.

NWDSRemoveObject() Function Prototype

NWDSCCODE N_API NWDSRemoveObject(



        NWDSContextHandle       context,



        pnstr8              object);

Let's take a closer look at these parameters:


Parameter
Description

context

The context handle governs the behavior of the remove operation.

objectName

This identifies the name of the object to be removed. Remember that by default, thecombination of the object name passed as this parameter and the context variableDCK_NAME_CONTEXT determine the full path to the object.

Novell Directory Services Modify RDN (Rename) Operation

The Modify RDN operation is implemented by the function NWDSModifyRDN(). This function is used to rename an object in the NDS database. Using this operation, the client can change the naming attribute of an existing object or the RDN of an existing object. If the naming attribute is changed, it must comply with the schema definition for the specified object or the operation will fail. Very few base schema object class definitions define multiple naming attribute definitions. The most common use for this operation is to change the RDN (name of the immediate leaf node).

NWDSModifyRDN() Function Prototype

NWDSCCODE N_API NWDSModifyRDN(



        NWDSContextHandle       context,



        pnstr8              objectName,



        pnstr8              newRDN,



        nbool8              deleteOldRDN);

Let's take a closer look at these parameters:


Parameter
Description

context

The context handle governs the behavior of the remove operation.

objectName

This identifies the name of the object to be removed. Remember that by default, thecombination of the object name passed as this parameter and the context variableDCK_NAME_CONTEXT determine the full path to the object.

newRDN

This parameter identifies the new RDN for the NDS object passed as objectName.

deleteOldRDN

If deleteOldRDN is set, all attributes in the old RDN which are not in the new RDN are deleted. If deleteOldRDN is not set, the old attribute values remain in the object as multiplevalues of the attribute. If this operation removes the last value of an attribute, that attribute isdeleted.

The Novell SDK provides some extensions to the ModifyRDN operation. These include:

  • NWDSModifyDN(): This function is used to rename an object in one container to a new object name in another container. The new object name can be specified the same for the destination container as the source object name which simply results in a move of the object from one container to another.

  • NWDSMoveObject: This function is used to move an object from one container to another container. It has the same functionality as NWDSModifyDN() with the exception that the destination container and destination RDN are specified separately.

Novell Directory Services Search Operation

The Search operation provides a very powerful mechanism for defining complex search criteria which returns selected information from NDS objects that meets this user-defined criteria.

NWDSSearch() Function Prototype

NWDSCCODE N_API NWDSSearch(



            NWDSContextHandle       context,



            pnstr8              baseObjectName,



            nint                scope,



            nbool8              searchAliases,



            pBuf_T              filter,



            nuint32             infoType,



            nbool8              allAttrs,



            pBuf_T              attrNames,



            pnint32             iterationHandle,



            nint32              countObjectsToSearch,



            pnint32             countObjectsSearched,



            pBuf_T              objectInfo);

Let's take a closer look at these parameters:


Parameter
Description

context

The context handle governs the behavior of the remove operation.

objectName

This identifies the base object where the search will begin. Set this object to [Root] to initiate a search of the entire tree.

scope

This parameter defines the depth of the search. The available options for this parameter are:

DS_SEARCH_ENTRY (0) - Just search the immediate entry defined by objectName.

DS_SEARCH_SUBORDINATES (1) - Search the immediate subordinates of the entry defined by objectName.

DS_SEARCH_SUBTREE (2) Search all "branches" of the tree beneath the entry defined by objectName.

searchAliases

This parameter can be set to TRUE or FALSE. If set to TRUE, will dereference any aliases found during the search and the search will proceed from the dereferenced alias object ondown the tree. Care must be taken when setting this parameter to TRUE because thedereferenced aliases could result in an endless loop. If set to FALSE, searched objects are not dereferenced.

filter

This parameter contains an input buffer wherein the search criteria are defined.

infoType

This parameter can be set to TRUE or FALSE. If set to TRUE, indicates that attribute names and values should be returned. If set to FALSE indicates that only attribute names should be returned.

allAttrs

This parameter can be set to TRUE or FALSE. If set to TRUE, indicates that all attributesshould be returned and the value passed to attrNames is ignored. If set to FALSE,indicates that the value of attrNames contains an input buffer wherein the attributes to be returned are defined.

attrNames

This parameter contains a pointer to an input buffer that defines the attributes to bereturned. If allAttrs is TRUE, this value is ignored.

iterationHandle

This handle governs the flow control between the Directory Server Agent (NDS Server) andthe requesting application. The DSA will only send data in chunks application outputbuffer can accommodate.

countObjectsToSearch

This parameter is not implemented at the current time. Reserved for use at a later time.

countObjectsSearched

This parameter is not implemented at the current time. Reserved for use at a later time.

objectInfo

This parameter contains a pointer to the result buffer wherein the data that met the searchcriteria is stored.

The NWDSSearch()function is similar to a combination of NWDSList() and NWDSRead() with some additional powerful capabilities to further discriminate the data returned from the operation. The search operation is capable of returning the subordinate object names beginning with a specified base object like NWDSList() and it can return specific attribute names and values like NWDSRead().

The key difference is the filter parameter which allows for complex search queries to be formulated. The search filter is composed by building what is called an expression tree. An expression tree can be visualized as demonstrated in Figure 1.

Each box represents a "node" of the expression tree.

Figure 1: An expression tree.

If the expression tree is read from left to right the resultant filter criteria is: Return all objects where the Surname is equal to Smith and Title is equal to Engineer. The filter buffer is built by using the NWDSAddFilterToken() API. Each filter token represents one node of the expression tree. Each node consists of three node components:

  • Token - Identifies the operation of the node.

  • Value - Identifies the value of the node.

  • Syntax - Identifies the syntax (NDS data type) of the specified Value component.

There are a number of Token component types.

Relational Operators

The following table lists the relational operators.


Relational Operators
Description

7 FTOK_EQ

Equal

8 FTOK_GE

Greater Than or Equal

FTOK_LE

Lesser Than

10 FTOK _ APPROX

Approximate

15 FTOK_PRESENT

Present - Used to test whether a value for a specific attribute is present.

16 FTOK_RDN

Special token which can be used to search for objects of a specific Relative Distinguished Name without requiring that the calling entity have specific rights to the CN (common name) attribute.

17 FTOK_BASECLS

Special token which can be used to search for objects of a specific schema Base Class without requiring that the calling entity have specific rights to the Object Class attribute.

Logical Operators

The following is a list of logical operators:

  • 1 FTOK_OR

  • 2 FTOK_AND

  • 3 FTOK_NOT

  • 4 FTOK_LPAREN

  • 5 FTOK_RPAREN

Other Token Specifiers

The following is a list of other token specifiers:

  • 14 FTOK_ANAME - Attribute Name

  • 6 FTOK_AVAL - Attribute Value

  • 0 FTOK_END - End Token

The value supplied for each node component depends on the value of the filter Token component. For example, the code to implement this expression tree would appear as follows:

Building The Expression Tree

NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &searchFilter);&


NWDSInitBuf(cx, DSV_SEARCH_FILTER, searchFilter);



NWDSAllocFilter(&cur);&


NWDSAddFilterToken(cur, FTOK_ANAME, "Surname", 0);



NWDSAddFilterToken(cur, FTOK_EQ, NULL, 0);



NWDSAddFilterToken(cur, FTOK_AVAL, "Smith", SYN_CI_STRING);



NWDSAddFilterToken(cur, FTOK_AND, NULL, 0);



NWDSAddFilterToken(cur, FTOK_ANAME, "Title", 0);



NWDSAddFilterToken(cur, FTOK_EQ, NULL, 0);



NWDSAddFilterToken(cur, FTOK_AVAL, "Engineer", SYN_CI_STRING);



NWDSAddFilterToken(cur, FTOK_END, NULL, 0);



NWDSPutFilter(context, searchFilter, cur, NULL);

Note that these three node components are passed to NWDSAddFilterToken(). The value of the node components depends on the filter token component. The value for each node component is determined by the following node rules:

  • A Value component only applies to attribute names and attribute values.

  • If the Token component is an operator or parenthesis, you pass a null for the value and syntax.

  • If the Token component is an attribute name, you pass a null for the syntax.

  • Use FTOK_ENDto mark the end of an expression.

The code begins by allocating an input buffer in preparation for storing the search filter. This input buffer is then initialized with DSV_SEARCH_FILTER. Then a temporary cursor buffer is allocated with NWDSAllocFilter() and the expression tree is constructed by using NWDSAddFilterToken() to add individual nodes to the cursor buffer. Once the expression tree is constructed, it is placed in the input buffer with NWDSPutFilter().

NWDSPutFilter() automatically frees the cursor buffer memory and places the constructed expression tree into the input buffer. You can provide your own routine to free the cursor buffer. This is accomplished by passing a pointer to the routine to NWDSPutFilter() (rather than NULL). This can be advantageous if the cursor buffer contains a complex expression tree that you want to use at a later time and you want to avoid having it destroyed by NWDSPutFilter().

The Novell SDK provides an extension to the search operation. This is NWDSExtSyncSearch(). This function is identical to NWDSSearch() with the exception of a time filter parameter which allows for additional filtering on object modification time stamps.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates