From 9593101ec118dd242bf25fabf3e17c58269e632c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 25 Sep 2005 21:01:56 +0000 Subject: r10491: First step towards wbinfo -t: This issues a name request for the primary domain and gets the DC's name via a mailslot call. Metze, I renamed wbsrv_queue_reply to wbsrv_send_reply in accordance with irpc_send_reply. Having _queue_ here and _send_ there is a bit confusing. And as everything is async anyway, the semantics should not be too much of a problem. Volker (This used to be commit 4637964b19c6e9f7d201b287e2d409d029fced01) --- source4/include/structs.h | 2 + source4/libcli/dgram/libdgram.h | 1 + source4/libcli/dgram/ntlogon.c | 3 +- source4/librpc/idl/irpc.idl | 12 +- source4/nbt_server/nbt_server.c | 119 ++++++++++++++++++++ source4/passdb/secrets.c | 43 ++++++++ source4/torture/nbt/dgram.c | 3 +- source4/winbind/config.mk | 3 +- source4/winbind/wb_async_helpers.c | 206 +++++++++++++++++++++++++++++++++++ source4/winbind/wb_async_helpers.h | 36 ++++++ source4/winbind/wb_samba3_cmd.c | 64 +++++++++++ source4/winbind/wb_samba3_protocol.c | 3 + source4/winbind/wb_server.c | 4 +- source4/winbind/wb_server.h | 21 ++-- 14 files changed, 504 insertions(+), 16 deletions(-) create mode 100644 source4/winbind/wb_async_helpers.c create mode 100644 source4/winbind/wb_async_helpers.h diff --git a/source4/include/structs.h b/source4/include/structs.h index bc37b0dec6..ca28c1fc7a 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -252,6 +252,8 @@ struct nbtd_server; struct nbtd_interface; struct wins_server; +struct wb_finddcs; + struct cldap_socket; struct cldapd_server; diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h index b9dfe84996..5bddd220d0 100644 --- a/source4/libcli/dgram/libdgram.h +++ b/source4/libcli/dgram/libdgram.h @@ -137,6 +137,7 @@ NTSTATUS dgram_mailslot_netlogon_parse(struct dgram_mailslot_handler *dgmslot, struct nbt_netlogon_packet *netlogon); NTSTATUS dgram_mailslot_ntlogon_send(struct nbt_dgram_socket *dgmsock, + enum dgram_msg_type msg_type, struct nbt_name *dest_name, const char *dest_address, int dest_port, diff --git a/source4/libcli/dgram/ntlogon.c b/source4/libcli/dgram/ntlogon.c index 03d1266af0..efa5d4ab9e 100644 --- a/source4/libcli/dgram/ntlogon.c +++ b/source4/libcli/dgram/ntlogon.c @@ -32,6 +32,7 @@ send a ntlogon mailslot request */ NTSTATUS dgram_mailslot_ntlogon_send(struct nbt_dgram_socket *dgmsock, + enum dgram_msg_type msg_type, struct nbt_name *dest_name, const char *dest_address, int dest_port, @@ -50,7 +51,7 @@ NTSTATUS dgram_mailslot_ntlogon_send(struct nbt_dgram_socket *dgmsock, } - status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE, + status = dgram_mailslot_send(dgmsock, msg_type, NBT_MAILSLOT_NTLOGON, dest_name, dest_address, dest_port, src_name, &blob); diff --git a/source4/librpc/idl/irpc.idl b/source4/librpc/idl/irpc.idl index dabf278e73..1c4b8d2c53 100644 --- a/source4/librpc/idl/irpc.idl +++ b/source4/librpc/idl/irpc.idl @@ -6,7 +6,8 @@ [ uuid("e770c620-0b06-4b5e-8d87-a26e20f28340"), version(1.0), pointer_default(unique), - pointer_default_top(unique) + pointer_default_top(unique), + depends(security) ] interface irpc { typedef bitmap { @@ -51,6 +52,15 @@ [out,switch_is(level)] nbtd_info info ); + void nbtd_getdcname( + [in] astring domainname, + [in] astring ip_address, + [in] astring my_computername, + [in] astring my_accountname, + [in] uint32 account_control, + [in,ref] dom_sid *domain_sid, + [out] astring dcname + ); /****************************************************** management calls for the smb server diff --git a/source4/nbt_server/nbt_server.c b/source4/nbt_server/nbt_server.c index 2119610988..83a7ae8a2f 100644 --- a/source4/nbt_server/nbt_server.c +++ b/source4/nbt_server/nbt_server.c @@ -43,6 +43,116 @@ static NTSTATUS nbtd_information(struct irpc_message *msg, return NT_STATUS_OK; } +struct getdc_state { + struct irpc_message *msg; + struct nbtd_getdcname *req; +}; + +static void getdc_recv_ntlogon_reply(struct dgram_mailslot_handler *dgmslot, + struct nbt_dgram_packet *packet, + const char *src_address, int src_port) +{ + struct getdc_state *s = + talloc_get_type(dgmslot->private, struct getdc_state); + + struct nbt_ntlogon_packet ntlogon; + NTSTATUS status; + + status = dgram_mailslot_ntlogon_parse(dgmslot, packet, packet, + &ntlogon); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("dgram_mailslot_ntlogon_parse failed: %s\n", + nt_errstr(status))); + goto done; + } + + status = NT_STATUS_NO_LOGON_SERVERS; + + DEBUG(10, ("reply: command=%d\n", ntlogon.command)); + + switch (ntlogon.command) { + case NTLOGON_SAM_LOGON: + DEBUG(0, ("Huh -- got NTLOGON_SAM_LOGON as reply\n")); + break; + case NTLOGON_SAM_LOGON_REPLY: + DEBUG(10, ("NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, " + "domain: %s\n", ntlogon.req.reply.server, + ntlogon.req.reply.user_name, + ntlogon.req.reply.domain)); + s->req->out.dcname = + talloc_strdup(s->req, ntlogon.req.reply.server); + if (s->req->out.dcname == NULL) { + DEBUG(0, ("talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto done; + } + status = NT_STATUS_OK; + break; + default: + DEBUG(0, ("Got unknown packet: %d\n", ntlogon.command)); + break; + } + + done: + irpc_send_reply(s->msg, status); +} + +static NTSTATUS nbtd_getdcname(struct irpc_message *msg, + struct nbtd_getdcname *req) +{ + struct nbtd_server *server = + talloc_get_type(msg->private, struct nbtd_server); + + struct getdc_state *s; + struct nbt_ntlogon_packet p; + struct nbt_ntlogon_sam_logon *r; + struct nbt_dgram_socket *sock; + struct nbt_name src, dst; + struct dgram_mailslot_handler *handler; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + + DEBUG(0, ("nbtd_getdcname called\n")); + + sock = server->interfaces[0].dgmsock; + + s = talloc(msg, struct getdc_state); + NT_STATUS_HAVE_NO_MEMORY(s); + + s->msg = msg; + s->req = req; + + handler = dgram_mailslot_temp(sock, NBT_MAILSLOT_GETDC, + getdc_recv_ntlogon_reply, s); + NT_STATUS_HAVE_NO_MEMORY(handler); + + ZERO_STRUCT(p); + p.command = NTLOGON_SAM_LOGON; + r = &p.req.logon; + r->request_count = 0; + r->computer_name = req->in.my_computername; + r->user_name = req->in.my_accountname; + r->mailslot_name = handler->mailslot_name; + r->acct_control = req->in.account_control; + r->sid = *req->in.domain_sid; + r->nt_version = 1; + r->lmnt_token = 0xffff; + r->lm20_token = 0xffff; + + make_nbt_name_client(&src, req->in.my_computername); + make_nbt_name(&dst, req->in.domainname, 0x1c); + + status = dgram_mailslot_ntlogon_send(sock, DGRAM_DIRECT_GROUP, + &dst, req->in.ip_address, 138, + &src, &p); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("dgram_mailslot_ntlogon_send failed: %s\n", + nt_errstr(status))); + return status; + } + + msg->defer_reply = True; + return NT_STATUS_OK; +} /* @@ -91,6 +201,15 @@ static void nbtd_task_init(struct task_server *task) return; } + /* Setup handler for getdcname call */ + status = IRPC_REGISTER(task->msg_ctx, irpc, NBTD_GETDCNAME, + nbtd_getdcname, nbtsrv); + if (!NT_STATUS_IS_OK(status)) { + task_server_terminate(task, "nbtd failed to setup getdcname " + "handler"); + return; + } + /* start the process of registering our names on all interfaces */ nbtd_register_names(nbtsrv); diff --git a/source4/passdb/secrets.c b/source4/passdb/secrets.c index 356847c6ee..13f82f61fd 100644 --- a/source4/passdb/secrets.c +++ b/source4/passdb/secrets.c @@ -28,6 +28,7 @@ #include "system/filesys.h" #include "pstring.h" #include "db_wrap.h" +#include "lib/ldb/include/ldb.h" static struct tdb_wrap *tdb; @@ -153,3 +154,45 @@ struct ldb_context *secrets_db_connect(TALLOC_CTX *mem_ctx) return ldb; } +struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx, + const char *domain) +{ + struct ldb_context *ldb; + struct ldb_message **msgs; + int ldb_ret; + const char *attrs[] = { "objectSid", NULL }; + struct dom_sid *result = NULL; + + ldb = secrets_db_connect(mem_ctx); + if (ldb == NULL) { + DEBUG(5, ("secrets_db_connect failed\n")); + goto done; + } + + ldb_ret = gendb_search(ldb, ldb, + ldb_dn_explode(mem_ctx, SECRETS_PRIMARY_DOMAIN_DN), + &msgs, attrs, + SECRETS_PRIMARY_DOMAIN_FILTER, domain); + + if (ldb_ret == 0) { + DEBUG(5, ("Did not find domain record for %s\n", domain)); + goto done; + } + + if (ldb_ret > 1) { + DEBUG(5, ("Found more than one (%d) domain records for %s\n", + ldb_ret, domain)); + goto done; + } + + result = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid"); + if (result == NULL) { + DEBUG(0, ("Domain object for %s does not contain a SID!\n", + domain)); + goto done; + } + + done: + talloc_free(ldb); + return result; +} diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c index 0df2fd8a70..b3249524ca 100644 --- a/source4/torture/nbt/dgram.c +++ b/source4/torture/nbt/dgram.c @@ -255,7 +255,8 @@ static BOOL nbt_test_ntlogon(TALLOC_CTX *mem_ctx, make_nbt_name_client(&myname, TEST_NAME); - status = dgram_mailslot_ntlogon_send(dgmsock, &name, address, + status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE, + &name, address, 0, &myname, &logon); if (!NT_STATUS_IS_OK(status)) { printf("Failed to send ntlogon request - %s\n", nt_errstr(status)); diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk index dea0782575..5f055768c0 100644 --- a/source4/winbind/config.mk +++ b/source4/winbind/config.mk @@ -8,7 +8,8 @@ SUBSYSTEM = SERVER_SERVICE INIT_OBJ_FILES = \ winbind/wb_server.o \ winbind/wb_samba3_protocol.o \ - winbind/wb_samba3_cmd.o + winbind/wb_samba3_cmd.o \ + winbind/wb_async_helpers.o REQUIRED_SUBSYSTEMS = # End MODULE server_service_winbind ################################################ diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c new file mode 100644 index 0000000000..17efd06c81 --- /dev/null +++ b/source4/winbind/wb_async_helpers.c @@ -0,0 +1,206 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + a composite API for finding a DC and its name +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" +#include "winbind/wb_async_helpers.h" + +#include "librpc/gen_ndr/nbt.h" +#include "librpc/gen_ndr/samr.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/irpc.h" +#include "librpc/gen_ndr/ndr_irpc.h" + +struct finddcs_state { + struct wb_finddcs *io; + struct composite_context *creq; + + struct nbtd_getdcname *r; + struct irpc_request *ireq; +}; + +static void finddcs_getdc(struct irpc_request *req) +{ + struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context); + struct finddcs_state *state = + talloc_get_type(c->private, struct finddcs_state); + + c->status = irpc_call_recv(req); + if (!NT_STATUS_IS_OK(c->status)) { + goto done; + } + + state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs, + state->r->out.dcname); + + c->status = NT_STATUS_OK; + c->state = SMBCLI_REQUEST_DONE; + + done: + if (!NT_STATUS_IS_OK(c->status)) { + c->state = SMBCLI_REQUEST_ERROR; + } + + if (c->state >= SMBCLI_REQUEST_DONE && + c->async.fn) { + c->async.fn(c); + } +} + +/* + called when name resolution is finished +*/ +static void finddcs_resolve(struct composite_context *res_ctx) +{ + struct composite_context *c = talloc_get_type(res_ctx->async.private, + struct composite_context); + struct finddcs_state *state = + talloc_get_type(c->private, struct finddcs_state); + uint32_t *nbt_servers; + + state->io->out.num_dcs = 1; + state->io->out.dcs = talloc_array(state, struct nbt_dc_name, + state->io->out.num_dcs); + if (state->io->out.dcs == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto done; + } + + c->status = resolve_name_recv(res_ctx, state->io->out.dcs, + &state->io->out.dcs[0].address); + if (!NT_STATUS_IS_OK(c->status)) { + goto done; + } + + nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server"); + if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) { + c->status = NT_STATUS_NO_LOGON_SERVERS; + goto done; + } + + state->r = talloc(state, struct nbtd_getdcname); + if (state->r == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto done; + } + + state->r->in.domainname = talloc_strdup(state->r, lp_workgroup()); + state->r->in.ip_address = state->io->out.dcs[0].address; + state->r->in.my_computername = lp_netbios_name(); + state->r->in.my_accountname = talloc_asprintf(state->r, "%s$", + lp_netbios_name()); + state->r->in.account_control = ACB_WSTRUST; + state->r->in.domain_sid = secrets_get_domain_sid(state->r, + lp_workgroup()); + + if ((state->r->in.domainname == NULL) || + (state->r->in.my_accountname == NULL)) { + DEBUG(0, ("talloc failed\n")); + c->status = NT_STATUS_NO_MEMORY; + goto done; + } + if (state->r->in.domain_sid == NULL) { + c->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + + state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0], + &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME, + state->r, state); + + if (state->ireq == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto done; + } + + c->status = NT_STATUS_OK; + state->ireq->async.fn = finddcs_getdc; + state->ireq->async.private = c; + + done: + if (!NT_STATUS_IS_OK(c->status)) { + c->state = SMBCLI_REQUEST_ERROR; + } + + if (c->state >= SMBCLI_REQUEST_DONE && + c->async.fn) { + c->async.fn(c); + } +} + +struct composite_context *wb_finddcs_send(struct wb_finddcs *io, + struct event_context *event_ctx) +{ + struct composite_context *c; + struct finddcs_state *state; + struct nbt_name name; + + c = talloc_zero(NULL, struct composite_context); + if (c == NULL) goto failed; + c->state = SMBCLI_REQUEST_SEND; + c->event_ctx = event_ctx; + + state = talloc(c, struct finddcs_state); + if (state == NULL) goto failed; + + state->io = io; + + make_nbt_name(&name, io->in.domain, 0x1c); + state->creq = resolve_name_send(&name, c->event_ctx, + lp_name_resolve_order()); + + if (state->creq == NULL) goto failed; + state->creq->async.private = c; + state->creq->async.fn = finddcs_resolve; + c->private = state; + + return c; +failed: + talloc_free(c); + return NULL; +} + +NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status; + + status = composite_wait(c); + + if (NT_STATUS_IS_OK(status)) { + struct finddcs_state *state = + talloc_get_type(c->private, struct finddcs_state); + talloc_steal(mem_ctx, state->io->out.dcs); + } + + talloc_free(c); + return status; +} + +NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx, + struct event_context *ev) +{ + struct composite_context *c = wb_finddcs_send(io, ev); + return wb_finddcs_recv(c, mem_ctx); +} diff --git a/source4/winbind/wb_async_helpers.h b/source4/winbind/wb_async_helpers.h new file mode 100644 index 0000000000..6c4f1d84a8 --- /dev/null +++ b/source4/winbind/wb_async_helpers.h @@ -0,0 +1,36 @@ +/* + Unix SMB/CIFS implementation. + + SMB composite request interfaces + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +struct wb_finddcs { + struct { + struct messaging_context *msg_ctx; + const char *domain; + } in; + + struct { + int num_dcs; + struct nbt_dc_name { + const char *address; + const char *name; + } *dcs; + } out; +}; diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c index 14e9ac9e6d..4ff54e25b4 100644 --- a/source4/winbind/wb_samba3_cmd.c +++ b/source4/winbind/wb_samba3_cmd.c @@ -26,6 +26,10 @@ #include "nsswitch/winbindd_nss.h" #include "winbind/wb_server.h" #include "winbind/wb_samba3_protocol.h" +#include "winbind/wb_async_helpers.h" +#include "librpc/gen_ndr/nbt.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/composite/composite.h" NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call) { @@ -48,3 +52,63 @@ NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call) s3call->response.result = WINBINDD_OK; return NT_STATUS_OK; } + +struct check_machacc_state { + struct wb_finddcs *io; +}; + +static void wbsrv_samba3_check_machacc_reply(struct composite_context *action) +{ + struct wbsrv_samba3_call *s3call = + talloc_get_type(action->async.private, + struct wbsrv_samba3_call); + struct check_machacc_state *state = + talloc_get_type(s3call->private_data, + struct check_machacc_state); + NTSTATUS status; + + status = wb_finddcs_recv(action, s3call); + if (NT_STATUS_IS_OK(status)) { + DEBUG(10, ("Got name %s\n", state->io->out.dcs[0].name)); + s3call->response.result = WINBINDD_OK; + } else { + DEBUG(10, ("Got no addr: %s\n", nt_errstr(status))); + s3call->response.result = WINBINDD_ERROR; + } + + status = wbsrv_send_reply(s3call->call); + if (!NT_STATUS_IS_OK(status)) { + wbsrv_terminate_connection(s3call->call->wbconn, + "wbsrv_queue_reply() failed"); + return; + } +} + +NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call) +{ + struct composite_context *resolve_req; + struct check_machacc_state *state; + + DEBUG(5, ("check_machacc called\n")); + + state = talloc(s3call, struct check_machacc_state); + NT_STATUS_HAVE_NO_MEMORY(state); + + state->io = talloc(s3call, struct wb_finddcs); + NT_STATUS_HAVE_NO_MEMORY(state->io); + s3call->private_data = state; + + state->io->in.msg_ctx = s3call->call->wbconn->conn->msg_ctx; + state->io->in.domain = lp_workgroup(); + + resolve_req = wb_finddcs_send(state->io, s3call->call->event_ctx); + NT_STATUS_HAVE_NO_MEMORY(resolve_req); + + /* setup the callbacks */ + resolve_req->async.fn = wbsrv_samba3_check_machacc_reply; + resolve_req->async.private = s3call; + + /* tell the caller we reply later */ + s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; + return NT_STATUS_OK; +} diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index a5ad66ae16..4519f89540 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -77,6 +77,9 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_call *call) case WINBINDD_PING: return wbsrv_samba3_ping(s3call); + + case WINBINDD_CHECK_MACHACC: + return wbsrv_samba3_check_machacc(s3call); } s3call->response.result = WINBINDD_ERROR; diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c index d8d8f19465..e18ea16662 100644 --- a/source4/winbind/wb_server.c +++ b/source4/winbind/wb_server.c @@ -149,7 +149,7 @@ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags) * and queue the reply, this implies talloc_free(call), * and set the socket to readable again */ - status = wbsrv_queue_reply(call); + status = wbsrv_send_reply(call); if (!NT_STATUS_IS_OK(status)) goto failed; return; @@ -170,7 +170,7 @@ failed: * return; * to drop the connection */ -NTSTATUS wbsrv_queue_reply(struct wbsrv_call *call) +NTSTATUS wbsrv_send_reply(struct wbsrv_call *call) { struct wbsrv_connection *wbconn = call->wbconn; const struct wbsrv_protocol_ops *ops = wbconn->listen_socket->ops; diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h index 2c93c02323..0c00394f7d 100644 --- a/source4/winbind/wb_server.h +++ b/source4/winbind/wb_server.h @@ -91,16 +91,17 @@ struct wbsrv_connection { NOTE about async replies: if the backend wants to reply later: - - it should set the WBSRV_CALL_FLAGS_REPLY_ASYNC flag, and may set a talloc_destructor - on the this structure or on the private_data (if it's a talloc child of this structure), - so that wbsrv_terminate_connection called by another call clean up the whole connection - correct. - - When the backend is ready to reply it should call wbsrv_queue_reply(call), - wbsrv_queue_reply implies talloc_free(call), so the backend should use talloc_reference(call), - if it needs it later. - - If wbsrv_queue_reply doesn't return NT_STATUS_OK, the backend function should call, - wbsrv_terminate_connection(call->wbconn, nt_errstr(status)); - return; + + - it should set the WBSRV_CALL_FLAGS_REPLY_ASYNC flag, and may set a + talloc_destructor on the this structure or on the private_data (if it's a + talloc child of this structure), so that wbsrv_terminate_connection + called by another call clean up the whole connection correct. + - When the backend is ready to reply it should call wbsrv_send_reply(call), + wbsrv_send_reply implies talloc_free(call), so the backend should use + talloc_reference(call), if it needs it later. + - If wbsrv_send_reply doesn't return NT_STATUS_OK, the backend function + should call, wbsrv_terminate_connection(call->wbconn, nt_errstr(status)); + return; */ struct wbsrv_call { -- cgit