dna.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2007 Red Hat, Inc.
  35. * All rights reserved.
  36. * END COPYRIGHT BLOCK **/
  37. #ifdef HAVE_CONFIG_H
  38. # include <config.h>
  39. #endif
  40. /**
  41. * Distributed Numeric Assignment plug-in
  42. */
  43. #include <stdio.h>
  44. #include <ctype.h>
  45. #include <string.h>
  46. #include <errno.h>
  47. #include "portable.h"
  48. #include "nspr.h"
  49. #include "slapi-private.h"
  50. #include "dirlite_strings.h"
  51. #include "dirver.h"
  52. #include "prclist.h"
  53. #include "ldif.h"
  54. /* get file mode flags for unix */
  55. #ifndef _WIN32
  56. #include <sys/stat.h>
  57. #endif
  58. #define DNA_PLUGIN_SUBSYSTEM "dna-plugin"
  59. #define DNA_PLUGIN_VERSION 0x00020000
  60. #define DNA_DN "cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config" /* temporary */
  61. #define DNA_SUCCESS 0
  62. #define DNA_FAILURE -1
  63. /**
  64. * DNA config types
  65. */
  66. #define DNA_TYPE "dnaType"
  67. #define DNA_PREFIX "dnaPrefix"
  68. #define DNA_NEXTVAL "dnaNextValue"
  69. #define DNA_INTERVAL "dnaInterval"
  70. #define DNA_GENERATE "dnaMagicRegen"
  71. #define DNA_FILTER "dnaFilter"
  72. #define DNA_SCOPE "dnaScope"
  73. /* since v2 */
  74. #define DNA_MAXVAL "dnaMaxValue"
  75. #define DNA_SHARED_CFG_DN "dnaSharedCfgDN"
  76. /* Shared Config */
  77. #define DNA_GLOBAL_RANGE "dnaGlobalRange"
  78. #define DNA_RANGE "dnaRange"
  79. #define DNA_MAX_RANGE_SIZE "dnaMaxRangeSize"
  80. #define DNA_CHUNK_SIZE "dnaChunkSize"
  81. #define FEATURE_DESC "Distributed Numeric Assignment"
  82. #define PLUGIN_DESC "Distributed Numeric Assignment plugin"
  83. static Slapi_PluginDesc pdesc = { FEATURE_DESC,
  84. PLUGIN_MAGIC_VENDOR_STR,
  85. PRODUCTTEXT,
  86. PLUGIN_DESC };
  87. /**
  88. * linked list of config entries
  89. */
  90. struct configEntry {
  91. PRCList list;
  92. char *dn;
  93. char *type;
  94. char *prefix;
  95. PRUint64 nextval;
  96. PRUint64 interval;
  97. PRUint64 maxval;
  98. char *filter;
  99. Slapi_Filter *slapi_filter;
  100. char *generate;
  101. char *scope;
  102. };
  103. static PRCList *dna_global_config = NULL;
  104. static PRRWLock *g_dna_cache_lock;
  105. static void *_PluginID = NULL;
  106. static char *_PluginDN = NULL;
  107. /*
  108. * new value lock
  109. */
  110. static Slapi_Mutex *g_new_value_lock;
  111. /**
  112. *
  113. * DNA plug-in management functions
  114. *
  115. */
  116. int dna_init(Slapi_PBlock * pb);
  117. static int dna_start(Slapi_PBlock * pb);
  118. static int dna_close(Slapi_PBlock * pb);
  119. static int dna_postop_init(Slapi_PBlock * pb);
  120. /**
  121. *
  122. * Local operation functions
  123. *
  124. */
  125. static int loadPluginConfig();
  126. static int parseConfigEntry(Slapi_Entry * e);
  127. static void deleteConfig();
  128. static void freeConfigEntry(struct configEntry ** entry);
  129. /**
  130. *
  131. * helpers
  132. *
  133. */
  134. static char *dna_get_dn(Slapi_PBlock * pb);
  135. static int dna_dn_is_config(char *dn);
  136. static int dna_get_next_value(struct configEntry * config_entry,
  137. char **next_value_ret);
  138. /**
  139. *
  140. * the ops (where the real work is done)
  141. *
  142. */
  143. static int dna_config_check_post_op(Slapi_PBlock * pb);
  144. static int dna_pre_op(Slapi_PBlock * pb, int modtype);
  145. static int dna_mod_pre_op(Slapi_PBlock * pb);
  146. static int dna_add_pre_op(Slapi_PBlock * pb);
  147. /**
  148. * debug functions - global, for the debugger
  149. */
  150. void dnaDumpConfig();
  151. void dnaDumpConfigEntry(struct configEntry *);
  152. /**
  153. * set the debug level
  154. */
  155. #ifdef _WIN32
  156. int *module_ldap_debug = 0;
  157. void plugin_init_debug_level(int *level_ptr)
  158. {
  159. module_ldap_debug = level_ptr;
  160. }
  161. #endif
  162. /**
  163. *
  164. * Deal with cache locking
  165. *
  166. */
  167. void dna_read_lock()
  168. {
  169. PR_RWLock_Rlock(g_dna_cache_lock);
  170. }
  171. void dna_write_lock()
  172. {
  173. PR_RWLock_Wlock(g_dna_cache_lock);
  174. }
  175. void dna_unlock()
  176. {
  177. PR_RWLock_Unlock(g_dna_cache_lock);
  178. }
  179. /**
  180. *
  181. * Get the dna plug-in version
  182. *
  183. */
  184. int dna_version()
  185. {
  186. return DNA_PLUGIN_VERSION;
  187. }
  188. /**
  189. * Plugin identity mgmt
  190. */
  191. void setPluginID(void *pluginID)
  192. {
  193. _PluginID = pluginID;
  194. }
  195. void *getPluginID()
  196. {
  197. return _PluginID;
  198. }
  199. void setPluginDN(char *pluginDN)
  200. {
  201. _PluginDN = pluginDN;
  202. }
  203. char *getPluginDN()
  204. {
  205. return _PluginDN;
  206. }
  207. /*
  208. dna_init
  209. -------------
  210. adds our callbacks to the list
  211. */
  212. int dna_init(Slapi_PBlock * pb)
  213. {
  214. int status = DNA_SUCCESS;
  215. char *plugin_identity = NULL;
  216. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  217. "--> dna_init\n");
  218. /**
  219. * Store the plugin identity for later use.
  220. * Used for internal operations
  221. */
  222. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
  223. PR_ASSERT(plugin_identity);
  224. setPluginID(plugin_identity);
  225. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  226. SLAPI_PLUGIN_VERSION_01) != 0 ||
  227. slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
  228. (void *) dna_start) != 0 ||
  229. slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
  230. (void *) dna_close) != 0 ||
  231. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  232. (void *) &pdesc) != 0 ||
  233. slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN,
  234. (void *) dna_mod_pre_op) != 0 ||
  235. slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN,
  236. (void *) dna_add_pre_op) != 0 ||
  237. /* the config change checking post op */
  238. slapi_register_plugin("postoperation", /* op type */
  239. 1, /* Enabled */
  240. "dna_init", /* this function desc */
  241. dna_postop_init, /* init func for post op */
  242. PLUGIN_DESC, /* plugin desc */
  243. NULL, /* ? */
  244. plugin_identity /* access control */
  245. )
  246. ) {
  247. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  248. "dna_init: failed to register plugin\n");
  249. status = DNA_FAILURE;
  250. }
  251. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  252. "<-- dna_init\n");
  253. return status;
  254. }
  255. static int dna_postop_init(Slapi_PBlock * pb)
  256. {
  257. int status = DNA_SUCCESS;
  258. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  259. SLAPI_PLUGIN_VERSION_01) != 0 ||
  260. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  261. (void *) &pdesc) != 0 ||
  262. slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
  263. (void *) dna_config_check_post_op) != 0 ||
  264. slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN,
  265. (void *) dna_config_check_post_op) != 0 ||
  266. slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
  267. (void *) dna_config_check_post_op) != 0 ||
  268. slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
  269. (void *) dna_config_check_post_op) != 0) {
  270. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  271. "dna_postop_init: failed to register plugin\n");
  272. status = DNA_FAILURE;
  273. }
  274. return status;
  275. }
  276. /*
  277. dna_start
  278. --------------
  279. Kicks off the config cache.
  280. It is called after dna_init.
  281. */
  282. static int dna_start(Slapi_PBlock * pb)
  283. {
  284. char *plugindn = NULL;
  285. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  286. "--> dna_start\n");
  287. g_dna_cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "dna");
  288. g_new_value_lock = slapi_new_mutex();
  289. if (!g_dna_cache_lock || !g_new_value_lock) {
  290. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  291. "dna_start: lock creation failed\n");
  292. return DNA_FAILURE;
  293. }
  294. /**
  295. * Get the plug-in target dn from the system
  296. * and store it for future use. This should avoid
  297. * hardcoding of DN's in the code.
  298. */
  299. slapi_pblock_get(pb, SLAPI_TARGET_DN, &plugindn);
  300. if (NULL == plugindn || 0 == strlen(plugindn)) {
  301. slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
  302. "dna_start: had to use hard coded config dn\n");
  303. plugindn = DNA_DN;
  304. } else {
  305. slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
  306. "dna_start: config at %s\n", plugindn);
  307. }
  308. setPluginDN(plugindn);
  309. /**
  310. * Load the config for our plug-in
  311. */
  312. dna_global_config = (PRCList *)
  313. slapi_ch_calloc(1, sizeof(struct configEntry));
  314. PR_INIT_CLIST(dna_global_config);
  315. if (loadPluginConfig() != DNA_SUCCESS) {
  316. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  317. "dna_start: unable to load plug-in configuration\n");
  318. return DNA_FAILURE;
  319. }
  320. slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
  321. "dna: ready for service\n");
  322. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  323. "<-- dna_start\n");
  324. return DNA_SUCCESS;
  325. }
  326. /*
  327. dna_close
  328. --------------
  329. closes down the cache
  330. */
  331. static int dna_close(Slapi_PBlock * pb)
  332. {
  333. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  334. "--> dna_close\n");
  335. deleteConfig();
  336. slapi_ch_free((void **)&dna_global_config);
  337. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  338. "<-- dna_close\n");
  339. return DNA_SUCCESS;
  340. }
  341. /*
  342. * config looks like this
  343. * - cn=myplugin
  344. * --- cn=posix
  345. * ------ cn=accounts
  346. * ------ cn=groups
  347. * --- cn=samba
  348. * --- cn=etc
  349. * ------ cn=etc etc
  350. */
  351. static int loadPluginConfig()
  352. {
  353. int status = DNA_SUCCESS;
  354. int result;
  355. int i;
  356. Slapi_PBlock *search_pb;
  357. Slapi_Entry **entries = NULL;
  358. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  359. "--> loadPluginConfig\n");
  360. dna_write_lock();
  361. deleteConfig();
  362. search_pb = slapi_pblock_new();
  363. slapi_search_internal_set_pb(search_pb, getPluginDN(),
  364. LDAP_SCOPE_SUBTREE, "objectclass=*",
  365. NULL, 0, NULL, NULL, getPluginID(), 0);
  366. slapi_search_internal_pb(search_pb);
  367. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
  368. if (LDAP_SUCCESS != result) {
  369. status = DNA_FAILURE;
  370. goto cleanup;
  371. }
  372. slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
  373. &entries);
  374. if (NULL == entries || NULL == entries[0]) {
  375. status = DNA_SUCCESS;
  376. goto cleanup;
  377. }
  378. for (i = 0; (entries[i] != NULL); i++) {
  379. status = parseConfigEntry(entries[i]);
  380. if (DNA_SUCCESS != status)
  381. break;
  382. }
  383. cleanup:
  384. slapi_free_search_results_internal(search_pb);
  385. slapi_pblock_destroy(search_pb);
  386. dna_unlock();
  387. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  388. "<-- loadPluginConfig\n");
  389. return status;
  390. }
  391. static int parseConfigEntry(Slapi_Entry * e)
  392. {
  393. char *value;
  394. struct configEntry *entry;
  395. struct configEntry *config_entry;
  396. PRCList *list;
  397. int entry_added = 0;
  398. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  399. "--> parseConfigEntry\n");
  400. entry = (struct configEntry *)
  401. slapi_ch_calloc(1, sizeof(struct configEntry));
  402. if (NULL == entry)
  403. goto bail;
  404. value = slapi_entry_get_ndn(e);
  405. if (value) {
  406. entry->dn = strdup(value);
  407. }
  408. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  409. "----------> dn [%s]\n", entry->dn, 0, 0);
  410. value = slapi_entry_attr_get_charptr(e, DNA_TYPE);
  411. if (value) {
  412. entry->type = value;
  413. } else
  414. goto bail;
  415. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  416. "----------> dnaType [%s]\n", entry->type, 0, 0);
  417. /* FIXME: check the attribute type, it must suport matching rules and be
  418. * indexed, these are requirements and failure to meet them should result in
  419. * the configuration to be disarded and an ERROR logged prominently */
  420. value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
  421. if (value) {
  422. entry->nextval = strtoul(value, 0, 0);
  423. slapi_ch_free_string(&value);
  424. } else
  425. goto bail;
  426. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  427. "----------> dnaNextValue [%d]\n", entry->nextval, 0,
  428. 0);
  429. value = slapi_entry_attr_get_charptr(e, DNA_PREFIX);
  430. if (value && value[0]) {
  431. entry->prefix = value;
  432. }
  433. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  434. "----------> dnaPrefix [%s]\n", entry->prefix, 0, 0);
  435. value = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
  436. if (value) {
  437. entry->interval = strtoul(value, 0, 0);
  438. } else
  439. goto bail;
  440. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  441. "----------> dnaInterval [%s]\n", value, 0, 0);
  442. slapi_ch_free_string(&value);
  443. value = slapi_entry_attr_get_charptr(e, DNA_GENERATE);
  444. if (value) {
  445. entry->generate = value;
  446. }
  447. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  448. "----------> dnaMagicRegen [%s]\n", entry->generate,
  449. 0, 0);
  450. value = slapi_entry_attr_get_charptr(e, DNA_FILTER);
  451. if (value) {
  452. entry->filter = value;
  453. if (NULL == (entry->slapi_filter = slapi_str2filter(value))) {
  454. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM ,
  455. "Error: Invalid search filter in entry [%s]: [%s]\n",
  456. entry->dn, value);
  457. goto bail;
  458. }
  459. } else {
  460. goto bail;
  461. }
  462. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  463. "----------> dnaFilter [%s]\n", value, 0, 0);
  464. value = slapi_entry_attr_get_charptr(e, DNA_SCOPE);
  465. if (value) {
  466. entry->scope = slapi_dn_normalize(value);
  467. }
  468. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  469. "----------> dnaScope [%s]\n", entry->scope, 0, 0);
  470. /* optional, if not specified set -1 which is converted to the max unisgnee
  471. * value */
  472. value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
  473. if (value) {
  474. entry->maxval = strtoul(value, 0, 0);
  475. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  476. "----------> dnaMaxValue [%ld]\n", value, 0, 0);
  477. slapi_ch_free_string(&value);
  478. } else
  479. entry->maxval = -1;
  480. /**
  481. * Finally add the entry to the list
  482. * we group by type then by filter
  483. * and finally sort by dn length with longer dn's
  484. * first - this allows the scope checking
  485. * code to be simple and quick and
  486. * cunningly linear
  487. */
  488. if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
  489. list = PR_LIST_HEAD(dna_global_config);
  490. while (list != dna_global_config) {
  491. config_entry = (struct configEntry *) list;
  492. if (slapi_attr_type_cmp(config_entry->type, entry->type, 1))
  493. goto next;
  494. if (slapi_filter_compare(config_entry->slapi_filter,
  495. entry->slapi_filter))
  496. goto next;
  497. if (slapi_dn_issuffix(entry->scope, config_entry->scope)) {
  498. PR_INSERT_BEFORE(&(entry->list), list);
  499. slapi_log_error(SLAPI_LOG_CONFIG,
  500. DNA_PLUGIN_SUBSYSTEM,
  501. "store [%s] before [%s] \n", entry->scope,
  502. config_entry->scope, 0);
  503. entry_added = 1;
  504. break;
  505. }
  506. next:
  507. list = PR_NEXT_LINK(list);
  508. if (dna_global_config == list) {
  509. /* add to tail */
  510. PR_INSERT_BEFORE(&(entry->list), list);
  511. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  512. "store [%s] at tail\n", entry->scope, 0,
  513. 0);
  514. entry_added = 1;
  515. break;
  516. }
  517. }
  518. } else {
  519. /* first entry */
  520. PR_INSERT_LINK(&(entry->list), dna_global_config);
  521. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  522. "store [%s] at head \n", entry->scope, 0, 0);
  523. entry_added = 1;
  524. }
  525. bail:
  526. if (0 == entry_added) {
  527. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  528. "config entry [%s] skipped\n", entry->dn, 0, 0);
  529. freeConfigEntry(&entry);
  530. }
  531. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  532. "<-- parseConfigEntry\n");
  533. return DNA_SUCCESS;
  534. }
  535. static void freeConfigEntry(struct configEntry ** entry)
  536. {
  537. struct configEntry *e = *entry;
  538. if (e->dn) {
  539. slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
  540. "freeing config entry [%s]\n", e->dn, 0, 0);
  541. slapi_ch_free_string(&e->dn);
  542. }
  543. if (e->type)
  544. slapi_ch_free_string(&e->type);
  545. if (e->prefix)
  546. slapi_ch_free_string(&e->prefix);
  547. if (e->filter)
  548. slapi_ch_free_string(&e->filter);
  549. if (e->slapi_filter)
  550. slapi_filter_free(e->slapi_filter, 1);
  551. if (e->generate)
  552. slapi_ch_free_string(&e->generate);
  553. if (e->scope)
  554. slapi_ch_free_string(&e->scope);
  555. slapi_ch_free((void **) entry);
  556. }
  557. static void deleteConfigEntry(PRCList * entry)
  558. {
  559. PR_REMOVE_LINK(entry);
  560. freeConfigEntry((struct configEntry **) & entry);
  561. }
  562. static void deleteConfig()
  563. {
  564. PRCList *list;
  565. while (!PR_CLIST_IS_EMPTY(dna_global_config)) {
  566. list = PR_LIST_HEAD(dna_global_config);
  567. deleteConfigEntry(list);
  568. }
  569. return;
  570. }
  571. /****************************************************
  572. Distributed ranges Helpers
  573. ****************************************************/
  574. static int dna_fix_maxval(Slapi_DN *dn, PRUint64 *cur, PRUint64 *max)
  575. {
  576. /* TODO: check the main partition to see if another range
  577. * is available, and set the new local configuration
  578. * accordingly.
  579. * If a new range is not available run the retrieval task
  580. * and simply return error
  581. */
  582. return LDAP_OPERATIONS_ERROR;
  583. }
  584. static void dna_notice_allocation(Slapi_DN *dn, PRUint64 new)
  585. {
  586. /* TODO: check if we passed a new chunk threshold and update
  587. * the shared configuration on the public partition.
  588. */
  589. return;
  590. }
  591. /****************************************************
  592. Helpers
  593. ****************************************************/
  594. static char *dna_get_dn(Slapi_PBlock * pb)
  595. {
  596. char *dn = 0;
  597. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  598. "--> dna_get_dn\n");
  599. if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn)) {
  600. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  601. "dna_get_dn: failed to get dn of changed entry");
  602. goto bail;
  603. }
  604. /* slapi_dn_normalize( dn );
  605. */
  606. bail:
  607. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  608. "<-- dna_get_dn\n");
  609. return dn;
  610. }
  611. /* config check
  612. matching config dn or a descendent reloads config
  613. */
  614. static int dna_dn_is_config(char *dn)
  615. {
  616. int ret = 0;
  617. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  618. "--> dna_is_config\n");
  619. if (slapi_dn_issuffix(dn, getPluginDN())) {
  620. ret = 1;
  621. }
  622. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  623. "<-- dna_is_config\n");
  624. return ret;
  625. }
  626. #define DNA_LDAP_TAG_SK_REVERSE 0x81L
  627. static LDAPControl *dna_build_sort_control(const char *attr)
  628. {
  629. LDAPControl *ctrl;
  630. BerElement *ber;
  631. int rc;
  632. ber = ber_alloc();
  633. if (NULL == ber)
  634. return NULL;
  635. rc = ber_printf(ber, "{{stb}}", attr, DNA_LDAP_TAG_SK_REVERSE, 1);
  636. if (-1 == rc) {
  637. ber_free(ber, 1);
  638. return NULL;
  639. }
  640. rc = slapi_build_control(LDAP_CONTROL_SORTREQUEST, ber, 1, &ctrl);
  641. ber_free(ber, 1);
  642. if (LDAP_SUCCESS != rc)
  643. return NULL;
  644. return ctrl;
  645. }
  646. /****************************************************
  647. Functions that actually do things other
  648. than config and startup
  649. ****************************************************/
  650. /* we do search all values between newval and maxval asking the
  651. * server to sort them, then we check the first free spot and
  652. * use it as newval */
  653. static int dna_first_free_value(struct configEntry *config_entry,
  654. PRUint64 *newval,
  655. PRUint64 maxval,
  656. PRUint64 increment)
  657. {
  658. Slapi_Entry **entries = NULL;
  659. Slapi_PBlock *pb = NULL;
  660. LDAPControl **ctrls;
  661. char *attrs[2];
  662. char *filter;
  663. char *prefix;
  664. char *type;
  665. int preflen;
  666. int result, status;
  667. PRUint64 tmpval, sval, i;
  668. char *strval = NULL;
  669. prefix = config_entry->prefix;
  670. type = config_entry->type;
  671. tmpval = *newval;
  672. attrs[0] = type;
  673. attrs[1] = NULL;
  674. ctrls = (LDAPControl **)slapi_ch_calloc(2, sizeof(LDAPControl));
  675. if (NULL == ctrls)
  676. return LDAP_OPERATIONS_ERROR;
  677. ctrls[0] = dna_build_sort_control(config_entry->type);
  678. if (NULL == ctrls[0]) {
  679. slapi_ch_free((void **)&ctrls);
  680. return LDAP_OPERATIONS_ERROR;
  681. }
  682. filter = slapi_ch_smprintf("(&%s(&(%s>=%s%llu)(%s<=%s%llu)))",
  683. config_entry->filter,
  684. type, prefix?prefix:"", tmpval,
  685. type, prefix?prefix:"", maxval);
  686. if (NULL == filter) {
  687. ldap_control_free(ctrls[0]);
  688. slapi_ch_free((void **)&ctrls);
  689. return LDAP_OPERATIONS_ERROR;
  690. }
  691. pb = slapi_pblock_new();
  692. if (NULL == pb) {
  693. ldap_control_free(ctrls[0]);
  694. slapi_ch_free((void **)&ctrls);
  695. slapi_ch_free_string(&filter);
  696. return LDAP_OPERATIONS_ERROR;
  697. }
  698. slapi_search_internal_set_pb(pb, config_entry->scope,
  699. LDAP_SCOPE_SUBTREE, filter,
  700. attrs, 0, ctrls,
  701. NULL, getPluginID(), 0);
  702. slapi_search_internal_pb(pb);
  703. /*
  704. ldap_control_free(ctrls[0]);
  705. */
  706. slapi_ch_free_string(&filter);
  707. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
  708. if (LDAP_SUCCESS != result) {
  709. status = LDAP_OPERATIONS_ERROR;
  710. goto cleanup;
  711. }
  712. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
  713. &entries);
  714. if (NULL == entries || NULL == entries[0]) {
  715. /* no values means we already have a good value */
  716. status = LDAP_SUCCESS;
  717. goto cleanup;
  718. }
  719. /* entries are sorted and filtered for value >= tval therefore if the
  720. * first one does not match tval it means that the value is free,
  721. * otherwise we need to cycle through values until we find a mismatch,
  722. * the first mismatch is the first free pit */
  723. preflen = prefix?strlen(prefix):0;
  724. sval = 0;
  725. for (i = 0; NULL != entries[i]; i++) {
  726. strval = slapi_entry_attr_get_charptr(entries[i], type);
  727. if (preflen) {
  728. if (strlen(strval) <= preflen) {
  729. /* something very wrong here ... */
  730. status = LDAP_OPERATIONS_ERROR;
  731. goto cleanup;
  732. }
  733. strval = &strval[preflen-1];
  734. }
  735. errno = 0;
  736. sval = strtoul(strval, 0, 0);
  737. if (errno) {
  738. /* something very wrong here ... */
  739. status = LDAP_OPERATIONS_ERROR;
  740. goto cleanup;
  741. }
  742. slapi_ch_free_string(&strval);
  743. if (tmpval != sval)
  744. break;
  745. if (maxval < sval)
  746. break;
  747. tmpval += increment;
  748. }
  749. *newval = tmpval;
  750. status = LDAP_SUCCESS;
  751. cleanup:
  752. slapi_ch_free_string(&strval);
  753. slapi_free_search_results_internal(pb);
  754. slapi_pblock_destroy(pb);
  755. return status;
  756. }
  757. /*
  758. * Perform ldap operationally atomic increment
  759. * Return the next value to be assigned
  760. * Method:
  761. * 1. retrieve entry
  762. * 2. do increment operations
  763. * 3. remove current value, add new value in one operation
  764. * 4. if failed, and less than 3 times, goto 1
  765. */
  766. static int dna_get_next_value(struct configEntry *config_entry,
  767. char **next_value_ret)
  768. {
  769. Slapi_PBlock *pb = NULL;
  770. char *old_value = NULL;
  771. Slapi_Entry *e = NULL;
  772. Slapi_DN *dn = NULL;
  773. char *attrlist[4];
  774. int attempts;
  775. int ret;
  776. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  777. "--> dna_get_next_value\n");
  778. /* get pre-requisites to search */
  779. dn = slapi_sdn_new_dn_byref(config_entry->dn);
  780. attrlist[0] = DNA_NEXTVAL;
  781. attrlist[1] = DNA_MAXVAL;
  782. attrlist[2] = DNA_INTERVAL;
  783. attrlist[3] = NULL;
  784. /* the operation is constructed such that race conditions
  785. * to increment the value are detected and avoided - one wins,
  786. * one loses - however, there is no need for the server to compete
  787. * with itself so we lock here
  788. */
  789. slapi_lock_mutex(g_new_value_lock);
  790. for (attempts = 0; attempts < 3; attempts++) {
  791. LDAPMod mod_add;
  792. LDAPMod mod_delete;
  793. LDAPMod *mods[3];
  794. char *delete_val[2];
  795. char *add_val[2];
  796. char new_value[16];
  797. char *interval;
  798. char *max_value;
  799. PRUint64 increment = 1; /* default increment */
  800. PRUint64 setval = 0;
  801. PRUint64 newval = 0;
  802. PRUint64 maxval = -1;
  803. /* do update */
  804. ret = slapi_search_internal_get_entry(dn, attrlist, &e,
  805. getPluginID());
  806. if (LDAP_SUCCESS != ret) {
  807. ret = LDAP_OPERATIONS_ERROR;
  808. goto done;
  809. }
  810. old_value = slapi_entry_attr_get_charptr(e, DNA_NEXTVAL);
  811. if (NULL == old_value) {
  812. ret = LDAP_OPERATIONS_ERROR;
  813. goto done;
  814. }
  815. setval = strtoul(old_value, 0, 0);
  816. max_value = slapi_entry_attr_get_charptr(e, DNA_MAXVAL);
  817. if (max_value) {
  818. maxval = strtoul(max_value, 0, 0);
  819. slapi_ch_free_string(&max_value);
  820. }
  821. /* if not present the default is 1 */
  822. interval = slapi_entry_attr_get_charptr(e, DNA_INTERVAL);
  823. if (NULL != interval) {
  824. increment = strtoul(interval, 0, 0);
  825. }
  826. slapi_entry_free(e);
  827. e = NULL;
  828. /* check the value is actually in range */
  829. /* verify the new value is actually free and get the first
  830. * one free if not*/
  831. ret = dna_first_free_value(config_entry, &setval, maxval, increment);
  832. if (LDAP_SUCCESS != ret)
  833. goto done;
  834. /* try for a new range or fail */
  835. if (setval > maxval) {
  836. ret = dna_fix_maxval(dn, &setval, &maxval);
  837. if (LDAP_SUCCESS != ret) {
  838. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  839. "dna_get_next_value: no more IDs available!!\n");
  840. goto done;
  841. }
  842. /* verify the new value is actually free and get the first
  843. * one free if not */
  844. ret = dna_first_free_value(config_entry, &setval, maxval, increment);
  845. if (LDAP_SUCCESS != ret)
  846. goto done;
  847. }
  848. if (setval > maxval) {
  849. ret = LDAP_OPERATIONS_ERROR;
  850. goto done;
  851. }
  852. newval = setval + increment;
  853. /* try for a new range or fail */
  854. if (newval > maxval) {
  855. ret = dna_fix_maxval(dn, &newval, &maxval);
  856. if (LDAP_SUCCESS != ret) {
  857. slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
  858. "dna_get_next_value: no more IDs available!!\n");
  859. goto done;
  860. }
  861. }
  862. /* try to set the new value */
  863. sprintf(new_value, "%llu", newval);
  864. delete_val[0] = old_value;
  865. delete_val[1] = 0;
  866. mod_delete.mod_op = LDAP_MOD_DELETE;
  867. mod_delete.mod_type = DNA_NEXTVAL;
  868. mod_delete.mod_values = delete_val;
  869. add_val[0] = new_value;
  870. add_val[1] = 0;
  871. mod_add.mod_op = LDAP_MOD_ADD;
  872. mod_add.mod_type = DNA_NEXTVAL;
  873. mod_add.mod_values = add_val;
  874. mods[0] = &mod_delete;
  875. mods[1] = &mod_add;
  876. mods[2] = 0;
  877. pb = slapi_pblock_new();
  878. if (NULL == pb) {
  879. ret = LDAP_OPERATIONS_ERROR;
  880. goto done;
  881. }
  882. slapi_modify_internal_set_pb(pb, config_entry->dn,
  883. mods, 0, 0, getPluginID(), 0);
  884. slapi_modify_internal_pb(pb);
  885. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
  886. slapi_pblock_destroy(pb);
  887. pb = NULL;
  888. slapi_ch_free_string(&interval);
  889. slapi_ch_free_string(&old_value);
  890. if (LDAP_SUCCESS == ret) {
  891. *next_value_ret = slapi_ch_smprintf("%llu", setval);
  892. if (NULL == *next_value_ret) {
  893. ret = LDAP_OPERATIONS_ERROR;
  894. goto done;
  895. }
  896. dna_notice_allocation(dn, newval);
  897. goto done;
  898. }
  899. if (LDAP_NO_SUCH_ATTRIBUTE != ret) {
  900. /* not the result of a race
  901. to change the value
  902. */
  903. goto done;
  904. }
  905. }
  906. done:
  907. slapi_unlock_mutex(g_new_value_lock);
  908. if (LDAP_SUCCESS != ret)
  909. slapi_ch_free_string(&old_value);
  910. if (dn)
  911. slapi_sdn_free(&dn);
  912. if (e)
  913. slapi_entry_free(e);
  914. if (pb)
  915. slapi_pblock_destroy(pb);
  916. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  917. "<-- dna_get_next_value\n");
  918. return ret;
  919. }
  920. /* for mods and adds:
  921. where dn's are supplied, the closest in scope
  922. is used as long as the type and filter
  923. are identical - otherwise all matches count
  924. */
  925. static int dna_pre_op(Slapi_PBlock * pb, int modtype)
  926. {
  927. char *dn = 0;
  928. PRCList *list = 0;
  929. struct configEntry *config_entry = 0;
  930. struct slapi_entry *e = 0;
  931. char *last_type = 0;
  932. char *value = 0;
  933. int generate = 0;
  934. Slapi_Mods *smods = 0;
  935. Slapi_Mod *smod = 0;
  936. LDAPMod **mods;
  937. int free_entry = 0;
  938. char *errstr = NULL;
  939. int ret = 0;
  940. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  941. "--> dna_pre_op\n");
  942. if (0 == (dn = dna_get_dn(pb)))
  943. goto bail;
  944. if (dna_dn_is_config(dn))
  945. goto bail;
  946. if (LDAP_CHANGETYPE_ADD == modtype) {
  947. slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
  948. } else {
  949. /* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
  950. * available but it turns out that is only true if you are
  951. * a dbm backend pre-op plugin - lucky dbm backend pre-op
  952. * plugins.
  953. * I think that is wrong since the entry is useful for filter
  954. * tests and schema checks and this plugin shouldn't be limited
  955. * to a single backend type, but I don't want that fight right
  956. * now so we go get the entry here
  957. *
  958. slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
  959. */
  960. Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(dn);
  961. if (tmp_dn) {
  962. slapi_search_internal_get_entry(tmp_dn, 0, &e, getPluginID());
  963. slapi_sdn_free(&tmp_dn);
  964. free_entry = 1;
  965. }
  966. /* grab the mods - we'll put them back later with
  967. * our modifications appended
  968. */
  969. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  970. smods = slapi_mods_new();
  971. slapi_mods_init_passin(smods, mods);
  972. }
  973. if (0 == e)
  974. goto bailmod;
  975. dna_read_lock();
  976. if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
  977. list = PR_LIST_HEAD(dna_global_config);
  978. while (list != dna_global_config && LDAP_SUCCESS == ret) {
  979. config_entry = (struct configEntry *) list;
  980. /* did we already service this type? */
  981. if (last_type) {
  982. if (!slapi_attr_type_cmp(config_entry->type, last_type, 1))
  983. goto next;
  984. }
  985. /* is the entry in scope? */
  986. if (config_entry->scope) {
  987. if (!slapi_dn_issuffix(dn, config_entry->scope))
  988. goto next;
  989. }
  990. /* does the entry match the filter? */
  991. if (config_entry->slapi_filter) {
  992. if (LDAP_SUCCESS != slapi_vattr_filter_test(pb,
  993. e,
  994. config_entry->
  995. slapi_filter, 0))
  996. goto next;
  997. }
  998. if (LDAP_CHANGETYPE_ADD == modtype) {
  999. /* does attribute contain the magic value
  1000. or is the type not there?
  1001. */
  1002. value =
  1003. slapi_entry_attr_get_charptr(e, config_entry->type);
  1004. if ((value
  1005. && !slapi_UTF8CASECMP(config_entry->generate, value))
  1006. || 0 == value) {
  1007. generate = 1;
  1008. }
  1009. } else {
  1010. /* check mods for magic value */
  1011. Slapi_Mod *next_mod = slapi_mod_new();
  1012. smod = slapi_mods_get_first_smod(smods, next_mod);
  1013. while (smod) {
  1014. char *type = (char *)
  1015. slapi_mod_get_type(smod);
  1016. if (slapi_attr_types_equivalent(type,
  1017. config_entry->type)) {
  1018. struct berval *bv =
  1019. slapi_mod_get_first_value(smod);
  1020. int len = strlen(config_entry->generate);
  1021. if (len == bv->bv_len) {
  1022. if (!slapi_UTF8NCASECMP(bv->bv_val,
  1023. config_entry->generate,
  1024. len))
  1025. generate = 1;
  1026. break;
  1027. }
  1028. }
  1029. slapi_mod_done(next_mod);
  1030. smod = slapi_mods_get_next_smod(smods, next_mod);
  1031. }
  1032. slapi_mod_free(&next_mod);
  1033. }
  1034. if (generate) {
  1035. char *new_value;
  1036. int len;
  1037. /* create the value to add */
  1038. ret = dna_get_next_value(config_entry, &value);
  1039. if (DNA_SUCCESS != ret) {
  1040. errstr = slapi_ch_smprintf("Allocation of a new value for"
  1041. " %s failed! Unable to proceed.",
  1042. config_entry->type);
  1043. break;
  1044. }
  1045. len = strlen(value) + 1;
  1046. if (config_entry->prefix) {
  1047. len += strlen(config_entry->prefix);
  1048. }
  1049. new_value = slapi_ch_malloc(len);
  1050. if (config_entry->prefix) {
  1051. strcpy(new_value, config_entry->prefix);
  1052. strcat(new_value, value);
  1053. } else
  1054. strcpy(new_value, value);
  1055. /* do the mod */
  1056. if (LDAP_CHANGETYPE_ADD == modtype) {
  1057. /* add - add to entry */
  1058. slapi_entry_attr_set_charptr(e,
  1059. config_entry->type,
  1060. new_value);
  1061. } else {
  1062. /* mod - add to mods */
  1063. slapi_mods_add_string(smods,
  1064. LDAP_MOD_REPLACE,
  1065. config_entry->type, new_value);
  1066. }
  1067. /* free up */
  1068. slapi_ch_free_string(&value);
  1069. slapi_ch_free_string(&new_value);
  1070. /* make sure we don't generate for this
  1071. * type again
  1072. */
  1073. if (LDAP_SUCCESS == ret) {
  1074. last_type = config_entry->type;
  1075. }
  1076. generate = 0;
  1077. }
  1078. next:
  1079. list = PR_NEXT_LINK(list);
  1080. }
  1081. }
  1082. dna_unlock();
  1083. bailmod:
  1084. if (LDAP_CHANGETYPE_MODIFY == modtype) {
  1085. /* these are the mods you made, really,
  1086. * I didn't change them, honest, just had a quick look
  1087. */
  1088. mods = slapi_mods_get_ldapmods_passout(smods);
  1089. slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
  1090. slapi_mods_free(&smods);
  1091. }
  1092. bail:
  1093. if (free_entry && e)
  1094. slapi_entry_free(e);
  1095. if (ret) {
  1096. slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
  1097. "dna_pre_op: operation failure [%d]\n", ret);
  1098. slapi_send_ldap_result(pb, ret, NULL, errstr, 0, NULL);
  1099. slapi_ch_free((void **)&errstr);
  1100. ret = DNA_FAILURE;
  1101. }
  1102. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  1103. "<-- dna_pre_op\n");
  1104. return ret;
  1105. }
  1106. static int dna_add_pre_op(Slapi_PBlock * pb)
  1107. {
  1108. return dna_pre_op(pb, LDAP_CHANGETYPE_ADD);
  1109. }
  1110. static int dna_mod_pre_op(Slapi_PBlock * pb)
  1111. {
  1112. return dna_pre_op(pb, LDAP_CHANGETYPE_MODIFY);
  1113. }
  1114. static int dna_config_check_post_op(Slapi_PBlock * pb)
  1115. {
  1116. char *dn;
  1117. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  1118. "--> dna_config_check_post_op\n");
  1119. if ((dn = dna_get_dn(pb))) {
  1120. if (dna_dn_is_config(dn))
  1121. loadPluginConfig();
  1122. }
  1123. slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
  1124. "<-- dna_config_check_post_op\n");
  1125. return 0;
  1126. }
  1127. /****************************************************
  1128. End of
  1129. Functions that actually do things other
  1130. than config and startup
  1131. ****************************************************/
  1132. /**
  1133. * debug functions to print config
  1134. */
  1135. void dnaDumpConfig()
  1136. {
  1137. PRCList *list;
  1138. dna_read_lock();
  1139. if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
  1140. list = PR_LIST_HEAD(dna_global_config);
  1141. while (list != dna_global_config) {
  1142. dnaDumpConfigEntry((struct configEntry *) list);
  1143. list = PR_NEXT_LINK(list);
  1144. }
  1145. }
  1146. dna_unlock();
  1147. }
  1148. void dnaDumpConfigEntry(struct configEntry * entry)
  1149. {
  1150. printf("<- type --------------> %s\n", entry->type);
  1151. printf("<---- prefix ---------> %s\n", entry->prefix);
  1152. printf("<---- next value -----> %lu\n", entry->nextval);
  1153. printf("<---- interval -------> %lu\n", entry->interval);
  1154. printf("<---- generate flag --> %s\n", entry->generate);
  1155. }