% run this through LaTeX with the appropriate wrapper

\chapter {Programming the Directory}

This part of the manual is written for implementors who wish to access the
Directory using the \man libdsap(3n) library.
This might be an OSI application wishing to look up information,
or an interactive Directory user-interface.
The interface to the Directory is defined as a series of procedures which
closely parallel the service defined in \cite{CCITT.Directory}.  This section
defines the procedures,
and shows how they relate to the standard.
To avoid unnecessary wordiness, the user is expected to be familiar with
the standard.

\section      {Conventions}
\label{quipu_conv}

The library defines various C structures, described in the 
following sections
Associated with the C structures, are routines which:

\begin{itemize}
\item allocate structures

\item free structures, including sub-structures

\item compare structures

\item copy structures

\item print structures

\item parse structures
\end{itemize}

The following conventions are followed in many routines, which are then
briefly identified later.
For a general structure x, there will be the following routines:
\begin{itemize}
\item Allocation:
\begin{quote}\small\begin{verbatim}
struct x *x_alloc ()
\end{verbatim}\end{quote}
Allocate memory for structure \verb"x".

\item Freeing:
\begin{quote}\small\begin{verbatim}
x_free (a)
struct x * a;
\end{verbatim}\end{quote}
Free structure \verb"x", and any nested structures.

If the structure, \verb"x", is a linked-list type of structure, then as well
as the routines described above, there will be routines of the
form \verb"x_comp_function" (where \verb"function" is \verb"alloc",
\verb"free", and so on).  These act upon a single element of the
list rather than the list as a whole.

\item Copying:
\begin{quote}\small\begin{verbatim}
struct x * x_cpy (a)
struct x *a;
\end{verbatim}\end{quote}
Return a copy of structure \verb"a".

\item Comparing:
\begin{quote}\small\begin{verbatim}
int     x_cmp (a, b)
struct x *a, *b;
\end{verbatim}\end{quote}
Return \verb"0" if the structures \verb"a" and \verb"b" same.  Return
\verb"-1" if \verb"a<b", or \verb"1" if \verb"a>b".
For some structures the notion of \verb"a>b" and \verb"a<b" is not defined,
but will be consistent.

\item Printing:
\begin{quote}
\index{rdn\_print}\index{dn\_print}\index{as\_print}\index{avs\_print}
\index{AttrT\_print}\index{AttrV\_print}
\small\begin{verbatim}
int     x_print (ps, a, format)
PS       ps;
struct x *a;
int      format;
\end{verbatim}\end{quote}
Print the structure \verb"a" to the presentation stream \verb"ps", using the
specified format, either \verb"READOUT", for a pretty-printed format (for
example the output of a showentry from \pgm{dish}); or,
\verb"EDBOUT", for a format suitable for inclusion in an EDB file.
The \verb"PS" structure is described in \volone/ of this manual.

For the structures representing a DN and RDN there is an extra format:-
\verb"DIROUT", which is used to get a representation of the name suitable
for inclusion in a \unix/ filename (essentially \verb"EDBOUT" with the
\verb"@" symbols replaced with \verb"/" separators).

\item String format:
\begin{quote}
\index{str2rdn}\index{str2dn}\index{str2as}
\index{str2AttrV}\index{str2AttrT}
\small\begin{verbatim}
struct x * str2x (str)
char * str;
\end{verbatim}\end{quote}
Most attribute syntaxes have a string representation.
A string of the required 
syntax can be converted to the relevant c structure with the ``str2x''
function.
Each of the string parsers assumes the input string has had multiple spaces
and tabs removed, and replaced with single spaces.
The function 
\begin{quote}\small\begin{verbatim}
char * Tidy_String (a)
char * a;
\end{verbatim}\end{quote}
will do the relevant tidying if required.
Strings printed with the \verb"EDBOUT" format of x\_print should be parsable.

NOTE \verb"str2AttrV()" \index{str2AttrV} does not follow the ``convention''
and has an extra parameter, 
which is the expected syntax
of the string.

\item Decoding:
\begin{quote}\small\begin{verbatim}
x_decode (a)
struct x *a;
\end{verbatim}\end{quote}
For efficiency reasons,
when information is read from a DSA any
structures that contain nested AttributeTypes and
AttributeValues will not be fully decoded.
This will not matter if
you only intend to use the structures internally, but if you
intend to show the structure to a ``user'' or write to a log file, 
you should call this
routine to complete the decoding, which will replace the
various ``unfriendly'' structures (such as OID) with string
representations.
\end{itemize}

The structures following the ``convention'' are listed below.
The ``prefix'' column shows the value
\verb"x" should be replaced by to use the routines for the associated
 structure.
\index{RDN}
\index{DN}
\index{AttributeType}\index{AttrT}
\index{AttributeValue}\index{AttrV}
\index{AV\_Sequence}\index{avs}
\index{Attr\_Sequence}\index{as}
\index{EntryInfo}


\[\begin{tabular}{|l|l|} \hline
Structure & Prefix \\ \hline
RDN & rdn \\
DN & dn \\
AttributeType & AttrT \\
AttributeValue & AttrV \\
AV\_Sequence & avs \\
Attr\_Sequence & as \\
EntryInfo& entryinfo \\ \hline
\end{tabular}\]

\section {Attributes}

Attributes are fundamental
components of the directory.  
Attributes have two parts, types and values, which are
(respectfully) represented by two structures,
\verb"AttributeType" and \verb"AttributeValue".

For programing purposes you should include the file \file{quipu/attrvalue.h}
into your programs, which contains the following structure definitions:-

\begin{quote}\index{AttributeType}\small\begin{verbatim}
typedef struct {
        OID              at_oid;
        oid_table_attr * at_table;
} attrType, * AttributeType;
#define NULLAttrT (AttributeType) NULL
\end{verbatim}\end{quote}


The \verb"AttributeType" structure contains two components, only one
of which is used at any one time.  An \verb"AttributeType" is defined
in \cite{CCITT.Directory} as an OBJECT IDENTIFIER, hence the field
\verb"at_oid".  

But
\man libdsap(3n) goes further than this, and has a table (described in
Section~\ref{oidtables}) which maps strings onto these OIDs.  The
second field (\verb"at_table") is a pointer to this table.  The table
then contains the OID.  

This table must be loaded by calling
\begin{quote}\index{load\_oid\_table}\small\begin{verbatim}
load_oid_table(name)
char * name;
\end{verbatim}\end{quote}
The \verb"name" parameter should be the name of the oidtable to load.
For most purposes this should be ``\verb"oidtable"''.

Before you load the table, any syntaxes you want special attribute handlers
for should be loaded.  To do this you will probably want to call
\label{quipusyntaxes}
\begin{quote}
\index{quipu\_syntaxes}
\begin{verbatim}
quipu_syntaxes()
\end{verbatim}
\end{quote}
which will load all the syntax handlers defined in Chapter~\ref{syntaxes}.
If not all there syntaxes are required, then a subset can be loaded by
calling only the handlers required.


The call
\begin{quote}\index{dsap\_init}\small\begin{verbatim}
dsap_init(argc,argv)
int *argc;
char *** argv;
\end{verbatim}\end{quote}
can be used to load the oidtable for you, with the additional 
benifit that it will
read the file \file{/etc/dsaptailor} to 
find the location on the oidtable.
The parameters it expects are the pointers to the 
\verb"argc" and \verb"argv"
parameters passed to your ``main()'' routine
(Beware: \verb"dsap_init" removes certain flags from the parameter list, if you care,
pass a copy of them, or pass nulls!).
If a ``\tt -c\rm '' flag is found then this is used as the name of
the DSA to contact as per dish (see Section~\ref{dish_bind}).
Other parameters are ignored.
As with loading the tables, the syntaxes you require should have been loaded
before you make this call.

The oidtables are represented using the following structures:-
\begin{quote}\index{oid\_table}\small\begin{verbatim}
typedef struct {
        char      ot_name [BUFSIZE];
        char      ot_stroid [BUFSIZE];
        OID       ot_oid;
} oid_table;
#define NULLTABLE ((oid_table * )0)

typedef struct {
        oid_table oa_ot;
        int       oa_syntax;
} oid_table_attr;
#define NULLTABLE_ATTR ((oid_table_attr *)0)
\end{verbatim}\end{quote}


As structures come across the network,
the AttributeType is decoded into the \verb"at_oid" field.  If you
want to use the string representation you must call
\verb"AttrT_decode" (described in Section~\ref{quipu_conv}), 
if you do not decode the structure, the
print routines will still work, but the result will numeric
OIDs.
If successfully decoded the field \verb"at_oid" will be set to \verb"NULLOID",
to indicate that there is a table version of the oid.

The table consists to two fields, an integer syntax :- \verb"oa_syntax".
This is an integer handle onto the abstract syntax of the attribute value.
The value `\verb"0"' indicates an unknown syntax hence ``ASN'' is used.

The second field \verb"oa_ot" is a reference to a \verb"oid_table" structure,
which contain the oid -- \verb"ot_oid", a numeric string representation of the oid
-- \verb"ot_stroid", and the local key string -- \verb"ot_name".

To create an \verb"AttributeType" given a string representation of an
OID, you should use
\begin{quote}\index{str2AttrT}\small\begin{verbatim}
AttributeType str2AttrT (str)
char   *str;
\end{verbatim}\end{quote}
which looks up the string ``\verb"str"'' in the OID table, and creates an
\verb"AttributeType" structure.

There are various low level routines to manipulate entries in
the OID table, however the \verb"AttributeType" routines described in 
Section~\ref{quipu_conv}
will be sufficient for most uses, so the details of these
``invisible'' routines are omitted here.


Attribute values are represented by the structure \verb"AttributeValue":-

\begin{quote}\index{AttributeValue}\small\begin{verbatim}
typedef struct attrVal {
        short      av_syntax;
        caddr_t	   av_struct;
} * AttributeValue;

#define NULLAttrV (AttributeValue) NULL
\end{verbatim}\end{quote}

The \verb"AttributeValue" structure can hold attribute values in two
formats. Firstly as a specialised {\em C\/} structure pointed to by
\verb"av_struct", the
field \verb"av_syntax" defines the syntax represented by the
\verb"av_struct" field.
Secondly as a presentation element (also in the \verb"av_struct" field), this is the case when an attribute has
been received from the net, but not decoded (indicated by
the syntax being zero).  The routine \verb"AttrV_decode"
will burst this presentation element into the relevant \verb"av_struct"
field.
Section ~\ref{add_syntax} describes this more fully.


Attribute values can now be linked together to form a multi-value attribute
value.
For this the \verb"AV_Sequence" structure is used.

\begin{quote}\index{AV\_Sequence}\small\begin{verbatim}
typedef struct avseqcomp {     
    attrVal             avseq_av;
    struct avseqcomp    *avseq_next;
} avseqcomp, *AV_Sequence;

#define NULLAV ((AV_Sequence) 0)
\end{verbatim}\end{quote}

This is simply a linked list of AttributeValues\footnote{
For those of you who wrote interfaces using ISODE-5.0, you should note that
the field \verb+avseq\_av+ is now an \verb+attrVal+ and not an 
\verb+attrVal *+.
}.

To create an \verb"AV_Sequence" the two routines
\begin{quote}\index{avs\_comp\_new}\index{avs\_merge}\small\begin{verbatim}
AV_Sequence avs_comp_new (av)
AttributeValue av;

AV_Sequence avs_merge (a,b)
AV_Sequence a,b;
\end{verbatim}\end{quote}
can be used.

Finally an attribute can now be formed by linking the attribute type, and
multiple attribute values using the \verb"AttrSequence" structure:-

\begin{quote}\index{Attr\_Sequence}\small\begin{verbatim}
typedef struct attrcomp {       
    attrType            attr_type;
    AV_Sequence         attr_value;
    struct attrcomp     *attr_link;
    struct acl_info     *attr_acl;
} attrcomp, *Attr_Sequence;

#define NULLATTR ((Attr_Sequence) 0)
\end{verbatim}\end{quote}

This structure is used singularly to represent an attribute, and as a linked
list (linked using \verb"attr_link") to represent a set of attributes.

To create an \verb"Attr_Sequence" the two routines
\begin{quote}\index{as\_comp\_new}\index{as\_merge}\small\begin{verbatim}
Attr_Sequence as_comp_new (at,as,acl)
AttributeType at;
AV_Sequence as;
struct acl_info * acl;

Attr_Sequence as_merge (a,b)
Attr_Sequence a,b;
\end{verbatim}\end{quote}

can be used.
The \verb"acl" parameter is only used by the DSA, for use in a DUA it should be
set to \verb"NULLACL_INFO".

The routine
\begin{quote}\index{as\_combine}\small\begin{verbatim}
Attr_Sequence as_combine (as,str)
AV_Sequence as;
char * str;
\end{verbatim}\end{quote}
is also provided, as an optimisation of
\begin{quote}\small\begin{verbatim}
as_merge(as,str2as(str));
\end{verbatim}\end{quote}

\section {Distinguished Names}
The structures which define names are critical.  
Names are essentially made up of attributes, but because of their
importance, a different --- more specific structure is used.

\begin{quote}\index{RDN}\small\begin{verbatim}
typedef struct rdncomp {       
    attrType            rdn_at;
    attrVal             rdn_av;
    struct rdncomp      *rdn_next;
} rdncomp, *RDN;

#define NULLRDN ((RDN) 0)
\end{verbatim}\end{quote}

An RDN consists of a set of Attribute Types 
(\verb"rdn_at"\footnote{This was an \verb+attrType *+ in ISODE-5.0})
and Attribute Values 
(\verb"rdn_av"\footnote{This was an \verb+attrVal *+ in ISODE-5.0}),
the set is linked using \verb"rdn_next".

RDNs can the be joined in a sequence to form a Distinguished Name (DN):-
\begin{quote}\index{DN}\small\begin{verbatim}
typedef struct dncomp {
    RDN                 dn_rdn;
    struct dncomp       *dn_parent;
} dncomp, *DN;

#define NULLDN ((DN) 0)
\end{verbatim}\end{quote}

The following routines are provided in addition to the routines defined is
Section~\ref{quipu_conv} to allow the user to create and manipulate names

\begin{itemize}
\item Create a DN given an RDN:
\begin{quote}\index{dn\_comp\_new}\small\begin{verbatim}
dn_comp_new (rdn)
RDN     rdn;
\end{verbatim}\end{quote}

\item Append a DN to the end of another DN:
\begin{quote}\index{dn\_append}\small\begin{verbatim}
dn_append (dn1, dn2)
DN      dn1,
        dn2;
\end{verbatim}\end{quote}
\verb"dn2" is added to \verb"dn1".

\item Create a RDN given and AttributeType and AttributeValue:
\begin{quote}\small\index{rdn\_comp\_new}\begin{verbatim}
RDN rdn_comp_new (at, av)
AttributeType  at;
AttributeValue av;
\end{verbatim}\end{quote}

\item Merge two RDNs:
\begin{quote}\small\index{rdn\_merge}\begin{verbatim}
RDN rdn_merge (rdn1, rdn2)
RDN     rdn1,
        rdn2;
\end{verbatim}\end{quote}
RDN's form a set, to make comparisons easier, this
implementation assumes them to be ordered sets.  This routine
takes two ordered RDN sets, and merges them.
If RDNs received across the network are not ordered, the decoding
process will order them for you.
\end{itemize}

The approach to access control is defined in
\cite{QUIPU.Design}.
The representation of the attribute for access control is given by the
structure shown below.  This closely follows the ASN.1
definition.

\begin{quote}\small\begin{verbatim}
struct acl_info {
    int              acl_categories;
#define ACL_NONE        0
#define ACL_DETECT      1
#define ACL_COMPARE     2
#define ACL_READ        3
#define ACL_ADD         4
#define ACL_WRITE       5
    int              acl_selector_type;
#define ACL_ENTRY       0
#define ACL_OTHER       1
#define ACL_PREFIX      2
#define ACL_GROUP       3
    DN               acl_name;
    struct acl_info *acl_next;
};
\end{verbatim}\end{quote}

The DN \verb"acl_name" is used for the type \verb"ACL_PREFIX" and
\verb"ACL_OTHER" only.

\section {Adding New Syntaxes to QUIPU}
\label{add_syntax}

It will probably be necessary to add knowledge of extra syntaxes to
Directory User Interfaces as the range of applications grow.
QUIPU has been designed to make this as easy as possible.

This section describes how you might do this, by adding knowledge
of a \verb"FOOBAR" syntax to \man libdsap(3n) library.
\verb"FOOBAR" is represented by the c structure
``\tt struct foobar \{\ldots\};\rm ''.

The DSA does not need to know about the new structure, as it will
handle unknown syntaxes as blocks of ASN.1.

The procedure call
\begin{quote}\small\begin{verbatim}
add_attribute_syntax (sntx,enc,dec,parse,
                      print,cpy,cmp,sfree,
                      print_pe,approx,multiline)
char *  sntx;
IFP     enc,dec,parse,print,cpy,cmp,sfree,approx;
char *  print_pe;
char    multiline;
\end{verbatim}\end{quote}
is used to add knowledge of new attribute syntaxes to quipu.

The parameters are used as follows:-

\begin{describe}
\item [\verb"sntx":] The string defining the syntax, in this case it should
be \verb"Foobar". Any attributes defined as having the syntax ``Foobar'' in
the oidtables will the be handled using the following routines.

\item [\verb"enc":] This is a function pointer to a routine that will convert
a C structure representation of foobar into a presentation element that can
be sent across the network.
The routine is given a single parameter --- a pointer to the foobar structure,
and is expected to return a PE.
You are reminded of the \man pepy(1c) and \man posy(1c) utilities described
in \volfour/ of this manual, they may be of help in creating this encoder.

\item [\verb"dec":] This performs the inverse of the above, it is passed a
PE, and should return a C structure representation.

\item [\verb"parse":] Each syntax needs to have a representation that can
be read from and written to an EDB file.  This defined routine should take
 a single
\verb"char *" argument and return a C structure representation.

\item [\verb"print":] This routine is used to print the syntax to a 
\verb+PStream+\footnote{\verb+PStream+'s are discussed in \volone/ of this
manual.}.
The arguments are:
\begin{quote}\small\begin{verbatim}
foobar_print (ps,fb,format)
PS ps;
struct foobar * fb;
int format;
\end{verbatim}\end{quote}
If \verb"format" is \verb"READOUT" the structure should be printed to the
stream PS in a ``human readable'' manner, otherwise is should be printed
in a form that can be parsed by the ``parse'' function.
NOTE in many case both formats will be the same.

\item [\verb"cpy":] This function should take a foobar structure as a
parameter and returns a copy of it.

\item [\verb"cmp":] A function that takes two foobar structures and compares
them --- returning 0 if they are the same, 1 is the first is considered
``greater'' than the second, -1 otherwise.
If there is no appropriate ordering for the syntax, return 2.
If an error occurs during the comparison return -2.

\item[\verb"sfree":] A routine to free the structure foobar.

\item[\verb"print\_pe":] The name of an external process to `exec' when the
\verb+READOUT+ option is supplied to the print routine.
This is generally set to \verb+NULLCP+ which means the default `print'
routine is used.

\item[\verb"approx":] A routine to perform approximate matching (if
required).
The routine should expect two parameters as shown:
\begin{quote}
\begin{verbatim}
foobar_approx (a,b)
    struct filter_item * a;
    AV_Sequence b;
\end{verbatim}
\end{quote}
The routine should return \verb+OK+ or \verb+NOTOK+ depending on whether 
any attribute value in the \verb+AV_Sequence+ approximately matches the 
\verb+filter_item+.

\item[\verb"multiline":] If \verb"TRUE" the multi-value attributes will be
printed on separate lines:
\begin{quote}\small\begin{verbatim}
foobar = value1
foobar = value2
\end{verbatim}\end{quote}
otherwise the attribute will be printed on one
line:
\begin{quote}\small\begin{verbatim}
foobar = value1 & value2
\end{verbatim}\end{quote}

\end{describe}

\subsection {Where to Add the Syntax Definition}

Where should you add this procedure call, to define the new syntaxes?

This depends on which applications you want to know about the syntax.
If you want the DSA and all DUAs to know about the syntax, then this call
should be added to libdsap, in the directory dsap/common.
The file dsap/common/quipu\_sntx.c is where other similar calls are made.
A small test program \verb"test" is included in the common directory, and is
made with ``\verb+make test+''.  It takes as input a string representation of
attributes, and exercises the handlers.
If this works for your new attribute, then it should be safe to re-compile the
DSA/DUA and try them.

If you only wish your DUAs to know about the new syntax, then add the call
into you DUAs code, before loading the oidtables of calling \verb+dsap_init+.

