atnds_test.c

This extended example shows how to convert AFTN address to the corresponding AMHS form, and vice versa. The example also makes use of DSAPI to connect to the directory and manipulate directory data.

To compile this example on Unix machines:

cc -c -I/opt/isode/include/isode/ds/atnds/ -I/opt/isode/include
      -I/opt/isode/include/h

To link this example on Unix machines:

cc -o atnds_test atnds_test.o -L/opt/isode/lib \
    -latnds -ldua -lisode -libase -lmdldap -lmdlber -lssl -lcrypto
/* Copyright (c) 2004-2020, Isode Limited, London, England.
* All rights reserved.
*
* Acquisition and use of this software and related materials for any
* purpose requires a written licence agreement from Isode Limited,
* or a written licence from an organisation licenced by Isode Limited
* to grant such a licence.
*
*/
/*
* atnds_test.c
*
* Test functions of ATNds C library.
*
*/
/*
*
* @VERSION@
*/
#include <stdio.h>
#include <string.h>
#include <isode/mhs/or.h>
DS_Session *ds;
static int read_atn_user (const char *prog, DS_DN *user_dn);
static const char underline[] =
"----------------------------------------------------------------";
static void usage(const char *prog)
{
fprintf( stderr, "Usage: %s "
"[-call presentation-address] "
"[-dn registry-dn] "
"[-read] "
"[-nodn] "
"[-inverse] "
"[-reverse] "
"[-verbose] "
"[-expect result] "
"aftn/caas/xf-address\n", prog );
}
int main( int argc, char *argv[] )
{
const char *call_addr = "Internet=localhost+19999";
const char *registry_dn_str = "o=Isode-MD-Register";
const char *expected_result = NULL;
int read_entry = 0;
int inverse = 0;
int verbose = 0;
int reverse = 0;
int show_dn = 1;
int arg = 1;
int expect = 0;
DS_DN *registry_dn;
DS_DN *user_dn;
char *orbuf = NULL;
size_t orbuf_len;
DS_Indication *di = NULL;
DS_Status status;
DS_ErrorType t;
DS_ErrorValue v;
char *dnbuf;
size_t dnbuf_len;
char aftnbuf[9];
/* Avoid getopt() as it doesn't exist everywhere */
while ( arg < argc && argv[arg][0] == '-' ) {
if ( strncmp( argv[arg], "-call", strlen( argv[arg] ) ) == 0 ) {
if ( arg + 1 <= argc ) {
call_addr = argv[arg + 1];
arg += 2;
continue;
}
}
if ( strncmp( argv[arg], "-dn", strlen( argv[arg] ) ) == 0 ) {
if ( arg + 1 <= argc ) {
registry_dn_str = argv[arg + 1];
arg += 2;
continue;
}
}
if ( strncmp( argv[arg], "-nodn", strlen( argv[arg] ) ) == 0 ) {
show_dn = 0;
arg++;
continue;
}
if ( strncmp( argv[arg], "-read", strlen( argv[arg] ) ) == 0 ) {
read_entry = 1;
arg++;
continue;
}
if ( strncmp( argv[arg], "-inverse", strlen( argv[arg] ) ) == 0 ) {
inverse = 1;
arg++;
continue;
}
if ( strncmp( argv[arg], "-verbose", strlen( argv[arg] ) ) == 0 ) {
verbose = 1;
arg++;
continue;
}
if ( strncmp( argv[arg], "-reverse", strlen( argv[arg] ) ) == 0 ) {
reverse = 1;
arg++;
continue;
}
if ( strncmp( argv[arg], "-expect", strlen( argv[arg] ) ) == 0 ) {
if ( arg + 1 <= argc ) {
expect = 1;
expected_result = argv[arg + 1];
arg += 2;
continue;
}
}
usage( argv[0] );
return 1;
}
/* argv[arg] should be the address to convert */
if ( arg != argc - 1 ) {
usage( argv[0] );
return 1;
}
/* Initialize the DUA library. */
if ( verbose ) {
printf( "\nTEST: initializing DUA library %s.\n", call_addr );
printf( "%s\n", underline );
}
status = DS_Initialize();
if ( status != DS_E_NOERROR ) {
fprintf( stderr, "%s: couldn't initialize DUA library\n", argv[0] );
return status;
}
/* Attempt to bind." */
if ( verbose ) {
printf( "\nTEST: bind (to %s)\n", call_addr );
printf( "%s\n", underline );
}
status = DS_Session_New( call_addr, 0, &ds );
if ( status != DS_E_NOERROR ) {
fprintf( stderr, "%s: failed to create session\n", argv[0] );
return 1;
}
status = DS_BindAnonymousSync( ds, NULL, &di );
if ( ! ( DS_Indication_GetErrorCodes( di, &t, &v ) == DS_E_NOERROR &&
t == DS_E_SUCCESS ) )
status = DS_E_DSOPFAILED;
DS_Indication_Delete( di );
if ( status != DS_E_NOERROR ) {
DS_UnbindSync( &ds );
fprintf( stderr, "%s: couldn't bind to directory\n", argv[0] );
return 1;
}
if ( verbose ) {
printf( "SUCCESS: bound to directory\n" );
}
/* Convert string registry DN to DSAPI DN structure. */
status = DS_String2DN( registry_dn_str, &registry_dn );
if ( status != DS_E_NOERROR ) {
fprintf ( stderr, "%s: error converting DN (%s)\n", argv[0],
registry_dn_str );
return DS_E_BADDN;
}
if ( verbose ) {
printf( "\nTEST: convert to X.400 (%s)\n", argv[arg] );
}
if (!reverse) {
status = ATNds_AFTN2AMHS( ds, registry_dn, argv[arg],
&orbuf, &orbuf_len, &user_dn );
if ( verbose ) {
printf( "%s\n", underline );
}
if ( status != DS_E_NOERROR ) {
switch ( status ) {
case DS_E_NOTFOUND:
fprintf( stderr, "%s: conversion data not found "
"in the ATN directory\n", argv[0] );
return status;
default:
fprintf ( stderr, "%s: conversion failed "
"(%d - no error message available)\n", argv[0], status );
return status;
}
}
if ( verbose ) {
printf( "SUCCESS: conversion succeeded.\n" );
printf( "DETAIL: O/R address is %s\n\n", orbuf );
} else {
printf( "X.400 = %s\n", orbuf );
}
if ( user_dn != NULL ) {
status = DS_DN2String( user_dn, &dnbuf, &dnbuf_len );
if ( status != DS_E_NOERROR ) {
fprintf( stderr, "%s: failed to parse aMHSUser entry DN\n",
argv[0] );
} else {
if ( verbose ) {
printf( "DETAIL: aMHSUser entry DN is %s.\n", dnbuf );
} else if ( show_dn ) {
printf( "User DN = %s\n", dnbuf );
}
ATNds_free( dnbuf );
}
DS_DN_Delete( user_dn );
} else {
if ( verbose ) {
printf( "DETAIL: no aMHSUser entry DN could be computed.\n");
}
}
/* Return now unless we want to do the inverse mapping. */
if ( inverse == 0 ) {
ATNds_free( ( void * ) orbuf );
DS_DN_Delete( registry_dn );
return 0;
}
}
/* Perform inverse conversion. */
if ( verbose ) {
printf( "\nTEST: performing inverse conversion\n(from %s)\n", orbuf );
printf( "%s\n", underline );
}
status = ATNds_AMHS2AFTN( ds, registry_dn, (reverse) ? argv[arg] : orbuf, aftnbuf, &user_dn );
if ( status != DS_E_NOERROR ) {
DS_DN_Delete( registry_dn );
if (orbuf != NULL)
ATNds_free( ( void * ) orbuf );
switch ( status ) {
case DS_E_NOTFOUND:
fprintf( stderr, "%s: conversion data not available\n", argv[0] );
return status;
default:
fprintf ( stderr, "%s: conversion failed "
"(%d - no error message available)\n", argv[0], status );
return status;
}
}
if ( verbose ) {
printf( "SUCCESS: conversion succeeded.\n" );
printf( "DETAIL: AFTN address is %s\n", aftnbuf );
} else {
printf( "AFTN (inverse) = %s\n", aftnbuf );
}
if ( expect ) {
printf( "Checking the conversion result.\n" );
if ( inverse ) {
/* Perform the comparison of the O/R addresses */
OR_ptr orAddr1 = or_std2or(expected_result);
if ( !orAddr1 ) {
fprintf ( stderr, "EXPECTED ERROR: "
"the expected result '%s' is not a valid O/R address\n", expected_result);
}
OR_ptr orAddr2 = or_std2or(orbuf);
if ( !orAddr2 ) {
fprintf ( stderr, "EXPECTED ERROR: "
"the conversion result '%s' is not a valid O/R address\n", orbuf);
}
if ( orAddr_cmp(orAddr1, orAddr2) == 0 ) {
printf( "EXPECTED OK\n" );
} else {
fprintf ( stderr, "EXPECTED ERROR: validation failed, "
"expected '%s' but the conversion result was '%s'\n", expected_result, orbuf);
}
or_free(orAddr1);
or_free(orAddr2);
} else {
if ( strncmp( aftnbuf, expected_result, strlen( expected_result ) ) == 0 ) {
printf( "EXPECTED OK\n" );
} else {
fprintf ( stderr, "EXPECTED ERROR: validation failed, "
"expected '%s' but the conversion result was '%s'\n", expected_result, aftnbuf);
}
}
}
if (orbuf != NULL)
ATNds_free( ( void * ) orbuf );
if ( user_dn != NULL ) {
status = DS_DN2String( user_dn, &dnbuf, &dnbuf_len );
if ( status != DS_E_NOERROR ) {
fprintf( stderr, "%s: failed to display aMHSUser entry DN\n",
argv[0] );
} else {
if ( verbose ) {
printf( "DETAIL: aMHSUser entry DN is %s.\n", dnbuf );
} else if ( show_dn ) {
printf( "User DN (inverse) = %s\n", dnbuf );
}
ATNds_free( dnbuf );
}
if ( read_entry )
read_atn_user( argv[0], user_dn );
DS_DN_Delete( user_dn );
} else {
if ( verbose ) {
printf( "DETAIL: no aMHSUser entry DN could be computed.\n");
}
}
/* Clean up. */
DS_DN_Delete( registry_dn );
/* Unbind from the DSA */
DS_UnbindSync( &ds );
/* All tests done. */
return 0;
}
static int
read_atn_user ( const char *prog, DS_DN *user_dn ) {
DS_Indication *di = NULL;
const DS_EntryList *el;
const DS_Entry *e;
const DS_AttrList *al;
const DS_Attr *a;
DS_ErrorType t;
DS_ErrorValue v;
DS_ErrorType type_p;
int status;
status = DS_ReadSync( ds, user_dn, NULL, NULL, &di );
if ( status != DS_E_NOERROR ) {
if ( di != NULL ) {
DS_Indication_GetStatus ( di, &type_p ) ;
DS_Indication_Delete ( di );
if ( type_p == DS_E_NAME ) {
fprintf( stderr, "%s: No DSA entry for this ATN User entry\n",
prog );
return 0;
}
}
fprintf( stderr, "%s: Failed to read ATN User entry (status=%d)\n",
prog, status );
return 1;
}
if ( ! ( DS_Indication_GetErrorCodes( di, &t, &v ) == DS_E_NOERROR && t == DS_E_SUCCESS ) ) {
return 1;
}
status = DS_Indication_GetEntryList( di, &el );
if ( status != DS_E_NOERROR ) {
DS_Indication_Delete ( di );
fprintf( stderr, "%s: Failed to read ATN User entry Indication\n",
prog );
return 2;
}
e = DS_EntryList_GetFirst( el );
status = DS_Entry_GetAttrList( e, &al );
if ( status != DS_E_NOERROR ) {
DS_Indication_Delete ( di );
fprintf( stderr, "%s: Failed to read attribute list for "
"ATN User entry\n", prog );
return 3;
}
for ( a = DS_AttrList_GetFirst( al );
a != NULL;
a = DS_AttrList_GetNext( a ) ) {
const char *name;
const DS_AttrValList *vl;
const DS_AttrVal *av;
DS_Attr_GetTypeName( a, &name );
/* Don't free name */
status = DS_Attr_GetValueList( a, &vl );
if ( status != DS_E_NOERROR ) {
DS_Indication_Delete ( di );
fprintf( stderr, "%s: Failed to read attribute values for "
"ATN User entry\n", prog );
return 4;
}
for ( av = DS_AttrValList_GetFirst( vl );
av != NULL;
av = DS_AttrValList_GetNext( av ) ) {
const char *val_str;
size_t val_len;
status = DS_AttrVal_GetStringPointer( av, &val_str, &val_len );
if ( status == DS_E_NOERROR )
printf( "%s: %s\n", name, val_str );
else
printf( "%s: (No string value)\n", name );
/* Don't free val_str */
}
}
DS_Indication_Delete ( di );
return 0;
}
DS_Status ATNds_AMHS2AFTN(DS_Session *session, const DS_DN *registry_dn, const char *x400_or_addr, char *aftn_buf, DS_DN **userdn_p)
Return the AFTN address associated with the given AMHS O/R address. If the user has an associated dir...
DS_Status ATNds_AFTN2AMHS(DS_Session *session, const DS_DN *registry_dn, const char *aftn_addr, char **orbuf_p, size_t *orbuf_len_p, DS_DN **userdn_p)
Convert an AFTN address to the AMHS O/R address. If the user has an associated directory entry the di...
ATN directory service client functions.
void ATNds_free(void *ptr)
Free a buffer which has been returned by ATNds_AFTN2AMHS or ATNds_AMHS2AFTN.

All rights reserved © 2002 - 2024 Isode Ltd.