#include "lib/events/events.h"
#include "lib/messaging/irpc.h"
#include "dsdb/kcc/kcc_service.h"
-#include "lib/ldb/include/ldb_errors.h"
+#include <ldb_errors.h>
#include "../lib/util/dlinklist.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "param/param.h"
+#include "libds/common/roles.h"
/*
establish system creds
{
const struct GUID *ntds_guid;
- service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info);
+ service->samdb = samdb_connect(service, service->task->event_ctx, lp_ctx, service->system_session_info, 0);
if (!service->samdb) {
return WERR_DS_UNAVAILABLE;
}
service->ntds_guid = *ntds_guid;
+ if (samdb_rodc(service->samdb, &service->am_rodc) != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to determine RODC status\n"));
+ return WERR_DS_UNAVAILABLE;
+ }
+
return WERR_OK;
}
struct ldb_result *r;
struct ldb_message_element *el;
static const char *attrs[] = { "namingContexts", "configurationNamingContext", NULL };
- uint32_t i;
+ unsigned int i;
int ret;
basedn = ldb_dn_new(s, s->samdb, NULL);
return WERR_FOOBAR;
}
- for (i=0; el && i < el->num_values; i++) {
+ for (i=0; i < el->num_values; i++) {
const char *v = (const char *)el->values[i].data;
struct ldb_dn *pdn;
struct kccsrv_partition *p;
}
+struct kcc_manual_runcmd_state {
+ struct irpc_message *msg;
+ struct drsuapi_DsExecuteKCC *r;
+ struct kccsrv_service *service;
+};
+
+
+/*
+ * Called when samba_kcc script has finished
+ */
+static void manual_samba_kcc_done(struct tevent_req *subreq)
+{
+ struct kcc_manual_runcmd_state *st =
+ tevent_req_callback_data(subreq,
+ struct kcc_manual_runcmd_state);
+ int rc;
+ int sys_errno;
+ NTSTATUS status;
+
+ st->service->periodic.subreq = NULL;
+
+ rc = samba_runcmd_recv(subreq, &sys_errno);
+ TALLOC_FREE(subreq);
+
+ if (rc != 0) {
+ status = map_nt_error_from_unix_common(sys_errno);
+ } else {
+ status = NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,(__location__ ": Failed manual run of samba_kcc - %s\n",
+ nt_errstr(status)));
+ } else {
+ DEBUG(3,("Completed manual run of samba_kcc OK\n"));
+ }
+
+ if (!(st->r->in.req->ctr1.flags & DRSUAPI_DS_EXECUTE_KCC_ASYNCHRONOUS_OPERATION)) {
+ irpc_send_reply(st->msg, status);
+ }
+}
+
+static NTSTATUS kccsrv_execute_kcc(struct irpc_message *msg, struct drsuapi_DsExecuteKCC *r)
+{
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status = NT_STATUS_OK;
+ struct kccsrv_service *service = talloc_get_type(msg->private_data, struct kccsrv_service);
+
+ const char * const *samba_kcc_command;
+ struct kcc_manual_runcmd_state *st;
+
+ if (!service->samba_kcc_code) {
+ mem_ctx = talloc_new(service);
+
+ status = kccsrv_simple_update(service, mem_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("kccsrv_execute_kcc failed - %s\n",
+ nt_errstr(status)));
+ }
+ talloc_free(mem_ctx);
+
+ return NT_STATUS_OK;
+ }
+
+ /* Invocation of the samba_kcc python script for replication
+ * topology generation.
+ */
+
+ samba_kcc_command =
+ lpcfg_samba_kcc_command(service->task->lp_ctx);
+
+ st = talloc(msg, struct kcc_manual_runcmd_state);
+ if (st == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ st->msg = msg;
+ st->r = r;
+ st->service = service;
+
+ /* don't run at the same time as an existing child */
+ if (service->periodic.subreq) {
+ status = NT_STATUS_DS_BUSY;
+ return status;
+ }
+
+ DEBUG(2, ("Calling samba_kcc script\n"));
+ service->periodic.subreq = samba_runcmd_send(service,
+ service->task->event_ctx,
+ timeval_current_ofs(40, 0),
+ 2, 0, samba_kcc_command, NULL);
+
+ if (service->periodic.subreq == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ DEBUG(0,(__location__ ": failed - %s\n", nt_errstr(status)));
+ return status;
+ } else {
+ tevent_req_set_callback(service->periodic.subreq,
+ manual_samba_kcc_done, st);
+ }
+
+ if (r->in.req->ctr1.flags & DRSUAPI_DS_EXECUTE_KCC_ASYNCHRONOUS_OPERATION) {
+ /* This actually means reply right away, let it run in the background */
+ } else {
+ /* mark the request as replied async, the caller wants to know when this is finished */
+ msg->defer_reply = true;
+ }
+ return status;
+
+}
+
+static NTSTATUS kccsrv_replica_get_info(struct irpc_message *msg, struct drsuapi_DsReplicaGetInfo *r)
+{
+ return kccdrs_replica_get_info(msg, r);
+}
+
/*
startup the kcc service task
*/
struct kccsrv_service *service;
uint32_t periodic_startup_interval;
- switch (lp_server_role(task->lp_ctx)) {
+ switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
task_server_terminate(task, "kccsrv: no KCC required in standalone configuration", false);
return;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "kccsrv: no KCC required in domain member configuration", false);
return;
- case ROLE_DOMAIN_CONTROLLER:
+ case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want a KCC */
break;
}
return;
}
- periodic_startup_interval = lp_parm_int(task->lp_ctx, NULL, "kccsrv",
- "periodic_startup_interval", 15); /* in seconds */
- service->periodic.interval = lp_parm_int(task->lp_ctx, NULL, "kccsrv",
- "periodic_interval", 300); /* in seconds */
+ periodic_startup_interval =
+ lpcfg_parm_int(task->lp_ctx, NULL, "kccsrv",
+ "periodic_startup_interval", 15); /* in seconds */
+ service->periodic.interval =
+ lpcfg_parm_int(task->lp_ctx, NULL, "kccsrv",
+ "periodic_interval", 300); /* in seconds */
+
+ /* (kccsrv:samba_kcc=true) will run newer samba_kcc replication
+ * topology generation code.
+ */
+ service->samba_kcc_code = lpcfg_parm_bool(task->lp_ctx, NULL,
+ "kccsrv", "samba_kcc", false);
status = kccsrv_periodic_schedule(service, periodic_startup_interval);
if (!W_ERROR_IS_OK(status)) {
}
irpc_add_name(task->msg_ctx, "kccsrv");
+
+ IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSEXECUTEKCC, kccsrv_execute_kcc, service);
+ IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAGETINFO, kccsrv_replica_get_info, service);
}
/*