/*
startup a copy of smbd as a child daemon
*/
-static void s3fs_task_init(struct task_server *task)
+static NTSTATUS s3fs_task_init(struct task_server *task)
{
struct tevent_req *subreq;
const char *smbd_path;
if (!winbind_off()) {
DEBUG(0,("Failed to re-disable recursive winbindd calls after forking smbd\n"));
task_server_terminate(task, "Failed to re-disable recursive winbindd calls", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
if (subreq == NULL) {
DEBUG(0, ("Failed to start smbd as child daemon\n"));
task_server_terminate(task, "Failed to startup s3fs smb task", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
tevent_req_set_callback(subreq, file_server_smbd_done, task);
DEBUG(5,("Started file server child smbd\n"));
+
+ return NT_STATUS_OK;
}
/* called at smbd startup - register ourselves as a server service */
{
struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = s3fs_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "s3fs", s3fs_task_init, &details);
+ return register_server_service(ctx, "s3fs", &details);
}
/*
startup the cldapd task
*/
-static void cldapd_task_init(struct task_server *task)
+static NTSTATUS cldapd_task_init(struct task_server *task)
{
struct cldapd_server *cldapd;
NTSTATUS status;
if (iface_list_count(ifaces) == 0) {
task_server_terminate(task, "cldapd: no network interfaces configured", false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want an CLDAP server */
break;
cldapd = talloc(task, struct cldapd_server);
if (cldapd == NULL) {
task_server_terminate(task, "cldapd: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
cldapd->task = task;
0);
if (cldapd->samctx == NULL) {
task_server_terminate(task, "cldapd failed to open samdb", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
/* start listening on the configured network interfaces */
status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "cldapd failed to setup interfaces", true);
- return;
+ return status;
}
irpc_add_name(task->msg_ctx, "cldap_server");
+
+ return NT_STATUS_OK;
}
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = cldapd_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "cldap", cldapd_task_init,
- &details);
+ return register_server_service(ctx, "cldap", &details);
}
return NT_STATUS_OK;
}
-static void dns_task_init(struct task_server *task)
+static NTSTATUS dns_task_init(struct task_server *task)
{
struct dns_server *dns;
NTSTATUS status;
switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
task_server_terminate(task, "dns: no DNS required in standalone configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "dns: no DNS required in member server configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want a DNS */
break;
if (iface_list_count(ifaces) == 0) {
task_server_terminate(task, "dns: no network interfaces configured", false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
dns = talloc_zero(task, struct dns_server);
if (dns == NULL) {
task_server_terminate(task, "dns: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
dns->task = task;
dns->server_credentials = cli_credentials_init(dns);
if (!dns->server_credentials) {
task_server_terminate(task, "Failed to init server credentials\n", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
dns->samdb = samdb_connect(dns,
0);
if (!dns->samdb) {
task_server_terminate(task, "dns: samdb_connect failed", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
cli_credentials_set_conf(dns->server_credentials, task->lp_ctx);
TALLOC_FREE(dns_acc);
if (!dns_spn) {
task_server_terminate(task, "dns: talloc_asprintf failed", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
status = cli_credentials_set_stored_principal(dns->server_credentials, task->lp_ctx, dns_spn);
if (!NT_STATUS_IS_OK(status)) {
"despite finding it in the samdb! %s\n",
nt_errstr(status)),
true);
- return;
+ return status;
}
} else {
TALLOC_FREE(dns_spn);
talloc_asprintf(task, "Failed to obtain server credentials, perhaps a standalone server?: %s\n",
nt_errstr(status)),
true);
- return;
+ return status;
}
}
dns->tkeys = tkey_store_init(dns, TKEY_BUFFER_SIZE);
if (!dns->tkeys) {
task_server_terminate(task, "Failed to allocate tkey storage\n", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
status = dns_server_reload_zones(dns);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "dns: failed to load DNS zones", true);
- return;
+ return status;
}
status = dns_startup_interfaces(dns, ifaces, task->model_ops);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "dns failed to setup interfaces", true);
- return;
+ return status;
}
/* Setup the IRPC interface and register handlers */
status = irpc_add_name(task->msg_ctx, "dnssrv");
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "dns: failed to register IRPC name", true);
- return;
+ return status;
}
status = IRPC_REGISTER(task->msg_ctx, irpc, DNSSRV_RELOAD_DNS_ZONES,
dns_reload_zones, dns);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "dns: failed to setup reload handler", true);
- return;
+ return status;
}
+ return NT_STATUS_OK;
}
NTSTATUS server_service_dns_init(TALLOC_CTX *ctx)
static const struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
+ .task_init = dns_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "dns", dns_task_init, &details);
+ return register_server_service(ctx, "dns", &details);
}
/*
startup the dns update task
*/
-static void dnsupdate_task_init(struct task_server *task)
+static NTSTATUS dnsupdate_task_init(struct task_server *task)
{
NTSTATUS status;
struct dnsupdate_service *service;
if (lpcfg_server_role(task->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC) {
/* not useful for non-DC */
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
}
task_server_set_title(task, "task[dnsupdate]");
service = talloc_zero(task, struct dnsupdate_service);
if (!service) {
task_server_terminate(task, "dnsupdate_task_init: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
service->task = task;
task->private_data = service;
task_server_terminate(task,
"dnsupdate: Failed to obtain server credentials\n",
true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
service->samdb = samdb_connect(service,
if (!service->samdb) {
task_server_terminate(task, "dnsupdate: Failed to connect to local samdb\n",
true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
service->confupdate.interval = lpcfg_parm_int(task->lp_ctx, NULL,
task_server_terminate(task, talloc_asprintf(task,
"dnsupdate: Failed to confupdate schedule: %s\n",
nt_errstr(status)), true);
- return;
+ return status;
}
dnsupdate_check_names(service);
task_server_terminate(task, talloc_asprintf(task,
"dnsupdate: Failed to nameupdate schedule: %s\n",
nt_errstr(status)), true);
- return;
+ return status;
}
irpc_add_name(task->msg_ctx, "dnsupdate");
/* create the intial file */
dnsupdate_rebuild(service);
+ return NT_STATUS_OK;
}
static const struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
+ .task_init = dnsupdate_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "dnsupdate", dnsupdate_task_init,
- &details);
+ return register_server_service(ctx, "dnsupdate", &details);
}
/*
startup the kcc service task
*/
-static void kccsrv_task_init(struct task_server *task)
+static NTSTATUS kccsrv_task_init(struct task_server *task)
{
WERROR status;
struct kccsrv_service *service;
switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
task_server_terminate(task, "kccsrv: no KCC required in standalone configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "kccsrv: no KCC required in domain member configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want a KCC */
break;
service = talloc_zero(task, struct kccsrv_service);
if (!service) {
task_server_terminate(task, "kccsrv_task_init: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
service->task = task;
service->startup_time = timeval_current();
talloc_asprintf(task,
"kccsrv: Failed to obtain server credentials: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
status = kccsrv_connect_samdb(service, task->lp_ctx);
task_server_terminate(task, talloc_asprintf(task,
"kccsrv: Failed to connect to local samdb: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
status = kccsrv_load_partitions(service);
task_server_terminate(task, talloc_asprintf(task,
"kccsrv: Failed to load partitions: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
periodic_startup_interval =
task_server_terminate(task, talloc_asprintf(task,
"kccsrv: Failed to periodic schedule: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(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);
+ return NT_STATUS_OK;
}
/*
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = kccsrv_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "kcc", kccsrv_task_init, &details);
+ return register_server_service(ctx, "kcc", &details);
}
/*
startup the dsdb replicator service task
*/
-static void dreplsrv_task_init(struct task_server *task)
+static NTSTATUS dreplsrv_task_init(struct task_server *task)
{
WERROR status;
struct dreplsrv_service *service;
case ROLE_STANDALONE:
task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want DSDB replication */
break;
service = talloc_zero(task, struct dreplsrv_service);
if (!service) {
task_server_terminate(task, "dreplsrv_task_init: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
service->task = task;
service->startup_time = timeval_current();
task_server_terminate(task, talloc_asprintf(task,
"dreplsrv: Failed to obtain server credentials: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
status = dreplsrv_connect_samdb(service, task->lp_ctx);
task_server_terminate(task, talloc_asprintf(task,
"dreplsrv: Failed to connect to local samdb: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
status = dreplsrv_load_partitions(service);
task_server_terminate(task, talloc_asprintf(task,
"dreplsrv: Failed to load partitions: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
periodic_startup_interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */
task_server_terminate(task, talloc_asprintf(task,
"dreplsrv: Failed to periodic schedule: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
service->pending.im = tevent_create_immediate(service);
"dreplsrv: Failed to create immediate "
"task for future DsReplicaSync\n",
true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
/* if we are a RODC then we do not send DSReplicaSync*/
task_server_terminate(task, talloc_asprintf(task,
"dreplsrv: Failed to setup notify schedule: %s\n",
win_errstr(status)), true);
- return;
+ return werror_to_ntstatus(status);
}
}
IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service);
IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service);
imessaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid);
+
+ return NT_STATUS_OK;
}
/*
static const struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
+ .task_init = dreplsrv_task_init,
+ .post_fork = NULL,
};
- return register_server_service(ctx, "drepl", dreplsrv_task_init,
- &details);
+ return register_server_service(ctx, "drepl", &details);
}
/* Do the basic task initialization, check if the task should run */
-static void echo_task_init(struct task_server *task)
+static NTSTATUS echo_task_init(struct task_server *task)
{
struct interface *ifaces;
struct echo_server *echo;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "echo: Not starting echo server " \
"for domain members", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want to run the echo server */
break;
task_server_terminate(task,
"echo: No network interfaces configured",
false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
task_server_set_title(task, "task[echo]");
echo = talloc_zero(task, struct echo_server);
if (echo == NULL) {
task_server_terminate(task, "echo: Out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
echo->task = task;
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "echo: Failed to set up interfaces",
true);
- return;
+ return status;
}
+ return NT_STATUS_OK;
}
/*
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = echo_task_init,
+ .post_fork = NULL
+
};
- return register_server_service(ctx, "echo", echo_task_init, &details);
+ return register_server_service(ctx, "echo", &details);
}
/*
startup the kdc task
*/
-static void kdc_task_init(struct task_server *task)
+static NTSTATUS kdc_task_init(struct task_server *task)
{
struct kdc_server *kdc;
krb5_kdc_configuration *kdc_config = NULL;
switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
task_server_terminate(task, "kdc: no KDC required in standalone configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "kdc: no KDC required in member server configuration", false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
task_server_terminate(task, "Cannot start KDC as a 'classic Samba' DC", true);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want a KDC */
break;
if (iface_list_count(ifaces) == 0) {
task_server_terminate(task, "kdc: no network interfaces configured", false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
task_server_set_title(task, "task[kdc]");
kdc = talloc_zero(task, struct kdc_server);
if (kdc == NULL) {
task_server_terminate(task, "kdc: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
kdc->task = task;
if (!kdc->samdb) {
DEBUG(1,("kdc_task_init: unable to connect to samdb\n"));
task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc);
DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n",
ldb_errstring(kdc->samdb)));
task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5);
DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
error_message(ret)));
task_server_terminate(task, "kdc: krb5_init_context failed", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r);
&kdc_config);
if(ret) {
task_server_terminate(task, "kdc: failed to get KDC configuration", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
kdc_config->logf = (krb5_log_facility *)kdc->smb_krb5_context->pvt_log_data;
kdc_config->db = talloc(kdc, struct HDB *);
if (!kdc_config->db) {
task_server_terminate(task, "kdc: out of memory", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
kdc_config->num_db = 1;
kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
if (!kdc->base_ctx) {
task_server_terminate(task, "kdc: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
kdc->base_ctx->ev_ctx = task->event_ctx;
&kdc_config->db[0]);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
- return;
+ return status;
}
ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
&hdb_samba4_interface);
if(ret) {
task_server_terminate(task, "kdc: failed to register hdb plugin", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops);
if(ret) {
task_server_terminate(task, "kdc: failed to register keytab plugin", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx);
task_server_terminate(task,
"kdc: Failed to set keytab name",
true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
/* Register WinDC hooks */
&windc_plugin_table);
if(ret) {
task_server_terminate(task, "kdc: failed to register windc plugin", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context);
if(ret) {
task_server_terminate(task, "kdc: failed to init windc plugin", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc_config);
if(ret) {
task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
kdc->private_data = kdc_config;
task->model_ops);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "kdc failed to setup interfaces", true);
- return;
+ return status;
}
status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS,
kdc_check_generic_kerberos, kdc);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "kdc failed to setup monitoring", true);
- return;
+ return status;
}
irpc_add_name(task->msg_ctx, "kdc_server");
+
+ return NT_STATUS_OK;
}
* the master process is responsible for managing the worker
* processes not performing work.
*/
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = kdc_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "kdc", kdc_task_init, &details);
+ return register_server_service(ctx, "kdc", &details);
}
* the master process is responsible for managing the worker
* processes not performing work.
*/
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = mitkdc_task_init,
+ .post_fork = NULL
};
- return register_server_service(mem_ctx, "kdc", mitkdc_task_init,
- &details);
+ return register_server_service(mem_ctx, "kdc", &details);
}
/*
open the ldap server sockets
*/
-static void ldapsrv_task_init(struct task_server *task)
+static NTSTATUS ldapsrv_task_init(struct task_server *task)
{
char *ldapi_path;
#ifdef WITH_LDAPI_PRIV_SOCKET
case ROLE_STANDALONE:
task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration",
false);
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
/* Yes, we want an LDAP server */
break;
task_server_set_title(task, "task[ldapsrv]");
ldap_service = talloc_zero(task, struct ldapsrv_service);
- if (ldap_service == NULL) goto failed;
+ if (ldap_service == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
ldap_service->task = task;
dns_host_name = talloc_asprintf(ldap_service, "%s.%s",
lpcfg_netbios_name(task->lp_ctx),
lpcfg_dnsdomain(task->lp_ctx));
- if (dns_host_name == NULL) goto failed;
+ if (dns_host_name == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
status = tstream_tls_params_server(ldap_service,
dns_host_name,
}
ldap_service->call_queue = tevent_queue_create(ldap_service, "ldapsrv_call_queue");
- if (ldap_service->call_queue == NULL) goto failed;
+ if (ldap_service->call_queue == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
if (lpcfg_interfaces(task->lp_ctx) && lpcfg_bind_interfaces_only(task->lp_ctx)) {
struct interface *ifaces;
wcard = iface_list_wildcard(task);
if (wcard == NULL) {
DEBUG(0,("No wildcard addresses available\n"));
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
for (i=0; wcard[i]; i++) {
}
talloc_free(wcard);
if (num_binds == 0) {
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
}
ldapi_path = lpcfg_private_path(ldap_service, task->lp_ctx, "ldapi");
if (!ldapi_path) {
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
#ifdef WITH_LDAPI_PRIV_SOCKET
priv_dir = lpcfg_private_path(ldap_service, task->lp_ctx, "ldap_priv");
if (priv_dir == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
/*
if (!directory_create_or_exist(priv_dir, 0750)) {
task_server_terminate(task, "Cannot create ldap "
"privileged ldapi directory", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
ldapi_path = talloc_asprintf(ldap_service, "%s/ldapi", priv_dir);
talloc_free(priv_dir);
if (ldapi_path == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto failed;
}
/* register the server */
irpc_add_name(task->msg_ctx, "ldap_server");
- return;
+ return NT_STATUS_OK;
failed:
task_server_terminate(task, "Failed to startup ldap server task", true);
+ return status;
}
{
static const struct service_details details = {
.inhibit_fork_on_accept = false,
- .inhibit_pre_fork = false
+ .inhibit_pre_fork = false,
+ .task_init = ldapsrv_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "ldap", ldapsrv_task_init,
- &details);
+ return register_server_service(ctx, "ldap", &details);
}
/*
startup the nbtd task
*/
-static void nbtd_task_init(struct task_server *task)
+static NTSTATUS nbtd_task_init(struct task_server *task)
{
struct nbtd_server *nbtsrv;
NTSTATUS status;
if (iface_list_count(ifaces) == 0) {
task_server_terminate(task, "nbtd: no network interfaces configured", false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
if (lpcfg_disable_netbios(task->lp_ctx)) {
task_server_terminate(task, "nbtd: 'disable netbios = yes' set in smb.conf, shutting down nbt server", false);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
task_server_set_title(task, "task[nbtd]");
nbtsrv = talloc(task, struct nbtd_server);
if (nbtsrv == NULL) {
task_server_terminate(task, "nbtd: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
nbtsrv->task = task;
status = nbtd_startup_interfaces(nbtsrv, task->lp_ctx, ifaces);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "nbtd failed to setup interfaces", true);
- return;
+ return status;
}
nbtsrv->sam_ctx = samdb_connect(nbtsrv,
0);
if (nbtsrv->sam_ctx == NULL) {
task_server_terminate(task, "nbtd failed to open samdb", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
/* start the WINS server, if appropriate */
status = nbtd_winsserver_init(nbtsrv);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "nbtd failed to start WINS server", true);
- return;
+ return status;
}
nbtd_register_irpc(nbtsrv);
nbtd_register_names(nbtsrv);
irpc_add_name(task->msg_ctx, "nbt_server");
+
+ return NT_STATUS_OK;
}
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = nbtd_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "nbt", nbtd_task_init, &details);
+ return register_server_service(ctx, "nbt", &details);
}
/*
startup the ntp_signd task
*/
-static void ntp_signd_task_init(struct task_server *task)
+static NTSTATUS ntp_signd_task_init(struct task_server *task)
{
struct ntp_signd_server *ntp_signd;
NTSTATUS status;
lpcfg_ntp_signd_socket_directory(task->lp_ctx));
task_server_terminate(task,
error, true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
task_server_set_title(task, "task[ntp_signd]");
ntp_signd = talloc(task, struct ntp_signd_server);
if (ntp_signd == NULL) {
task_server_terminate(task, "ntp_signd: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
ntp_signd->task = task;
0);
if (ntp_signd->samdb == NULL) {
task_server_terminate(task, "ntp_signd failed to open samdb", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
address = talloc_asprintf(ntp_signd, "%s/socket", lpcfg_ntp_signd_socket_directory(task->lp_ctx));
+ if (address == NULL) {
+ task_server_terminate(
+ task, "ntp_signd out of memory in talloc_asprintf()", true);
+ return NT_STATUS_NO_MEMORY;
+ }
status = stream_setup_socket(ntp_signd->task,
ntp_signd->task->event_ctx,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("Failed to bind to %s - %s\n",
address, nt_errstr(status)));
- return;
+ return status;
}
+ return NT_STATUS_OK;
+
}
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = ntp_signd_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "ntp_signd", ntp_signd_task_init,
- &details);
+ return register_server_service(ctx, "ntp_signd", &details);
}
/*
open the dcerpc server sockets
*/
-static void dcesrv_task_init(struct task_server *task)
+static NTSTATUS dcesrv_task_init(struct task_server *task)
{
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
struct dcesrv_context *dce_ctx;
struct dcesrv_endpoint *e;
const struct model_ops *single_model_ops;
}
irpc_add_name(task->msg_ctx, "rpc_server");
- return;
+ return NT_STATUS_OK;
failed:
task_server_terminate(task, "Failed to startup dcerpc server task", true);
+ return status;
}
NTSTATUS server_service_rpc_init(TALLOC_CTX *ctx)
* mode by defult to get a forking NETLOGON server
*/
.inhibit_fork_on_accept = false,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = dcesrv_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "rpc", dcesrv_task_init, &details);
+ return register_server_service(ctx, "rpc", &details);
}
/*
open the smb server sockets
*/
-static void smbsrv_task_init(struct task_server *task)
+static NTSTATUS smbsrv_task_init(struct task_server *task)
{
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
task_server_set_title(task, "task[smbsrv]");
wcard = iface_list_wildcard(task);
if (wcard == NULL) {
DEBUG(0,("No wildcard addresses available\n"));
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
for (i=0; wcard[i]; i++) {
}
irpc_add_name(task->msg_ctx, "smb_server");
- return;
+ return NT_STATUS_OK;
failed:
task_server_terminate(task, "Failed to startup smb server task", true);
+ return status;
}
/* called at smbd startup - register ourselves as a server service */
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = smbsrv_task_init,
+ .post_fork = NULL
};
ntvfs_init(cmdline_lp_ctx);
share_init();
- return register_server_service(ctx, "smb", smbsrv_task_init, &details);
+ return register_server_service(ctx, "smb", &details);
}
void (*new_task)(struct tevent_context *,
struct loadparm_context *lp_ctx,
const char *service_name,
- void (*)(struct tevent_context *,
+ struct task_server * (*)(struct tevent_context *,
struct loadparm_context *, struct server_id,
void *, void *),
void *,
struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *service_name,
- void (*new_task_fn)(struct tevent_context *,
+ struct task_server *(*new_task_fn)(struct tevent_context *,
struct loadparm_context *lp_ctx,
struct server_id , void *, void *),
void *private_data,
int i, num_children;
struct tevent_context *ev2;
+ struct task_server *task = NULL;
t = tfork_create();
if (t == NULL) {
setup_handlers(ev, from_parent_fd);
if (service_details->inhibit_pre_fork) {
- new_task_fn(ev, lp_ctx, cluster_id(pid, 0), private_data, NULL);
- /* The task does not support pre-fork */
+ task = new_task_fn(
+ ev, lp_ctx, cluster_id(pid, 0), private_data, NULL);
+ /*
+ * The task does not support pre-fork
+ */
+ if (task != NULL && service_details->post_fork != NULL) {
+ service_details->post_fork(task);
+ }
tevent_loop_wait(ev);
TALLOC_FREE(ev);
exit(0);
* process accepting and handling requests, it's responsible for
* monitoring and controlling the child work processes.
*/
- new_task_fn(ev2, lp_ctx, cluster_id(pid, 0), private_data, NULL);
+ task = new_task_fn(ev2, lp_ctx, cluster_id(pid, 0), private_data, NULL);
+ if (task == NULL) {
+ TALLOC_FREE(ev);
+ TALLOC_FREE(ev2);
+ exit(0);
+ }
{
int default_children;
}
DBG_NOTICE("Forking %d %s worker processes\n",
num_children, service_name);
- /* We are now free to spawn some worker processes */
+ /*
+ * We are now free to spawn some worker processes
+ */
for (i=0; i < num_children; i++) {
struct tfork* w = NULL;
}
tevent_fd_set_auto_close(fde);
} else {
- /* tfork uses malloc */
+ /*
+ * tfork uses malloc
+ */
free(w);
TALLOC_FREE(ev);
service_name);
prefork_reload_after_fork();
setup_handlers(ev2, from_parent_fd);
+ if (service_details->post_fork != NULL) {
+ service_details->post_fork(task);
+ }
tevent_loop_wait(ev2);
talloc_free(ev2);
exit(0);
static void single_new_task(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *service_name,
- void (*new_task)(struct tevent_context *,
+ struct task_server *(*new_task)(struct tevent_context *,
struct loadparm_context *,
struct server_id, void *, void *),
void *private_data,
pid_t pid = getpid();
/* start our taskids at MAX_INT32, the first 2^31 tasks are is reserved for fd numbers */
static uint32_t taskid = INT32_MAX;
-
+ struct task_server *task = NULL;
/*
* We use the PID so we cannot collide in with cluster ids
* generated in other single mode tasks, and, and won't
* Using the pid unaltered makes debugging of which process
* owns the messaging socket easier.
*/
- new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data, NULL);
+ task = new_task(ev, lp_ctx, cluster_id(pid, taskid++), private_data, NULL);
+ if (task != NULL && service_details->post_fork != NULL) {
+ service_details->post_fork(task);
+ }
}
static void standard_new_task(struct tevent_context *ev,
struct loadparm_context *lp_ctx,
const char *service_name,
- void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *),
+ struct task_server *(*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *),
void *private_data,
const struct service_details *service_details,
int from_parent_fd)
struct tevent_fd *fde = NULL;
struct tevent_signal *se = NULL;
struct process_context *proc_ctx = NULL;
+ struct task_server* task = NULL;
state = setup_standard_child_pipe(ev, service_name);
if (state == NULL) {
proc_ctx->forked_on_accept = false;
/* setup this new task. Cluster ID is PID based for this process model */
- new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx);
+ task = new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx);
+ /*
+ * Currently we don't support the post_fork functionality in the
+ * standard model, i.e. it is only called here not after a new process
+ * is forked in standard_accept_connection.
+ */
+ if (task != NULL && service_details->post_fork != NULL) {
+ service_details->post_fork(task);
+ }
+
/* we can't return to the top level here, as that event context is gone,
so we now process events in the new event context until there are no
static struct registered_server {
struct registered_server *next, *prev;
const char *service_name;
- struct service_details *service_details;
- void (*task_init)(struct task_server *);
+ const struct service_details *service_details;
} *registered_servers;
/*
*/
NTSTATUS register_server_service(TALLOC_CTX *ctx,
const char *name,
- void (*task_init) (struct task_server *),
const struct service_details *details)
{
struct registered_server *srv;
srv = talloc(ctx, struct registered_server);
NT_STATUS_HAVE_NO_MEMORY(srv);
srv->service_name = name;
- srv->task_init = task_init;
srv->service_details =
talloc_memdup(ctx, details, sizeof(struct service_details));
NT_STATUS_HAVE_NO_MEMORY(srv->service_details);
return task_server_startup(event_context, lp_ctx,
srv->service_name,
model_ops,
- srv->task_init,
srv->service_details,
from_parent_fd);
}
* processes. In this mode pre-fork is equivalent to standard with
* inhibit_fork_on_accept set.
*/
- bool inhibit_pre_fork;
+ bool inhibit_pre_fork;
+ /*
+ * Initialise the server task.
+ */
+ NTSTATUS (*task_init) (struct task_server *);
+ /*
+ * post fork processing this is called:
+ * - standard process model
+ * immediately after the task_init.
+ *
+ * - single process model
+ * immediately after the task_init
+ *
+ * - prefork process model, inhibit_pre_fork = true
+ * immediately after the task_init
+ *
+ * - prefork process model, inhibit_pre_fork = false
+ * after each service worker has forked. It is not run on the
+ * service master process.
+ *
+ * The post fork hook is not called in the standard model if a new
+ * process is forked on a new connection. It is instead called
+ * immediately after the task_init.
+ */
+ void (*post_fork) (struct task_server *);
};
#include "smbd/service_proto.h"
/* used for the callback from the process model code */
struct task_state {
- void (*task_init)(struct task_server *);
+ const struct service_details *service_details;
const struct model_ops *model_ops;
};
called by the process model code when the new task starts up. This then calls
the server specific startup code
*/
-static void task_server_callback(struct tevent_context *event_ctx,
+static struct task_server *task_server_callback(struct tevent_context *event_ctx,
struct loadparm_context *lp_ctx,
struct server_id server_id,
void *private_data,
void *context)
{
- struct task_state *state = talloc_get_type(private_data, struct task_state);
struct task_server *task;
+ NTSTATUS status = NT_STATUS_OK;
+ struct task_state *state = talloc_get_type(private_data, struct task_state);
task = talloc(event_ctx, struct task_server);
- if (task == NULL) return;
+ if (task == NULL) return NULL;
task->event_ctx = event_ctx;
task->model_ops = state->model_ops;
task->event_ctx);
if (!task->msg_ctx) {
task_server_terminate(task, "imessaging_init() failed", true);
- return;
+ return NULL;
}
- state->task_init(task);
+ status = state->service_details->task_init(task);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+ return task;
}
/*
struct loadparm_context *lp_ctx,
const char *service_name,
const struct model_ops *model_ops,
- void (*task_init)(struct task_server *),
const struct service_details *service_details,
int from_parent_fd)
{
state = talloc(event_ctx, struct task_state);
NT_STATUS_HAVE_NO_MEMORY(state);
- state->task_init = task_init;
+ state->service_details = service_details;
state->model_ops = model_ops;
state->model_ops->new_task(event_ctx, lp_ctx, service_name,
/*
startup the web server task
*/
-static void websrv_task_init(struct task_server *task)
+static NTSTATUS websrv_task_init(struct task_server *task)
{
NTSTATUS status;
uint16_t port = lpcfg_web_port(task->lp_ctx);
/* startup the Python processor - unfortunately we can't do this
per connection as that wouldn't allow for session variables */
wdata = talloc_zero(task, struct web_server_data);
- if (wdata == NULL) goto failed;
+ if (wdata == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
wdata->task = task;
task->private_data = wdata;
wcard = iface_list_wildcard(task);
if (wcard == NULL) {
DEBUG(0,("No wildcard addresses available\n"));
+ status = NT_STATUS_UNSUCCESSFUL;
goto failed;
}
for (i=0; wcard[i]; i++) {
}
wdata->tls_params = tls_initialise(wdata, task->lp_ctx);
- if (wdata->tls_params == NULL) goto failed;
+ if (wdata->tls_params == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto failed;
+ }
- if (!wsgi_initialize(wdata)) goto failed;
+ if (!wsgi_initialize(wdata)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto failed;
+ }
- return;
+ return NT_STATUS_OK;
failed:
task_server_terminate(task, "websrv_task_init: failed to startup web server task", true);
+ return status;
}
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = websrv_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "web", websrv_task_init, &details);
+ return register_server_service(ctx, "web", &details);
}
/*
startup a copy of winbindd as a child daemon
*/
-static void winbindd_task_init(struct task_server *task)
+static NTSTATUS winbindd_task_init(struct task_server *task)
{
struct tevent_req *subreq;
const char *winbindd_path;
if (subreq == NULL) {
DEBUG(0, ("Failed to start winbindd as child daemon\n"));
task_server_terminate(task, "Failed to startup winbindd task", true);
- return;
+ return NT_STATUS_UNSUCCESSFUL;
}
tevent_req_set_callback(subreq, winbindd_done, task);
DEBUG(5,("Started winbindd as a child daemon\n"));
+ return NT_STATUS_OK;
}
/* called at winbindd startup - register ourselves as a server service */
static const struct service_details details = {
.inhibit_fork_on_accept = true,
.inhibit_pre_fork = true,
+ .task_init = winbindd_task_init,
+ .post_fork = NULL
};
- NTSTATUS status = register_server_service(ctx, "winbindd",
- winbindd_task_init, &details);
+ NTSTATUS status = register_server_service(ctx, "winbindd", &details);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return register_server_service(ctx, "winbind", winbindd_task_init,
- &details);
+ return register_server_service(ctx, "winbind", &details);
}
/*
startup the wrepl task
*/
-static void wreplsrv_task_init(struct task_server *task)
+static NTSTATUS wreplsrv_task_init(struct task_server *task)
{
NTSTATUS status;
struct wreplsrv_service *service;
if (!lpcfg_we_are_a_wins_server(task->lp_ctx)) {
- return;
+ return NT_STATUS_INVALID_DOMAIN_ROLE;
}
task_server_set_title(task, "task[wreplsrv]");
service = talloc_zero(task, struct wreplsrv_service);
if (!service) {
task_server_terminate(task, "wreplsrv_task_init: out of memory", true);
- return;
+ return NT_STATUS_NO_MEMORY;
}
service->task = task;
service->startup_time = timeval_current();
status = wreplsrv_open_winsdb(service, task->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "wreplsrv_task_init: wreplsrv_open_winsdb() failed", true);
- return;
+ return status;
}
/*
status = wreplsrv_setup_partners(service);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_partners() failed", true);
- return;
+ return status;
}
/*
status = wreplsrv_setup_sockets(service, task->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_sockets() failed", true);
- return;
+ return status;
}
status = wreplsrv_setup_periodic(service);
if (!NT_STATUS_IS_OK(status)) {
task_server_terminate(task, "wreplsrv_task_init: wreplsrv_setup_periodic() failed", true);
- return;
+ return status;
}
irpc_add_name(task->msg_ctx, "wrepl_server");
+
+ return NT_STATUS_OK;
}
/*
{
static const struct service_details details = {
.inhibit_fork_on_accept = true,
- .inhibit_pre_fork = true
+ .inhibit_pre_fork = true,
+ .task_init = wreplsrv_task_init,
+ .post_fork = NULL
};
- return register_server_service(ctx, "wrepl", wreplsrv_task_init,
- &details);
+ return register_server_service(ctx, "wrepl", &details);
}