+ return -1;
+ }
+
+ if ( is_entry_referral( p ) ) {
+ /* parent is a referral, don't allow add */
+ char *matched_dn = ch_strdup( p->e_dn );
+ BerVarray refs = is_entry_referral( p )
+ ? get_entry_referrals( be, conn, op, p )
+ : NULL;
+
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+ ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( BACK_LDBM, ERR,
+ "ldbm_back_add: Parent is referral.\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+#endif
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvarray_free( refs );
+ free( matched_dn );
+ return -1;
+ }
+
+ } else {
+ if(pdn.bv_val != NULL) {
+ assert( *pdn.bv_val == '\0' );
+ }
+
+ /* no parent, must be adding entry to root */
+ if ( !be_isroot( be, &op->o_ndn ) ) {
+ if ( be_issuffix( be, (struct berval *)&slap_empty_bv ) || be_isupdate( be, &op->o_ndn ) ) {
+ p = (Entry *)&slap_entry_root;
+
+ rc = access_allowed( be, conn, op, p,
+ children, NULL, ACL_WRITE, NULL );
+ p = NULL;
+
+ if ( ! rc ) {
+ ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( BACK_LDBM, ERR,
+ "ldbm_back_add: No write "
+ "access to parent (\"\").\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "no write access to parent\n",
+ 0, 0, 0 );
+#endif
+
+ send_ldap_result( conn, op,
+ LDAP_INSUFFICIENT_ACCESS,
+ NULL,
+ "no write access to parent",
+ NULL, NULL );
+
+ return -1;
+ }
+
+ } else {
+ ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
+
+#ifdef NEW_LOGGING
+ LDAP_LOG( BACK_LDBM, ERR,
+ "ldbm_back_add: %s add denied.\n",
+ pdn.bv_val == NULL ? "suffix"
+ : "entry at root", 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
+ pdn.bv_val == NULL ? "suffix"
+ : "entry at root", 0, 0 );
+#endif
+
+ send_ldap_result( conn, op,
+ LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+
+ return -1;
+ }