Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tero Saarni
OpenLDAP
Commits
3e0f1360
Commit
3e0f1360
authored
Jan 27, 2011
by
Quanah Gibson-Mount
Browse files
ITS#6801
parent
fe3c56a2
Changes
6
Hide whitespace changes
Inline
Side-by-side
CHANGES
View file @
3e0f1360
...
...
@@ -11,6 +11,7 @@ OpenLDAP 2.4.24 Engineering
Added slapd syncrepl suffixmassage support (ITS#6781)
Added slapd multiple listener threads (ITS#6780)
Added slapd-meta paged results control fowarding (ITS#6664)
Added slapd-meta subtree-include support (ITS#6801)
Added slapd-null back-config support (ITS#6624)
Added slapd-sql autocommit support (ITS#6612)
Added slapd-sql support for long long keys (ITS#6617)
...
...
@@ -146,6 +147,7 @@ OpenLDAP 2.4.24 Engineering
slapd-config(5) GnuTLS cipher spec info (ITS#6525)
slapd-config(5) multi-listener support (ITS#6780)
slapd-meta(5) note deprecated items (ITS#6800)
slapd-meta(5) document subtree-include (ITS#6801)
slapo-pcache(5) note rootdn requirement (ITS#6522)
slapo-refint(5) rootdn requirement (ITS#6364)
...
...
doc/man/man5/slapd-meta.5
View file @
3e0f1360
...
...
@@ -570,13 +570,58 @@ specification.
The rewrite options are described in the "REWRITING" section.
.TP
.B subtree\-exclude "<DN>"
This directive instructs back-meta to ignore the current target
for operations whose requestDN is subordinate to
.BR DN .
.B subtree\-{exclude|include} "<rule>"
This directive allows to indicate what subtrees are actually served
by a target.
The syntax of the supported rules is
\fB<rule>: [dn[.<style>]:]<pattern>\fP
\fB<style>: subtree|children|regex\fP
When \fB<style>\fP is either \fBsubtree\fP or \fBchildren\fP
the \fB<pattern>\fP is a DN that must be within the naming context
served by the target.
When \fB<style>\fP is \fBregex\fP the \fB<pattern>\fP is a
.BR regex (5)
pattern.
If the \fBdn.<style>:\fP prefix is omitted, \fBdn.subtree:\fP
is implicitly assumed for backward compatibility.
In the
.B subtree\-exclude
form if the \fIrequest DN\fP matches at least one rule,
the target is not considered while fulfilling the request;
otherwise, the target is considered based on the value of the \fIrequest DN\fP.
When the request is a search, also the \fIscope\fP is considered.
In the
.B subtree\-include
form if the \fIrequest DN\fP matches at least one rule,
the target is considered while fulfilling the request;
otherwise the target is ignored.
.LP
.RS
.nf
| match | exclude |
+---------+---------+-------------------+
| T | T | not candidate |
| F | T | continue checking |
+---------+---------+-------------------+
| T | F | candidate |
| F | F | not candidate |
+---------+---------+-------------------+
.fi
.RE
.RS
There may be multiple occurrences of the
.B subtree\-exclude
directive for each of the targets.
or
.B subtree\-include
directive for each of the targets, but they are mutually exclusive.
.RE
.TP
.B suffixmassage "<virtual naming context>" "<real naming context>"
...
...
servers/slapd/back-meta/back-meta.h
View file @
3e0f1360
...
...
@@ -259,6 +259,31 @@ typedef struct metaconn_t {
* in one block with the metaconn_t structure */
}
metaconn_t
;
typedef
enum
meta_st_t
{
#if 0 /* todo */
META_ST_EXACT = LDAP_SCOPE_BASE,
#endif
META_ST_SUBTREE
=
LDAP_SCOPE_SUBTREE
,
META_ST_SUBORDINATE
=
LDAP_SCOPE_SUBORDINATE
,
META_ST_REGEX
/* last + 1 */
}
meta_st_t
;
typedef
struct
metasubtree_t
{
meta_st_t
ms_type
;
union
{
struct
berval
msu_dn
;
struct
{
regex_t
msr_regex
;
char
*
msr_regex_pattern
;
}
msu_regex
;
}
ms_un
;
#define ms_dn ms_un.msu_dn
#define ms_regex ms_un.msu_regex.msr_regex
#define ms_regex_pattern ms_un.msu_regex.msr_regex_pattern
struct
metasubtree_t
*
ms_next
;
}
metasubtree_t
;
typedef
struct
metatarget_t
{
char
*
mt_uri
;
ldap_pvt_thread_mutex_t
mt_uri_mutex
;
...
...
@@ -269,7 +294,10 @@ typedef struct metatarget_t {
LDAP_URLLIST_PROC
*
mt_urllist_f
;
void
*
mt_urllist_p
;
BerVarray
mt_subtree_exclude
;
metasubtree_t
*
mt_subtree
;
/* F: subtree-include; T: subtree-exclude */
int
mt_subtree_exclude
;
int
mt_scope
;
struct
berval
mt_psuffix
;
/* pretty suffix */
...
...
@@ -636,6 +664,9 @@ meta_dncache_delete_entry(
extern
void
meta_dncache_free
(
void
*
entry
);
extern
int
meta_subtree_destroy
(
metasubtree_t
*
ms
);
extern
LDAP_REBIND_PROC
meta_back_default_rebind
;
extern
LDAP_URLLIST_PROC
meta_back_default_urllist
;
...
...
servers/slapd/back-meta/candidates.c
View file @
3e0f1360
...
...
@@ -32,25 +32,58 @@
/*
* The meta-directory has one suffix, called <suffix>.
* It handles a pool of target servers, each with a branch suffix
* of the form <branch X>,<suffix>
* of the form <branch X>,<suffix>
, where <branch X> may be empty.
*
* When the meta-directory receives a request with a
dn
that belongs
* to a branch, the corresponding target is invoked. When the
dn
* When the meta-directory receives a request with a
request DN
that belongs
* to a branch, the corresponding target is invoked. When the
request DN
* does not belong to a specific branch, all the targets that
* are compatible with the
dn
are selected as candidates, and
* are compatible with the
request DN
are selected as candidates, and
* the request is spawned to all the candidate targets
*
* A request is characterized by a dn. The following cases are handled:
* - the dn is the suffix: <dn> == <suffix>,
* A request is characterized by a request DN. The following cases are
* handled:
* - the request DN is the suffix: <dn> == <suffix>,
* all the targets are candidates (search ...)
* - the
dn
is a branch suffix: <dn> == <branch X>,<suffix>, or
* - the
dn
is a subtree of a branch suffix:
* - the
request DN
is a branch suffix: <dn> == <branch X>,<suffix>, or
* - the
request DN
is a subtree of a branch suffix:
* <dn> == <rdn>,<branch X>,<suffix>,
* the target is the only candidate.
*
* A possible extension will include the handling of multiple suffixes
*/
static
metasubtree_t
*
meta_subtree_match
(
metatarget_t
*
mt
,
struct
berval
*
ndn
,
int
scope
)
{
metasubtree_t
*
ms
=
mt
->
mt_subtree
;
for
(
ms
=
mt
->
mt_subtree
;
ms
;
ms
=
ms
->
ms_next
)
{
switch
(
ms
->
ms_type
)
{
case
META_ST_SUBTREE
:
if
(
dnIsSuffix
(
ndn
,
&
ms
->
ms_dn
)
)
{
return
ms
;
}
break
;
case
META_ST_SUBORDINATE
:
if
(
dnIsSuffix
(
ndn
,
&
ms
->
ms_dn
)
&&
(
ndn
->
bv_len
>
ms
->
ms_dn
.
bv_len
||
scope
!=
LDAP_SCOPE_BASE
)
)
{
return
ms
;
}
break
;
case
META_ST_REGEX
:
/* NOTE: cannot handle scope */
if
(
regexec
(
&
ms
->
ms_regex
,
ndn
->
bv_val
,
0
,
NULL
,
0
)
==
0
)
{
return
ms
;
}
break
;
}
}
return
NULL
;
}
/*
* returns 1 if suffix is candidate for dn, otherwise 0
...
...
@@ -70,14 +103,27 @@ meta_back_is_candidate(
if
(
!
dnIsSuffix
(
ndn
,
&
mt
->
mt_nsuffix
)
)
{
return
META_NOT_CANDIDATE
;
}
/*
* | match | exclude |
* +---------+---------+-------------------+
* | T | T | not candidate |
* | F | T | continue checking |
* +---------+---------+-------------------+
* | T | F | candidate |
* | F | F | not candidate |
* +---------+---------+-------------------+
*/
if
(
mt
->
mt_subtree
_exclude
)
{
int
i
;
if
(
mt
->
mt_subtree
)
{
int
match
=
(
meta_subtree_match
(
mt
,
ndn
,
scope
)
!=
NULL
)
;
for
(
i
=
0
;
!
BER_BVISNULL
(
&
mt
->
mt_subtree_exclude
[
i
]
);
i
++
)
{
if
(
dnIsSuffix
(
ndn
,
&
mt
->
mt_subtree_exclude
[
i
]
)
)
{
return
META_NOT_CANDIDATE
;
}
if
(
!
mt
->
mt_subtree_exclude
)
{
return
match
?
META_CANDIDATE
:
META_NOT_CANDIDATE
;
}
if
(
match
/* && mt->mt_subtree_exclude */
)
{
return
META_NOT_CANDIDATE
;
}
}
...
...
servers/slapd/back-meta/config.c
View file @
3e0f1360
...
...
@@ -92,6 +92,312 @@ check_true_false( char *str )
return
-
1
;
}
int
meta_subtree_destroy
(
metasubtree_t
*
ms
)
{
if
(
ms
->
ms_next
)
{
meta_subtree_destroy
(
ms
->
ms_next
);
}
switch
(
ms
->
ms_type
)
{
case
META_ST_SUBTREE
:
case
META_ST_SUBORDINATE
:
ber_memfree
(
ms
->
ms_dn
.
bv_val
);
break
;
case
META_ST_REGEX
:
regfree
(
&
ms
->
ms_regex
);
ch_free
(
ms
->
ms_regex_pattern
);
break
;
default:
return
-
1
;
}
ch_free
(
ms
);
return
0
;
}
static
int
meta_subtree_config
(
metatarget_t
*
mt
,
int
argc
,
char
**
argv
,
char
*
buf
,
ber_len_t
buflen
,
char
*
log_prefix
)
{
meta_st_t
type
=
META_ST_SUBTREE
;
char
*
pattern
;
struct
berval
ndn
=
BER_BVNULL
;
metasubtree_t
*
ms
=
NULL
;
if
(
strcasecmp
(
argv
[
0
],
"subtree-exclude"
)
==
0
)
{
if
(
mt
->
mt_subtree
&&
!
mt
->
mt_subtree_exclude
)
{
snprintf
(
buf
,
buflen
,
"
\"
subtree-exclude
\"
incompatible with previous
\"
subtree-include
\"
directives"
);
return
1
;
}
mt
->
mt_subtree_exclude
=
1
;
}
else
{
if
(
mt
->
mt_subtree
&&
mt
->
mt_subtree_exclude
)
{
snprintf
(
buf
,
buflen
,
"
\"
subtree-include
\"
incompatible with previous
\"
subtree-exclude
\"
directives"
);
return
1
;
}
}
switch
(
argc
)
{
case
1
:
snprintf
(
buf
,
buflen
,
"missing pattern"
);
return
1
;
case
2
:
break
;
default:
snprintf
(
buf
,
buflen
,
"too many args"
);
return
1
;
}
pattern
=
argv
[
1
];
if
(
strncasecmp
(
pattern
,
"dn"
,
STRLENOF
(
"dn"
)
)
==
0
)
{
char
*
style
;
pattern
=
&
pattern
[
STRLENOF
(
"dn"
)];
if
(
pattern
[
0
]
==
'.'
)
{
style
=
&
pattern
[
1
];
if
(
strncasecmp
(
style
,
"subtree"
,
STRLENOF
(
"subtree"
)
)
==
0
)
{
type
=
META_ST_SUBTREE
;
pattern
=
&
style
[
STRLENOF
(
"subtree"
)];
}
else
if
(
strncasecmp
(
style
,
"children"
,
STRLENOF
(
"children"
)
)
==
0
)
{
type
=
META_ST_SUBORDINATE
;
pattern
=
&
style
[
STRLENOF
(
"children"
)];
}
else
if
(
strncasecmp
(
style
,
"sub"
,
STRLENOF
(
"sub"
)
)
==
0
)
{
type
=
META_ST_SUBTREE
;
pattern
=
&
style
[
STRLENOF
(
"sub"
)];
}
else
if
(
strncasecmp
(
style
,
"regex"
,
STRLENOF
(
"regex"
)
)
==
0
)
{
type
=
META_ST_REGEX
;
pattern
=
&
style
[
STRLENOF
(
"regex"
)];
}
else
{
snprintf
(
buf
,
buflen
,
"unknown style in
\"
dn.<style>
\"
"
);
return
1
;
}
}
if
(
pattern
[
0
]
!=
':'
)
{
snprintf
(
buf
,
buflen
,
"missing colon after
\"
dn.<style>
\"
"
);
return
1
;
}
pattern
++
;
}
switch
(
type
)
{
case
META_ST_SUBTREE
:
case
META_ST_SUBORDINATE
:
{
struct
berval
dn
;
ber_str2bv
(
pattern
,
0
,
0
,
&
dn
);
if
(
dnNormalize
(
0
,
NULL
,
NULL
,
&
dn
,
&
ndn
,
NULL
)
!=
LDAP_SUCCESS
)
{
snprintf
(
buf
,
buflen
,
"DN=
\"
%s
\"
is invalid"
,
pattern
);
return
1
;
}
if
(
!
dnIsSuffix
(
&
ndn
,
&
mt
->
mt_nsuffix
)
)
{
snprintf
(
buf
,
buflen
,
"DN=
\"
%s
\"
is not a subtree of target
\"
%s
\"
"
,
pattern
,
mt
->
mt_nsuffix
.
bv_val
);
ber_memfree
(
ndn
.
bv_val
);
return
(
1
);
}
}
break
;
default:
/* silence warnings */
break
;
}
ms
=
ch_calloc
(
sizeof
(
metasubtree_t
),
1
);
ms
->
ms_type
=
type
;
switch
(
ms
->
ms_type
)
{
case
META_ST_SUBTREE
:
case
META_ST_SUBORDINATE
:
ms
->
ms_dn
=
ndn
;
break
;
case
META_ST_REGEX
:
{
int
rc
;
rc
=
regcomp
(
&
ms
->
ms_regex
,
pattern
,
REG_EXTENDED
|
REG_ICASE
);
if
(
rc
!=
0
)
{
char
regerr
[
SLAP_TEXT_BUFLEN
];
regerror
(
rc
,
&
ms
->
ms_regex
,
regerr
,
sizeof
(
regerr
)
);
snprintf
(
buf
,
sizeof
(
buf
),
"regular expression
\"
%s
\"
bad because of %s"
,
pattern
,
regerr
);
ch_free
(
ms
);
return
1
;
}
ms
->
ms_regex_pattern
=
ch_strdup
(
pattern
);
}
break
;
}
if
(
mt
->
mt_subtree
==
NULL
)
{
mt
->
mt_subtree
=
ms
;
}
else
{
metasubtree_t
**
msp
;
for
(
msp
=
&
mt
->
mt_subtree
;
*
msp
;
)
{
switch
(
ms
->
ms_type
)
{
case
META_ST_SUBTREE
:
switch
(
(
*
msp
)
->
ms_type
)
{
case
META_ST_SUBTREE
:
if
(
dnIsSuffix
(
&
(
*
msp
)
->
ms_dn
,
&
ms
->
ms_dn
)
)
{
metasubtree_t
*
tmp
=
*
msp
;
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.subtree:%s
\"
is contained in rule
\"
dn.subtree:%s
\"
(replaced)
\n
"
,
log_prefix
,
pattern
,
(
*
msp
)
->
ms_dn
.
bv_val
);
*
msp
=
(
*
msp
)
->
ms_next
;
tmp
->
ms_next
=
NULL
;
meta_subtree_destroy
(
tmp
);
continue
;
}
else
if
(
dnIsSuffix
(
&
ms
->
ms_dn
,
&
(
*
msp
)
->
ms_dn
)
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.subtree:%s
\"
contains rule
\"
dn.subtree:%s
\"
(ignored)
\n
"
,
log_prefix
,
(
*
msp
)
->
ms_dn
.
bv_val
,
pattern
);
meta_subtree_destroy
(
ms
);
ms
=
NULL
;
return
(
0
);
}
break
;
case
META_ST_SUBORDINATE
:
if
(
dnIsSuffix
(
&
(
*
msp
)
->
ms_dn
,
&
ms
->
ms_dn
)
)
{
metasubtree_t
*
tmp
=
*
msp
;
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
is contained in rule
\"
dn.subtree:%s
\"
(replaced)
\n
"
,
log_prefix
,
pattern
,
(
*
msp
)
->
ms_dn
.
bv_val
);
*
msp
=
(
*
msp
)
->
ms_next
;
tmp
->
ms_next
=
NULL
;
meta_subtree_destroy
(
tmp
);
continue
;
}
else
if
(
dnIsSuffix
(
&
ms
->
ms_dn
,
&
(
*
msp
)
->
ms_dn
)
&&
ms
->
ms_dn
.
bv_len
>
(
*
msp
)
->
ms_dn
.
bv_len
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
contains rule
\"
dn.subtree:%s
\"
(ignored)
\n
"
,
log_prefix
,
(
*
msp
)
->
ms_dn
.
bv_val
,
pattern
);
meta_subtree_destroy
(
ms
);
ms
=
NULL
;
return
(
0
);
}
break
;
case
META_ST_REGEX
:
if
(
regexec
(
&
(
*
msp
)
->
ms_regex
,
ms
->
ms_dn
.
bv_val
,
0
,
NULL
,
0
)
==
0
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.regex:%s
\"
may contain rule
\"
dn.subtree:%s
\"\n
"
,
log_prefix
,
(
*
msp
)
->
ms_regex_pattern
,
ms
->
ms_dn
.
bv_val
);
}
break
;
}
break
;
case
META_ST_SUBORDINATE
:
switch
(
(
*
msp
)
->
ms_type
)
{
case
META_ST_SUBTREE
:
if
(
dnIsSuffix
(
&
(
*
msp
)
->
ms_dn
,
&
ms
->
ms_dn
)
)
{
metasubtree_t
*
tmp
=
*
msp
;
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
is contained in rule
\"
dn.subtree:%s
\"
(replaced)
\n
"
,
log_prefix
,
pattern
,
(
*
msp
)
->
ms_dn
.
bv_val
);
*
msp
=
(
*
msp
)
->
ms_next
;
tmp
->
ms_next
=
NULL
;
meta_subtree_destroy
(
tmp
);
continue
;
}
else
if
(
dnIsSuffix
(
&
ms
->
ms_dn
,
&
(
*
msp
)
->
ms_dn
)
&&
ms
->
ms_dn
.
bv_len
>
(
*
msp
)
->
ms_dn
.
bv_len
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
contains rule
\"
dn.subtree:%s
\"
(ignored)
\n
"
,
log_prefix
,
(
*
msp
)
->
ms_dn
.
bv_val
,
pattern
);
meta_subtree_destroy
(
ms
);
ms
=
NULL
;
return
(
0
);
}
break
;
case
META_ST_SUBORDINATE
:
if
(
dnIsSuffix
(
&
(
*
msp
)
->
ms_dn
,
&
ms
->
ms_dn
)
)
{
metasubtree_t
*
tmp
=
*
msp
;
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
is contained in rule
\"
dn.children:%s
\"
(replaced)
\n
"
,
log_prefix
,
pattern
,
(
*
msp
)
->
ms_dn
.
bv_val
);
*
msp
=
(
*
msp
)
->
ms_next
;
tmp
->
ms_next
=
NULL
;
meta_subtree_destroy
(
tmp
);
continue
;
}
else
if
(
dnIsSuffix
(
&
ms
->
ms_dn
,
&
(
*
msp
)
->
ms_dn
)
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.children:%s
\"
contains rule
\"
dn.children:%s
\"
(ignored)
\n
"
,
log_prefix
,
(
*
msp
)
->
ms_dn
.
bv_val
,
pattern
);
meta_subtree_destroy
(
ms
);
ms
=
NULL
;
return
(
0
);
}
break
;
case
META_ST_REGEX
:
if
(
regexec
(
&
(
*
msp
)
->
ms_regex
,
ms
->
ms_dn
.
bv_val
,
0
,
NULL
,
0
)
==
0
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.regex:%s
\"
may contain rule
\"
dn.subtree:%s
\"\n
"
,
log_prefix
,
(
*
msp
)
->
ms_regex_pattern
,
ms
->
ms_dn
.
bv_val
);
}
break
;
}
break
;
case
META_ST_REGEX
:
switch
(
(
*
msp
)
->
ms_type
)
{
case
META_ST_SUBTREE
:
case
META_ST_SUBORDINATE
:
if
(
regexec
(
&
ms
->
ms_regex
,
(
*
msp
)
->
ms_dn
.
bv_val
,
0
,
NULL
,
0
)
==
0
)
{
Debug
(
LDAP_DEBUG_CONFIG
,
"%s: previous rule
\"
dn.subtree:%s
\"
may be contained in rule
\"
dn.regex:%s
\"\n
"
,
log_prefix
,
(
*
msp
)
->
ms_dn
.
bv_val
,
ms
->
ms_regex_pattern
);
}
break
;
case
META_ST_REGEX
:
/* no check possible */
break
;
}
break
;
}
msp
=
&
(
*
msp
)
->
ms_next
;
}
*
msp
=
ms
;
}
return
0
;
}
int
meta_back_db_config
(
...
...
@@ -99,8 +405,7 @@ meta_back_db_config(
const
char
*
fname
,
int
lineno
,
int
argc
,
char
**
argv
)
char
**
argv
)
{
metainfo_t
*
mi
=
(
metainfo_t
*
)
be
->
be_private
;
...
...
@@ -315,81 +620,35 @@ meta_back_db_config(
}
/* subtree-exclude */
}
else
if
(
strcasecmp
(
argv
[
0
],
"subtree-exclude"
)
==
0
)
{
int
i
=
mi
->
mi_ntargets
-
1
;
struct
berval
dn
,
ndn
;
}
else
if
(
strcasecmp
(
argv
[
0
],
"subtree-exclude"
)
==
0
||
strcasecmp
(
argv
[
0
],
"subtree-include"
)
==
0
)
{
char
log_prefix
[
SLAP_TEXT_BUFLEN
];
char
textbuf
[
SLAP_TEXT_BUFLEN
];
char
*
arg0
;
int
i
=
mi
->
mi_ntargets
-
1
;
if
(
i
<
0
)
{
Debug
(
LDAP_DEBUG_ANY
,
"%s: line %d: need
\"
uri
\"
directive first
\n
"
,
"%s: line %d: need
\"
uri
\"
directive first
\n
"
,
fname
,
lineno
,
0
);
return
1
;
}
switch
(
argc
)
{
case
1
:
Debug
(
LDAP_DEBUG_ANY
,
"%s: line %d: missing DN in
\"
subtree-exclude <DN>
\"
line
\n
"
,
fname
,
lineno
,
0
);
return
1
;
case
2
:
break
;
default:
Debug
(
LDAP_DEBUG_ANY
,
"%s: line %d: too many args in
\"
subtree-exclude <DN>
\"
line
\n
"
,
fname
,
lineno
,
0
);
return
1
;
}
if
(
strcasecmp
(
argv
[
0
],
"subtree-exclude"
)
==
0
)
{
arg0
=
"subtree-exclude"
;
ber_str2bv
(
argv
[
1
],
0
,
0
,
&
dn
);
if
(
dnNormalize
(
0
,
NULL
,
NULL
,
&
dn
,
&
ndn
,
NULL
)
!=
LDAP_SUCCESS
)
{
Debug
(
LDAP_DEBUG_ANY
,
"%s: line %d: "
"subtree-exclude DN=
\"
%s
\"
is invalid
\n
"
,
fname
,
lineno
,
argv
[
1
]
);
return
(
1
);
}
if
(
!
dnIsSuffix
(
&
ndn
,
&
mi
->
mi_targets
[
i
]
->
mt_nsuffix
)
)
{
Debug
(
LDAP_DEBUG_ANY
,
"%s: line %d: "
"subtree-exclude DN=
\"
%s
\"
"
"must be subtree of target
\n
"
,