1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

s4:lib/messaging: add irpc dcerpc_binding_handle backend

metze
This commit is contained in:
Stefan Metzmacher 2010-08-30 13:44:01 +02:00
parent 328c7084f2
commit e26f0abe91
3 changed files with 289 additions and 1 deletions

View File

@ -79,6 +79,10 @@ struct irpc_request {
void (*fn)(struct irpc_request *);
void *private_data;
} async;
struct {
void (*handler)(struct irpc_request *irpc, struct irpc_message *m);
void *private_data;
} incoming;
};
NTSTATUS irpc_register(struct messaging_context *msg_ctx,
@ -94,6 +98,11 @@ NTSTATUS irpc_call(struct messaging_context *msg_ctx,
const struct ndr_interface_table *table,
int callnum, void *r, TALLOC_CTX *ctx);
struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
struct server_id server_id,
const struct ndr_interface_table *table);
NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name);
struct server_id *irpc_servers_byname(struct messaging_context *msg_ctx, TALLOC_CTX *mem_ctx, const char *name);
void irpc_remove_name(struct messaging_context *msg_ctx, const char *name);

View File

@ -33,6 +33,7 @@
#include "../tdb/include/tdb.h"
#include "../lib/util/util_tdb.h"
#include "cluster/cluster.h"
#include "../lib/util/tevent_ntstatus.h"
/* change the message version with any incompatible changes in the protocol */
#define MESSAGING_VERSION 1
@ -683,6 +684,11 @@ static void irpc_handler_reply(struct messaging_context *msg_ctx, struct irpc_me
irpc = (struct irpc_request *)idr_find(msg_ctx->idr, m->header.callid);
if (irpc == NULL) return;
if (irpc->incoming.handler) {
irpc->incoming.handler(irpc, m);
return;
}
/* parse the reply data */
ndr_err = irpc->table->calls[irpc->callnum].ndr_pull(m->ndr, NDR_OUT, irpc->r);
if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@ -889,6 +895,8 @@ struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx,
irpc->async.fn = NULL;
irpc->mem_ctx = ctx;
irpc->reject_free = false;
irpc->incoming.handler = NULL;
irpc->incoming.private_data = NULL;
talloc_set_destructor(irpc, irpc_destructor);
@ -1122,3 +1130,274 @@ struct server_id messaging_get_server_id(struct messaging_context *msg_ctx)
{
return msg_ctx->server_id;
}
struct irpc_bh_state {
struct messaging_context *msg_ctx;
struct server_id server_id;
const struct ndr_interface_table *table;
};
static bool irpc_bh_is_connected(struct dcerpc_binding_handle *h)
{
struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
struct irpc_bh_state);
if (!hs->msg_ctx) {
return false;
}
return true;
}
struct irpc_bh_raw_call_state {
struct irpc_request *irpc;
uint32_t opnum;
DATA_BLOB in_data;
DATA_BLOB in_packet;
DATA_BLOB out_data;
};
static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
struct irpc_message *m);
static struct tevent_req *irpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct dcerpc_binding_handle *h,
const struct GUID *object,
uint32_t opnum,
uint32_t in_flags,
const uint8_t *in_data,
size_t in_length)
{
struct irpc_bh_state *hs =
dcerpc_binding_handle_data(h,
struct irpc_bh_state);
struct tevent_req *req;
struct irpc_bh_raw_call_state *state;
bool ok;
struct irpc_header header;
struct ndr_push *ndr;
NTSTATUS status;
enum ndr_err_code ndr_err;
req = tevent_req_create(mem_ctx, &state,
struct irpc_bh_raw_call_state);
if (req == NULL) {
return NULL;
}
state->opnum = opnum;
state->in_data.data = discard_const_p(uint8_t, in_data);
state->in_data.length = in_length;
ok = irpc_bh_is_connected(h);
if (!ok) {
tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
return tevent_req_post(req, ev);
}
state->irpc = talloc_zero(state, struct irpc_request);
if (tevent_req_nomem(state->irpc, req)) {
return tevent_req_post(req, ev);
}
state->irpc->msg_ctx = hs->msg_ctx;
state->irpc->table = hs->table;
state->irpc->callnum = state->opnum;
state->irpc->callid = idr_get_new(hs->msg_ctx->idr,
state->irpc, UINT16_MAX);
if (state->irpc->callid == -1) {
tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
return tevent_req_post(req, ev);
}
state->irpc->r = NULL;
state->irpc->done = false;
state->irpc->async.fn = NULL;
state->irpc->mem_ctx = state;
state->irpc->reject_free = false;
state->irpc->incoming.handler = irpc_bh_raw_call_incoming_handler;
state->irpc->incoming.private_data = req;
talloc_set_destructor(state->irpc, irpc_destructor);
/* setup the header */
header.uuid = hs->table->syntax_id.uuid;
header.if_version = hs->table->syntax_id.if_version;
header.callid = state->irpc->callid;
header.callnum = state->opnum;
header.flags = 0;
header.status = NT_STATUS_OK;
/* construct the irpc packet */
ndr = ndr_push_init_ctx(state->irpc);
if (tevent_req_nomem(ndr, req)) {
return tevent_req_post(req, ev);
}
ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);
status = ndr_map_error2ntstatus(ndr_err);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
ndr_err = ndr_push_bytes(ndr, in_data, in_length);
status = ndr_map_error2ntstatus(ndr_err);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
/* and send it */
state->in_packet = ndr_push_blob(ndr);
status = messaging_send(hs->msg_ctx, hs->server_id,
MSG_IRPC, &state->in_packet);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
return tevent_req_post(req, ev);
}
tevent_req_set_endtime(req, ev, timeval_current_ofs(IRPC_CALL_TIMEOUT, 0));
return req;
}
static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
struct irpc_message *m)
{
struct tevent_req *req =
talloc_get_type_abort(irpc->incoming.private_data,
struct tevent_req);
struct irpc_bh_raw_call_state *state =
tevent_req_data(req,
struct irpc_bh_raw_call_state);
talloc_steal(state, m);
if (!NT_STATUS_IS_OK(m->header.status)) {
tevent_req_nterror(req, m->header.status);
return;
}
state->out_data = data_blob_talloc(state,
m->ndr->data + m->ndr->offset,
m->ndr->data_size - m->ndr->offset);
if ((m->ndr->data_size - m->ndr->offset) > 0 && !state->out_data.data) {
tevent_req_nomem(NULL, req);
return;
}
tevent_req_done(req);
}
static NTSTATUS irpc_bh_raw_call_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
uint8_t **out_data,
size_t *out_length,
uint32_t *out_flags)
{
struct irpc_bh_raw_call_state *state =
tevent_req_data(req,
struct irpc_bh_raw_call_state);
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
*out_data = talloc_move(mem_ctx, &state->out_data.data);
*out_length = state->out_data.length;
*out_flags = 0;
tevent_req_received(req);
return NT_STATUS_OK;
}
struct irpc_bh_disconnect_state {
uint8_t _dummy;
};
static struct tevent_req *irpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct dcerpc_binding_handle *h)
{
struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
struct irpc_bh_state);
struct tevent_req *req;
struct irpc_bh_disconnect_state *state;
bool ok;
req = tevent_req_create(mem_ctx, &state,
struct irpc_bh_disconnect_state);
if (req == NULL) {
return NULL;
}
ok = irpc_bh_is_connected(h);
if (!ok) {
tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
return tevent_req_post(req, ev);
}
hs->msg_ctx = NULL;
tevent_req_done(req);
return tevent_req_post(req, ev);
}
static NTSTATUS irpc_bh_disconnect_recv(struct tevent_req *req)
{
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
tevent_req_received(req);
return NT_STATUS_OK;
}
static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
{
return true;
}
static const struct dcerpc_binding_handle_ops irpc_bh_ops = {
.name = "wbint",
.is_connected = irpc_bh_is_connected,
.raw_call_send = irpc_bh_raw_call_send,
.raw_call_recv = irpc_bh_raw_call_recv,
.disconnect_send = irpc_bh_disconnect_send,
.disconnect_recv = irpc_bh_disconnect_recv,
.ref_alloc = irpc_bh_ref_alloc,
};
/* initialise a irpc binding handle */
struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
struct messaging_context *msg_ctx,
struct server_id server_id,
const struct ndr_interface_table *table)
{
struct dcerpc_binding_handle *h;
struct irpc_bh_state *hs;
h = dcerpc_binding_handle_create(mem_ctx,
&irpc_bh_ops,
NULL,
table,
&hs,
struct irpc_bh_state,
__location__);
if (h == NULL) {
return NULL;
}
hs->msg_ctx = msg_ctx;
hs->server_id = server_id;
hs->table = table;
dcerpc_binding_handle_set_sync_ev(h, msg_ctx->event.ev);
return h;
}

View File

@ -3,7 +3,7 @@
bld.SAMBA_SUBSYSTEM('MESSAGING',
source='messaging.c',
public_deps='LIBSAMBA-UTIL TDB_WRAP NDR_IRPC UNIX_PRIVS UTIL_TDB CLUSTER LIBNDR samba_socket'
public_deps='LIBSAMBA-UTIL TDB_WRAP NDR_IRPC UNIX_PRIVS UTIL_TDB CLUSTER LIBNDR samba_socket dcerpc'
)