#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include <ac/string.h>
#include "slap.h"
#include "back-netinfo.h"
int
netinfo_back_search(
struct slap_op *op,
struct slap_rep *rs
)
{
struct dsinfo *di = (struct dsinfo *)op->o_bd->be_private;
struct berval *base = &op->o_req_dn;
struct berval *nbase = &op->o_req_ndn;
dsfilter *dsf;
dsstatus status;
u_int32_t dsid, *match, count, scopemin, scopemax;
int i, rc;
time_t stoptime;
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, ARGS, "netinfo_back_search base %s scope %d\n", base->bv_val, op->ors_scope));
#else
Debug(LDAP_DEBUG_TRACE, "==> netinfo_back_search base=%s nbase=%s scope=%d\n", base->bv_val, nbase->bv_val, op->ors_scope);
#endif
if (netinfo_back_send_referrals(op, rs, nbase) == DSStatusOK)
{
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: sent referrals\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search\n", 0, 0, 0);
#endif
return 1;
}
ENGINE_LOCK(di);
if (di->flags & DSENGINE_FLAGS_NATIVE_AUTHORIZATION)
{
status = is_trusted_network(op->o_bd, op->o_conn);
if (status != DSStatusOK)
{
ENGINE_UNLOCK(di);
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: untrusted network\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: untrusted network\n", 0, 0, 0);
#endif
return netinfo_back_op_result(op, rs, status);
}
}
status = netinfo_back_dn_pathmatch(op->o_bd, nbase, &dsid);
if (status != DSStatusOK)
{
ENGINE_UNLOCK(di);
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: pathmatch failed\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: pathmatch failed\n", 0, 0, 0);
#endif
return netinfo_back_op_result(op, rs, status);
}
switch (op->ors_scope)
{
case LDAP_SCOPE_BASE:
scopemin = scopemax = 0;
break;
case LDAP_SCOPE_SUBTREE:
scopemin = 0;
scopemax = (u_int32_t)-1;
break;
case LDAP_SCOPE_ONELEVEL:
default:
scopemin = scopemax = 1;
break;
}
dsf = filter_to_dsfilter(op->o_bd, op->ors_filter);
if (dsf == NULL)
{
ENGINE_UNLOCK(di);
send_ldap_error( op, rs, LDAP_OPERATIONS_ERROR, "Could not translate filter" );
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: could not translate filter\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: could not translate filter\n", 0, 0, 0);
#endif
return -1;
}
#if 0
if (be_isroot(op->o_bd, &op->o_ndn))
{
isroot = 1;
}
else
{
get_limits(op, &op->o_ndn, &limit);
}
if (isroot)
{
if (tlimit == 0)
tlimit = -1;
if (slimit == 0)
slimit = -1;
}
else
{
if (tlimit <= 0)
{
tlimit = limit->lms_t_soft;
}
else if (tlimit > limit->lms_t_hard)
{
if (limit->lms_t_hard == 0)
tlimit = limit->lms_t_soft;
else if (limit->lms_t_hard > 0)
{
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, NULL );
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: reached hard time limit\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: reached hard time limit\n", 0, 0, 0);
#endif
return 0;
}
}
if (slimit <= 0)
{
slimit = limit->lms_s_soft;
}
else if (slimit > limit->lms_s_hard)
{
if (limit->lms_s_hard == 0)
slimit = limit->lms_s_soft;
else if (limit->lms_s_hard > 0)
{
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, NULL );
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: reached hard size limit\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: reached hard size limit\n", 0, 0, 0);
#endif
return 0;
}
}
}
#endif
stoptime = op->o_time + op->ors_tlimit;
status = dsengine_search_filter(di->engine, dsid, dsf, scopemin, scopemax, &match, &count);
if (status != DSStatusOK)
{
dsfilter_release(dsf);
ENGINE_UNLOCK(di);
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: search failed\n"));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search: search failed\n", 0, 0, 0);
#endif
return netinfo_back_op_result(op, rs, status);
}
dsfilter_release(dsf);
if (op->ors_slimit != LDAP_NO_LIMIT && count > op->ors_slimit)
{
count = op->ors_slimit;
rc = LDAP_SIZELIMIT_EXCEEDED;
}
else
{
rc = LDAP_SUCCESS;
}
for (i = 0; i < count; i++)
{
Entry *ent;
dsrecord *rec;
if (op->o_abandon)
{
ENGINE_UNLOCK(di);
free(match);
return 0;
}
if (op->ors_tlimit != -1 && slap_get_time() > stoptime)
{
rc = LDAP_TIMELIMIT_EXCEEDED;
break;
}
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: "
"Fetching record dSID %d\n", match[i]));
#else
Debug(LDAP_DEBUG_TRACE, "Fetching DS record ID=%d\n", match[i], 0, 0);
#endif
status = dsengine_fetch(di->engine, match[i], &rec);
if (status != DSStatusOK)
{
ENGINE_UNLOCK(di);
free(match);
return netinfo_back_op_result(op, rs, status);
}
if (di->flags & DSENGINE_FLAGS_NATIVE_AUTHORIZATION)
{
status = netinfo_back_authorize(op, rec, slap_schema.si_ad_entry, ACL_READ);
if (status != DSStatusOK)
{
dsrecord_release(rec);
continue;
}
}
status = dsrecord_to_entry(op->o_bd, rec, &ent);
if (status != DSStatusOK)
{
dsrecord_release(rec);
continue;
}
dsrecord_release(rec);
rs->sr_attrs = op->ors_attrs;
rs->sr_entry = ent;
send_search_entry( op, rs );
rs->sr_entry = NULL;
rs->sr_attrs = NULL;
netinfo_back_entry_free(ent);
}
if (rc == LDAP_SUCCESS)
{
struct berval canonicalRelativeDN;
status = netinfo_back_local_dn(op->o_bd, dsid, &canonicalRelativeDN);
if (status == DSStatusOK)
{
status = netinfo_back_send_references(op, rs, &canonicalRelativeDN);
ch_free(canonicalRelativeDN.bv_val);
}
rc = dsstatus_to_ldap_err(status);
}
ENGINE_UNLOCK(di);
if (count > 0)
free(match);
rs->sr_err = rc;
send_ldap_result(op, rs);
#ifdef NEW_LOGGING
LDAP_LOG((BACK_NETINFO, INFO, "netinfo_back_search: %d entries\n", count));
#else
Debug(LDAP_DEBUG_TRACE, "<== netinfo_back_search count=%d\n", count, 0, 0);
#endif
return rs->sr_err;
}