cb_instance.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. #include "cb.h"
  7. #include "plstr.h"
  8. /*
  9. ** 1 set/get function for each parameter of a backend instance
  10. ** NOTE: Some parameters won't be taken into account until the server has restarted
  11. ** In such cases, the internal conf is not updated but the new value is stored in the
  12. ** dse.ldif file.
  13. **/
  14. /* Get functions */
  15. static void *cb_instance_hosturl_get(void *arg);
  16. static void *cb_instance_binduser_get(void *arg);
  17. static void *cb_instance_userpassword_get(void *arg);
  18. static void *cb_instance_maxbconn_get(void *arg);
  19. static void *cb_instance_maxconn_get(void *arg);
  20. static void *cb_instance_abandonto_get(void *arg);
  21. static void *cb_instance_maxbconc_get(void *arg);
  22. static void *cb_instance_maxconc_get(void *arg);
  23. static void *cb_instance_imperson_get(void *arg);
  24. static void *cb_instance_connlife_get(void *arg);
  25. static void *cb_instance_bindto_get(void *arg);
  26. static void *cb_instance_opto_get(void *arg);
  27. static void *cb_instance_ref_get(void *arg);
  28. static void *cb_instance_acl_get(void *arg);
  29. static void *cb_instance_bindretry_get(void *arg);
  30. static void *cb_instance_sizelimit_get(void *arg);
  31. static void *cb_instance_timelimit_get(void *arg);
  32. static void *cb_instance_hoplimit_get(void *arg);
  33. static void *cb_instance_max_idle_get(void *arg);
  34. static void *cb_instance_max_test_get(void *arg);
  35. /* Set functions */
  36. static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  37. static int cb_instance_binduser_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  38. static int cb_instance_userpassword_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  39. static int cb_instance_maxbconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  40. static int cb_instance_maxconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  41. static int cb_instance_abandonto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  42. static int cb_instance_maxbconc_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  43. static int cb_instance_maxconc_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  44. static int cb_instance_imperson_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  45. static int cb_instance_connlife_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  46. static int cb_instance_bindto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  47. static int cb_instance_opto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  48. static int cb_instance_ref_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  49. static int cb_instance_acl_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  50. static int cb_instance_bindretry_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  51. static int cb_instance_sizelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  52. static int cb_instance_timelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  53. static int cb_instance_hoplimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  54. static int cb_instance_max_idle_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  55. static int cb_instance_max_test_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  56. /* Default hardwired values */
  57. cb_instance_config_info cb_the_instance_config[] = {
  58. {CB_CONFIG_HOSTURL,CB_CONFIG_TYPE_STRING,"",&cb_instance_hosturl_get,&cb_instance_hosturl_set,CB_ALWAYS_SHOW},
  59. {CB_CONFIG_BINDUSER, CB_CONFIG_TYPE_STRING, "", &cb_instance_binduser_get, &cb_instance_binduser_set,CB_ALWAYS_SHOW},
  60. {CB_CONFIG_USERPASSWORD,CB_CONFIG_TYPE_STRING,"",&cb_instance_userpassword_get,&cb_instance_userpassword_set,CB_ALWAYS_SHOW},
  61. {CB_CONFIG_MAXBINDCONNECTIONS,CB_CONFIG_TYPE_INT,CB_DEF_BIND_MAXCONNECTIONS,&cb_instance_maxbconn_get, &cb_instance_maxbconn_set,CB_ALWAYS_SHOW},
  62. {CB_CONFIG_MAXCONNECTIONS,CB_CONFIG_TYPE_INT,CB_DEF_MAXCONNECTIONS,&cb_instance_maxconn_get, &cb_instance_maxconn_set,CB_ALWAYS_SHOW},
  63. {CB_CONFIG_ABANDONTIMEOUT,CB_CONFIG_TYPE_INT,CB_DEF_ABANDON_TIMEOUT,&cb_instance_abandonto_get, &cb_instance_abandonto_set,CB_ALWAYS_SHOW},
  64. {CB_CONFIG_MAXBINDCONCURRENCY,CB_CONFIG_TYPE_INT,CB_DEF_BIND_MAXCONCURRENCY,&cb_instance_maxbconc_get, &cb_instance_maxbconc_set,CB_ALWAYS_SHOW},
  65. {CB_CONFIG_MAXCONCURRENCY,CB_CONFIG_TYPE_INT,CB_DEF_MAXCONCURRENCY,&cb_instance_maxconc_get, &cb_instance_maxconc_set,CB_ALWAYS_SHOW},
  66. {CB_CONFIG_IMPERSONATION,CB_CONFIG_TYPE_ONOFF,CB_DEF_IMPERSONATION,&cb_instance_imperson_get, &cb_instance_imperson_set,CB_ALWAYS_SHOW},
  67. {CB_CONFIG_CONNLIFETIME,CB_CONFIG_TYPE_INT,CB_DEF_CONNLIFETIME,&cb_instance_connlife_get, &cb_instance_connlife_set,CB_ALWAYS_SHOW},
  68. {CB_CONFIG_BINDTIMEOUT,CB_CONFIG_TYPE_INT,CB_DEF_BINDTIMEOUT,&cb_instance_bindto_get, &cb_instance_bindto_set,CB_ALWAYS_SHOW},
  69. {CB_CONFIG_TIMEOUT,CB_CONFIG_TYPE_INT,"0",&cb_instance_opto_get, &cb_instance_opto_set,0},
  70. {CB_CONFIG_REFERRAL,CB_CONFIG_TYPE_ONOFF,CB_DEF_SEARCHREFERRAL,&cb_instance_ref_get, &cb_instance_ref_set,CB_ALWAYS_SHOW},
  71. {CB_CONFIG_LOCALACL,CB_CONFIG_TYPE_ONOFF,CB_DEF_LOCALACL,&cb_instance_acl_get, &cb_instance_acl_set,CB_ALWAYS_SHOW},
  72. {CB_CONFIG_BINDRETRY,CB_CONFIG_TYPE_INT,CB_DEF_BINDRETRY,&cb_instance_bindretry_get, &cb_instance_bindretry_set,CB_ALWAYS_SHOW},
  73. {CB_CONFIG_SIZELIMIT,CB_CONFIG_TYPE_INT,CB_DEF_SIZELIMIT,&cb_instance_sizelimit_get, &cb_instance_sizelimit_set,CB_ALWAYS_SHOW},
  74. {CB_CONFIG_TIMELIMIT,CB_CONFIG_TYPE_INT,CB_DEF_TIMELIMIT,&cb_instance_timelimit_get, &cb_instance_timelimit_set,CB_ALWAYS_SHOW},
  75. {CB_CONFIG_HOPLIMIT,CB_CONFIG_TYPE_INT,CB_DEF_HOPLIMIT,&cb_instance_hoplimit_get, &cb_instance_hoplimit_set,CB_ALWAYS_SHOW},
  76. {CB_CONFIG_MAX_IDLE_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_IDLE_TIME,&cb_instance_max_idle_get, &cb_instance_max_idle_set,CB_ALWAYS_SHOW},
  77. {CB_CONFIG_MAX_TEST_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_TEST_TIME,&cb_instance_max_test_get, &cb_instance_max_test_set,CB_ALWAYS_SHOW},
  78. {NULL, 0, NULL, NULL, NULL, 0}
  79. };
  80. /* Others forward declarations */
  81. int cb_instance_delete_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  82. int *returncode, char *returntext, void *arg);
  83. int cb_instance_search_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  84. int *returncode, char *returntext, void *arg);
  85. int cb_instance_add_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  86. int *returncode, char *returntext, void *arg);
  87. static int
  88. cb_instance_config_set(void *arg, char *attr_name, cb_instance_config_info *config_array,
  89. struct berval *bval, char *err_buf, int phase, int apply_mod);
  90. int
  91. cb_dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  92. int *returncode, char *returntext, void *arg)
  93. {
  94. *returncode=LDAP_UNWILLING_TO_PERFORM;
  95. return SLAPI_DSE_CALLBACK_ERROR;
  96. }
  97. static char *cb_skeleton_entries[] =
  98. {
  99. "dn:cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config\n"
  100. "objectclass:top\n"
  101. "objectclass:extensibleObject\n"
  102. "cn:monitor\n",
  103. ""
  104. };
  105. /*
  106. ** Initialize a backend instance with a default configuration
  107. */
  108. static void cb_instance_config_set_default(cb_backend_instance *inst)
  109. {
  110. cb_instance_config_info *config;
  111. char err_buf[SLAPI_DSE_RETURNTEXT_SIZE];
  112. for (config = cb_the_instance_config; config->config_name != NULL; config++) {
  113. cb_instance_config_set((void *)inst,
  114. config->config_name, cb_the_instance_config, NULL /* use default */, err_buf,
  115. CB_CONFIG_PHASE_INITIALIZATION, 1 /* apply */);
  116. }
  117. /* Set backend instance flags */
  118. if (inst->inst_be)
  119. slapi_be_set_flag(inst->inst_be,SLAPI_BE_FLAG_REMOTE_DATA);
  120. }
  121. /*
  122. ** Allocate a new chaining backend instance. Internal structure
  123. */
  124. static cb_backend_instance * cb_instance_alloc(cb_backend * cb, char * name, char * basedn) {
  125. int i;
  126. cb_backend_instance * inst =
  127. (cb_backend_instance *)slapi_ch_calloc(1, sizeof(cb_backend_instance));
  128. /* associated_be_is_disabled defaults to 0 - this may be a problem if the associated
  129. be is disabled at instance creation time
  130. */
  131. inst->inst_name = slapi_ch_strdup(name);
  132. inst->monitor.mutex = slapi_new_mutex();
  133. inst->monitor_availability.cpt_lock = slapi_new_mutex();
  134. inst->monitor_availability.lock_timeLimit = slapi_new_mutex();
  135. inst->pool= (cb_conn_pool *) slapi_ch_calloc(1,sizeof(cb_conn_pool));
  136. inst->pool->conn.conn_list_mutex = slapi_new_mutex();
  137. inst->pool->conn.conn_list_cv = slapi_new_condvar(inst->pool->conn.conn_list_mutex);
  138. inst->pool->bindit=1;
  139. inst->bind_pool= (cb_conn_pool *) slapi_ch_calloc(1,sizeof(cb_conn_pool));
  140. inst->bind_pool->conn.conn_list_mutex = slapi_new_mutex();
  141. inst->bind_pool->conn.conn_list_cv = slapi_new_condvar(inst->bind_pool->conn.conn_list_mutex);
  142. inst->backend_type=cb;
  143. /* initialize monitor_availability */
  144. inst->monitor_availability.farmserver_state = FARMSERVER_AVAILABLE ; /* we expect the farm to be available */
  145. inst->monitor_availability.cpt = 0 ; /* set up the failed conn counter to 0 */
  146. /* create RW lock to protect the config */
  147. inst->rwl_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, slapi_ch_strdup(name));
  148. /* quick hack */
  149. /* put a ref to the config lock in the pool */
  150. /* so that the connection mgmt module can */
  151. /* access the config safely */
  152. inst->pool->rwl_config_lock = inst->rwl_config_lock;
  153. inst->bind_pool->rwl_config_lock = inst->rwl_config_lock;
  154. for (i=0; i < MAX_CONN_ARRAY; i++) {
  155. inst->pool->connarray[i] = NULL;
  156. inst->bind_pool->connarray[i] = NULL;
  157. }
  158. /* Config is now merged with the backend entry */
  159. inst->configDn=slapi_ch_strdup(basedn);
  160. inst->monitorDn=slapi_ch_smprintf("cn=monitor,%s",basedn);
  161. inst->eq_ctx = NULL;
  162. return inst;
  163. }
  164. void cb_instance_free(cb_backend_instance * inst) {
  165. if (inst) {
  166. PR_RWLock_Wlock(inst->rwl_config_lock);
  167. if ( inst->eq_ctx != NULL )
  168. {
  169. slapi_eq_cancel(inst->eq_ctx);
  170. inst->eq_ctx = NULL;
  171. }
  172. if (inst->bind_pool)
  173. cb_close_conn_pool(inst->bind_pool);
  174. if (inst->pool)
  175. cb_close_conn_pool(inst->pool);
  176. slapi_destroy_condvar(inst->bind_pool->conn.conn_list_cv);
  177. slapi_destroy_condvar(inst->pool->conn.conn_list_cv);
  178. slapi_destroy_mutex(inst->monitor.mutex);
  179. slapi_destroy_mutex(inst->bind_pool->conn.conn_list_mutex);
  180. slapi_destroy_mutex(inst->pool->conn.conn_list_mutex);
  181. slapi_destroy_mutex(inst->monitor_availability.cpt_lock);
  182. slapi_destroy_mutex(inst->monitor_availability.lock_timeLimit);
  183. slapi_ch_free((void **) &inst->configDn);
  184. slapi_ch_free((void **) &inst->monitorDn);
  185. slapi_ch_free((void **) &inst->inst_name);
  186. charray_free(inst->every_attribute);
  187. slapi_ch_free((void **) &inst->bind_pool);
  188. slapi_ch_free((void **) &inst->pool);
  189. PR_RWLock_Unlock(inst->rwl_config_lock);
  190. PR_DestroyRWLock(inst->rwl_config_lock);
  191. slapi_ch_free((void **) &inst);
  192. }
  193. /* XXXSD */
  194. }
  195. /*
  196. ** Check the change the configuration of an existing chaining
  197. ** backend instance.
  198. */
  199. int cb_instance_modify_config_check_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  200. int *returncode, char *returntext, void *arg) {
  201. cb_backend_instance * inst = (cb_backend_instance *) arg;
  202. LDAPMod **mods;
  203. int rc = LDAP_SUCCESS;
  204. int i;
  205. char * attr_name;
  206. returntext[0] = '\0';
  207. CB_ASSERT(inst!=NULL);
  208. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  209. /* First pass to validate input */
  210. for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
  211. attr_name = mods[i]->mod_type;
  212. /* specific processing for multi-valued attributes */
  213. if ( !strcasecmp ( attr_name, CB_CONFIG_SUFFIX )) {
  214. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "suffix modification not allowed\n");
  215. rc = LDAP_UNWILLING_TO_PERFORM;
  216. continue;
  217. } else
  218. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  219. continue;
  220. } else
  221. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  222. continue;
  223. } else
  224. /* CB_CONFIG_BINDUSER & CB_CONFIG_USERPASSWORD may be added */
  225. /* or deleted */
  226. if ( !strcasecmp ( attr_name, CB_CONFIG_USERPASSWORD )) {
  227. continue;
  228. } else
  229. if ( !strcasecmp ( attr_name, CB_CONFIG_BINDUSER )) {
  230. /* Make sure value is not forbidden */
  231. if ((mods[i]->mod_op & LDAP_MOD_REPLACE) ||
  232. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  233. rc = cb_instance_config_set((void *) inst, attr_name,
  234. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  235. CB_CONFIG_PHASE_RUNNING, 0);
  236. continue;
  237. }
  238. }
  239. if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
  240. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  241. rc= LDAP_UNWILLING_TO_PERFORM;
  242. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
  243. (mods[i]->mod_op & LDAP_MOD_DELETE) ? "Deleting" : "Adding");
  244. } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
  245. /* This assumes there is only one bval for this mod. */
  246. rc = cb_instance_config_set((void *) inst, attr_name,
  247. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  248. CB_CONFIG_PHASE_RUNNING, 0);
  249. }
  250. }
  251. *returncode= rc;
  252. return ((LDAP_SUCCESS == rc) ? 1:-1);
  253. }
  254. /*
  255. ** Change the configuration of an existing chaining
  256. ** backend instance.
  257. */
  258. int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  259. int *returncode, char *returntext, void *arg) {
  260. cb_backend_instance * inst = (cb_backend_instance *) arg;
  261. LDAPMod **mods;
  262. int rc = LDAP_SUCCESS;
  263. int i;
  264. int reopen_conn=0;
  265. char * attr_name;
  266. returntext[0] = '\0';
  267. CB_ASSERT(inst!=NULL);
  268. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  269. /* input checked in the preop modify callback */
  270. for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
  271. attr_name = mods[i]->mod_type;
  272. /* specific processing for multi-valued attributes */
  273. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  274. char * config_attr_value;
  275. int done=0;
  276. int j;
  277. PR_RWLock_Wlock(inst->rwl_config_lock);
  278. for (j = 0; mods[i]->mod_bvalues && mods[i]->mod_bvalues[j]; j++) {
  279. config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
  280. if ( mods[i]->mod_op & LDAP_MOD_REPLACE) {
  281. if (!done) {
  282. charray_free(inst->illegal_attributes);
  283. inst->illegal_attributes=NULL;
  284. done=1;
  285. }
  286. charray_add(&inst->illegal_attributes,
  287. slapi_ch_strdup(config_attr_value));
  288. } else
  289. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD) {
  290. charray_add(&inst->illegal_attributes,
  291. slapi_ch_strdup(config_attr_value));
  292. } else
  293. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
  294. charray_remove(inst->illegal_attributes,
  295. slapi_ch_strdup(config_attr_value));
  296. }
  297. }
  298. if (NULL == mods[i]->mod_bvalues) {
  299. charray_free(inst->illegal_attributes);
  300. inst->illegal_attributes=NULL;
  301. }
  302. PR_RWLock_Unlock(inst->rwl_config_lock);
  303. continue;
  304. }
  305. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  306. char * config_attr_value;
  307. int done=0;
  308. int j;
  309. PR_RWLock_Wlock(inst->rwl_config_lock);
  310. for (j = 0; mods[i]->mod_bvalues && mods[i]->mod_bvalues[j]; j++) {
  311. config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
  312. if ( mods[i]->mod_op & LDAP_MOD_REPLACE) {
  313. if (!done) {
  314. charray_free(inst->chaining_components);
  315. inst->chaining_components=NULL;
  316. done=1;
  317. }
  318. /* XXXSD assume dns */
  319. charray_add(&inst->chaining_components,
  320. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
  321. } else
  322. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD) {
  323. charray_add(&inst->chaining_components,
  324. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
  325. } else
  326. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
  327. charray_remove(inst->chaining_components,
  328. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
  329. }
  330. }
  331. if (NULL == mods[i]->mod_bvalues) {
  332. charray_free(inst->chaining_components);
  333. inst->chaining_components=NULL;
  334. }
  335. PR_RWLock_Unlock(inst->rwl_config_lock);
  336. continue;
  337. }
  338. if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
  339. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  340. /* Special processing for binddn & password */
  341. /* because they are optional */
  342. if (( !strcasecmp ( attr_name, CB_CONFIG_BINDUSER )) ||
  343. ( !strcasecmp ( attr_name, CB_CONFIG_USERPASSWORD ))) {
  344. if (mods[i]->mod_op & LDAP_MOD_DELETE) {
  345. rc = cb_instance_config_set((void *) inst, attr_name,
  346. cb_the_instance_config, NULL, returntext,
  347. CB_CONFIG_PHASE_RUNNING, 1); }
  348. else {
  349. rc = cb_instance_config_set((void *) inst, attr_name,
  350. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  351. CB_CONFIG_PHASE_RUNNING, 1);
  352. }
  353. if (rc==CB_REOPEN_CONN) {
  354. reopen_conn=1;
  355. rc=LDAP_SUCCESS;
  356. }
  357. continue;
  358. }
  359. rc= LDAP_UNWILLING_TO_PERFORM;
  360. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
  361. (mods[i]->mod_op & LDAP_MOD_DELETE) ? "Deleting" : "Adding");
  362. } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
  363. /* This assumes there is only one bval for this mod. */
  364. rc = cb_instance_config_set((void *) inst, attr_name,
  365. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  366. CB_CONFIG_PHASE_RUNNING, 1);
  367. /* Update requires to reopen connections */
  368. /* Expensive operation so do it only once */
  369. if (rc==CB_REOPEN_CONN) {
  370. reopen_conn=1;
  371. rc=LDAP_SUCCESS;
  372. }
  373. }
  374. }
  375. *returncode= rc;
  376. if (reopen_conn) {
  377. cb_stale_all_connections(inst);
  378. }
  379. return ((LDAP_SUCCESS == rc) ? SLAPI_DSE_CALLBACK_OK:SLAPI_DSE_CALLBACK_ERROR);
  380. }
  381. /*
  382. ** Parse and instantiate backend instances
  383. */
  384. int
  385. cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) {
  386. int rc =LDAP_SUCCESS;
  387. Slapi_Attr *attr = NULL;
  388. Slapi_Value *sval;
  389. const struct berval *attrValue;
  390. cb_backend_instance *inst=NULL;
  391. char *instname;
  392. char retmsg[CB_BUFSIZE];
  393. CB_ASSERT(e!=NULL);
  394. /*
  395. ** Retrieve the instance name and make sure it is not
  396. ** already declared.
  397. */
  398. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  399. slapi_attr_first_value(attr, &sval);
  400. attrValue = slapi_value_get_berval(sval);
  401. instname=attrValue->bv_val;
  402. } else {
  403. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  404. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  405. return LDAP_LOCAL_ERROR;
  406. }
  407. /* Allocate a new backend internal data structure */
  408. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  409. /* Emulate a add config entry to configure */
  410. /* this backend instance. */
  411. cb_instance_add_config_callback(NULL,e,NULL,&rc,retmsg,inst);
  412. if ( rc != LDAP_SUCCESS ) {
  413. cb_instance_free(inst);
  414. }
  415. return rc;
  416. }
  417. /*
  418. ** Update the instance configuration
  419. */
  420. static int
  421. cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int phase, int apply) {
  422. int rc =LDAP_SUCCESS;
  423. Slapi_Attr *attr = NULL;
  424. Slapi_Value *sval;
  425. struct berval * bval;
  426. int using_def_connlifetime,i;
  427. char err_buf[SLAPI_DSE_RETURNTEXT_SIZE];
  428. int urlfound=0;
  429. char *rootdn;
  430. using_def_connlifetime=1;
  431. for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) {
  432. char * attr_name=NULL;
  433. slapi_attr_get_type(attr, &attr_name);
  434. if ( !strcasecmp ( attr_name, CB_CONFIG_SUFFIX )) {
  435. if (apply && ( inst->inst_be != NULL )) {
  436. Slapi_DN *suffix;
  437. suffix = slapi_sdn_new();
  438. i = slapi_attr_first_value(attr, &sval);
  439. while (i != -1 ) {
  440. bval = (struct berval *) slapi_value_get_berval(sval);
  441. slapi_sdn_init_dn_byref(suffix, bval->bv_val);
  442. if (!slapi_be_issuffix(inst->inst_be, suffix)) {
  443. slapi_be_addsuffix(inst->inst_be, suffix);
  444. }
  445. slapi_sdn_done(suffix);
  446. slapi_sdn_free(&suffix);
  447. i = slapi_attr_next_value(attr, i, &sval);
  448. }
  449. }
  450. continue;
  451. } else
  452. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  453. if (apply) {
  454. PR_RWLock_Wlock(inst->rwl_config_lock);
  455. i = slapi_attr_first_value(attr, &sval);
  456. charray_free(inst->chaining_components);
  457. inst->chaining_components=NULL;
  458. while (i != -1 ) {
  459. bval = (struct berval *) slapi_value_get_berval(sval);
  460. charray_add(&inst->chaining_components,
  461. slapi_dn_normalize(slapi_ch_strdup(bval->bv_val)));
  462. i = slapi_attr_next_value(attr, i, &sval);
  463. }
  464. PR_RWLock_Unlock(inst->rwl_config_lock);
  465. }
  466. continue;
  467. } else
  468. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  469. if (apply) {
  470. PR_RWLock_Wlock(inst->rwl_config_lock);
  471. i = slapi_attr_first_value(attr, &sval);
  472. charray_free(inst->illegal_attributes);
  473. inst->illegal_attributes=NULL;
  474. while (i != -1 ) {
  475. bval = (struct berval *) slapi_value_get_berval(sval);
  476. charray_add(&inst->illegal_attributes,
  477. slapi_ch_strdup(bval->bv_val));
  478. i = slapi_attr_next_value(attr, i, &sval);
  479. }
  480. PR_RWLock_Unlock(inst->rwl_config_lock);
  481. }
  482. continue;
  483. }
  484. if ( !strcasecmp ( attr_name, CB_CONFIG_HOSTURL )) {
  485. urlfound=1;
  486. }
  487. /* We are assuming that each of these attributes are to have
  488. * only one value. If they have more than one value, like
  489. * the nsslapd-suffix attribute, then they need to be
  490. * handled differently. */
  491. slapi_attr_first_value(attr, &sval);
  492. bval = (struct berval *) slapi_value_get_berval(sval);
  493. if (cb_instance_config_set((void *) inst, attr_name,
  494. cb_the_instance_config, bval, err_buf, phase, apply ) != LDAP_SUCCESS) {
  495. slapi_log_error( SLAPI_LOG_FATAL,
  496. CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s : %s\n",
  497. attr_name, err_buf);
  498. rc=LDAP_LOCAL_ERROR;
  499. break;
  500. }
  501. if ( !strcasecmp ( attr_name, CB_CONFIG_CONNLIFETIME )) {
  502. using_def_connlifetime=0;
  503. }
  504. }
  505. /*
  506. ** Check for mandatory attributes
  507. ** Post-Processing
  508. */
  509. if (LDAP_SUCCESS == rc) {
  510. if (!urlfound) {
  511. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  512. "Malformed backend instance entry. Mandatory attr <%s> missing\n",
  513. CB_CONFIG_HOSTURL);
  514. rc= LDAP_LOCAL_ERROR;
  515. }
  516. if (apply ) {
  517. if ( using_def_connlifetime &&
  518. strchr( inst->pool->hostname, ' ' ) != NULL ) {
  519. cb_instance_config_set((void *)inst, CB_CONFIG_CONNLIFETIME,
  520. cb_the_instance_config, NULL /* use default */, err_buf,
  521. CB_CONFIG_PHASE_INITIALIZATION, 1 );
  522. }
  523. }
  524. }
  525. /*
  526. ** Additional checks
  527. ** It is forbidden to use directory manager as proxy user
  528. ** due to a bug in the acl check
  529. */
  530. rootdn=cb_get_rootdn();
  531. if (inst->impersonate && inst->pool && inst->pool->binddn &&
  532. !strcmp(inst->pool->binddn,rootdn)) { /* UTF8 aware */
  533. slapi_log_error( SLAPI_LOG_FATAL,
  534. CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s (%s: forbidden value)\n",
  535. CB_CONFIG_BINDUSER, rootdn);
  536. rc=LDAP_LOCAL_ERROR;
  537. }
  538. slapi_ch_free((void **)&rootdn);
  539. return rc;
  540. }
  541. /********************************************************
  542. ** Get and set functions for chaining backend instances *
  543. *********************************************************
  544. */
  545. static void *cb_instance_hosturl_get(void *arg)
  546. {
  547. cb_backend_instance * inst=(cb_backend_instance *) arg;
  548. char * data;
  549. PR_RWLock_Rlock(inst->rwl_config_lock);
  550. data = slapi_ch_strdup(inst->pool->url);
  551. PR_RWLock_Unlock(inst->rwl_config_lock);
  552. return data;
  553. }
  554. static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  555. {
  556. cb_backend_instance *inst=(cb_backend_instance *) arg;
  557. char *url = (char *) value;
  558. LDAPURLDesc *ludp=NULL;
  559. int rc=LDAP_SUCCESS;
  560. if (( rc = ldap_url_parse( url, &ludp )) != 0 ) {
  561. PL_strncpyz(errorbuf,cb_urlparse_err2string( rc ), SLAPI_DSE_RETURNTEXT_SIZE);
  562. if (CB_CONFIG_PHASE_INITIALIZATION == phase)
  563. inst->pool->url=slapi_ch_strdup("");
  564. return(LDAP_INVALID_SYNTAX);
  565. }
  566. if (apply) {
  567. char * ptr;
  568. PR_RWLock_Wlock(inst->rwl_config_lock);
  569. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  570. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  571. /* Dynamic modification */
  572. /* Don't free char * pointer now */
  573. /* STore them in a waste basket */
  574. /* Will be relesase when the backend stops */
  575. if (inst->pool->hostname)
  576. charray_add(&inst->pool->waste_basket,inst->pool->hostname);
  577. if (inst->pool->url)
  578. charray_add(&inst->pool->waste_basket,inst->pool->url);
  579. if (inst->bind_pool->hostname)
  580. charray_add(&inst->bind_pool->waste_basket,inst->bind_pool->hostname);
  581. if (inst->bind_pool->url)
  582. charray_add(&inst->bind_pool->waste_basket,inst->bind_pool->url);
  583. /* Require connection cleanup */
  584. rc=CB_REOPEN_CONN;
  585. }
  586. /* Normal case. Extract useful data from */
  587. /* the url and update the configuration */
  588. if ((ludp->lud_host==NULL) || (strlen(ludp->lud_host)==0)) {
  589. inst->pool->hostname=(char *)slapi_ch_strdup((char *)get_localhost_DNS());
  590. } else {
  591. inst->pool->hostname = slapi_ch_strdup( ludp->lud_host );
  592. }
  593. inst->pool->url = slapi_ch_strdup( url);
  594. inst->pool->secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 );
  595. if ((ludp->lud_port==0) && inst->pool->secure)
  596. inst->pool->port=CB_LDAP_SECURE_PORT;
  597. else
  598. inst->pool->port = ludp->lud_port;
  599. /* Build a charray of <host>:<port> */
  600. /* hostname is of the form <host>[:port] <host>[:port] */
  601. { char * aBufCopy, * aHostName;
  602. char * iter = NULL;
  603. aBufCopy=slapi_ch_strdup(inst->pool->hostname);
  604. aHostName=ldap_utf8strtok_r(aBufCopy," ", &iter);
  605. charray_free(inst->url_array);
  606. inst->url_array=NULL;
  607. while (aHostName) {
  608. char * aHostPort;
  609. if ( NULL == ( ptr=strstr(aHostName,":"))) {
  610. aHostPort = slapi_ch_smprintf("%s://%s:%d/",
  611. inst->pool->secure ? "ldaps" : "ldap",
  612. aHostName,inst->pool->port);
  613. } else {
  614. aHostPort = slapi_ch_smprintf("%s://%s/",
  615. inst->pool->secure ? "ldaps" : "ldap",
  616. aHostName);
  617. }
  618. charray_add(&inst->url_array,aHostPort);
  619. aHostName=ldap_utf8strtok_r(NULL," ", &iter);
  620. }
  621. slapi_ch_free((void **) &aBufCopy);
  622. }
  623. inst->bind_pool->port=inst->pool->port;
  624. inst->bind_pool->secure=inst->pool->secure;
  625. inst->bind_pool->hostname=slapi_ch_strdup(inst->pool->hostname);
  626. PR_RWLock_Unlock(inst->rwl_config_lock);
  627. }
  628. if ( ludp != NULL ) {
  629. ldap_free_urldesc( ludp );
  630. }
  631. return rc;
  632. }
  633. static void *cb_instance_binduser_get(void *arg)
  634. {
  635. cb_backend_instance * inst=(cb_backend_instance *) arg;
  636. char * data;
  637. PR_RWLock_Rlock(inst->rwl_config_lock);
  638. data = slapi_ch_strdup(inst->pool->binddn2); /* not normalized */
  639. PR_RWLock_Unlock(inst->rwl_config_lock);
  640. return data;
  641. }
  642. static int cb_instance_binduser_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  643. {
  644. cb_backend_instance * inst=(cb_backend_instance *) arg;
  645. int rc=LDAP_SUCCESS;
  646. if (apply) {
  647. PR_RWLock_Wlock(inst->rwl_config_lock);
  648. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  649. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  650. /* Dynamic modif */
  651. /* Free user later */
  652. charray_add(&inst->pool->waste_basket,inst->pool->binddn);
  653. charray_add(&inst->pool->waste_basket,inst->pool->binddn2);
  654. rc=CB_REOPEN_CONN;
  655. }
  656. inst->pool->binddn=slapi_ch_strdup((char *) value);
  657. inst->pool->binddn2=slapi_ch_strdup((char *) value);
  658. slapi_dn_normalize_case(inst->pool->binddn);
  659. PR_RWLock_Unlock(inst->rwl_config_lock);
  660. } else {
  661. /* Security check */
  662. /* directory manager of the farm server should not be used as */
  663. /* proxing user. This is hard to check, so assume same directory */
  664. /* manager across servers. */
  665. char * rootdn = cb_get_rootdn();
  666. char * theValueCopy = NULL;
  667. if (value) {
  668. theValueCopy=slapi_ch_strdup((char *) value);
  669. slapi_dn_normalize_case(theValueCopy);
  670. }
  671. PR_RWLock_Rlock(inst->rwl_config_lock);
  672. if (inst->impersonate && theValueCopy &&
  673. !strcmp(theValueCopy,rootdn)) { /* UTF8-aware. See cb_get_dn() */
  674. rc=LDAP_UNWILLING_TO_PERFORM;
  675. if (errorbuf) {
  676. PR_snprintf(errorbuf,SLAPI_DSE_RETURNTEXT_SIZE, "value %s not allowed",rootdn);
  677. }
  678. }
  679. PR_RWLock_Unlock(inst->rwl_config_lock);
  680. slapi_ch_free((void **)&theValueCopy);
  681. slapi_ch_free((void **)&rootdn);
  682. }
  683. return rc;
  684. }
  685. static void *cb_instance_userpassword_get(void *arg)
  686. {
  687. cb_backend_instance * inst=(cb_backend_instance *) arg;
  688. char * data;
  689. PR_RWLock_Rlock(inst->rwl_config_lock);
  690. data = slapi_ch_strdup(inst->pool->password);
  691. PR_RWLock_Unlock(inst->rwl_config_lock);
  692. return data;
  693. }
  694. static int cb_instance_userpassword_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  695. {
  696. cb_backend_instance * inst=(cb_backend_instance *) arg;
  697. int rc=LDAP_SUCCESS;
  698. if (apply) {
  699. PR_RWLock_Wlock(inst->rwl_config_lock);
  700. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  701. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  702. /* Dynamic modif */
  703. charray_add(&inst->pool->waste_basket,inst->pool->password);
  704. rc=CB_REOPEN_CONN;
  705. }
  706. inst->pool->password=slapi_ch_strdup((char *) value);
  707. PR_RWLock_Unlock(inst->rwl_config_lock);
  708. }
  709. return rc;
  710. }
  711. static void *cb_instance_sizelimit_get(void *arg)
  712. {
  713. cb_backend_instance * inst=(cb_backend_instance *) arg;
  714. int data;
  715. PR_RWLock_Rlock(inst->rwl_config_lock);
  716. data = inst->sizelimit;
  717. PR_RWLock_Unlock(inst->rwl_config_lock);
  718. return (void *) data;
  719. }
  720. static int cb_instance_sizelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  721. {
  722. cb_backend_instance * inst=(cb_backend_instance *) arg;
  723. if (apply) {
  724. PR_RWLock_Wlock(inst->rwl_config_lock);
  725. inst->sizelimit=(int) value;
  726. PR_RWLock_Unlock(inst->rwl_config_lock);
  727. if (inst->inst_be)
  728. be_set_sizelimit(inst->inst_be, (int) value);
  729. }
  730. return LDAP_SUCCESS;
  731. }
  732. static void *cb_instance_timelimit_get(void *arg)
  733. {
  734. cb_backend_instance * inst=(cb_backend_instance *) arg;
  735. int data;
  736. PR_RWLock_Rlock(inst->rwl_config_lock);
  737. data = inst->timelimit;
  738. PR_RWLock_Unlock(inst->rwl_config_lock);
  739. return (void *) data;
  740. }
  741. static int cb_instance_timelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  742. {
  743. cb_backend_instance * inst=(cb_backend_instance *) arg;
  744. if (apply) {
  745. PR_RWLock_Wlock(inst->rwl_config_lock);
  746. inst->timelimit=(int) value;
  747. PR_RWLock_Unlock(inst->rwl_config_lock);
  748. if (inst->inst_be)
  749. be_set_timelimit(inst->inst_be, (int) value);
  750. }
  751. return LDAP_SUCCESS;
  752. }
  753. static void *cb_instance_max_test_get(void *arg)
  754. {
  755. cb_backend_instance * inst=(cb_backend_instance *) arg;
  756. int data;
  757. PR_RWLock_Rlock(inst->rwl_config_lock);
  758. data = inst->max_test_time;
  759. PR_RWLock_Unlock(inst->rwl_config_lock);
  760. return (void *) data;
  761. }
  762. static int cb_instance_max_test_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  763. {
  764. cb_backend_instance * inst=(cb_backend_instance *) arg;
  765. if (apply) {
  766. PR_RWLock_Wlock(inst->rwl_config_lock);
  767. inst->max_test_time=(int) value;
  768. PR_RWLock_Unlock(inst->rwl_config_lock);
  769. }
  770. return LDAP_SUCCESS;
  771. }
  772. static void *cb_instance_max_idle_get(void *arg)
  773. {
  774. cb_backend_instance * inst=(cb_backend_instance *) arg;
  775. int data;
  776. PR_RWLock_Rlock(inst->rwl_config_lock);
  777. data = inst->max_idle_time;
  778. PR_RWLock_Unlock(inst->rwl_config_lock);
  779. return (void *) data;
  780. }
  781. static int cb_instance_max_idle_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  782. {
  783. cb_backend_instance * inst=(cb_backend_instance *) arg;
  784. if (apply) {
  785. PR_RWLock_Wlock(inst->rwl_config_lock);
  786. inst->max_idle_time=(int) value;
  787. PR_RWLock_Unlock(inst->rwl_config_lock);
  788. }
  789. return LDAP_SUCCESS;
  790. }
  791. static void *cb_instance_hoplimit_get(void *arg)
  792. {
  793. cb_backend_instance * inst=(cb_backend_instance *) arg;
  794. int data;
  795. PR_RWLock_Rlock(inst->rwl_config_lock);
  796. data = inst->hoplimit;
  797. PR_RWLock_Unlock(inst->rwl_config_lock);
  798. return (void *) data;
  799. }
  800. static int cb_instance_hoplimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  801. {
  802. cb_backend_instance * inst=(cb_backend_instance *) arg;
  803. if (apply) {
  804. PR_RWLock_Wlock(inst->rwl_config_lock);
  805. inst->hoplimit=(int) value;
  806. PR_RWLock_Unlock(inst->rwl_config_lock);
  807. }
  808. return LDAP_SUCCESS;
  809. }
  810. static void *cb_instance_maxbconn_get(void *arg)
  811. {
  812. cb_backend_instance * inst=(cb_backend_instance *) arg;
  813. int data;
  814. PR_RWLock_Rlock(inst->rwl_config_lock);
  815. data = inst->bind_pool->conn.maxconnections;
  816. PR_RWLock_Unlock(inst->rwl_config_lock);
  817. return (void *) data;
  818. }
  819. static int cb_instance_maxbconn_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  820. {
  821. cb_backend_instance * inst=(cb_backend_instance *) arg;
  822. if (apply) {
  823. PR_RWLock_Wlock(inst->rwl_config_lock);
  824. inst->bind_pool->conn.maxconnections=(int) value;
  825. PR_RWLock_Unlock(inst->rwl_config_lock);
  826. }
  827. return LDAP_SUCCESS;
  828. }
  829. static void *cb_instance_maxconn_get(void *arg)
  830. {
  831. cb_backend_instance * inst=(cb_backend_instance *) arg;
  832. int data;
  833. PR_RWLock_Rlock(inst->rwl_config_lock);
  834. data = inst->pool->conn.maxconnections;
  835. PR_RWLock_Unlock(inst->rwl_config_lock);
  836. return (void *) data;
  837. }
  838. static int cb_instance_maxconn_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  839. {
  840. cb_backend_instance * inst=(cb_backend_instance *) arg;
  841. if (apply) {
  842. PR_RWLock_Wlock(inst->rwl_config_lock);
  843. inst->pool->conn.maxconnections=(int) value;
  844. PR_RWLock_Unlock(inst->rwl_config_lock);
  845. }
  846. return LDAP_SUCCESS;
  847. }
  848. static void *cb_instance_abandonto_get(void *arg)
  849. {
  850. cb_backend_instance * inst=(cb_backend_instance *) arg;
  851. int data;
  852. PR_RWLock_Rlock(inst->rwl_config_lock);
  853. data = inst->abandon_timeout.tv_sec;
  854. PR_RWLock_Unlock(inst->rwl_config_lock);
  855. return (void *) data;
  856. }
  857. static int cb_instance_abandonto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  858. {
  859. cb_backend_instance * inst=(cb_backend_instance *) arg;
  860. if (apply) {
  861. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  862. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  863. /* Dynamic modif not supported */
  864. /* Stored in ldif only */
  865. return LDAP_SUCCESS;
  866. }
  867. PR_RWLock_Wlock(inst->rwl_config_lock);
  868. inst->abandon_timeout.tv_sec=(int) value;
  869. inst->abandon_timeout.tv_usec=0;
  870. PR_RWLock_Unlock(inst->rwl_config_lock);
  871. }
  872. return LDAP_SUCCESS;
  873. }
  874. static void *cb_instance_maxbconc_get(void *arg)
  875. {
  876. cb_backend_instance * inst=(cb_backend_instance *) arg;
  877. int data;
  878. PR_RWLock_Rlock(inst->rwl_config_lock);
  879. data = inst->bind_pool->conn.maxconcurrency;
  880. PR_RWLock_Unlock(inst->rwl_config_lock);
  881. return (void *) data;
  882. }
  883. static int cb_instance_maxbconc_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  884. {
  885. cb_backend_instance * inst=(cb_backend_instance *) arg;
  886. if (apply) {
  887. PR_RWLock_Wlock(inst->rwl_config_lock);
  888. inst->bind_pool->conn.maxconcurrency=(int) value;
  889. PR_RWLock_Unlock(inst->rwl_config_lock);
  890. }
  891. return LDAP_SUCCESS;
  892. }
  893. static void *cb_instance_maxconc_get(void *arg)
  894. {
  895. cb_backend_instance * inst=(cb_backend_instance *) arg;
  896. int data;
  897. PR_RWLock_Rlock(inst->rwl_config_lock);
  898. data = inst->pool->conn.maxconcurrency;
  899. PR_RWLock_Unlock(inst->rwl_config_lock);
  900. return (void *) data;
  901. }
  902. static int cb_instance_maxconc_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  903. {
  904. cb_backend_instance * inst=(cb_backend_instance *) arg;
  905. if (apply) {
  906. PR_RWLock_Wlock(inst->rwl_config_lock);
  907. inst->pool->conn.maxconcurrency=(int) value;
  908. PR_RWLock_Unlock(inst->rwl_config_lock);
  909. }
  910. return LDAP_SUCCESS;
  911. }
  912. static void *cb_instance_imperson_get(void *arg)
  913. {
  914. cb_backend_instance * inst=(cb_backend_instance *) arg;
  915. int data;
  916. PR_RWLock_Rlock(inst->rwl_config_lock);
  917. data = inst->impersonate;
  918. PR_RWLock_Unlock(inst->rwl_config_lock);
  919. return (void *) data;
  920. }
  921. static int cb_instance_imperson_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  922. {
  923. cb_backend_instance * inst=(cb_backend_instance *) arg;
  924. int rc=LDAP_SUCCESS;
  925. if (apply) {
  926. PR_RWLock_Wlock(inst->rwl_config_lock);
  927. inst->impersonate=(int) value;
  928. PR_RWLock_Unlock(inst->rwl_config_lock);
  929. } else {
  930. /* Security check: Make sure the proxing user is */
  931. /* not the directory manager. */
  932. char * rootdn=cb_get_rootdn();
  933. PR_RWLock_Rlock(inst->rwl_config_lock);
  934. if (((int) value) && inst->pool && inst->pool->binddn &&
  935. !strcmp(inst->pool->binddn,rootdn)) { /* UTF-8 aware */
  936. rc=LDAP_UNWILLING_TO_PERFORM;
  937. if (errorbuf)
  938. PR_snprintf(errorbuf,SLAPI_DSE_RETURNTEXT_SIZE, "Proxy mode incompatible with %s value (%s not allowed)",
  939. CB_CONFIG_BINDUSER,rootdn);
  940. }
  941. PR_RWLock_Unlock(inst->rwl_config_lock);
  942. slapi_ch_free((void **)&rootdn);
  943. }
  944. return rc;
  945. }
  946. static void *cb_instance_connlife_get(void *arg)
  947. {
  948. cb_backend_instance * inst=(cb_backend_instance *) arg;
  949. int data;
  950. PR_RWLock_Rlock(inst->rwl_config_lock);
  951. data=inst->pool->conn.connlifetime;
  952. PR_RWLock_Unlock(inst->rwl_config_lock);
  953. return (void *) data;
  954. }
  955. static int cb_instance_connlife_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  956. {
  957. cb_backend_instance * inst=(cb_backend_instance *) arg;
  958. if (apply) {
  959. PR_RWLock_Wlock(inst->rwl_config_lock);
  960. inst->pool->conn.connlifetime=(int) value;
  961. PR_RWLock_Unlock(inst->rwl_config_lock);
  962. }
  963. return LDAP_SUCCESS;
  964. }
  965. static void *cb_instance_bindto_get(void *arg)
  966. {
  967. cb_backend_instance * inst=(cb_backend_instance *) arg;
  968. int data;
  969. PR_RWLock_Rlock(inst->rwl_config_lock);
  970. data=inst->bind_pool->conn.op_timeout.tv_sec;
  971. PR_RWLock_Unlock(inst->rwl_config_lock);
  972. return (void *) data;
  973. }
  974. static int cb_instance_bindto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  975. {
  976. cb_backend_instance * inst=(cb_backend_instance *) arg;
  977. if (apply) {
  978. PR_RWLock_Wlock(inst->rwl_config_lock);
  979. inst->bind_pool->conn.op_timeout.tv_sec=(int) value;
  980. inst->bind_pool->conn.op_timeout.tv_usec=0;
  981. inst->bind_pool->conn.bind_timeout.tv_sec=(int) value;
  982. inst->bind_pool->conn.bind_timeout.tv_usec=0;
  983. /* Used to bind to the farm server */
  984. inst->pool->conn.bind_timeout.tv_sec=(int) value;
  985. inst->pool->conn.bind_timeout.tv_usec=0;
  986. PR_RWLock_Unlock(inst->rwl_config_lock);
  987. }
  988. return LDAP_SUCCESS;
  989. }
  990. static void *cb_instance_opto_get(void *arg)
  991. {
  992. cb_backend_instance * inst=(cb_backend_instance *) arg;
  993. int data;
  994. PR_RWLock_Rlock(inst->rwl_config_lock);
  995. data=inst->pool->conn.op_timeout.tv_sec;
  996. PR_RWLock_Unlock(inst->rwl_config_lock);
  997. return (void *) data;
  998. }
  999. static int cb_instance_opto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1000. {
  1001. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1002. if (apply) {
  1003. PR_RWLock_Wlock(inst->rwl_config_lock);
  1004. inst->pool->conn.op_timeout.tv_sec=(int) value;
  1005. inst->pool->conn.op_timeout.tv_usec=0;
  1006. PR_RWLock_Unlock(inst->rwl_config_lock);
  1007. }
  1008. return LDAP_SUCCESS;
  1009. }
  1010. static void *cb_instance_ref_get(void *arg)
  1011. {
  1012. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1013. int data;
  1014. PR_RWLock_Rlock(inst->rwl_config_lock);
  1015. data=inst->searchreferral;
  1016. PR_RWLock_Unlock(inst->rwl_config_lock);
  1017. return (void *) data;
  1018. }
  1019. static int cb_instance_ref_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1020. {
  1021. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1022. if (apply) {
  1023. PR_RWLock_Wlock(inst->rwl_config_lock);
  1024. inst->searchreferral=(int) value;
  1025. PR_RWLock_Unlock(inst->rwl_config_lock);
  1026. }
  1027. return LDAP_SUCCESS;
  1028. }
  1029. static void *cb_instance_acl_get(void *arg)
  1030. {
  1031. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1032. int data;
  1033. PR_RWLock_Rlock(inst->rwl_config_lock);
  1034. data=inst->local_acl;
  1035. PR_RWLock_Unlock(inst->rwl_config_lock);
  1036. return (void *) data;
  1037. }
  1038. static int cb_instance_acl_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1039. {
  1040. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1041. if (apply) {
  1042. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  1043. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  1044. /* Dynamic modif not supported */
  1045. /* Stored in ldif only */
  1046. return LDAP_SUCCESS;
  1047. }
  1048. PR_RWLock_Wlock(inst->rwl_config_lock);
  1049. inst->local_acl=(int) value;
  1050. PR_RWLock_Unlock(inst->rwl_config_lock);
  1051. }
  1052. return LDAP_SUCCESS;
  1053. }
  1054. static void *cb_instance_bindretry_get(void *arg)
  1055. {
  1056. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1057. int data;
  1058. PR_RWLock_Rlock(inst->rwl_config_lock);
  1059. data=inst->bind_retry;
  1060. PR_RWLock_Unlock(inst->rwl_config_lock);
  1061. return (void *) data;
  1062. }
  1063. static int cb_instance_bindretry_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1064. {
  1065. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1066. if (apply) {
  1067. PR_RWLock_Wlock(inst->rwl_config_lock);
  1068. inst->bind_retry=(int) value;
  1069. PR_RWLock_Unlock(inst->rwl_config_lock);
  1070. }
  1071. return LDAP_SUCCESS;
  1072. }
  1073. /* Finds an entry in a config_info array with the given name. Returns
  1074. * the entry on success and NULL when not found.
  1075. */
  1076. static cb_instance_config_info *cb_get_config_info(cb_instance_config_info *config_array, char *attr_name)
  1077. {
  1078. int x;
  1079. for(x = 0; config_array[x].config_name != NULL; x++) {
  1080. if (!strcasecmp(config_array[x].config_name, attr_name)) {
  1081. return &(config_array[x]);
  1082. }
  1083. }
  1084. return NULL;
  1085. }
  1086. /*
  1087. ** Update an attribute value
  1088. ** For now, unknown attributes are ignored
  1089. ** Return a LDAP error code OR CB_REOPEN_CONN when the
  1090. ** update requires to close open connections.
  1091. ** err_buf is size SLAPI_DSE_RETURNTEXT_SIZE
  1092. */
  1093. static int
  1094. cb_instance_config_set(void *arg, char *attr_name, cb_instance_config_info *config_array,
  1095. struct berval *bval, char *err_buf, int phase, int apply_mod)
  1096. {
  1097. cb_instance_config_info *config;
  1098. int use_default;
  1099. int int_val;
  1100. long long_val;
  1101. int retval=LDAP_LOCAL_ERROR;
  1102. config = cb_get_config_info(config_array, attr_name);
  1103. if (NULL == config) {
  1104. /* Ignore unknown attributes */
  1105. return LDAP_SUCCESS;
  1106. }
  1107. /* If the config phase is initialization or if bval is NULL, we will use
  1108. * the default value for the attribute. */
  1109. if (CB_CONFIG_PHASE_INITIALIZATION == phase || NULL == bval) {
  1110. use_default = 1;
  1111. } else {
  1112. use_default = 0;
  1113. /* Since we are setting the value for the config attribute, we
  1114. * need to turn on the CB_PREVIOUSLY_SET flag to make
  1115. * sure this attribute is shown. */
  1116. config->config_flags |= CB_PREVIOUSLY_SET;
  1117. }
  1118. switch(config->config_type) {
  1119. case CB_CONFIG_TYPE_INT:
  1120. if (use_default) {
  1121. int_val = cb_atoi(config->config_default_value);
  1122. } else {
  1123. int_val = cb_atoi((char *)bval->bv_val);
  1124. }
  1125. retval = config->config_set_fn(arg, (void *) int_val, err_buf, phase, apply_mod);
  1126. break;
  1127. case CB_CONFIG_TYPE_INT_OCTAL:
  1128. if (use_default) {
  1129. int_val = (int) strtol(config->config_default_value, NULL, 8);
  1130. } else {
  1131. int_val = (int) strtol((char *)bval->bv_val, NULL, 8);
  1132. }
  1133. retval = config->config_set_fn(arg, (void *) int_val, err_buf, phase, apply_mod);
  1134. break;
  1135. case CB_CONFIG_TYPE_LONG:
  1136. if (use_default) {
  1137. long_val = cb_atol(config->config_default_value);
  1138. } else {
  1139. long_val = cb_atol((char *)bval->bv_val);
  1140. }
  1141. retval = config->config_set_fn(arg, (void *) long_val, err_buf, phase, apply_mod);
  1142. break;
  1143. case CB_CONFIG_TYPE_STRING:
  1144. if (use_default) {
  1145. retval = config->config_set_fn(arg, config->config_default_value, err_buf, phase, apply_mod);
  1146. } else {
  1147. retval = config->config_set_fn(arg, bval->bv_val, err_buf, phase, apply_mod);
  1148. }
  1149. break;
  1150. case CB_CONFIG_TYPE_ONOFF:
  1151. if (use_default) {
  1152. int_val = !strcasecmp(config->config_default_value, "on");
  1153. } else {
  1154. int_val = !strcasecmp((char *) bval->bv_val, "on");
  1155. }
  1156. retval = config->config_set_fn(arg, (void *) int_val, err_buf, phase, apply_mod);
  1157. break;
  1158. }
  1159. return retval;
  1160. }
  1161. /* Utility function used in creating config entries. Using the
  1162. * config_info, this function gets info and formats in the correct
  1163. * way.
  1164. * buf is CB_BUFSIZE size
  1165. */
  1166. void cb_instance_config_get(void *arg, cb_instance_config_info *config, char *buf)
  1167. {
  1168. char *tmp_string;
  1169. if (config == NULL) {
  1170. buf[0] = '\0';
  1171. }
  1172. switch(config->config_type) {
  1173. case CB_CONFIG_TYPE_INT:
  1174. sprintf(buf, "%d", (int) config->config_get_fn(arg));
  1175. break;
  1176. case CB_CONFIG_TYPE_INT_OCTAL:
  1177. sprintf(buf, "%o", (int) config->config_get_fn(arg));
  1178. break;
  1179. case CB_CONFIG_TYPE_LONG:
  1180. sprintf(buf, "%d", (long) config->config_get_fn(arg));
  1181. break;
  1182. case CB_CONFIG_TYPE_STRING:
  1183. /* Remember the get function for strings returns memory
  1184. * that must be freed. */
  1185. tmp_string = (char *) config->config_get_fn(arg);
  1186. PR_snprintf(buf, CB_BUFSIZE, "%s", (char *) tmp_string);
  1187. slapi_ch_free((void **)&tmp_string);
  1188. break;
  1189. case CB_CONFIG_TYPE_ONOFF:
  1190. if ((int) config->config_get_fn(arg)) {
  1191. sprintf(buf,"%s","on");
  1192. } else {
  1193. sprintf(buf,"%s","off");
  1194. }
  1195. break;
  1196. default:
  1197. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1198. "Invalid attribute syntax.\n");
  1199. }
  1200. }
  1201. /*
  1202. ** Search for instance config entry
  1203. ** Always return 'active' values because some configuration changes
  1204. ** won't be taken into account until the server restarts
  1205. */
  1206. int cb_instance_search_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
  1207. int *returncode, char *returntext, void *arg) {
  1208. char buf[CB_BUFSIZE];
  1209. struct berval val;
  1210. struct berval *vals[2];
  1211. int i = 0;
  1212. cb_backend_instance *inst = (cb_backend_instance *)arg;
  1213. cb_instance_config_info * config;
  1214. vals[0] = &val;
  1215. vals[1] = NULL;
  1216. /* suffixes */
  1217. PR_RWLock_Rlock(inst->rwl_config_lock);
  1218. {
  1219. const Slapi_DN *aSuffix;
  1220. i=0;
  1221. if (inst->inst_be) {
  1222. while ((aSuffix=slapi_be_getsuffix(inst->inst_be,i))) {
  1223. val.bv_val = (char *)slapi_sdn_get_dn(aSuffix);
  1224. val.bv_len = strlen( val.bv_val );
  1225. if (val.bv_len) {
  1226. if (i==0)
  1227. slapi_entry_attr_replace(e,CB_CONFIG_SUFFIX,(struct berval **)vals );
  1228. else
  1229. slapi_entry_attr_merge(e,CB_CONFIG_SUFFIX,(struct berval **)vals );
  1230. }
  1231. i++;
  1232. }
  1233. }
  1234. }
  1235. for (i=0; inst->chaining_components && inst->chaining_components[i]; i++) {
  1236. val.bv_val = inst->chaining_components[i];
  1237. val.bv_len = strlen( val.bv_val );
  1238. if (val.bv_len) {
  1239. if (i==0)
  1240. slapi_entry_attr_replace(e,CB_CONFIG_CHAINING_COMPONENTS,(struct berval **)vals );
  1241. else
  1242. slapi_entry_attr_merge(e,CB_CONFIG_CHAINING_COMPONENTS,(struct berval **)vals );
  1243. }
  1244. }
  1245. for (i=0; inst->illegal_attributes && inst->illegal_attributes[i]; i++) {
  1246. val.bv_val = inst->illegal_attributes[i];
  1247. val.bv_len = strlen( val.bv_val );
  1248. if (val.bv_len) {
  1249. if (i==0)
  1250. slapi_entry_attr_replace(e,CB_CONFIG_ILLEGAL_ATTRS,(struct berval **)vals );
  1251. else
  1252. slapi_entry_attr_merge(e,CB_CONFIG_ILLEGAL_ATTRS,(struct berval **)vals );
  1253. }
  1254. }
  1255. PR_RWLock_Unlock(inst->rwl_config_lock);
  1256. /* standard attributes */
  1257. for(config = cb_the_instance_config; config->config_name != NULL; config++) {
  1258. if (!(config->config_flags & (CB_ALWAYS_SHOW | CB_PREVIOUSLY_SET))) {
  1259. /* This config option shouldn't be shown */
  1260. continue;
  1261. }
  1262. cb_instance_config_get((void *) inst, config, buf);
  1263. val.bv_val = buf;
  1264. val.bv_len = strlen(buf);
  1265. if (val.bv_len)
  1266. slapi_entry_attr_replace(e, config->config_name, vals);
  1267. }
  1268. *returncode = LDAP_SUCCESS;
  1269. return SLAPI_DSE_CALLBACK_OK;
  1270. }
  1271. /*
  1272. ** Ooops!!! The backend instance is beeing deleted
  1273. */
  1274. int cb_instance_delete_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1275. int *returncode, char *returntext, void *arg) {
  1276. cb_backend_instance * inst = (cb_backend_instance *) arg;
  1277. int rc;
  1278. Slapi_Entry * anEntry=NULL;
  1279. Slapi_DN * aDn;
  1280. CB_ASSERT( inst!=NULL );
  1281. /* notify the front-end */
  1282. slapi_mtn_be_stopping(inst->inst_be);
  1283. /* Now it is safe to stop */
  1284. /* No pending op */
  1285. /* unregister callbacks */
  1286. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->configDn,
  1287. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_search_config_callback);
  1288. slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, inst->configDn,
  1289. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_delete_config_callback);
  1290. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->configDn,
  1291. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_modify_config_check_callback);
  1292. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, inst->configDn,
  1293. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_modify_config_callback);
  1294. /* At this point, the monitor entry should have been removed */
  1295. /* If not, manually call delete callback */
  1296. aDn = slapi_sdn_new_dn_byref(inst->monitorDn);
  1297. if ( LDAP_SUCCESS==(slapi_search_internal_get_entry(aDn,NULL, &anEntry,inst->backend_type->identity))) {
  1298. cb_delete_monitor_callback( NULL, anEntry, NULL, &rc , NULL, inst );
  1299. if (anEntry)
  1300. slapi_entry_free(anEntry);
  1301. }
  1302. slapi_sdn_done(aDn);
  1303. slapi_sdn_free(&aDn);
  1304. /* free resources */
  1305. cb_close_conn_pool(inst->bind_pool);
  1306. cb_close_conn_pool(inst->pool);
  1307. slapi_be_free(&(inst->inst_be));
  1308. cb_instance_free(inst);
  1309. return SLAPI_DSE_CALLBACK_OK;
  1310. }
  1311. static void cb_instance_add_monitor_later(time_t when, void *arg) {
  1312. cb_backend_instance * inst = (cb_backend_instance *) arg;
  1313. if ( inst != NULL )
  1314. {
  1315. PR_RWLock_Rlock(inst->rwl_config_lock);
  1316. /* create the monitor entry if it is not there yet */
  1317. if (LDAP_SUCCESS == cb_config_add_dse_entries(inst->backend_type, cb_skeleton_entries,
  1318. inst->inst_name,CB_PLUGIN_NAME, NULL))
  1319. {
  1320. /* add monitor callbacks */
  1321. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->monitorDn, LDAP_SCOPE_BASE,
  1322. "(objectclass=*)", cb_search_monitor_callback, (void *) inst);
  1323. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->monitorDn, LDAP_SCOPE_BASE,
  1324. "(objectclass=*)", cb_dont_allow_that, (void *) NULL);
  1325. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP , inst->monitorDn, LDAP_SCOPE_BASE,
  1326. "(objectclass=*)", cb_delete_monitor_callback, (void *) inst);
  1327. }
  1328. PR_RWLock_Unlock(inst->rwl_config_lock);
  1329. }
  1330. }
  1331. int cb_instance_add_config_check_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1332. int *returncode, char *returntext, void *arg) {
  1333. int rc=LDAP_SUCCESS;
  1334. cb_backend_instance *inst;
  1335. cb_backend *cb=(cb_backend *) arg;
  1336. Slapi_Attr *attr = NULL;
  1337. Slapi_Value *sval;
  1338. const struct berval *attrValue;
  1339. char *instname=NULL;
  1340. if (returntext)
  1341. returntext[0]='\0';
  1342. /* Basic entry check */
  1343. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  1344. slapi_attr_first_value(attr, &sval);
  1345. attrValue = slapi_value_get_berval(sval);
  1346. instname=attrValue->bv_val;
  1347. }
  1348. if ( instname == NULL ) {
  1349. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1350. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  1351. *returncode = LDAP_LOCAL_ERROR;
  1352. return SLAPI_DSE_CALLBACK_ERROR;
  1353. }
  1354. /* Allocate a new backend internal data structure */
  1355. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  1356. /* build the backend instance from the default hardcoded conf, */
  1357. /* the default instance config and the specific entry specified */
  1358. if ((rc=cb_build_backend_instance_config(inst,e,0))
  1359. != LDAP_SUCCESS) {
  1360. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  1361. "Can't instantiate chaining backend instance %s.\n",inst->inst_name);
  1362. *returncode=rc;
  1363. cb_instance_free(inst);
  1364. return SLAPI_DSE_CALLBACK_ERROR;
  1365. }
  1366. /* Free the dummy instance */
  1367. *returncode=rc;
  1368. cb_instance_free(inst);
  1369. return SLAPI_DSE_CALLBACK_OK;
  1370. }
  1371. /* Create the default instance config from hard-coded values */
  1372. /*
  1373. ** Initialize the backend instance with the config entry
  1374. ** passed in arguments.
  1375. ** <arg> : (cb_backend *)
  1376. */
  1377. int cb_instance_add_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1378. int *returncode, char *returntext, void *arg) {
  1379. int rc=LDAP_SUCCESS;
  1380. cb_backend_instance *inst;
  1381. cb_backend *cb=(cb_backend *) arg;
  1382. Slapi_Attr *attr = NULL;
  1383. Slapi_Value *sval;
  1384. const struct berval *attrValue;
  1385. char *instname=NULL;
  1386. if (returntext)
  1387. returntext[0]='\0';
  1388. /* Basic entry check */
  1389. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  1390. slapi_attr_first_value(attr, &sval);
  1391. attrValue = slapi_value_get_berval(sval);
  1392. instname=attrValue->bv_val;
  1393. }
  1394. if ( instname == NULL ) {
  1395. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1396. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  1397. *returncode = LDAP_LOCAL_ERROR;
  1398. return SLAPI_DSE_CALLBACK_ERROR;
  1399. }
  1400. /* Allocate a new backend internal data structure */
  1401. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  1402. /* build the backend instance from the default hardcoded conf, */
  1403. /* the default instance config and the specific entry specified */
  1404. if ((rc=cb_build_backend_instance_config(inst,e,0))
  1405. != LDAP_SUCCESS) {
  1406. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  1407. "Can't instantiate chaining backend instance %s.\n",inst->inst_name);
  1408. *returncode=rc;
  1409. cb_instance_free(inst);
  1410. return SLAPI_DSE_CALLBACK_ERROR;
  1411. }
  1412. /* Instantiate a Slapi_Backend if necessary */
  1413. if (!inst->isconfigured) {
  1414. Slapi_PBlock *aPb=NULL;
  1415. inst->inst_be = slapi_be_new(CB_CHAINING_BACKEND_TYPE,slapi_ch_strdup(inst->inst_name),0,0);
  1416. aPb=slapi_pblock_new();
  1417. slapi_pblock_set(aPb, SLAPI_PLUGIN, inst->backend_type->plugin);
  1418. slapi_be_setentrypoint(inst->inst_be,0,(void *)NULL,aPb);
  1419. slapi_be_set_instance_info(inst->inst_be,inst);
  1420. slapi_pblock_set(aPb, SLAPI_PLUGIN, NULL);
  1421. slapi_pblock_destroy(aPb);
  1422. }
  1423. cb_build_backend_instance_config(inst,e,1);
  1424. /* kexcoff: the order of the following calls is very important to prevent the deletion of the
  1425. instance to happen before the creation of the monitor part of the config.
  1426. However, not sure it solves all the situations, but at least it is worth to maintain
  1427. this order. */
  1428. if (!inst->isconfigured)
  1429. {
  1430. /* Add monitor entry and callback on it
  1431. * called from an add...
  1432. * we can't call recursively into the DSE to do more adds, they'll
  1433. * silently fail. instead, schedule the adds to happen in 1 second.
  1434. */
  1435. inst->eq_ctx = slapi_eq_once(cb_instance_add_monitor_later, (void *)inst, time(NULL)+1);
  1436. }
  1437. /* Get the list of operational attrs defined in the schema */
  1438. /* see cb_search file for a reason for that */
  1439. inst->every_attribute=slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR);
  1440. charray_add(&inst->every_attribute,slapi_ch_strdup(LDAP_ALL_USER_ATTRS));
  1441. if (!inst->isconfigured)
  1442. {
  1443. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->configDn,
  1444. LDAP_SCOPE_BASE,"(objectclass=*)",cb_instance_modify_config_check_callback, (void *) inst);
  1445. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, inst->configDn,
  1446. LDAP_SCOPE_BASE,"(objectclass=*)",cb_instance_modify_config_callback, (void *) inst);
  1447. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->configDn,
  1448. LDAP_SCOPE_BASE,"(objectclass=*)", cb_instance_search_config_callback, (void *) inst);
  1449. /* allow deletion otherwise impossible to remote a backend instance */
  1450. /* dynamically... */
  1451. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, inst->configDn,
  1452. LDAP_SCOPE_BASE,"(objectclass=*)", cb_instance_delete_config_callback, (void *) inst);
  1453. }
  1454. /* Notify the front-end */
  1455. /* After the call below, we can receive ops */
  1456. slapi_mtn_be_started(inst->inst_be);
  1457. inst->isconfigured=1;
  1458. return SLAPI_DSE_CALLBACK_OK;
  1459. }
  1460. /* Create the default instance config from hard-coded values */
  1461. int cb_create_default_backend_instance_config(cb_backend * cb) {
  1462. int rc;
  1463. cb_backend_instance *dummy;
  1464. Slapi_Entry *e=slapi_entry_alloc();
  1465. char *defaultDn;
  1466. char *olddn;
  1467. struct berval val;
  1468. struct berval *vals[2];
  1469. Slapi_PBlock *pb;
  1470. dummy = cb_instance_alloc(cb, "dummy", "o=dummy");
  1471. cb_instance_config_set_default(dummy);
  1472. cb_instance_search_config_callback(NULL,e,NULL, &rc, NULL,(void *) dummy);
  1473. /* set right dn and objectclass */
  1474. defaultDn = PR_smprintf("cn=default instance config,%s",cb->pluginDN);
  1475. olddn = slapi_entry_get_dn(e);
  1476. slapi_ch_free((void **) &olddn);
  1477. slapi_entry_set_dn(e,slapi_ch_strdup(defaultDn));
  1478. vals[0] = &val;
  1479. vals[1] = NULL;
  1480. val.bv_val = "top";
  1481. val.bv_len = strlen( val.bv_val );
  1482. slapi_entry_attr_replace( e, "objectclass", (struct berval **)vals );
  1483. val.bv_val = CB_CONFIG_EXTENSIBLEOCL;
  1484. val.bv_len = strlen( val.bv_val );
  1485. slapi_entry_attr_merge( e, "objectclass", (struct berval **)vals );
  1486. val.bv_val = "default instance config";
  1487. val.bv_len = strlen( val.bv_val );
  1488. slapi_entry_attr_replace( e, "cn", (struct berval **)vals );
  1489. /* create entry */
  1490. pb = slapi_pblock_new();
  1491. slapi_add_entry_internal_set_pb(pb, e, NULL, cb->identity, 0);
  1492. slapi_add_internal_pb(pb);
  1493. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1494. if ( LDAP_SUCCESS != rc ) {
  1495. slapi_log_error(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1496. "Add %s failed (%s)\n",defaultDn,ldap_err2string(rc));
  1497. }
  1498. slapi_pblock_destroy(pb);
  1499. /* cleanup */
  1500. cb_instance_free(dummy);
  1501. /* BEWARE: entry is consummed */
  1502. PR_smprintf_free(defaultDn);
  1503. return rc;
  1504. }
  1505. /* Extract backend instance configuration from the LDAP entry */
  1506. int cb_build_backend_instance_config(cb_backend_instance *inst, Slapi_Entry * conf, int apply) {
  1507. cb_backend *cb = inst->backend_type;
  1508. Slapi_PBlock *default_pb;
  1509. Slapi_Entry **default_entries = NULL;
  1510. Slapi_Entry *default_conf=NULL;
  1511. int default_res, rc;
  1512. char *defaultDn;
  1513. cb_backend_instance * current_inst;
  1514. rc=LDAP_SUCCESS;
  1515. if (apply)
  1516. current_inst=inst;
  1517. else
  1518. current_inst=cb_instance_alloc(cb,inst->inst_name,"cn=dummy");
  1519. /* set default configuration */
  1520. cb_instance_config_set_default(current_inst);
  1521. /* 2: Overwrite values present in the default instance config */
  1522. defaultDn = PR_smprintf("cn=default instance config,%s",cb->pluginDN);
  1523. default_pb = slapi_pblock_new();
  1524. slapi_search_internal_set_pb(default_pb, defaultDn, LDAP_SCOPE_BASE,
  1525. "objectclass=*", NULL, 0, NULL, NULL, cb->identity, 0);
  1526. slapi_search_internal_pb (default_pb);
  1527. PR_smprintf_free(defaultDn);
  1528. slapi_pblock_get(default_pb, SLAPI_PLUGIN_INTOP_RESULT, &default_res);
  1529. if ( LDAP_SUCCESS == default_res ) {
  1530. slapi_pblock_get(default_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &default_entries);
  1531. if (default_entries && default_entries[0] ) {
  1532. struct berval val;
  1533. struct berval *vals[2];
  1534. vals[0] = &val;
  1535. vals[1] = NULL;
  1536. default_conf=default_entries[0];
  1537. /* hack: add a dummy url (mandatory) to avoid error */
  1538. /* will be overwritten by the one in conf entry */
  1539. val.bv_val = "ldap://localhost/";
  1540. val.bv_len = strlen( val.bv_val );
  1541. slapi_entry_attr_replace( default_conf, CB_CONFIG_HOSTURL, (struct berval **)vals );
  1542. rc=cb_instance_config_initialize(current_inst,default_conf,CB_CONFIG_PHASE_STARTUP,1);
  1543. }
  1544. }
  1545. slapi_free_search_results_internal(default_pb);
  1546. slapi_pblock_destroy(default_pb);
  1547. if (rc == LDAP_SUCCESS)
  1548. rc=cb_instance_config_initialize(current_inst,conf,CB_CONFIG_PHASE_STARTUP,1);
  1549. if (!apply)
  1550. cb_instance_free(current_inst);
  1551. return rc;
  1552. }