repl5_total.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  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_ERR, 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_ERR, 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_ERR, 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_ERR, 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_ERR, 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_ERR, 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_ERR, repl_plugin_name, "my_ber_scanf_value - 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_ERR, 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_ERR, repl_plugin_name, "my_ber_scanf_value - BAD 10\n");
  476. goto loser;
  477. }
  478. if (attrval) {
  479. ber_bvfree(attrval);
  480. }
  481. return 0;
  482. loser:
  483. /* Free any stuff we allocated */
  484. if (csn)
  485. csn_free (&csn);
  486. if (attrval)
  487. ber_bvfree(attrval);
  488. if (value)
  489. {
  490. slapi_value_free (value);
  491. }
  492. return -1;
  493. }
  494. static int
  495. my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
  496. {
  497. char *attrtype = NULL;
  498. CSN *attr_deletion_csn = NULL;
  499. PRBool val_deleted;
  500. char *lasti;
  501. ber_len_t len;
  502. ber_tag_t tag;
  503. char *str = NULL;
  504. int rc;
  505. Slapi_Value *value = NULL;
  506. if (attr == NULL)
  507. {
  508. goto loser;
  509. }
  510. PR_ASSERT (ber && attr && deleted);
  511. /* allocate the attribute */
  512. *attr = slapi_attr_new ();
  513. if (*attr == NULL)
  514. {
  515. goto loser;
  516. }
  517. if (ber_scanf(ber, "{a", &attrtype) == LBER_ERROR) /* Begin sequence for this attr */
  518. {
  519. goto loser;
  520. }
  521. slapi_attr_init(*attr, attrtype);
  522. slapi_ch_free ((void **)&attrtype);
  523. /* The attribute deletion CSN is next and is optional? */
  524. if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
  525. {
  526. if (ber_scanf(ber, "a", &str) == LBER_ERROR)
  527. {
  528. goto loser;
  529. }
  530. attr_deletion_csn = csn_new_by_string(str);
  531. slapi_ch_free((void **)&str);
  532. }
  533. if (attr_deletion_csn)
  534. {
  535. rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
  536. csn_free (&attr_deletion_csn);
  537. if (rc != 0)
  538. {
  539. goto loser;
  540. }
  541. }
  542. /* The "attribute deleted" flag is next, and is optional */
  543. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  544. {
  545. if (ber_scanf(ber, "b", deleted) == LBER_DEFAULT)
  546. {
  547. goto loser;
  548. }
  549. }
  550. else /* default is present */
  551. {
  552. *deleted = PR_FALSE;
  553. }
  554. /* loop over the list of attribute values */
  555. for (tag = ber_first_element(ber, &len, &lasti);
  556. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  557. tag = ber_next_element(ber, &len, lasti))
  558. {
  559. value = NULL;
  560. if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
  561. {
  562. goto loser;
  563. }
  564. if (val_deleted)
  565. {
  566. /* Add the value to the attribute */
  567. if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
  568. {
  569. goto loser;
  570. }
  571. }
  572. else
  573. {
  574. /* Add the value to the attribute */
  575. if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
  576. {
  577. goto loser;
  578. }
  579. }
  580. if (value)
  581. slapi_value_free(&value);
  582. }
  583. if (ber_scanf(ber, "}") == LBER_ERROR) /* End sequence for this attribute */
  584. {
  585. goto loser;
  586. }
  587. return 0;
  588. loser:
  589. if (attr && *attr)
  590. slapi_attr_free (attr);
  591. if (value)
  592. slapi_value_free (&value);
  593. slapi_ch_free_string(&attrtype);
  594. slapi_ch_free_string(&str);
  595. return -1;
  596. }
  597. /*
  598. * Extract the payload from a total update extended operation,
  599. * decode it, and produce a Slapi_Entry structure representing a new
  600. * entry to be added to the local database.
  601. */
  602. static int
  603. decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
  604. {
  605. BerElement *tmp_bere = NULL;
  606. Slapi_Entry *e = NULL;
  607. Slapi_Attr *attr = NULL;
  608. char *str = NULL;
  609. struct berval *extop_value = NULL;
  610. char *extop_oid = NULL;
  611. ber_len_t len;
  612. char *lasto;
  613. ber_tag_t tag;
  614. int rc;
  615. PRBool deleted;
  616. PR_ASSERT(NULL != pb);
  617. PR_ASSERT(NULL != ep);
  618. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
  619. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
  620. if ((NULL == extop_oid) ||
  621. ((strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0) &&
  622. (strcmp(extop_oid, REPL_NSDS71_REPLICATION_ENTRY_REQUEST_OID) != 0)) ||
  623. !BV_HAS_DATA(extop_value))
  624. {
  625. /* Bogus */
  626. goto loser;
  627. }
  628. if ((tmp_bere = ber_init(extop_value)) == NULL)
  629. {
  630. goto loser;
  631. }
  632. if ((e = slapi_entry_alloc()) == NULL)
  633. {
  634. goto loser;
  635. }
  636. if (ber_scanf(tmp_bere, "{") == LBER_ERROR) /* Begin outer sequence */
  637. {
  638. goto loser;
  639. }
  640. /* The entry's uniqueid is first */
  641. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  642. {
  643. goto loser;
  644. }
  645. slapi_entry_set_uniqueid(e, str);
  646. str = NULL; /* Slapi_Entry now owns the uniqueid */
  647. /* The entry's DN is next */
  648. if (ber_scanf(tmp_bere, "a", &str) == LBER_ERROR)
  649. {
  650. goto loser;
  651. }
  652. slapi_entry_set_dn(e, str);
  653. str = NULL; /* Slapi_Entry now owns the dn */
  654. /* Get the attributes */
  655. for ( tag = ber_first_element( tmp_bere, &len, &lasto );
  656. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  657. tag = ber_next_element( tmp_bere, &len, lasto ) )
  658. {
  659. if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
  660. {
  661. goto loser;
  662. }
  663. /* Add the attribute to the entry */
  664. if (deleted)
  665. entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
  666. else
  667. entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
  668. attr = NULL;
  669. }
  670. if (ber_scanf(tmp_bere, "}") == LBER_ERROR) /* End sequence for this entry */
  671. {
  672. goto loser;
  673. }
  674. /* Check for ldapsubentries and tombstone entries to set flags properly */
  675. slapi_entry_attr_find(e, "objectclass", &attr);
  676. if (attr != NULL) {
  677. struct berval bv;
  678. bv.bv_val = "ldapsubentry";
  679. bv.bv_len = strlen(bv.bv_val);
  680. if (slapi_attr_value_find(attr, &bv) == 0) {
  681. slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
  682. }
  683. bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
  684. bv.bv_len = strlen(bv.bv_val);
  685. if (slapi_attr_value_find(attr, &bv) == 0) {
  686. slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
  687. }
  688. }
  689. /* If we get here, the entry is properly constructed. Return it. */
  690. rc = 0;
  691. *ep = e;
  692. goto free_and_return;
  693. loser:
  694. rc = -1;
  695. /* slapi_ch_free accepts NULL pointer */
  696. slapi_ch_free((void **)&str);
  697. if (attr != NULL)
  698. {
  699. slapi_attr_free (&attr);
  700. }
  701. if (NULL != e)
  702. {
  703. slapi_entry_free (e);
  704. }
  705. *ep = NULL;
  706. slapi_log_error(SLAPI_LOG_ERR, repl_plugin_name, "decode_total_update_extop - Could not decode extended "
  707. "operation containing entry for total update.\n");
  708. free_and_return:
  709. if (NULL != tmp_bere)
  710. {
  711. ber_free(tmp_bere, 1);
  712. tmp_bere = NULL;
  713. }
  714. return rc;
  715. }
  716. /*
  717. * This plugin entry point is called whenever an NSDS50ReplicationEntry
  718. * extended operation is received.
  719. */
  720. int
  721. multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
  722. {
  723. int rc;
  724. Slapi_Entry *e = NULL;
  725. Slapi_Connection *conn = NULL;
  726. PRUint64 connid = 0;
  727. int opid = 0;
  728. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  729. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
  730. /* Decode the extended operation */
  731. rc = decode_total_update_extop(pb, &e);
  732. if (0 == rc)
  733. {
  734. #ifdef notdef
  735. /*
  736. * Just spew LDIF so we're sure we got it right. Later we'll firehose
  737. * this into the database import code
  738. */
  739. int len;
  740. char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
  741. puts(str);
  742. free(str);
  743. #endif
  744. rc = slapi_import_entry (pb, e);
  745. /* slapi_import_entry returns an LDAP error in case of a
  746. * problem. If there's a problem, it's our responsibility
  747. * to free the slapi_entry that we're trying to import.
  748. */
  749. if (rc != LDAP_SUCCESS)
  750. {
  751. const char *dn = slapi_entry_get_dn_const(e);
  752. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  753. "multimaster_extop_NSDS50ReplicationEntry - "
  754. "Error %d: could not import entry dn %s for total update operation conn=%" NSPRIu64 " op=%d\n",
  755. rc, dn, connid, opid);
  756. rc = -1;
  757. }
  758. }
  759. else
  760. {
  761. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
  762. "multimaster_extop_NSDS50ReplicationEntry - "
  763. "Error %d: could not decode the total update extop "
  764. "for total update operation conn=%" NSPRIu64 " op=%d\n",
  765. rc, connid, opid);
  766. }
  767. if (LDAP_SUCCESS != rc) {
  768. /* just disconnect from the supplier. bulk import is stopped when
  769. connection object is destroyed */
  770. slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
  771. if (conn)
  772. {
  773. slapi_disconnect_server(conn);
  774. }
  775. /* cleanup */
  776. if (e)
  777. {
  778. slapi_entry_free (e);
  779. }
  780. }
  781. return rc;
  782. }