Novell is now a part of Micro Focus

Novell Directory Services Q & A

Articles and Tips: article

JOHN BUCKLE
Developer Support Engineer
Developer Support

01 Nov 1996


Novell Directory Services Q & A

Q. After changing the tree name in a directory context, all subsequent NDS calls fail with unknown object or invalid context. Has the directory context been corrupted?

A. The directory context has not been corrupted, it's just that the name context has not been updated for the new tree. The directory context records the tree name and name context in character buffers. These buffers are independent of each other and can be modified separately. Hence, whenever the tree name is modified you should modify the name context. Two possible values for the name context after the tree name has been modified are [Root] or the tree's default name context. The default name context is obtained by using the API NWDSGetDefNameContext. The code in Listing 1 uses this API to set the name context when the tree name is changed. If there is no authenticated connection to the tree then the name context is set to [Root].

Q. How do you list all the trees to which the client has an NDS authenticated connection?

A. There is a specific API to do this: NWDSScanConnsForTrees. This API will return a sorted list of tree names associated with the client. Listing 2 demonstrates how to use the API. The first call to the API is used to get the number of tree names; the second call is then used to fill the buffer.

An alternative approach which avoids using DS APIs is to use the NWCC Client Connection APIs. The function NWCCScanConnRefs can be used to iterate through all client connections. This function returns a connection reference which can be used with the function NWCCGetConnRefInfo to determine if the connection is an NDS authenticated connection and the tree name. Listing 3 uses the above functions to print out the server name and tree name for each connection. In this example the names are not sorted and may be repeated.

The sample code in Listing 3 also gets the tree name for bindery connections to NDS servers. The variable auth can be used to determine if the connection is bindery or NDS. The variable nds can be used to determine if the connection is capable of NDS authentication.

Q. Do you need to be authenticated, or have a connection to a server in the tree, to be able to access information in an NDS tree?

A. No. You can just create a context handle and set the tree name. Once that has been done the requester will locate a server to access the NDS tree. However, until you log in to the tree using NWDSLogin you will only have [Public] access rights.

Q. How can you determine if an NDS tree is available on the network?

A. All NDS trees use SAP to advertise themselves. SAP packets are recorded by NetWare servers as dynamic bindery objects so that clients can locate servers on the network. The Bindery object type for NDS trees is 0x7802. Hence to determine if an NDS tree is available use the API NWGetObjectID to see if the tree name has be recorded in a server's Bindery.

Q. I tried that but it didn't work. What went wrong?

A. Ah, forgot to mention that tree names are 32 characters long, while bindery names are 48. Also tree names have to be padded with underscores. So before searching the bindery, pad the tree name up to 32 characters with underscore characters and add an asterisk at the end. Since there is now a wild card character in the name it is not possible to use NWGetObjectID. Use NWScanObject and count the number of object names returned. If no names are returned then the tree is not available.

Alternatively, you can get the client to do all the work. Create a context handle and set the tree name. Then use the API NWDSGetPartitionRoot asking for the [Root] partition. The client will then search the bindery to find the address of a server it can use to find the partition root. If the tree exists the function will return 0; otherwise it will return 0x89FC (Object not found).

Q. Why does a server mangle the NDS tree names in the bindery?

A. All the servers in an NDS tree that hold a partition will be sending SAP packets for that tree. The last 16 bytes of the dynamic bindery name are used to distinguish the entries. Underscores are used to pad the name since bindery names cannot contain spaces.

Q. How do you get the names of all the trees that are advertised on the network?

A. Use the API NWDSScanForAvailableTrees. This function requires a connection to a server. The function will then return all the Bindery objects of type 0x7802 located in the server's Bindery. Unfortunately this function does not remove the duplicates caused by multiple servers advertising the same tree name.

Alternatively, the API NWDSReturnBlockOfAvailableTrees can be used. According to the documentation, this function returns a sorted list of available trees in blocks and can also return the number of available trees. In practice it appears to be only able to return all the tree names if you provide it with a sufficiently large buffer. The documentation also gives an example of using the function that is incorrect. An example of this function is given in Listing 4.

Listing 1

bool SetCurrentTree(char * treeName)

{

char defContext[MAX_DN_CHARS + 1] ;



    NWDSSetContext(Context,DCK_TREE_NAME,treeName) ;



    if (NWDSCanDSAuthenticate(Context) == 0 ||

        NWDSGetDefNameContext(Context,MAX_DN_CHARS,defContext)){

            NWDSSetContext(Context,DCK_NAME_CONTEXT,DS_ROOT_NAME) ;

            return false ;

            }

    NWDSSetContext(Context,DCK_NAME_CONTEXT,defContext) ;



    return true ;

}

Listing 2

NWDSContextHandle handle = NWDSCreateContext() ;



    if (handle == (NWDSContextHandle) 0xFEB8)

        return ;



    nuint    number = 0 ;

    char **  buffer ;



    if (NWDSScanConnsForTrees(handle,0,& number,0) == 0){

        buffer = new char * [number] ;

        for (int i = 0 ; i < number ; i++)

             buffer[i] = new char[48] ;



        NWDSScanConnsForTrees(handle,number,& number,buffer) ;& number,buffer) ;
        for (int i = 0 ; i < number ; i++){

             puts(buffer[i]) ;

             delete buffer[i] ;

             }

        delete [] buffer ;

        }



    NWDSFreeContext(handle)

;

Listing 3

nuint32 iterator = 0 ;

nuint32 connRef = 0 ;



    NWCallsInit(0,0) ;



    char  treeName  [MAX_TREE_NAME_CHARS + 1] ;

    char  serverName[MAX_SAP_NAME_CHARS + 1] ;



    while (NWCCScanConnRefs(& iterator,& connRef) == 0){

        nuint auth = 0, nds = 0 ;

        treeName  [0] = 0 ;

        serverName[0] = 0 ;



        NWCCGetConnRefInfo(connRef,NWCC_INFO_AUTHENT_STATE,4,& auth) ;& auth) ;
        NWCCGetConnRefInfo(connRef,NWCC_INFO_NDS_STATE, 4,& nds) ;& nds) ;
        NWCCGetConnRefInfo(connRef,NWCC_INFO_TREE_NAME,

                sizeof(treeName), treeName) ;

        NWCCGetConnRefInfo(connRef,NWCC_INFO_SERVER_NAME,

                sizeof(serverName),serverName) ;

        printf("%x %x %s %s\n",auth,nds,treeName,serverName) ;

        }

Listing 4

NWDSContextHandle handle =

NWDSCreateContext() ;



    if (handle == (NWDSContextHandle) 0xFEB8)

        return 0 ;



    nuint32 number  = 0 ;

    nuint32 total   = 0 ;

    nuint32 connRef ;

    char *  buffer[MAX_TREES] ;

    NWCONN_HANDLE connHandle ;



    NWCCGetPrimConnRef(& connRef) ;& connRef) ;
    NWCCOpenConnByRef(connRef,1,0,&connHandle) ;&


    for (int i = 0 ; i < MAX_TREES ; i++)

        buffer[i] = new char[NW_MAX_TREE_NAME_LEN] ;



    NWDSReturnBlockOfAvailableTrees(handle,connHandle,

                "*",0,"*",MAX_TREES,buffer,& number,& total) ;& number,& total) ;


    for (int i = 0 ; i < number ; i++)

        puts(buffer[i]) ;





    for (int i = 0 ; i < MAX_TREES ; i++)

        delete buffer[i] ;

* 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