repl5_total.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  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. /*
  13. repl5_total.c - code that implements a total replica update.
  14. The requestValue of the NSDS50ReplicationEntry looks like this:
  15. requestValue ::= SEQUENCE {
  16. uniqueid OCTET STRING,
  17. dn LDAPDN,
  18. annotatedAttributes AnnotatedAttributeList
  19. }
  20. AnnotatedAttributeList ::= SET OF SEQUENCE {
  21. attributeType AttributeDescription,
  22. attributeDeletionCSN OCTET STRING OPTIONAL,
  23. attributeDeleted BOOLEAN DEFAULT FALSE,
  24. annotatedValues SET OF AnnotatedValue
  25. }
  26. AnnotatedValue ::= SEQUENCE {
  27. value AttributeValue,
  28. valueDeleted BOOLEAN DEFAULT FALSE,
  29. valueCSNSet SEQUENCE OF ValueCSN,
  30. }
  31. ValueCSN ::= SEQUENCE {
  32. CSNType ENUMERATED {
  33. valuePresenceCSN (1),
  34. valueDeletionCSN (2),
  35. valueDistinguishedCSN (3)
  36. }
  37. CSN OCTET STRING,
  38. }
  39. */
  40. #include "repl.h"
  41. #include "repl5.h"
  42. #define CSN_TYPE_VALUE_UPDATED_ON_WIRE 1
  43. #define CSN_TYPE_VALUE_DELETED_ON_WIRE 2
  44. #define CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE 3
  45. /* #define GORDONS_PATENTED_BER_DEBUG 1 */
  46. #ifdef GORDONS_PATENTED_BER_DEBUG
  47. #define BER_DEBUG(a) printf(a)
  48. #else
  49. #define BER_DEBUG(a)
  50. #endif
  51. /* Forward declarations */
  52. static int my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t);
  53. static int my_ber_printf_value(BerElement *ber, const char *type,
  54. const Slapi_Value *value, PRBool deleted);
  55. static int my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted);
  56. static int my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted);
  57. static int my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted);
  58. /*
  59. * Get a Slapi_Entry ready to send over the wire as part of
  60. * a total update protocol stream. Convert the entry and all
  61. * of its state information to a BerElement which will be the
  62. * payload of an extended LDAP operation.
  63. *
  64. * Entries consist of:
  65. * - An entry DN
  66. * - A uniqueID
  67. * - A set of present attributes, each of which consists of:
  68. * - A set of present values, each of which consists of:
  69. * - A value
  70. * - A set of CSNs
  71. * - A set of deleted values, each of which consists of:
  72. * - A value
  73. * - A set of CSNs
  74. * - A set of deleted attibutes, each of which consists of:
  75. * - An attribute type
  76. * - A set of CSNs. Note that this list of CSNs will always contain exactly one CSN.
  77. *
  78. * This all gets mashed into one BerElement, ready to be blasted over the wire to
  79. * a replica.
  80. *
  81. */
  82. BerElement *
  83. entry2bere(const Slapi_Entry *e, char **excluded_attrs)
  84. {
  85. BerElement *ber = NULL;
  86. const char *str = NULL;
  87. const char *dnstr = NULL;
  88. char *type;
  89. Slapi_DN *sdn = NULL;
  90. Slapi_Attr *attr = NULL, *prev_attr;
  91. int rc;
  92. PR_ASSERT(NULL != e);
  93. if ((ber = ber_alloc()) == NULL)
  94. {
  95. goto loser;
  96. }
  97. BER_DEBUG("{");
  98. if (ber_printf(ber, "{") == -1) /* Begin outer sequence */
  99. {
  100. goto loser;
  101. }
  102. /* Get the entry's uniqueid */
  103. if ((str = slapi_entry_get_uniqueid(e)) == NULL)
  104. {
  105. goto loser;
  106. }
  107. BER_DEBUG("s(uniqueid)");
  108. if (ber_printf(ber, "s", str) == -1)
  109. {
  110. goto loser;
  111. }
  112. /* Get the entry's DN */
  113. if ((sdn = slapi_entry_get_sdn((Slapi_Entry *)e)) == NULL) /* XXXggood had to cast away const */
  114. {
  115. goto loser;
  116. }
  117. if ((dnstr = slapi_sdn_get_dn(sdn)) == NULL)
  118. {
  119. goto loser;
  120. }
  121. BER_DEBUG("s(dn)");
  122. if (ber_printf(ber, "s", dnstr) == -1)
  123. {
  124. goto loser;
  125. }
  126. /* Next comes the annoted list of the entry's attributes */
  127. BER_DEBUG("[");
  128. if (ber_printf(ber, "[") == -1) /* Begin set of attributes */
  129. {
  130. goto loser;
  131. }
  132. /*
  133. * We iterate over all of the non-deleted attributes first.
  134. */
  135. slapi_entry_first_attr(e, &attr);
  136. while (NULL != attr)
  137. {
  138. /* ONREPL - skip uniqueid attribute since we already sent uniqueid
  139. This is a hack; need to figure a better way of storing uniqueid
  140. in an entry */
  141. slapi_attr_get_type (attr, &type);
  142. if (strcasecmp (type, SLAPI_ATTR_UNIQUEID) != 0)
  143. {
  144. /* Check to see if this attribute is excluded by the fractional list */
  145. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  146. {
  147. /* Process this attribute */
  148. rc = my_ber_printf_attr (ber, attr, PR_FALSE);
  149. if (rc != 0)
  150. {
  151. goto loser;
  152. }
  153. }
  154. }
  155. prev_attr = attr;
  156. slapi_entry_next_attr(e, prev_attr, &attr);
  157. }
  158. /*
  159. * Now iterate over the deleted attributes.
  160. */
  161. entry_first_deleted_attribute(e, &attr);
  162. while (attr != NULL)
  163. {
  164. slapi_attr_get_type (attr, &type);
  165. /* Check to see if this attribute is excluded by the fractional list */
  166. if ( (NULL == excluded_attrs) || !charray_inlist(excluded_attrs,type))
  167. {
  168. /* Process this attribute */
  169. rc = my_ber_printf_attr (ber, attr, PR_TRUE);
  170. if (rc != 0)
  171. {
  172. goto loser;
  173. }
  174. }
  175. entry_next_deleted_attribute(e, &attr);
  176. }
  177. BER_DEBUG("]");
  178. if (ber_printf(ber, "]") == -1) /* End set for attributes */
  179. {
  180. goto loser;
  181. }
  182. BER_DEBUG("}");
  183. if (ber_printf(ber, "}") == -1) /* End sequence for this entry */
  184. {
  185. goto loser;
  186. }
  187. /* If we get here, everything went ok */
  188. BER_DEBUG("\n");
  189. goto free_and_return;
  190. loser:
  191. if (NULL != ber)
  192. {
  193. ber_free(ber, 1);
  194. ber = NULL;
  195. }
  196. free_and_return:
  197. return ber;
  198. }
  199. /*
  200. * Helper function - convert a CSN to a string and ber_printf() it.
  201. */
  202. static int
  203. my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
  204. {
  205. char csn_str[CSN_STRSIZE];
  206. int rc = -1;
  207. ber_int_t csn_type_as_ber = -1;
  208. switch (t)
  209. {
  210. case CSN_TYPE_VALUE_UPDATED:
  211. csn_type_as_ber = CSN_TYPE_VALUE_UPDATED_ON_WIRE;
  212. break;
  213. case CSN_TYPE_VALUE_DELETED:
  214. csn_type_as_ber = CSN_TYPE_VALUE_DELETED_ON_WIRE;
  215. break;
  216. case CSN_TYPE_VALUE_DISTINGUISHED:
  217. csn_type_as_ber = CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE;
  218. break;
  219. case CSN_TYPE_ATTRIBUTE_DELETED:
  220. break;
  221. default:
  222. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_printf_csn: unknown "
  223. "csn type %d encountered.\n", (int)t);
  224. return -1;
  225. }
  226. csn_as_string(csn,PR_FALSE,csn_str);
  227. /* we don't send type for attr csn since there is only one */
  228. if (t == CSN_TYPE_ATTRIBUTE_DELETED)
  229. {
  230. rc = ber_printf(ber, "s", csn_str);
  231. BER_DEBUG("s(csn_str)");
  232. }
  233. else
  234. {
  235. rc = ber_printf(ber, "{es}", csn_type_as_ber, csn_str);
  236. BER_DEBUG("{e(csn type)s(csn)}");
  237. }
  238. return rc;
  239. }
  240. /*
  241. * Send a single annotated attribute value.
  242. */
  243. static int
  244. my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value, PRBool deleted)
  245. {
  246. const struct berval *bval = NULL;
  247. int rc = -1;
  248. const CSNSet *csnset;
  249. void *cookie;
  250. CSN *csn;
  251. CSNType t;
  252. bval = slapi_value_get_berval(value);
  253. BER_DEBUG("{o(value)");
  254. if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
  255. {
  256. goto done;
  257. }
  258. /* if (ber_printf(ber, "o", bval->bv_val, bval->bv_len) == -1)
  259. {
  260. goto done;
  261. } */
  262. if (deleted)
  263. {
  264. BER_DEBUG("b(deleted flag)");
  265. if (ber_printf (ber, "b", PR_TRUE) == -1)
  266. {
  267. goto done;
  268. }
  269. }
  270. /* Send value CSN list */
  271. BER_DEBUG("{");
  272. if (ber_printf(ber, "{") == -1) /* Start set */
  273. {
  274. goto done;
  275. }
  276. /* Iterate over the sequence of CSNs. */
  277. csnset = value_get_csnset (value);
  278. if (csnset)
  279. {
  280. for (cookie = csnset_get_first_csn (csnset, &csn, &t); NULL != cookie;
  281. cookie = csnset_get_next_csn (csnset, cookie, &csn, &t))
  282. {
  283. /* Don't send any adcsns, since that was already sent */
  284. if (t != CSN_TYPE_ATTRIBUTE_DELETED)
  285. {
  286. if (my_ber_printf_csn(ber, csn, t) == -1)
  287. {
  288. goto done;
  289. }
  290. }
  291. }
  292. }
  293. BER_DEBUG("}");
  294. if (ber_printf(ber, "}") == -1) /* End CSN sequence */
  295. {
  296. goto done;
  297. }
  298. BER_DEBUG("}");
  299. if (ber_printf(ber, "}") == -1) /* End sequence */
  300. {
  301. goto done;
  302. }
  303. /* Everything's ok */
  304. rc = 0;
  305. done:
  306. return rc;
  307. }
  308. /* send a single attribute */
  309. static int
  310. my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
  311. {
  312. Slapi_Value *value;
  313. char *type;
  314. int i;
  315. const CSN *csn;
  316. /* First, send the type */
  317. slapi_attr_get_type(attr, &type);
  318. BER_DEBUG("{s(type ");
  319. BER_DEBUG(type);
  320. BER_DEBUG(")");
  321. if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */
  322. {
  323. goto loser;
  324. }
  325. /* Send the attribute deletion CSN if present */
  326. csn = attr_get_deletion_csn(attr);
  327. if (csn)
  328. {
  329. if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1)
  330. {
  331. goto loser;
  332. }
  333. }
  334. /* only send "is deleted" flag for deleted attributes since it defaults to false */
  335. if (deleted)
  336. {
  337. BER_DEBUG("b(del flag)");
  338. if (ber_printf (ber, "b", PR_TRUE) == -1)
  339. {
  340. goto loser;
  341. }
  342. }
  343. /*
  344. * Iterate through all the values.
  345. */
  346. BER_DEBUG("[");
  347. if (ber_printf(ber, "[") == -1) /* Begin set */
  348. {
  349. goto loser;
  350. }
  351. /*
  352. * Process the non-deleted values first.
  353. */
  354. i = slapi_attr_first_value(attr, &value);
  355. while (i != -1)
  356. {
  357. if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1)
  358. {
  359. goto loser;
  360. }
  361. i= slapi_attr_next_value(attr, i, &value);
  362. }
  363. /*
  364. * Now iterate over all of the deleted values.
  365. */
  366. i= attr_first_deleted_value(attr, &value);
  367. while (i != -1)
  368. {
  369. if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1)
  370. {
  371. goto loser;
  372. }
  373. i= attr_next_deleted_value(attr, i, &value);
  374. }
  375. BER_DEBUG("]");
  376. if (ber_printf(ber, "]") == -1) /* End set */
  377. {
  378. goto loser;
  379. }
  380. BER_DEBUG("}");
  381. if (ber_printf(ber, "}") == -1) /* End sequence for this type */
  382. {
  383. goto loser;
  384. }
  385. return 0;
  386. loser:
  387. return -1;
  388. }
  389. /*
  390. * Get an annotated value from the BerElement. Returns 0 on
  391. * success, -1 on failure.
  392. */
  393. static int
  394. my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
  395. {
  396. struct berval *attrval = NULL;
  397. ber_len_t len = -1;
  398. ber_tag_t tag;
  399. CSN *csn = NULL;
  400. char csnstring[CSN_STRSIZE + 1];
  401. CSNType csntype;
  402. char *lasti;
  403. PR_ASSERT(ber && value && deleted);
  404. if (NULL == ber && NULL == value)
  405. {
  406. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 1\n");
  407. goto loser;
  408. }
  409. *value = NULL;
  410. /* Each value is a sequence */
  411. if (ber_scanf(ber, "{O", &attrval) == LBER_ERROR)
  412. {
  413. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 2\n");
  414. goto loser;
  415. }
  416. /* Allocate and fill in the attribute value */
  417. if ((*value = slapi_value_new_berval(attrval)) == NULL)
  418. {
  419. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 3\n");
  420. goto loser;
  421. }
  422. /* check if this is a deleted value */
  423. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  424. {
  425. if (ber_scanf(ber, "b", deleted) == LBER_ERROR)
  426. {
  427. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 4\n");
  428. goto loser;
  429. }
  430. }
  431. else /* default is present value */
  432. {
  433. *deleted = PR_FALSE;
  434. }
  435. /* Read the sequence of CSNs */
  436. for (tag = ber_first_element(ber, &len, &lasti);
  437. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  438. tag = ber_next_element(ber, &len, lasti))
  439. {
  440. ber_int_t csntype_tmp;
  441. /* Each CSN is in a sequence that includes a csntype and CSN */
  442. len = CSN_STRSIZE;
  443. if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == LBER_ERROR)
  444. {
  445. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
  446. goto loser;
  447. }
  448. switch (csntype_tmp)
  449. {
  450. case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
  451. csntype = CSN_TYPE_VALUE_UPDATED;
  452. break;
  453. case CSN_TYPE_VALUE_DELETED_ON_WIRE:
  454. csntype = CSN_TYPE_VALUE_DELETED;
  455. break;
  456. case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
  457. csntype = CSN_TYPE_VALUE_DISTINGUISHED;
  458. break;
  459. default:
  460. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: preposterous CSN type "
  461. "%d received during total update.\n", csntype_tmp);
  462. goto loser;
  463. }
  464. csn = csn_new_by_string(csnstring);
  465. if (csn == NULL)
  466. {
  467. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 8\n");
  468. goto loser;
  469. }
  470. value_add_csn(*value, csntype, csn);
  471. csn_free (&csn);
  472. }
  473. if (ber_scanf(ber, "}") == LBER_ERROR) /* End of annotated attribute value seq */
  474. {
  475. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "my_ber_scanf_value BAD 10\n");
  476. goto loser;
  477. }
  478. if (attrval)
  479. ber_bvfree(attrval);
  480. return 0;
  481. loser:
  482. /* Free any stuff we allocated */
  483. if (csn)
  484. csn_free (&csn);
  485. if (attrval)
  486. ber_bvfree(attrval);
  487. if (value)
  488. {
  489. slapi_value_free (value);
  490. }
  491. return -1;
  492. }
  493. static int
  494. my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
  495. {
  496. char *attrtype = NULL;
  497. CSN *attr_deletion_csn = NULL;
  498. PRBool val_deleted;
  499. char *lasti;
  500. ber_len_t len;
  501. ber_tag_t tag;
  502. char *str = NULL;
  503. int rc;
  504. Slapi_Value *value = NULL;
  505. if (attr == NULL)
  506. {
  507. goto loser;
  508. }
  509. PR_ASSERT (ber && attr && deleted);
  510. /* allocate the attribute */
  511. *attr = slapi_attr_new ();
  512. if (*attr == NULL)
  513. {
  514. goto loser;
  515. }
  516. if (ber_scanf(ber, "{a", &attrtype) == LBER_ERROR) /* Begin sequence for this attr */
  517. {
  518. goto loser;
  519. }
  520. slapi_attr_init(*attr, attrtype);
  521. slapi_ch_free ((void **)&attrtype);
  522. /* The attribute deletion CSN is next and is optional? */
  523. if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
  524. {
  525. if (ber_scanf(ber, "a", &str) == LBER_ERROR)
  526. {
  527. goto loser;
  528. }
  529. attr_deletion_csn = csn_new_by_string(str);
  530. slapi_ch_free((void **)&str);
  531. }
  532. if (attr_deletion_csn)
  533. {
  534. rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
  535. csn_free (&attr_deletion_csn);
  536. if (rc != 0)
  537. {
  538. goto loser;
  539. }
  540. }
  541. /* The "attribute deleted" flag is next, and is optional */
  542. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  543. {
  544. if (ber_scanf(ber, "b", deleted) == LBER_DEFAULT)
  545. {
  546. goto loser;
  547. }
  548. }
  549. else /* default is present */
  550. {
  551. *deleted = PR_FALSE;
  552. }
  553. /* loop over the list of attribute values */
  554. for (tag = ber_first_element(ber, &len, &lasti);
  555. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  556. tag = ber_next_element(ber, &len, lasti))
  557. {
  558. value = NULL;
  559. if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
  560. {
  561. goto loser;
  562. }
  563. if (val_deleted)
  564. {
  565. /* Add the value to the attribute */
  566. if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
  567. {
  568. goto loser;
  569. }
  570. }
  571. else
  572. {
  573. /* Add the value to the attribute */
  574. if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
  575. {
  576. goto loser;
  577. }
  578. }
  579. if (value)
  580. slapi_value_free(&value);
  581. }
  582. if (ber_scanf(ber, "}") == LBER_ERROR) /* End sequence for this attribute */
  583. {
  584. goto loser;
  585. }
  586. return 0;
  587. loser:
  588. if (attr && *attr)
  589. slapi_attr_free (attr);
  590. if (value)
  591. slapi_value_free (&value);
  592. slapi_ch_free_string(&attrtype);
  593. slapi_ch_free_string(&str);
  594. return -1;
  595. }
  596. /*
  597. * Extract the payload from a total update extended operation,
  598. * decode it, and produce a Slapi_Entry structure representing a new
  599. * entry to be added to the local database.
  600. */
  601. static int
  602. decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
  603. {
  604. BerElement *tmp_bere = NULL;
  605. Slapi_Entry *e = NULL;
  606. Slapi_Attr *attr = NULL;
  607. char *str = NULL;
  608. struct berval *extop_value = NULL;
  609. char *extop_oid = NULL;
  610. ber_len_t len;
  611. char *lasto;
  612. ber_tag_t tag;
  613. int rc;
  614. PRBool deleted;
  615. PR_ASSERT(NULL != pb);
  616. PR_ASSERT(NULL != ep);
  617. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
  618. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
  619. if ((NULL == extop_oid) ||
  620. ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) &&
  621. (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
  622. !BV_HAS_DATA(extop_value))
  623. {
  624. /* Bogus */
  625. goto loser;
  626. }
  627. if ((tmp_bere = ber_init(extop_value)) == NULL)
  628. {
  629. goto loser;
  630. }
  631. if ((e = slapi_entry_alloc()) == NULL)
  632. {
  633. goto loser;
  634. }
  635. if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */
  636. {
  637. goto loser;
  638. }
  639. /* The entry's uniqueid is first */
  640. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  641. {
  642. goto loser;
  643. }
  644. slapi_entry_set_uniqueid(e, str);
  645. str = NULL; /* Slapi_Entry now owns the uniqueid */
  646. /* The entry's DN is next */
  647. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  648. {
  649. goto loser;
  650. }
  651. slapi_entry_set_dn(e, str);
  652. str = NULL; /* Slapi_Entry now owns the dn */
  653. /* Get the attributes */
  654. for ( tag = ber_first_element( tmp_bere, &len, &lasto );
  655. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  656. tag = ber_next_element( tmp_bere, &len, lasto ) )
  657. {
  658. if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
  659. {
  660. goto loser;
  661. }
  662. /* Add the attribute to the entry */
  663. if (deleted)
  664. entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
  665. else
  666. entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
  667. attr = NULL;
  668. }
  669. if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */
  670. {
  671. goto loser;
  672. }
  673. /* Check for ldapsubentries and tombstone entries to set flags properly */
  674. slapi_entry_attr_find(e, "objectclass", &attr);
  675. if (attr != NULL) {
  676. struct berval bv;
  677. bv.bv_val = "ldapsubentry";
  678. bv.bv_len = strlen(bv.bv_val);
  679. if (slapi_attr_value_find(attr, &bv) == 0) {
  680. slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
  681. }
  682. bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
  683. bv.bv_len = strlen(bv.bv_val);
  684. if (slapi_attr_value_find(attr, &bv) == 0) {
  685. slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
  686. }
  687. }
  688. /* If we get here, the entry is properly constructed. Return it. */
  689. rc = 0;
  690. *ep = e;
  691. goto free_and_return;
  692. loser:
  693. rc = -1;
  694. /* slapi_ch_free accepts NULL pointer */
  695. slapi_ch_free((void **)&str);
  696. if (attr != NULL)
  697. {
  698. slapi_attr_free (&attr);
  699. }
  700. if (NULL != e)
  701. {
  702. slapi_entry_free (e);
  703. }
  704. *ep = NULL;
  705. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Error: could not decode extended "
  706. "operation containing entry for total update.\n");
  707. free_and_return:
  708. if (NULL != tmp_bere)
  709. {
  710. ber_free(tmp_bere, 1);
  711. tmp_bere = NULL;
  712. }
  713. return rc;
  714. }
  715. /*
  716. * This plugin entry point is called whenever an NSDS50ReplicationEntry
  717. * extended operation is received.
  718. */
  719. int
  720. multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
  721. {
  722. int rc;
  723. Slapi_Entry *e = NULL;
  724. Slapi_Connection *conn = NULL;
  725. PRUint64 connid = 0;
  726. int opid = 0;
  727. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  728. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
  729. /* Decode the extended operation */
  730. rc = decode_total_update_extop(pb, &e);
  731. if (0 == rc)
  732. {
  733. #ifdef notdef
  734. /*
  735. * Just spew LDIF so we're sure we got it right. Later we'll firehose
  736. * this into the database import code
  737. */
  738. int len;
  739. char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
  740. puts(str);
  741. free(str);
  742. #endif
  743. rc = slapi_import_entry (pb, e);
  744. /* slapi_import_entry returns an LDAP error in case of a
  745. * problem. If there's a problem, it's our responsibility
  746. * to free the slapi_entry that we're trying to import.
  747. */
  748. if (rc != LDAP_SUCCESS)
  749. {
  750. const char *dn = slapi_entry_get_dn_const(e);
  751. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  752. "Error %d: could not import entry dn %s "
  753. "for total update operation conn=%" NSPRIu64 " op=%d\n",
  754. rc, dn, connid, opid);
  755. rc = -1;
  756. }
  757. }
  758. else
  759. {
  760. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  761. "Error %d: could not decode the total update extop "
  762. "for total update operation conn=%" NSPRIu64 " op=%d\n",
  763. rc, connid, opid);
  764. }
  765. if (LDAP_SUCCESS != rc) {
  766. /* just disconnect from the supplier. bulk import is stopped when
  767. connection object is destroyed */
  768. slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
  769. if (conn)
  770. {
  771. slapi_disconnect_server(conn);
  772. }
  773. /* cleanup */
  774. if (e)
  775. {
  776. slapi_entry_free (e);
  777. }
  778. }
  779. return rc;
  780. }