repl5_total.c 22 KB

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