1 1.3 christos /* $NetBSD: distproc.c,v 1.4 2025/09/05 21:16:27 christos Exp $ */ 2 1.2 christos 3 1.1 lukem /* distproc.c - implement distributed procedures */ 4 1.2 christos /* $OpenLDAP$ */ 5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 1.1 lukem * 7 1.4 christos * Copyright 2005-2024 The OpenLDAP Foundation. 8 1.1 lukem * Portions Copyright 2003 Howard Chu. 9 1.1 lukem * All rights reserved. 10 1.1 lukem * 11 1.1 lukem * Redistribution and use in source and binary forms, with or without 12 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP 13 1.1 lukem * Public License. 14 1.1 lukem * 15 1.1 lukem * A copy of this license is available in the file LICENSE in the 16 1.1 lukem * top-level directory of the distribution or, alternatively, at 17 1.1 lukem * <http://www.OpenLDAP.org/license.html>. 18 1.1 lukem */ 19 1.1 lukem /* ACKNOWLEDGEMENTS: 20 1.1 lukem * This work was initially developed by Pierangelo Masarati for inclusion 21 1.1 lukem * in OpenLDAP Software. 22 1.1 lukem * Based on back-ldap and slapo-chain, developed by Howard Chu 23 1.1 lukem */ 24 1.1 lukem 25 1.2 christos #include <sys/cdefs.h> 26 1.3 christos __RCSID("$NetBSD: distproc.c,v 1.4 2025/09/05 21:16:27 christos Exp $"); 27 1.2 christos 28 1.1 lukem #include "portable.h" 29 1.1 lukem 30 1.1 lukem #include <stdio.h> 31 1.1 lukem 32 1.1 lukem #include <ac/string.h> 33 1.1 lukem #include <ac/socket.h> 34 1.1 lukem 35 1.1 lukem #include "slap.h" 36 1.1 lukem 37 1.1 lukem #ifdef SLAP_DISTPROC 38 1.1 lukem 39 1.1 lukem #include "back-ldap.h" 40 1.1 lukem 41 1.3 christos #include "slap-config.h" 42 1.1 lukem 43 1.1 lukem /* 44 1.1 lukem * From <draft-sermersheim-ldap-distproc> 45 1.1 lukem * 46 1.1 lukem 47 1.1 lukem ContinuationReference ::= SET { 48 1.1 lukem referralURI [0] SET SIZE (1..MAX) OF URI, 49 1.1 lukem localReference [2] LDAPDN, 50 1.1 lukem referenceType [3] ReferenceType, 51 1.1 lukem remainingName [4] RelativeLDAPDN OPTIONAL, 52 1.1 lukem searchScope [5] SearchScope OPTIONAL, 53 1.1 lukem searchedSubtrees [6] SearchedSubtrees OPTIONAL, 54 1.1 lukem failedName [7] LDAPDN OPTIONAL, 55 1.1 lukem ... } 56 1.1 lukem 57 1.1 lukem ReferenceType ::= ENUMERATED { 58 1.1 lukem superior (0), 59 1.1 lukem subordinate (1), 60 1.1 lukem cross (2), 61 1.1 lukem nonSpecificSubordinate (3), 62 1.1 lukem supplier (4), 63 1.1 lukem master (5), 64 1.1 lukem immediateSuperior (6), 65 1.1 lukem self (7), 66 1.1 lukem ... } 67 1.1 lukem 68 1.1 lukem SearchScope ::= ENUMERATED { 69 1.1 lukem baseObject (0), 70 1.1 lukem singleLevel (1), 71 1.1 lukem wholeSubtree (2), 72 1.1 lukem subordinateSubtree (3), 73 1.1 lukem ... } 74 1.1 lukem 75 1.1 lukem SearchedSubtrees ::= SET OF RelativeLDAPDN 76 1.1 lukem 77 1.1 lukem LDAPDN, RelativeLDAPDN, and LDAPString, are defined in [RFC2251]. 78 1.1 lukem 79 1.1 lukem */ 80 1.1 lukem 81 1.1 lukem typedef enum ReferenceType_t { 82 1.1 lukem LDAP_DP_RT_UNKNOWN = -1, 83 1.1 lukem LDAP_DP_RT_SUPERIOR = 0, 84 1.1 lukem LDAP_DP_RT_SUBORDINATE = 1, 85 1.1 lukem LDAP_DP_RT_CROSS = 2, 86 1.1 lukem LDAP_DP_RT_NONSPECIFICSUBORDINATE = 3, 87 1.1 lukem LDAP_DP_RT_SUPPLIER = 4, 88 1.1 lukem LDAP_DP_RT_MASTER = 5, 89 1.1 lukem LDAP_DP_RT_IMMEDIATESUPERIOR = 6, 90 1.1 lukem LDAP_DP_RT_SELF = 7, 91 1.1 lukem LDAP_DP_RT_LAST 92 1.1 lukem } ReferenceType_t; 93 1.1 lukem 94 1.1 lukem typedef enum SearchScope_t { 95 1.1 lukem LDAP_DP_SS_UNKNOWN = -1, 96 1.1 lukem LDAP_DP_SS_BASEOBJECT = 0, 97 1.1 lukem LDAP_DP_SS_SINGLELEVEL = 1, 98 1.1 lukem LDAP_DP_SS_WHOLESUBTREE = 2, 99 1.1 lukem LDAP_DP_SS_SUBORDINATESUBTREE = 3, 100 1.1 lukem LDAP_DP_SS_LAST 101 1.1 lukem } SearchScope_t; 102 1.1 lukem 103 1.1 lukem typedef struct ContinuationReference_t { 104 1.1 lukem BerVarray cr_referralURI; 105 1.1 lukem /* ? [1] ? */ 106 1.1 lukem struct berval cr_localReference; 107 1.1 lukem ReferenceType_t cr_referenceType; 108 1.1 lukem struct berval cr_remainingName; 109 1.1 lukem SearchScope_t cr_searchScope; 110 1.1 lukem BerVarray cr_searchedSubtrees; 111 1.1 lukem struct berval cr_failedName; 112 1.1 lukem } ContinuationReference_t; 113 1.1 lukem #define CR_INIT { NULL, BER_BVNULL, LDAP_DP_RT_UNKNOWN, BER_BVNULL, LDAP_DP_SS_UNKNOWN, NULL, BER_BVNULL } 114 1.1 lukem 115 1.2 christos #ifdef unused 116 1.1 lukem static struct berval bv2rt[] = { 117 1.1 lukem BER_BVC( "superior" ), 118 1.1 lukem BER_BVC( "subordinate" ), 119 1.1 lukem BER_BVC( "cross" ), 120 1.1 lukem BER_BVC( "nonSpecificSubordinate" ), 121 1.1 lukem BER_BVC( "supplier" ), 122 1.1 lukem BER_BVC( "master" ), 123 1.1 lukem BER_BVC( "immediateSuperior" ), 124 1.1 lukem BER_BVC( "self" ), 125 1.1 lukem BER_BVNULL 126 1.1 lukem }; 127 1.1 lukem 128 1.1 lukem static struct berval bv2ss[] = { 129 1.1 lukem BER_BVC( "baseObject" ), 130 1.1 lukem BER_BVC( "singleLevel" ), 131 1.1 lukem BER_BVC( "wholeSubtree" ), 132 1.1 lukem BER_BVC( "subordinateSubtree" ), 133 1.1 lukem BER_BVNULL 134 1.1 lukem }; 135 1.1 lukem 136 1.1 lukem static struct berval * 137 1.1 lukem ldap_distproc_rt2bv( ReferenceType_t rt ) 138 1.1 lukem { 139 1.1 lukem return &bv2rt[ rt ]; 140 1.1 lukem } 141 1.1 lukem 142 1.1 lukem static const char * 143 1.1 lukem ldap_distproc_rt2str( ReferenceType_t rt ) 144 1.1 lukem { 145 1.1 lukem return bv2rt[ rt ].bv_val; 146 1.1 lukem } 147 1.1 lukem 148 1.1 lukem static ReferenceType_t 149 1.1 lukem ldap_distproc_bv2rt( struct berval *bv ) 150 1.1 lukem { 151 1.1 lukem ReferenceType_t rt; 152 1.1 lukem 153 1.1 lukem for ( rt = 0; !BER_BVISNULL( &bv2rt[ rt ] ); rt++ ) { 154 1.1 lukem if ( ber_bvstrcasecmp( bv, &bv2rt[ rt ] ) == 0 ) { 155 1.1 lukem return rt; 156 1.1 lukem } 157 1.1 lukem } 158 1.1 lukem 159 1.1 lukem return LDAP_DP_RT_UNKNOWN; 160 1.1 lukem } 161 1.1 lukem 162 1.1 lukem static ReferenceType_t 163 1.1 lukem ldap_distproc_str2rt( const char *s ) 164 1.1 lukem { 165 1.1 lukem struct berval bv; 166 1.1 lukem 167 1.1 lukem ber_str2bv( s, 0, 0, &bv ); 168 1.1 lukem return ldap_distproc_bv2rt( &bv ); 169 1.1 lukem } 170 1.1 lukem 171 1.1 lukem static struct berval * 172 1.1 lukem ldap_distproc_ss2bv( SearchScope_t ss ) 173 1.1 lukem { 174 1.1 lukem return &bv2ss[ ss ]; 175 1.1 lukem } 176 1.1 lukem 177 1.1 lukem static const char * 178 1.1 lukem ldap_distproc_ss2str( SearchScope_t ss ) 179 1.1 lukem { 180 1.1 lukem return bv2ss[ ss ].bv_val; 181 1.1 lukem } 182 1.1 lukem 183 1.1 lukem static SearchScope_t 184 1.1 lukem ldap_distproc_bv2ss( struct berval *bv ) 185 1.1 lukem { 186 1.1 lukem ReferenceType_t ss; 187 1.1 lukem 188 1.1 lukem for ( ss = 0; !BER_BVISNULL( &bv2ss[ ss ] ); ss++ ) { 189 1.1 lukem if ( ber_bvstrcasecmp( bv, &bv2ss[ ss ] ) == 0 ) { 190 1.1 lukem return ss; 191 1.1 lukem } 192 1.1 lukem } 193 1.1 lukem 194 1.1 lukem return LDAP_DP_SS_UNKNOWN; 195 1.1 lukem } 196 1.1 lukem 197 1.1 lukem static SearchScope_t 198 1.1 lukem ldap_distproc_str2ss( const char *s ) 199 1.1 lukem { 200 1.1 lukem struct berval bv; 201 1.1 lukem 202 1.1 lukem ber_str2bv( s, 0, 0, &bv ); 203 1.1 lukem return ldap_distproc_bv2ss( &bv ); 204 1.1 lukem } 205 1.2 christos #endif /* unused */ 206 1.1 lukem 207 1.1 lukem /* 208 1.1 lukem * NOTE: this overlay assumes that the chainingBehavior control 209 1.1 lukem * is registered by the chain overlay; it may move here some time. 210 1.1 lukem * This overlay provides support for that control as well. 211 1.1 lukem */ 212 1.1 lukem 213 1.1 lukem 214 1.1 lukem static int sc_returnContRef; 215 1.1 lukem #define o_returnContRef o_ctrlflag[sc_returnContRef] 216 1.1 lukem #define get_returnContRef(op) ((op)->o_returnContRef & SLAP_CONTROL_MASK) 217 1.1 lukem 218 1.1 lukem static struct berval slap_EXOP_CHAINEDREQUEST = BER_BVC( LDAP_EXOP_X_CHAINEDREQUEST ); 219 1.1 lukem static struct berval slap_FEATURE_CANCHAINOPS = BER_BVC( LDAP_FEATURE_X_CANCHAINOPS ); 220 1.1 lukem 221 1.1 lukem static BackendInfo *lback; 222 1.1 lukem 223 1.1 lukem typedef struct ldap_distproc_t { 224 1.1 lukem /* "common" configuration info (anything occurring before an "uri") */ 225 1.1 lukem ldapinfo_t *lc_common_li; 226 1.1 lukem 227 1.1 lukem /* current configuration info */ 228 1.1 lukem ldapinfo_t *lc_cfg_li; 229 1.1 lukem 230 1.1 lukem /* tree of configured[/generated?] "uri" info */ 231 1.1 lukem ldap_avl_info_t lc_lai; 232 1.1 lukem 233 1.1 lukem unsigned lc_flags; 234 1.1 lukem #define LDAP_DISTPROC_F_NONE (0x00U) 235 1.1 lukem #define LDAP_DISTPROC_F_CHAINING (0x01U) 236 1.1 lukem #define LDAP_DISTPROC_F_CACHE_URI (0x10U) 237 1.1 lukem 238 1.1 lukem #define LDAP_DISTPROC_CHAINING( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CHAINING ) == LDAP_DISTPROC_F_CHAINING ) 239 1.1 lukem #define LDAP_DISTPROC_CACHE_URI( lc ) ( ( (lc)->lc_flags & LDAP_DISTPROC_F_CACHE_URI ) == LDAP_DISTPROC_F_CACHE_URI ) 240 1.1 lukem 241 1.1 lukem } ldap_distproc_t; 242 1.1 lukem 243 1.1 lukem static int ldap_distproc_db_init_common( BackendDB *be ); 244 1.1 lukem static int ldap_distproc_db_init_one( BackendDB *be ); 245 1.1 lukem #define ldap_distproc_db_open_one(be) (lback)->bi_db_open( (be) ) 246 1.1 lukem #define ldap_distproc_db_close_one(be) (0) 247 1.1 lukem #define ldap_distproc_db_destroy_one(be, ca) (lback)->bi_db_destroy( (be), (ca) ) 248 1.1 lukem 249 1.1 lukem static int 250 1.1 lukem ldap_distproc_uri_cmp( const void *c1, const void *c2 ) 251 1.1 lukem { 252 1.1 lukem const ldapinfo_t *li1 = (const ldapinfo_t *)c1; 253 1.1 lukem const ldapinfo_t *li2 = (const ldapinfo_t *)c2; 254 1.1 lukem 255 1.1 lukem assert( li1->li_bvuri != NULL ); 256 1.1 lukem assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) ); 257 1.1 lukem assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) ); 258 1.1 lukem 259 1.1 lukem assert( li2->li_bvuri != NULL ); 260 1.1 lukem assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) ); 261 1.1 lukem assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) ); 262 1.1 lukem 263 1.1 lukem /* If local DNs don't match, it is definitely not a match */ 264 1.1 lukem return ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ); 265 1.1 lukem } 266 1.1 lukem 267 1.1 lukem static int 268 1.1 lukem ldap_distproc_uri_dup( void *c1, void *c2 ) 269 1.1 lukem { 270 1.1 lukem ldapinfo_t *li1 = (ldapinfo_t *)c1; 271 1.1 lukem ldapinfo_t *li2 = (ldapinfo_t *)c2; 272 1.1 lukem 273 1.1 lukem assert( li1->li_bvuri != NULL ); 274 1.1 lukem assert( !BER_BVISNULL( &li1->li_bvuri[ 0 ] ) ); 275 1.1 lukem assert( BER_BVISNULL( &li1->li_bvuri[ 1 ] ) ); 276 1.1 lukem 277 1.1 lukem assert( li2->li_bvuri != NULL ); 278 1.1 lukem assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) ); 279 1.1 lukem assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) ); 280 1.1 lukem 281 1.1 lukem /* Cannot have more than one shared session with same DN */ 282 1.1 lukem if ( ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ) == 0 ) { 283 1.1 lukem return -1; 284 1.1 lukem } 285 1.1 lukem 286 1.1 lukem return 0; 287 1.1 lukem } 288 1.1 lukem 289 1.1 lukem static int 290 1.1 lukem ldap_distproc_operational( Operation *op, SlapReply *rs ) 291 1.1 lukem { 292 1.1 lukem /* Trap entries generated by back-ldap. 293 1.1 lukem * 294 1.1 lukem * FIXME: we need a better way to recognize them; a cleaner 295 1.1 lukem * solution would be to be able to intercept the response 296 1.1 lukem * of be_operational(), so that we can divert only those 297 1.1 lukem * calls that fail because operational attributes were 298 1.1 lukem * requested for entries that do not belong to the underlying 299 1.1 lukem * database. This fix is likely to intercept also entries 300 1.1 lukem * generated by back-perl and so. */ 301 1.1 lukem if ( rs->sr_entry->e_private == NULL ) { 302 1.1 lukem return LDAP_SUCCESS; 303 1.1 lukem } 304 1.1 lukem 305 1.1 lukem return SLAP_CB_CONTINUE; 306 1.1 lukem } 307 1.1 lukem 308 1.1 lukem static int 309 1.1 lukem ldap_distproc_response( Operation *op, SlapReply *rs ) 310 1.1 lukem { 311 1.1 lukem return SLAP_CB_CONTINUE; 312 1.1 lukem } 313 1.1 lukem 314 1.1 lukem /* 315 1.1 lukem * configuration... 316 1.1 lukem */ 317 1.1 lukem 318 1.1 lukem enum { 319 1.1 lukem /* NOTE: the chaining behavior control is registered 320 1.1 lukem * by the chain overlay; it may move here some time */ 321 1.1 lukem DP_CHAINING = 1, 322 1.1 lukem DP_CACHE_URI, 323 1.1 lukem 324 1.1 lukem DP_LAST 325 1.1 lukem }; 326 1.1 lukem 327 1.1 lukem static ConfigDriver distproc_cfgen; 328 1.1 lukem static ConfigCfAdd distproc_cfadd; 329 1.1 lukem static ConfigLDAPadd distproc_ldadd; 330 1.1 lukem 331 1.1 lukem static ConfigTable distproc_cfg[] = { 332 1.1 lukem { "distproc-chaining", "args", 333 1.1 lukem 2, 4, 0, ARG_MAGIC|ARG_BERVAL|DP_CHAINING, distproc_cfgen, 334 1.1 lukem /* NOTE: using the same attributeTypes defined 335 1.1 lukem * for the "chain" overlay */ 336 1.1 lukem "( OLcfgOvAt:3.1 NAME 'olcChainingBehavior' " 337 1.1 lukem "DESC 'Chaining behavior control parameters (draft-sermersheim-ldap-chaining)' " 338 1.1 lukem "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, 339 1.1 lukem { "distproc-cache-uri", "TRUE/FALSE", 340 1.1 lukem 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|DP_CACHE_URI, distproc_cfgen, 341 1.1 lukem "( OLcfgOvAt:3.2 NAME 'olcChainCacheURI' " 342 1.1 lukem "DESC 'Enables caching of URIs not present in configuration' " 343 1.1 lukem "SYNTAX OMsBoolean " 344 1.1 lukem "SINGLE-VALUE )", NULL, NULL }, 345 1.1 lukem { NULL, NULL, 0, 0, 0, ARG_IGNORED } 346 1.1 lukem }; 347 1.1 lukem 348 1.1 lukem static ConfigOCs distproc_ocs[] = { 349 1.1 lukem { "( OLcfgOvOc:7.1 " 350 1.1 lukem "NAME 'olcDistProcConfig' " 351 1.1 lukem "DESC 'Distributed procedures <draft-sermersheim-ldap-distproc> configuration' " 352 1.1 lukem "SUP olcOverlayConfig " 353 1.1 lukem "MAY ( " 354 1.1 lukem "olcChainingBehavior $ " 355 1.1 lukem "olcChainCacheURI " 356 1.1 lukem ") )", 357 1.1 lukem Cft_Overlay, distproc_cfg, NULL, distproc_cfadd }, 358 1.1 lukem { "( OLcfgOvOc:7.2 " 359 1.1 lukem "NAME 'olcDistProcDatabase' " 360 1.1 lukem "DESC 'Distributed procedure remote server configuration' " 361 1.1 lukem "AUXILIARY )", 362 1.1 lukem Cft_Misc, distproc_cfg, distproc_ldadd }, 363 1.1 lukem { NULL, 0, NULL } 364 1.1 lukem }; 365 1.1 lukem 366 1.1 lukem static int 367 1.1 lukem distproc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) 368 1.1 lukem { 369 1.1 lukem slap_overinst *on; 370 1.1 lukem ldap_distproc_t *lc; 371 1.1 lukem 372 1.1 lukem ldapinfo_t *li; 373 1.1 lukem 374 1.1 lukem AttributeDescription *ad = NULL; 375 1.1 lukem Attribute *at; 376 1.1 lukem const char *text; 377 1.1 lukem 378 1.1 lukem int rc; 379 1.1 lukem 380 1.1 lukem if ( p->ce_type != Cft_Overlay 381 1.1 lukem || !p->ce_bi 382 1.1 lukem || p->ce_bi->bi_cf_ocs != distproc_ocs ) 383 1.1 lukem { 384 1.1 lukem return LDAP_CONSTRAINT_VIOLATION; 385 1.1 lukem } 386 1.1 lukem 387 1.1 lukem on = (slap_overinst *)p->ce_bi; 388 1.1 lukem lc = (ldap_distproc_t *)on->on_bi.bi_private; 389 1.1 lukem 390 1.1 lukem assert( ca->be == NULL ); 391 1.1 lukem ca->be = (BackendDB *)ch_calloc( 1, sizeof( BackendDB ) ); 392 1.1 lukem 393 1.1 lukem ca->be->bd_info = (BackendInfo *)on; 394 1.1 lukem 395 1.1 lukem rc = slap_str2ad( "olcDbURI", &ad, &text ); 396 1.1 lukem assert( rc == LDAP_SUCCESS ); 397 1.1 lukem 398 1.1 lukem at = attr_find( e->e_attrs, ad ); 399 1.1 lukem if ( lc->lc_common_li == NULL && at != NULL ) { 400 1.1 lukem /* FIXME: we should generate an empty default entry 401 1.1 lukem * if none is supplied */ 402 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 403 1.1 lukem "first underlying database \"%s\" " 404 1.1 lukem "cannot contain attribute \"%s\".\n", 405 1.3 christos e->e_name.bv_val, ad->ad_cname.bv_val ); 406 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION; 407 1.1 lukem goto done; 408 1.1 lukem 409 1.1 lukem } else if ( lc->lc_common_li != NULL && at == NULL ) { 410 1.1 lukem /* FIXME: we should generate an empty default entry 411 1.1 lukem * if none is supplied */ 412 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 413 1.1 lukem "subsequent underlying database \"%s\" " 414 1.1 lukem "must contain attribute \"%s\".\n", 415 1.3 christos e->e_name.bv_val, ad->ad_cname.bv_val ); 416 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION; 417 1.1 lukem goto done; 418 1.1 lukem } 419 1.1 lukem 420 1.1 lukem if ( lc->lc_common_li == NULL ) { 421 1.1 lukem rc = ldap_distproc_db_init_common( ca->be ); 422 1.1 lukem 423 1.1 lukem } else { 424 1.1 lukem rc = ldap_distproc_db_init_one( ca->be ); 425 1.1 lukem } 426 1.1 lukem 427 1.1 lukem if ( rc != 0 ) { 428 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 429 1.1 lukem "unable to init %sunderlying database \"%s\".\n", 430 1.3 christos lc->lc_common_li == NULL ? "common " : "", e->e_name.bv_val ); 431 1.2 christos rc = LDAP_CONSTRAINT_VIOLATION; 432 1.2 christos goto done; 433 1.1 lukem } 434 1.1 lukem 435 1.1 lukem li = ca->be->be_private; 436 1.1 lukem 437 1.1 lukem if ( lc->lc_common_li == NULL ) { 438 1.1 lukem lc->lc_common_li = li; 439 1.1 lukem 440 1.3 christos } else if ( ldap_tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, 441 1.1 lukem ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) ) 442 1.1 lukem { 443 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 444 1.1 lukem "database \"%s\" insert failed.\n", 445 1.3 christos e->e_name.bv_val ); 446 1.1 lukem rc = LDAP_CONSTRAINT_VIOLATION; 447 1.1 lukem goto done; 448 1.1 lukem } 449 1.1 lukem 450 1.1 lukem done:; 451 1.1 lukem if ( rc != LDAP_SUCCESS ) { 452 1.1 lukem (void)ldap_distproc_db_destroy_one( ca->be, NULL ); 453 1.1 lukem ch_free( ca->be ); 454 1.1 lukem ca->be = NULL; 455 1.1 lukem } 456 1.1 lukem 457 1.1 lukem return rc; 458 1.1 lukem } 459 1.1 lukem 460 1.1 lukem typedef struct ldap_distproc_cfadd_apply_t { 461 1.1 lukem Operation *op; 462 1.1 lukem SlapReply *rs; 463 1.1 lukem Entry *p; 464 1.1 lukem ConfigArgs *ca; 465 1.1 lukem int count; 466 1.1 lukem } ldap_distproc_cfadd_apply_t; 467 1.1 lukem 468 1.3 christos static void 469 1.3 christos ldap_distproc_cfadd_apply( 470 1.3 christos ldapinfo_t *li, 471 1.3 christos Operation *op, 472 1.3 christos SlapReply *rs, 473 1.3 christos Entry *p, 474 1.3 christos ConfigArgs *ca, 475 1.3 christos int count ) 476 1.1 lukem { 477 1.1 lukem struct berval bv; 478 1.1 lukem 479 1.1 lukem /* FIXME: should not hardcode "olcDatabase" here */ 480 1.3 christos bv.bv_len = snprintf( ca->cr_msg, sizeof( ca->cr_msg ), 481 1.3 christos "olcDatabase={%d}%s", count, lback->bi_type ); 482 1.3 christos bv.bv_val = ca->cr_msg; 483 1.1 lukem 484 1.3 christos ca->be->be_private = (void *)li; 485 1.3 christos config_build_entry( op, rs, p->e_private, ca, 486 1.1 lukem &bv, lback->bi_cf_ocs, &distproc_ocs[ 1 ] ); 487 1.1 lukem 488 1.3 christos return; 489 1.1 lukem } 490 1.1 lukem 491 1.1 lukem static int 492 1.1 lukem distproc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) 493 1.1 lukem { 494 1.1 lukem CfEntryInfo *pe = p->e_private; 495 1.1 lukem slap_overinst *on = (slap_overinst *)pe->ce_bi; 496 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 497 1.1 lukem void *priv = (void *)ca->be->be_private; 498 1.3 christos TAvlnode *edge; 499 1.3 christos int count = 0; 500 1.1 lukem 501 1.1 lukem if ( lback->bi_cf_ocs ) { 502 1.1 lukem ldap_distproc_cfadd_apply_t lca = { 0 }; 503 1.1 lukem 504 1.1 lukem lca.op = op; 505 1.1 lukem lca.rs = rs; 506 1.1 lukem lca.p = p; 507 1.1 lukem lca.ca = ca; 508 1.1 lukem lca.count = 0; 509 1.1 lukem 510 1.3 christos ldap_distproc_cfadd_apply( lc->lc_common_li, op, rs, p, ca, count++ ); 511 1.1 lukem 512 1.3 christos edge = ldap_tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); 513 1.3 christos while ( edge ) { 514 1.3 christos TAvlnode *next = ldap_tavl_next( edge, TAVL_DIR_RIGHT ); 515 1.3 christos ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; 516 1.3 christos ldap_distproc_cfadd_apply( li, op, rs, p, ca, count++ ); 517 1.3 christos edge = next; 518 1.3 christos } 519 1.1 lukem 520 1.1 lukem ca->be->be_private = priv; 521 1.1 lukem } 522 1.1 lukem 523 1.1 lukem return 0; 524 1.1 lukem } 525 1.1 lukem 526 1.1 lukem static int 527 1.1 lukem distproc_cfgen( ConfigArgs *c ) 528 1.1 lukem { 529 1.1 lukem slap_overinst *on = (slap_overinst *)c->bi; 530 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 531 1.1 lukem 532 1.1 lukem int rc = 0; 533 1.1 lukem 534 1.1 lukem if ( c->op == SLAP_CONFIG_EMIT ) { 535 1.1 lukem switch( c->type ) { 536 1.1 lukem case DP_CACHE_URI: 537 1.1 lukem c->value_int = LDAP_DISTPROC_CACHE_URI( lc ); 538 1.1 lukem break; 539 1.1 lukem 540 1.1 lukem default: 541 1.1 lukem assert( 0 ); 542 1.1 lukem rc = 1; 543 1.1 lukem } 544 1.1 lukem return rc; 545 1.1 lukem 546 1.1 lukem } else if ( c->op == LDAP_MOD_DELETE ) { 547 1.1 lukem switch( c->type ) { 548 1.1 lukem case DP_CHAINING: 549 1.1 lukem return 1; 550 1.1 lukem 551 1.1 lukem case DP_CACHE_URI: 552 1.1 lukem lc->lc_flags &= ~LDAP_DISTPROC_F_CACHE_URI; 553 1.1 lukem break; 554 1.1 lukem 555 1.1 lukem default: 556 1.1 lukem return 1; 557 1.1 lukem } 558 1.1 lukem return rc; 559 1.1 lukem } 560 1.1 lukem 561 1.1 lukem switch( c->type ) { 562 1.1 lukem case DP_CACHE_URI: 563 1.1 lukem if ( c->value_int ) { 564 1.1 lukem lc->lc_flags |= LDAP_DISTPROC_F_CACHE_URI; 565 1.1 lukem } else { 566 1.1 lukem lc->lc_flags &= ~LDAP_DISTPROC_F_CACHE_URI; 567 1.1 lukem } 568 1.1 lukem break; 569 1.1 lukem 570 1.1 lukem default: 571 1.1 lukem assert( 0 ); 572 1.1 lukem return 1; 573 1.1 lukem } 574 1.1 lukem 575 1.1 lukem return rc; 576 1.1 lukem } 577 1.1 lukem 578 1.1 lukem static int 579 1.1 lukem ldap_distproc_db_init( 580 1.1 lukem BackendDB *be, 581 1.1 lukem ConfigReply *cr ) 582 1.1 lukem { 583 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 584 1.1 lukem ldap_distproc_t *lc = NULL; 585 1.1 lukem 586 1.1 lukem if ( lback == NULL ) { 587 1.1 lukem lback = backend_info( "ldap" ); 588 1.1 lukem 589 1.1 lukem if ( lback == NULL ) { 590 1.1 lukem return 1; 591 1.1 lukem } 592 1.1 lukem } 593 1.1 lukem 594 1.1 lukem lc = ch_malloc( sizeof( ldap_distproc_t ) ); 595 1.1 lukem if ( lc == NULL ) { 596 1.1 lukem return 1; 597 1.1 lukem } 598 1.1 lukem memset( lc, 0, sizeof( ldap_distproc_t ) ); 599 1.1 lukem ldap_pvt_thread_mutex_init( &lc->lc_lai.lai_mutex ); 600 1.1 lukem 601 1.1 lukem on->on_bi.bi_private = (void *)lc; 602 1.1 lukem 603 1.1 lukem return 0; 604 1.1 lukem } 605 1.1 lukem 606 1.1 lukem static int 607 1.1 lukem ldap_distproc_db_config( 608 1.1 lukem BackendDB *be, 609 1.1 lukem const char *fname, 610 1.1 lukem int lineno, 611 1.1 lukem int argc, 612 1.1 lukem char **argv ) 613 1.1 lukem { 614 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 615 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 616 1.1 lukem 617 1.1 lukem int rc = SLAP_CONF_UNKNOWN; 618 1.1 lukem 619 1.1 lukem if ( lc->lc_common_li == NULL ) { 620 1.1 lukem void *be_private = be->be_private; 621 1.1 lukem ldap_distproc_db_init_common( be ); 622 1.1 lukem lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)be->be_private; 623 1.1 lukem be->be_private = be_private; 624 1.1 lukem } 625 1.1 lukem 626 1.1 lukem /* Something for the distproc database? */ 627 1.1 lukem if ( strncasecmp( argv[ 0 ], "distproc-", STRLENOF( "distproc-" ) ) == 0 ) { 628 1.1 lukem char *save_argv0 = argv[ 0 ]; 629 1.1 lukem BackendInfo *bd_info = be->bd_info; 630 1.1 lukem void *be_private = be->be_private; 631 1.1 lukem ConfigOCs *be_cf_ocs = be->be_cf_ocs; 632 1.1 lukem int is_uri = 0; 633 1.1 lukem 634 1.1 lukem argv[ 0 ] += STRLENOF( "distproc-" ); 635 1.1 lukem 636 1.1 lukem if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) { 637 1.1 lukem rc = ldap_distproc_db_init_one( be ); 638 1.1 lukem if ( rc != 0 ) { 639 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: " 640 1.1 lukem "underlying slapd-ldap initialization failed.\n.", 641 1.3 christos fname, lineno ); 642 1.1 lukem return 1; 643 1.1 lukem } 644 1.1 lukem lc->lc_cfg_li = be->be_private; 645 1.1 lukem is_uri = 1; 646 1.1 lukem } 647 1.1 lukem 648 1.1 lukem /* TODO: add checks on what other slapd-ldap(5) args 649 1.1 lukem * should be put in the template; this is not quite 650 1.1 lukem * harmful, because attributes that shouldn't don't 651 1.1 lukem * get actually used, but the user should at least 652 1.1 lukem * be warned. 653 1.1 lukem */ 654 1.1 lukem 655 1.1 lukem be->bd_info = lback; 656 1.1 lukem be->be_private = (void *)lc->lc_cfg_li; 657 1.1 lukem be->be_cf_ocs = lback->bi_cf_ocs; 658 1.1 lukem 659 1.1 lukem rc = config_generic_wrapper( be, fname, lineno, argc, argv ); 660 1.1 lukem 661 1.1 lukem argv[ 0 ] = save_argv0; 662 1.1 lukem be->be_cf_ocs = be_cf_ocs; 663 1.1 lukem be->be_private = be_private; 664 1.1 lukem be->bd_info = bd_info; 665 1.1 lukem 666 1.1 lukem if ( is_uri ) { 667 1.1 lukem private_destroy:; 668 1.1 lukem if ( rc != 0 ) { 669 1.1 lukem BackendDB db = *be; 670 1.1 lukem 671 1.1 lukem db.bd_info = lback; 672 1.1 lukem db.be_private = (void *)lc->lc_cfg_li; 673 1.1 lukem ldap_distproc_db_destroy_one( &db, NULL ); 674 1.1 lukem lc->lc_cfg_li = NULL; 675 1.1 lukem 676 1.1 lukem } else { 677 1.1 lukem if ( lc->lc_cfg_li->li_bvuri == NULL 678 1.1 lukem || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] ) 679 1.1 lukem || !BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 1 ] ) ) 680 1.1 lukem { 681 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: " 682 1.1 lukem "no URI list allowed in slapo-distproc.\n", 683 1.3 christos fname, lineno ); 684 1.1 lukem rc = 1; 685 1.1 lukem goto private_destroy; 686 1.1 lukem } 687 1.1 lukem 688 1.3 christos if ( ldap_tavl_insert( &lc->lc_lai.lai_tree, 689 1.1 lukem (caddr_t)lc->lc_cfg_li, 690 1.1 lukem ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) ) 691 1.1 lukem { 692 1.1 lukem Debug( LDAP_DEBUG_ANY, "%s: line %d: " 693 1.1 lukem "duplicate URI in slapo-distproc.\n", 694 1.3 christos fname, lineno ); 695 1.1 lukem rc = 1; 696 1.1 lukem goto private_destroy; 697 1.1 lukem } 698 1.1 lukem } 699 1.1 lukem } 700 1.1 lukem } 701 1.1 lukem 702 1.1 lukem return rc; 703 1.1 lukem } 704 1.1 lukem 705 1.1 lukem enum db_which { 706 1.1 lukem db_open = 0, 707 1.1 lukem db_close, 708 1.1 lukem db_destroy, 709 1.1 lukem 710 1.1 lukem db_last 711 1.1 lukem }; 712 1.1 lukem 713 1.1 lukem static int 714 1.1 lukem ldap_distproc_db_func( 715 1.1 lukem BackendDB *be, 716 1.1 lukem enum db_which which 717 1.1 lukem ) 718 1.1 lukem { 719 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 720 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 721 1.1 lukem 722 1.1 lukem int rc = 0; 723 1.1 lukem 724 1.1 lukem if ( lc ) { 725 1.1 lukem BI_db_func *func = (&lback->bi_db_open)[ which ]; 726 1.1 lukem 727 1.1 lukem if ( func != NULL && lc->lc_common_li != NULL ) { 728 1.1 lukem BackendDB db = *be; 729 1.1 lukem 730 1.1 lukem db.bd_info = lback; 731 1.1 lukem db.be_private = lc->lc_common_li; 732 1.1 lukem 733 1.1 lukem rc = func( &db, NULL ); 734 1.1 lukem 735 1.1 lukem if ( rc != 0 ) { 736 1.1 lukem return rc; 737 1.1 lukem } 738 1.1 lukem 739 1.1 lukem if ( lc->lc_lai.lai_tree != NULL ) { 740 1.3 christos TAvlnode *edge = ldap_tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); 741 1.3 christos while ( edge ) { 742 1.3 christos TAvlnode *next = ldap_tavl_next( edge, TAVL_DIR_RIGHT ); 743 1.3 christos ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; 744 1.3 christos be->be_private = (void *)li; 745 1.3 christos rc = func( &db, NULL ); 746 1.3 christos if ( rc == 1 ) { 747 1.3 christos break; 748 1.3 christos } 749 1.3 christos edge = next; 750 1.3 christos } 751 1.1 lukem } 752 1.1 lukem } 753 1.1 lukem } 754 1.1 lukem 755 1.1 lukem return rc; 756 1.1 lukem } 757 1.1 lukem 758 1.1 lukem static int 759 1.1 lukem ldap_distproc_db_open( 760 1.1 lukem BackendDB *be, 761 1.1 lukem ConfigReply *cr ) 762 1.1 lukem { 763 1.1 lukem return ldap_distproc_db_func( be, db_open ); 764 1.1 lukem } 765 1.1 lukem 766 1.1 lukem static int 767 1.1 lukem ldap_distproc_db_close( 768 1.1 lukem BackendDB *be, 769 1.1 lukem ConfigReply *cr ) 770 1.1 lukem { 771 1.1 lukem return ldap_distproc_db_func( be, db_close ); 772 1.1 lukem } 773 1.1 lukem 774 1.1 lukem static int 775 1.1 lukem ldap_distproc_db_destroy( 776 1.1 lukem BackendDB *be, 777 1.1 lukem ConfigReply *cr ) 778 1.1 lukem { 779 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info; 780 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 781 1.1 lukem 782 1.1 lukem int rc; 783 1.1 lukem 784 1.1 lukem rc = ldap_distproc_db_func( be, db_destroy ); 785 1.1 lukem 786 1.1 lukem if ( lc ) { 787 1.3 christos ldap_tavl_free( lc->lc_lai.lai_tree, NULL ); 788 1.1 lukem ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex ); 789 1.1 lukem ch_free( lc ); 790 1.1 lukem } 791 1.1 lukem 792 1.1 lukem return rc; 793 1.1 lukem } 794 1.1 lukem 795 1.1 lukem /* 796 1.1 lukem * inits one instance of the slapd-ldap backend, and stores 797 1.1 lukem * the private info in be_private of the arg 798 1.1 lukem */ 799 1.1 lukem static int 800 1.1 lukem ldap_distproc_db_init_common( 801 1.1 lukem BackendDB *be ) 802 1.1 lukem { 803 1.1 lukem BackendInfo *bi = be->bd_info; 804 1.1 lukem int t; 805 1.1 lukem 806 1.1 lukem be->bd_info = lback; 807 1.1 lukem be->be_private = NULL; 808 1.1 lukem t = lback->bi_db_init( be, NULL ); 809 1.1 lukem if ( t != 0 ) { 810 1.1 lukem return t; 811 1.1 lukem } 812 1.1 lukem be->bd_info = bi; 813 1.1 lukem 814 1.1 lukem return 0; 815 1.1 lukem } 816 1.1 lukem 817 1.1 lukem /* 818 1.1 lukem * inits one instance of the slapd-ldap backend, stores 819 1.1 lukem * the private info in be_private of the arg and fills 820 1.1 lukem * selected fields with data from the template. 821 1.1 lukem * 822 1.1 lukem * NOTE: add checks about the other fields of the template, 823 1.1 lukem * which are ignored and SHOULD NOT be configured by the user. 824 1.1 lukem */ 825 1.1 lukem static int 826 1.1 lukem ldap_distproc_db_init_one( 827 1.1 lukem BackendDB *be ) 828 1.1 lukem { 829 1.1 lukem slap_overinst *on = (slap_overinst *)be->bd_info; 830 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 831 1.1 lukem 832 1.1 lukem BackendInfo *bi = be->bd_info; 833 1.1 lukem ldapinfo_t *li; 834 1.1 lukem 835 1.1 lukem slap_op_t t; 836 1.1 lukem 837 1.1 lukem be->bd_info = lback; 838 1.1 lukem be->be_private = NULL; 839 1.1 lukem t = lback->bi_db_init( be, NULL ); 840 1.1 lukem if ( t != 0 ) { 841 1.1 lukem return t; 842 1.1 lukem } 843 1.1 lukem li = (ldapinfo_t *)be->be_private; 844 1.1 lukem 845 1.1 lukem /* copy common data */ 846 1.1 lukem li->li_nretries = lc->lc_common_li->li_nretries; 847 1.1 lukem li->li_flags = lc->lc_common_li->li_flags; 848 1.1 lukem li->li_version = lc->lc_common_li->li_version; 849 1.1 lukem for ( t = 0; t < SLAP_OP_LAST; t++ ) { 850 1.1 lukem li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ]; 851 1.1 lukem } 852 1.1 lukem be->bd_info = bi; 853 1.1 lukem 854 1.1 lukem return 0; 855 1.1 lukem } 856 1.1 lukem 857 1.1 lukem static int 858 1.1 lukem ldap_distproc_connection_destroy( 859 1.1 lukem BackendDB *be, 860 1.1 lukem Connection *conn 861 1.1 lukem ) 862 1.1 lukem { 863 1.1 lukem slap_overinst *on = (slap_overinst *) be->bd_info; 864 1.1 lukem ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; 865 1.1 lukem void *private = be->be_private; 866 1.1 lukem int rc; 867 1.3 christos TAvlnode *edge; 868 1.1 lukem 869 1.1 lukem be->be_private = NULL; 870 1.1 lukem ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); 871 1.3 christos edge = ldap_tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); 872 1.3 christos while ( edge ) { 873 1.3 christos TAvlnode *next = ldap_tavl_next( edge, TAVL_DIR_RIGHT ); 874 1.3 christos ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; 875 1.3 christos be->be_private = (void *)li; 876 1.3 christos rc = lback->bi_connection_destroy( be, conn ); 877 1.3 christos if ( rc == 1 ) { 878 1.3 christos break; 879 1.3 christos } 880 1.3 christos edge = next; 881 1.3 christos } 882 1.1 lukem ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); 883 1.1 lukem be->be_private = private; 884 1.1 lukem 885 1.1 lukem return rc; 886 1.1 lukem } 887 1.1 lukem 888 1.1 lukem static int 889 1.1 lukem ldap_distproc_parse_returnContRef_ctrl( 890 1.1 lukem Operation *op, 891 1.1 lukem SlapReply *rs, 892 1.1 lukem LDAPControl *ctrl ) 893 1.1 lukem { 894 1.1 lukem if ( get_returnContRef( op ) != SLAP_CONTROL_NONE ) { 895 1.1 lukem rs->sr_text = "returnContinuationReference control specified multiple times"; 896 1.1 lukem return LDAP_PROTOCOL_ERROR; 897 1.1 lukem } 898 1.1 lukem 899 1.1 lukem if ( op->o_pagedresults != SLAP_CONTROL_NONE ) { 900 1.1 lukem rs->sr_text = "returnContinuationReference control specified with pagedResults control"; 901 1.1 lukem return LDAP_PROTOCOL_ERROR; 902 1.1 lukem } 903 1.1 lukem 904 1.1 lukem if ( !BER_BVISEMPTY( &ctrl->ldctl_value ) ) { 905 1.1 lukem rs->sr_text = "returnContinuationReference control: value must be NULL"; 906 1.1 lukem return LDAP_PROTOCOL_ERROR; 907 1.1 lukem } 908 1.1 lukem 909 1.1 lukem op->o_returnContRef = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; 910 1.1 lukem 911 1.1 lukem return LDAP_SUCCESS; 912 1.1 lukem } 913 1.1 lukem 914 1.1 lukem static int 915 1.1 lukem ldap_exop_chained_request( 916 1.1 lukem Operation *op, 917 1.1 lukem SlapReply *rs ) 918 1.1 lukem { 919 1.3 christos Debug( LDAP_DEBUG_STATS, "%s CHAINED REQUEST\n", 920 1.3 christos op->o_log_prefix ); 921 1.1 lukem 922 1.1 lukem rs->sr_err = backend_check_restrictions( op, rs, 923 1.1 lukem (struct berval *)&slap_EXOP_CHAINEDREQUEST ); 924 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) { 925 1.1 lukem return rs->sr_err; 926 1.1 lukem } 927 1.1 lukem 928 1.1 lukem /* by now, just reject requests */ 929 1.1 lukem rs->sr_text = "under development"; 930 1.1 lukem return LDAP_UNWILLING_TO_PERFORM; 931 1.1 lukem } 932 1.1 lukem 933 1.1 lukem 934 1.1 lukem static slap_overinst distproc; 935 1.1 lukem 936 1.1 lukem int 937 1.1 lukem distproc_initialize( void ) 938 1.1 lukem { 939 1.1 lukem int rc; 940 1.1 lukem 941 1.1 lukem /* Make sure we don't exceed the bits reserved for userland */ 942 1.1 lukem config_check_userland( DP_LAST ); 943 1.1 lukem 944 1.1 lukem rc = load_extop( (struct berval *)&slap_EXOP_CHAINEDREQUEST, 945 1.1 lukem SLAP_EXOP_HIDE, ldap_exop_chained_request ); 946 1.1 lukem if ( rc != LDAP_SUCCESS ) { 947 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 948 1.1 lukem "unable to register chainedRequest exop: %d.\n", 949 1.3 christos rc ); 950 1.1 lukem return rc; 951 1.1 lukem } 952 1.1 lukem 953 1.1 lukem rc = supported_feature_load( &slap_FEATURE_CANCHAINOPS ); 954 1.1 lukem if ( rc != LDAP_SUCCESS ) { 955 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 956 1.1 lukem "unable to register canChainOperations supported feature: %d.\n", 957 1.3 christos rc ); 958 1.1 lukem return rc; 959 1.1 lukem } 960 1.1 lukem 961 1.1 lukem rc = register_supported_control( LDAP_CONTROL_X_RETURNCONTREF, 962 1.1 lukem SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL, 963 1.1 lukem ldap_distproc_parse_returnContRef_ctrl, &sc_returnContRef ); 964 1.1 lukem if ( rc != LDAP_SUCCESS ) { 965 1.1 lukem Debug( LDAP_DEBUG_ANY, "slapd-distproc: " 966 1.1 lukem "unable to register returnContinuationReference control: %d.\n", 967 1.3 christos rc ); 968 1.1 lukem return rc; 969 1.1 lukem } 970 1.1 lukem 971 1.1 lukem distproc.on_bi.bi_type = "distproc"; 972 1.1 lukem distproc.on_bi.bi_db_init = ldap_distproc_db_init; 973 1.1 lukem distproc.on_bi.bi_db_config = ldap_distproc_db_config; 974 1.1 lukem distproc.on_bi.bi_db_open = ldap_distproc_db_open; 975 1.1 lukem distproc.on_bi.bi_db_close = ldap_distproc_db_close; 976 1.1 lukem distproc.on_bi.bi_db_destroy = ldap_distproc_db_destroy; 977 1.1 lukem 978 1.1 lukem /* ... otherwise the underlying backend's function would be called, 979 1.1 lukem * likely passing an invalid entry; on the contrary, the requested 980 1.1 lukem * operational attributes should have been returned while chasing 981 1.1 lukem * the referrals. This all in all is a bit messy, because part 982 1.1 lukem * of the operational attributes are generated by the backend; 983 1.1 lukem * part by the frontend; back-ldap should receive all the available 984 1.1 lukem * ones from the remote server, but then, on its own, it strips those 985 1.1 lukem * it assumes will be (re)generated by the frontend (e.g. 986 1.1 lukem * subschemaSubentry, entryDN, ...) */ 987 1.1 lukem distproc.on_bi.bi_operational = ldap_distproc_operational; 988 1.1 lukem 989 1.1 lukem distproc.on_bi.bi_connection_destroy = ldap_distproc_connection_destroy; 990 1.1 lukem 991 1.1 lukem distproc.on_response = ldap_distproc_response; 992 1.1 lukem 993 1.1 lukem distproc.on_bi.bi_cf_ocs = distproc_ocs; 994 1.1 lukem 995 1.1 lukem rc = config_register_schema( distproc_cfg, distproc_ocs ); 996 1.1 lukem if ( rc ) { 997 1.1 lukem return rc; 998 1.1 lukem } 999 1.1 lukem 1000 1.1 lukem return overlay_register( &distproc ); 1001 1.1 lukem } 1002 1.1 lukem 1003 1.1 lukem #endif /* SLAP_DISTPROC */ 1004