]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
ITS#6242
[openldap] / servers / slapd / syncrepl.c
index 35e431f6dd76d8b7881381aeaf43258a72db6165..22496b66b3825f246c2f5f7a5f75bb097aafa2ae 100644 (file)
@@ -1620,6 +1620,13 @@ syncrepl_message_to_op(
        op->o_tag = LBER_DEFAULT;
        op->o_bd = si->si_wbe;
 
+       if ( BER_BVISEMPTY( &bdn ) && !BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] ) ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "syncrepl_message_to_op: %s got empty dn",
+                       si->si_ridtxt, 0, 0 );
+               return LDAP_OTHER;
+       }
+
        while (( rc = ldap_get_attribute_ber( si->si_ld, msg, ber, &bv, &bvals ) )
                == LDAP_SUCCESS ) {
                if ( bv.bv_val == NULL )
@@ -1857,6 +1864,13 @@ syncrepl_message_to_entry(
                return rc;
        }
 
+       if ( BER_BVISEMPTY( &bdn ) && !BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] ) ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "syncrepl_message_to_entry: %s got empty dn",
+                       si->si_ridtxt, 0, 0 );
+               return LDAP_OTHER;
+       }
+
        if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) {
                /* NOTE: this could be done even before decoding the DN,
                 * although encoding errors wouldn't be detected */
@@ -3088,6 +3102,10 @@ syncrepl_updateCookie(
        return rc;
 }
 
+/* Compare the attribute from the old entry to the one in the new
+ * entry. The Modifications from the new entry will either be left
+ * in place, or changed to an Add or Delete as needed.
+ */
 static void
 attr_cmp( Operation *op, Attribute *old, Attribute *new,
        Modifications ***mret, Modifications ***mcur )
@@ -3231,6 +3249,86 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
        *mret = modtail;
 }
 
+/* Generate a set of modifications to change the old entry into the
+ * new one. On input ml is a list of modifications equivalent to
+ * the new entry. It will be massaged and the result will be stored
+ * in mods.
+ */
+void syncrepl_diff_entry( Operation *op, Attribute *old, Attribute *new,
+       Modifications **mods, Modifications **ml, int is_ctx)
+{
+       Modifications **modtail = mods;
+
+       /* We assume that attributes are saved in the same order
+        * in the remote and local databases. So if we walk through
+        * the attributeDescriptions one by one they should match in
+        * lock step. If not, look for an add or delete.
+        */
+       while ( old && new )
+       {
+               /* If we've seen this before, use its mod now */
+               if ( new->a_flags & SLAP_ATTR_IXADD ) {
+                       attr_cmp( op, NULL, new, &modtail, &ml );
+                       new = new->a_next;
+                       continue;
+               }
+               /* Skip contextCSN */
+               if ( is_ctx && old->a_desc ==
+                       slap_schema.si_ad_contextCSN ) {
+                       old = old->a_next;
+                       continue;
+               }
+
+               if ( old->a_desc != new->a_desc ) {
+                       Modifications *mod;
+                       Attribute *tmp;
+
+                       /* If it's just been re-added later,
+                        * remember that we've seen it.
+                        */
+                       tmp = attr_find( new, old->a_desc );
+                       if ( tmp ) {
+                               tmp->a_flags |= SLAP_ATTR_IXADD;
+                       } else {
+                               /* If it's a new attribute, pull it in.
+                                */
+                               tmp = attr_find( old, new->a_desc );
+                               if ( !tmp ) {
+                                       attr_cmp( op, NULL, new, &modtail, &ml );
+                                       new = new->a_next;
+                                       continue;
+                               }
+                               /* Delete old attr */
+                               mod = ch_malloc( sizeof( Modifications ) );
+                               mod->sml_op = LDAP_MOD_DELETE;
+                               mod->sml_flags = 0;
+                               mod->sml_desc = old->a_desc;
+                               mod->sml_type = mod->sml_desc->ad_cname;
+                               mod->sml_numvals = 0;
+                               mod->sml_values = NULL;
+                               mod->sml_nvalues = NULL;
+                               *modtail = mod;
+                               modtail = &mod->sml_next;
+                       }
+                       old = old->a_next;
+                       continue;
+               }
+               /* kludge - always update modifiersName so that it
+                * stays co-located with the other mod opattrs. But only
+                * if we know there are other valid mods.
+                */
+               if ( *mods && ( old->a_desc == slap_schema.si_ad_modifiersName ||
+                       old->a_desc == slap_schema.si_ad_modifyTimestamp ))
+                       attr_cmp( op, NULL, new, &modtail, &ml );
+               else
+                       attr_cmp( op, old, new, &modtail, &ml );
+               new = new->a_next;
+               old = old->a_next;
+       }
+       *modtail = *ml;
+       *ml = NULL;
+}
+
 static int
 dn_callback(
        Operation*      op,
@@ -3351,78 +3449,9 @@ dn_callback(
                                         */
                                }
 
-                               modtail = &dni->mods;
-                               ml = dni->modlist;
-
-                               /* We assume that attributes are saved in the same order
-                                * in the remote and local databases. So if we walk through
-                                * the attributeDescriptions one by one they should match in
-                                * lock step. If not, look for an add or delete.
-                                */
-                               for ( old = rs->sr_entry->e_attrs, new = dni->new_entry->e_attrs;
-                                               old && new; )
-                               {
-                                       /* If we've seen this before, use its mod now */
-                                       if ( new->a_flags & SLAP_ATTR_IXADD ) {
-                                               attr_cmp( op, NULL, new, &modtail, &ml );
-                                               new = new->a_next;
-                                               continue;
-                                       }
-                                       /* Skip contextCSN */
-                                       if ( is_ctx && old->a_desc ==
-                                               slap_schema.si_ad_contextCSN ) {
-                                               old = old->a_next;
-                                               continue;
-                                       }
-
-                                       if ( old->a_desc != new->a_desc ) {
-                                               Modifications *mod;
-                                               Attribute *tmp;
-
-                                               /* If it's just been re-added later,
-                                                * remember that we've seen it.
-                                                */
-                                               tmp = attr_find( new, old->a_desc );
-                                               if ( tmp ) {
-                                                       tmp->a_flags |= SLAP_ATTR_IXADD;
-                                               } else {
-                                                       /* If it's a new attribute, pull it in.
-                                                        */
-                                                       tmp = attr_find( old, new->a_desc );
-                                                       if ( !tmp ) {
-                                                               attr_cmp( op, NULL, new, &modtail, &ml );
-                                                               new = new->a_next;
-                                                               continue;
-                                                       }
-                                                       /* Delete old attr */
-                                                       mod = ch_malloc( sizeof( Modifications ) );
-                                                       mod->sml_op = LDAP_MOD_DELETE;
-                                                       mod->sml_flags = 0;
-                                                       mod->sml_desc = old->a_desc;
-                                                       mod->sml_type = mod->sml_desc->ad_cname;
-                                                       mod->sml_numvals = 0;
-                                                       mod->sml_values = NULL;
-                                                       mod->sml_nvalues = NULL;
-                                                       *modtail = mod;
-                                                       modtail = &mod->sml_next;
-                                               }
-                                               old = old->a_next;
-                                               continue;
-                                       }
-                                       /* kludge - always update modifiersName so that it
-                                        * stays co-located with the other mod opattrs. But only
-                                        * if we know there are other valid mods.
-                                        */
-                                       if ( dni->mods && ( old->a_desc == slap_schema.si_ad_modifiersName ||
-                                               old->a_desc == slap_schema.si_ad_modifyTimestamp ))
-                                               attr_cmp( op, NULL, new, &modtail, &ml );
-                                       else
-                                               attr_cmp( op, old, new, &modtail, &ml );
-                                       new = new->a_next;
-                                       old = old->a_next;
-                               }
-                               *modtail = *ml;
-                               *ml = NULL;
+                               syncrepl_diff_entry( op, rs->sr_entry->e_attrs,
+                                       dni->new_entry->e_attrs, &dni->mods, dni->modlist,
+                                       is_ctx );
                        }
                }
        } else if ( rs->sr_type == REP_RESULT ) {
@@ -3793,21 +3822,6 @@ enum {
        GOT_REQUIRED            = (GOT_RID|GOT_PROVIDER|GOT_SEARCHBASE)
 };
 
-static struct {
-       struct berval key;
-       int val;
-} scopes[] = {
-       { BER_BVC("base"), LDAP_SCOPE_BASE },
-       { BER_BVC("one"), LDAP_SCOPE_ONELEVEL },
-       { BER_BVC("onelevel"), LDAP_SCOPE_ONELEVEL },   /* OpenLDAP extension */
-       { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE },
-       { BER_BVC("subord"), LDAP_SCOPE_SUBORDINATE },
-       { BER_BVC("subordinate"), LDAP_SCOPE_SUBORDINATE },
-       { BER_BVC("sub"), LDAP_SCOPE_SUBTREE },
-       { BER_BVC("subtree"), LDAP_SCOPE_SUBTREE },     /* OpenLDAP extension */
-       { BER_BVNULL, 0 }
-};
-
 static slap_verbmasks datamodes[] = {
        { BER_BVC("default"), SYNCDATA_DEFAULT },
        { BER_BVC("accesslog"), SYNCDATA_ACCESSLOG },
@@ -4025,19 +4039,15 @@ parse_syncrepl_line(
                {
                        int j;
                        val = c->argv[ i ] + STRLENOF( SCOPESTR "=" );
-                       for ( j = 0; !BER_BVISNULL(&scopes[j].key); j++ ) {
-                               if (!strcasecmp( val, scopes[j].key.bv_val ) ) {
-                                       si->si_scope = scopes[j].val;
-                                       break;
-                               }
-                       }
-                       if ( BER_BVISNULL(&scopes[j].key) ) {
+                       j = ldap_pvt_str2scope( val );
+                       if ( j < 0 ) {
                                snprintf( c->cr_msg, sizeof( c->cr_msg ),
                                        "Error: parse_syncrepl_line: "
                                        "unknown scope \"%s\"", val);
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
                                return -1;
                        }
+                       si->si_scope = j;
                        si->si_got |= GOT_SCOPE;
                } else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR,
                                        STRLENOF( ATTRSONLYSTR ) ) )
@@ -4441,7 +4451,7 @@ add_syncrepl(
 static void
 syncrepl_unparse( syncinfo_t *si, struct berval *bv )
 {
-       struct berval bc, uri;
+       struct berval bc, uri, bs;
        char buf[BUFSIZ*2], *ptr;
        ber_len_t len;
        int i;
@@ -4495,13 +4505,10 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv )
                ptr = lutil_strcopy( ptr, si->si_logbase.bv_val );
                *ptr++ = '"';
        }
-       for (i=0; !BER_BVISNULL(&scopes[i].key);i++) {
-               if ( si->si_scope == scopes[i].val ) {
-                       if ( WHATSLEFT <= STRLENOF( " " SCOPESTR "=" ) + scopes[i].key.bv_len ) return;
-                       ptr = lutil_strcopy( ptr, " " SCOPESTR "=" );
-                       ptr = lutil_strcopy( ptr, scopes[i].key.bv_val );
-                       break;
-               }
+       if ( ldap_pvt_scope2bv( si->si_scope, &bs ) == LDAP_SUCCESS ) {
+               if ( WHATSLEFT <= STRLENOF( " " SCOPESTR "=" ) + bs.bv_len ) return;
+               ptr = lutil_strcopy( ptr, " " SCOPESTR "=" );
+               ptr = lutil_strcopy( ptr, bs.bv_val );
        }
        if ( si->si_attrsonly ) {
                if ( WHATSLEFT <= STRLENOF( " " ATTRSONLYSTR "=\"" "\"" ) ) return;