operation.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* operation.c - routines to deal with pending ldap operations */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include "slap.h"
  18. #include "fe.h"
  19. int
  20. slapi_is_operation_abandoned( Slapi_Operation *op )
  21. {
  22. if (op) {
  23. return( op->o_status == SLAPI_OP_STATUS_ABANDONED );
  24. }
  25. return 0;
  26. }
  27. int
  28. slapi_op_abandoned( Slapi_PBlock *pb )
  29. {
  30. int op_status;
  31. if (pb && pb->pb_op) {
  32. op_status = pb->pb_op->o_status;
  33. return( op_status == SLAPI_OP_STATUS_ABANDONED );
  34. }
  35. return 0;
  36. }
  37. int
  38. slapi_op_internal( Slapi_PBlock *pb )
  39. {
  40. if (pb && pb->pb_op) {
  41. return operation_is_flag_set(pb->pb_op, OP_FLAG_INTERNAL);
  42. }
  43. return 0;
  44. }
  45. void
  46. operation_out_of_disk_space()
  47. {
  48. LDAPDebug(LDAP_DEBUG_ANY, "*** DISK FULL ***\n", 0, 0, 0);
  49. LDAPDebug(LDAP_DEBUG_ANY, "Attempting to shut down gracefully.\n", 0, 0, 0);
  50. g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
  51. }
  52. /* Setting the flags on the operation allows more control to the plugin
  53. * to disable and enable checks
  54. * Flags that we support for setting in the operation from the plugin are
  55. * SLAPI_OP_FLAG_NO_ACCESS_CHECK - do not check for access control
  56. * This function can be extended to support other flag setting as well
  57. */
  58. void slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag)
  59. {
  60. operation_set_flag(op, flag);
  61. }
  62. void slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag)
  63. {
  64. operation_clear_flag(op, flag);
  65. }
  66. int slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag)
  67. {
  68. return operation_is_flag_set(op, flag);
  69. }
  70. static int operation_type = -1; /* The type number assigned by the Factory for 'Operation' */
  71. int
  72. get_operation_object_type()
  73. {
  74. if(operation_type==-1)
  75. {
  76. /* The factory is given the name of the object type, in
  77. * return for a type handle. Whenever the object is created
  78. * or destroyed the factory is called with the handle so
  79. * that it may call the constructors or destructors registered
  80. * with it.
  81. */
  82. operation_type= factory_register_type(SLAPI_EXT_OPERATION,offsetof(Operation,o_extension));
  83. }
  84. return operation_type;
  85. }
  86. #if defined(USE_OPENLDAP)
  87. /* openldap doesn't have anything like this, nor does it have
  88. a way to portably and without cheating discover the
  89. sizeof BerElement - see lber_pvt.h for the trick used
  90. for BerElementBuffer
  91. so we just allocate everything separately
  92. If we wanted to get fancy, we could use LBER_OPT_MEMORY_FNS
  93. to override the ber malloc, realloc, etc. and use
  94. LBER_OPT_BER_MEMCTX to provide callback data for use
  95. with those functions
  96. */
  97. static void*
  98. ber_special_alloc(size_t size, BerElement **ppBer)
  99. {
  100. void *mem = NULL;
  101. /* starts out with a null buffer - will grow as needed */
  102. *ppBer = ber_alloc_t(0);
  103. /* Make sure mem size requested is aligned */
  104. if (0 != ( size & 0x03 )) {
  105. size += (sizeof(ber_int_t) - (size & 0x03));
  106. }
  107. mem = slapi_ch_malloc(size);
  108. return mem;
  109. }
  110. static void
  111. ber_special_free(void* buf, BerElement *ber)
  112. {
  113. ber_free(ber, 1);
  114. slapi_ch_free(&buf);
  115. }
  116. #endif
  117. void
  118. operation_init(Slapi_Operation *o, int flags)
  119. {
  120. if (NULL != o)
  121. {
  122. BerElement *ber = o->o_ber; /* may have already been set */
  123. memset(o,0,sizeof(Slapi_Operation));
  124. o->o_ber = ber;
  125. o->o_msgid = -1;
  126. o->o_tag = LBER_DEFAULT;
  127. o->o_status = SLAPI_OP_STATUS_PROCESSING;
  128. slapi_sdn_init(&(o->o_sdn));
  129. o->o_authtype = NULL;
  130. o->o_isroot = 0;
  131. o->o_time = current_time();
  132. o->o_opid = 0;
  133. o->o_connid = 0;
  134. o->o_next = NULL;
  135. o->o_flags= flags;
  136. o->o_reverse_search_state = 0;
  137. if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) {
  138. o->o_interval = PR_IntervalNow();
  139. } else {
  140. o->o_interval = (PRIntervalTime)0;
  141. }
  142. o->o_pagedresults_sizelimit = -1;
  143. }
  144. }
  145. Slapi_Operation *
  146. slapi_operation_new(int flags)
  147. {
  148. return (operation_new(flags));
  149. }
  150. /*
  151. * Allocate a new Slapi_Operation.
  152. * The flag parameter indicates whether the the operation is
  153. * external (from an LDAP Client), or internal (from a plugin).
  154. */
  155. Slapi_Operation *
  156. operation_new(int flags)
  157. {
  158. /* To improve performance, we allocate the Operation, BerElement and
  159. * ber buffer in one block, instead of a separate malloc() for each.
  160. * Subsequently, ber_special_free() frees them all; we're careful
  161. * not to free the Operation separately, and the ber software knows
  162. * not to free the buffer separately.
  163. */
  164. Slapi_Operation *o;
  165. BerElement *ber = NULL;
  166. if(flags & OP_FLAG_INTERNAL)
  167. {
  168. o = (Slapi_Operation *) slapi_ch_malloc(sizeof(Slapi_Operation));
  169. }
  170. else
  171. {
  172. o= (Slapi_Operation *) ber_special_alloc( sizeof(Slapi_Operation), &ber );
  173. }
  174. if (NULL != o)
  175. {
  176. o->o_ber = ber;
  177. operation_init(o, flags);
  178. }
  179. return o;
  180. }
  181. void
  182. operation_done( Slapi_Operation **op, Connection *conn )
  183. {
  184. if(op!=NULL && *op!=NULL)
  185. {
  186. /* Call the plugin extension destructors */
  187. factory_destroy_extension(get_operation_object_type(),*op,conn,&((*op)->o_extension));
  188. slapi_sdn_done(&(*op)->o_sdn);
  189. slapi_sdn_free(&(*op)->o_target_spec);
  190. slapi_ch_free_string( &(*op)->o_authtype );
  191. if ( (*op)->o_searchattrs != NULL ) {
  192. charray_free( (*op)->o_searchattrs );
  193. (*op)->o_searchattrs = NULL;
  194. }
  195. if ( NULL != (*op)->o_params.request_controls ) {
  196. ldap_controls_free( (*op)->o_params.request_controls );
  197. (*op)->o_params.request_controls = NULL;
  198. }
  199. if ( NULL != (*op)->o_results.result_controls ) {
  200. ldap_controls_free( (*op)->o_results.result_controls );
  201. (*op)->o_results.result_controls = NULL;
  202. }
  203. slapi_ch_free_string(&(*op)->o_results.result_matched);
  204. #if defined(USE_OPENLDAP)
  205. int options = 0;
  206. /* save the old options */
  207. if ((*op)->o_ber) {
  208. ber_get_option((*op)->o_ber, LBER_OPT_BER_OPTIONS, &options);
  209. /* we don't have a way to reuse the BerElement buffer so just free it */
  210. ber_free_buf((*op)->o_ber);
  211. /* clear out the ber for the next operation */
  212. ber_init2((*op)->o_ber, NULL, options);
  213. }
  214. #else
  215. if((*op)->o_ber){
  216. ber_special_free(*op, (*op)->o_ber); /* have to free everything here */
  217. *op = NULL;
  218. }
  219. #endif
  220. }
  221. }
  222. void
  223. operation_free( Slapi_Operation **op, Connection *conn )
  224. {
  225. operation_done(op, conn);
  226. if(op!=NULL && *op!=NULL)
  227. {
  228. if(operation_is_flag_set(*op, OP_FLAG_INTERNAL))
  229. {
  230. slapi_ch_free((void**)op);
  231. }
  232. else
  233. {
  234. ber_special_free( *op , (*op)->o_ber);
  235. }
  236. /* counters_to_errors_log("after operation"); */
  237. }
  238. }
  239. void
  240. slapi_operation_set_csngen_handler ( Slapi_Operation *op, void *callback )
  241. {
  242. op->o_csngen_handler = (csngen_handler) callback;
  243. }
  244. void
  245. slapi_operation_set_replica_attr_handler ( Slapi_Operation *op, void *callback )
  246. {
  247. op->o_replica_attr_handler = (replica_attr_handler) callback;
  248. }
  249. int
  250. slapi_operation_get_replica_attr ( Slapi_PBlock *pb, Slapi_Operation *op, const char *type, void *value )
  251. {
  252. int rc = -1;
  253. if (op->o_replica_attr_handler)
  254. {
  255. rc = op->o_replica_attr_handler ( pb, type, value );
  256. }
  257. return rc;
  258. }
  259. CSN *
  260. operation_get_csn(Slapi_Operation *op)
  261. {
  262. return op->o_params.csn;
  263. }
  264. void
  265. operation_set_csn(Slapi_Operation *op,CSN *csn)
  266. {
  267. op->o_params.csn= csn;
  268. }
  269. unsigned long
  270. slapi_op_get_type(Slapi_Operation *op)
  271. {
  272. return op->o_params.operation_type;
  273. }
  274. char *
  275. slapi_op_type_to_string(unsigned long type)
  276. {
  277. switch (type)
  278. {
  279. case SLAPI_OPERATION_ADD:
  280. return "add";
  281. case SLAPI_OPERATION_DELETE:
  282. return "delete";
  283. case SLAPI_OPERATION_MODIFY:
  284. return "modify";
  285. case SLAPI_OPERATION_MODRDN:
  286. return "modrdn";
  287. case SLAPI_OPERATION_BIND:
  288. return "bind";
  289. case SLAPI_OPERATION_COMPARE:
  290. return "compare";
  291. case SLAPI_OPERATION_SEARCH:
  292. return "search";
  293. default:
  294. return "unknown operation type";
  295. }
  296. }
  297. /* DEPRECATED : USE FUNCTION ABOVE FOR NEW DVLPT */
  298. unsigned long
  299. operation_get_type(Slapi_Operation *op)
  300. {
  301. return op->o_params.operation_type;
  302. }
  303. void
  304. operation_set_type(Slapi_Operation *op, unsigned long type)
  305. {
  306. op->o_params.operation_type= type;
  307. }
  308. void
  309. operation_set_flag(Slapi_Operation *op, int flag)
  310. {
  311. op->o_flags|= flag;
  312. }
  313. void
  314. operation_clear_flag(Slapi_Operation *op, int flag)
  315. {
  316. op->o_flags &= ~flag;
  317. }
  318. int
  319. operation_is_flag_set(Slapi_Operation *op, int flag)
  320. {
  321. return op->o_flags & flag;
  322. }
  323. Slapi_DN*
  324. operation_get_target_spec (Slapi_Operation *op)
  325. {
  326. return op->o_target_spec;
  327. }
  328. void
  329. operation_set_target_spec (Slapi_Operation *op, const Slapi_DN *target_spec)
  330. {
  331. PR_ASSERT (op);
  332. PR_ASSERT (target_spec);
  333. op->o_target_spec = slapi_sdn_dup(target_spec);
  334. }
  335. void
  336. operation_set_target_spec_str (Slapi_Operation *op, const char *target_spec)
  337. {
  338. PR_ASSERT (op);
  339. op->o_target_spec = slapi_sdn_new_dn_byval (target_spec);
  340. }
  341. unsigned long operation_get_abandoned_op (const Slapi_Operation *op)
  342. {
  343. PR_ASSERT (op);
  344. return op->o_abandoned_op;
  345. }
  346. void operation_set_abandoned_op (Slapi_Operation *op, unsigned long abandoned_op)
  347. {
  348. PR_ASSERT (op);
  349. op->o_abandoned_op = abandoned_op;
  350. }
  351. /* slapi_operation_parameters manipulation functions */
  352. struct slapi_operation_parameters *operation_parameters_new()
  353. {
  354. return (slapi_operation_parameters *)slapi_ch_calloc (1, sizeof (slapi_operation_parameters));
  355. }
  356. ber_tag_t
  357. slapi_operation_get_tag(Slapi_Operation *op)
  358. {
  359. return op->o_tag;
  360. }
  361. ber_int_t
  362. slapi_operation_get_msgid(Slapi_Operation *op)
  363. {
  364. return op->o_msgid;
  365. }
  366. void
  367. slapi_operation_set_tag(Slapi_Operation *op, ber_tag_t tag)
  368. {
  369. op->o_tag = tag;
  370. }
  371. void
  372. slapi_operation_set_msgid(Slapi_Operation *op, ber_int_t msgid)
  373. {
  374. op->o_msgid = msgid;
  375. }
  376. LDAPMod **
  377. copy_mods(LDAPMod **orig_mods)
  378. {
  379. LDAPMod **new_mods = NULL;
  380. LDAPMod *mod;
  381. Slapi_Mods smods_old;
  382. Slapi_Mods smods_new;
  383. slapi_mods_init_byref(&smods_old,orig_mods);
  384. slapi_mods_init_passin(&smods_new,new_mods);
  385. mod= slapi_mods_get_first_mod(&smods_old);
  386. while(mod!=NULL)
  387. {
  388. slapi_mods_add_modbvps(&smods_new,mod->mod_op,mod->mod_type,mod->mod_bvalues);
  389. mod= slapi_mods_get_next_mod(&smods_old);
  390. }
  391. new_mods= slapi_mods_get_ldapmods_passout(&smods_new);
  392. slapi_mods_done(&smods_old);
  393. slapi_mods_done(&smods_new);
  394. return new_mods;
  395. }
  396. struct slapi_operation_parameters *
  397. operation_parameters_dup(struct slapi_operation_parameters *sop)
  398. {
  399. struct slapi_operation_parameters *sop_new = (struct slapi_operation_parameters *)
  400. slapi_ch_malloc(sizeof(struct slapi_operation_parameters));
  401. memcpy(sop_new,sop,sizeof(struct slapi_operation_parameters));
  402. if(sop->target_address.uniqueid!=NULL)
  403. {
  404. sop_new->target_address.uniqueid= slapi_ch_strdup(sop->target_address.uniqueid);
  405. }
  406. if(sop->target_address.sdn != NULL)
  407. {
  408. sop_new->target_address.sdn = slapi_sdn_dup(sop->target_address.sdn);
  409. }
  410. sop_new->csn= csn_dup(sop->csn);
  411. switch(sop->operation_type)
  412. {
  413. case SLAPI_OPERATION_ADD:
  414. sop_new->p.p_add.target_entry= slapi_entry_dup(sop->p.p_add.target_entry);
  415. sop_new->p.p_add.parentuniqueid = slapi_ch_strdup(sop->p.p_add.parentuniqueid);
  416. break;
  417. case SLAPI_OPERATION_MODIFY:
  418. sop_new->p.p_modify.modify_mods= NULL;
  419. if (sop->p.p_modify.modify_mods!=NULL)
  420. {
  421. sop_new->p.p_modify.modify_mods = copy_mods(sop->p.p_modify.modify_mods);
  422. }
  423. break;
  424. case SLAPI_OPERATION_MODRDN:
  425. if(sop->p.p_modrdn.modrdn_newrdn!=NULL)
  426. {
  427. sop_new->p.p_modrdn.modrdn_newrdn= slapi_ch_strdup(sop->p.p_modrdn.modrdn_newrdn);
  428. }
  429. if(sop->p.p_modrdn.modrdn_newsuperior_address.sdn!=NULL)
  430. {
  431. sop_new->p.p_modrdn.modrdn_newsuperior_address.sdn =
  432. slapi_sdn_dup(sop->p.p_modrdn.modrdn_newsuperior_address.sdn);
  433. }
  434. if(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid!=NULL)
  435. {
  436. sop_new->p.p_modrdn.modrdn_newsuperior_address.uniqueid =
  437. slapi_ch_strdup(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid);
  438. }
  439. sop_new->p.p_modrdn.modrdn_mods= NULL;
  440. if (sop->p.p_modrdn.modrdn_mods!=NULL)
  441. {
  442. sop_new->p.p_modrdn.modrdn_mods = copy_mods(sop->p.p_modrdn.modrdn_mods);
  443. }
  444. break;
  445. case SLAPI_OPERATION_DELETE:
  446. /* Has no extra parameters. */
  447. case SLAPI_OPERATION_BIND:
  448. case SLAPI_OPERATION_COMPARE:
  449. case SLAPI_OPERATION_SEARCH:
  450. default:
  451. /* We are not interested in these. */
  452. break;
  453. }
  454. return sop_new;
  455. }
  456. void
  457. operation_parameters_done (struct slapi_operation_parameters *sop)
  458. {
  459. if(sop!=NULL)
  460. {
  461. slapi_ch_free((void **)&sop->target_address.uniqueid);
  462. slapi_sdn_free(&sop->target_address.sdn);
  463. csn_free(&sop->csn);
  464. switch(sop->operation_type)
  465. {
  466. case SLAPI_OPERATION_ADD:
  467. slapi_entry_free(sop->p.p_add.target_entry);
  468. sop->p.p_add.target_entry= NULL;
  469. slapi_ch_free((void **)&(sop->p.p_add.parentuniqueid));
  470. break;
  471. case SLAPI_OPERATION_MODIFY:
  472. ldap_mods_free(sop->p.p_modify.modify_mods, 1 /* Free the Array and the Elements */);
  473. sop->p.p_modify.modify_mods= NULL;
  474. break;
  475. case SLAPI_OPERATION_MODRDN:
  476. slapi_ch_free((void **)&(sop->p.p_modrdn.modrdn_newrdn));
  477. slapi_ch_free((void **)&(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid));
  478. slapi_sdn_free(&sop->p.p_modrdn.modrdn_newsuperior_address.sdn);
  479. ldap_mods_free(sop->p.p_modrdn.modrdn_mods, 1 /* Free the Array and the Elements */);
  480. sop->p.p_modrdn.modrdn_mods= NULL;
  481. break;
  482. case SLAPI_OPERATION_DELETE:
  483. /* Has no extra parameters. */
  484. case SLAPI_OPERATION_BIND:
  485. case SLAPI_OPERATION_COMPARE:
  486. case SLAPI_OPERATION_SEARCH:
  487. default:
  488. /* We are not interested in these */
  489. break;
  490. }
  491. }
  492. }
  493. void operation_parameters_free(struct slapi_operation_parameters **sop)
  494. {
  495. if (sop)
  496. {
  497. operation_parameters_done (*sop);
  498. slapi_ch_free ((void**)sop);
  499. }
  500. }
  501. int slapi_connection_acquire(Slapi_Connection *conn)
  502. {
  503. int rc;
  504. PR_EnterMonitor(conn->c_mutex);
  505. /* rc = connection_acquire_nolock(conn); */
  506. /* connection in the closing state can't be acquired */
  507. if (conn->c_flags & CONN_FLAG_CLOSING)
  508. {
  509. /* This may happen while other threads are still working on this connection */
  510. slapi_log_error(SLAPI_LOG_FATAL, "connection",
  511. "conn=%" NSPRIu64 " fd=%d Attempt to acquire connection in the closing state\n",
  512. conn->c_connid, conn->c_sd);
  513. rc = -1;
  514. }
  515. else
  516. {
  517. conn->c_refcnt++;
  518. rc = 0;
  519. }
  520. PR_ExitMonitor(conn->c_mutex);
  521. return(rc);
  522. }
  523. int
  524. slapi_connection_remove_operation( Slapi_PBlock *pb, Slapi_Connection *conn, Slapi_Operation *op, int release)
  525. {
  526. int rc = 0;
  527. Slapi_Operation **olist= &conn->c_ops;
  528. Slapi_Operation **tmp;
  529. PR_EnterMonitor(conn->c_mutex);
  530. /* connection_remove_operation_ext(pb, conn,op); */
  531. for ( tmp = olist; *tmp != NULL && *tmp != op; tmp = &(*tmp)->o_next )
  532. ; /* NULL */
  533. if ( *tmp == NULL ) {
  534. if (op) {
  535. LDAPDebug( LDAP_DEBUG_ANY, "connection_remove_operation: can't find op %d for conn %" NSPRIu64 "\n",
  536. (int)op->o_msgid, conn->c_connid, 0 );
  537. } else {
  538. LDAPDebug( LDAP_DEBUG_ANY, "connection_remove_operation: no operation provided\n",0, 0, 0);
  539. }
  540. } else {
  541. *tmp = (*tmp)->o_next;
  542. }
  543. if (release) {
  544. /* connection_release_nolock(conn); */
  545. if (conn->c_refcnt <= 0) {
  546. slapi_log_error(SLAPI_LOG_FATAL, "connection",
  547. "conn=%" NSPRIu64 " fd=%d Attempt to release connection that is not acquired\n",
  548. conn->c_connid, conn->c_sd);
  549. rc = -1;
  550. } else {
  551. conn->c_refcnt--;
  552. rc = 0;
  553. }
  554. }
  555. PR_ExitMonitor(conn->c_mutex);
  556. return (rc);
  557. }