repl5_total.c 22 KB

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