diff options
author | Andreas Schneider <asn@redhat.com> | 2010-01-17 10:21:21 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2010-01-20 22:46:59 +0100 |
commit | fd6a79228347ec032294a1f462dda56095fc1d8b (patch) | |
tree | a70efb66a9a09faad2ba9b4f5b151e578a1bc5e2 /source4 | |
parent | 3471d3677a781e6a03e1a8010946aa82ad7aad83 (diff) | |
download | samba-fd6a79228347ec032294a1f462dda56095fc1d8b.tar.gz samba-fd6a79228347ec032294a1f462dda56095fc1d8b.tar.bz2 samba-fd6a79228347ec032294a1f462dda56095fc1d8b.zip |
s4-winbind: Migrated winbind connection to tsocket.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4')
-rw-r--r-- | source4/winbind/wb_samba3_protocol.c | 101 | ||||
-rw-r--r-- | source4/winbind/wb_server.c | 157 | ||||
-rw-r--r-- | source4/winbind/wb_server.h | 11 |
3 files changed, 191 insertions, 78 deletions
diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index 250525cfb2..ae933054cf 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -23,6 +23,7 @@ #include "winbind/wb_server.h" #include "smbd/service_stream.h" #include "lib/stream/packet.h" +#include "lib/tsocket/tsocket.h" /* work out if a packet is complete for protocols that use a 32 bit host byte @@ -43,28 +44,18 @@ NTSTATUS wbsrv_samba3_packet_full_request(void *private_data, DATA_BLOB blob, si } -NTSTATUS wbsrv_samba3_pull_request(DATA_BLOB blob, struct wbsrv_connection *wbconn, - struct wbsrv_samba3_call **_call) +NTSTATUS wbsrv_samba3_pull_request(struct wbsrv_samba3_call *call) { - struct wbsrv_samba3_call *call; - - if (blob.length != sizeof(call->request)) { + if (call->in.length != sizeof(call->request)) { DEBUG(0,("wbsrv_samba3_pull_request: invalid blob length %lu should be %lu\n" " make sure you use the correct winbind client tools!\n", - (long)blob.length, (long)sizeof(call->request))); + (long)call->in.length, (long)sizeof(call->request))); return NT_STATUS_INVALID_PARAMETER; } - call = talloc_zero(wbconn, struct wbsrv_samba3_call); - NT_STATUS_HAVE_NO_MEMORY(call); - /* the packet layout is the same as the in memory layout of the request, so just copy it */ - memcpy(&call->request, blob.data, sizeof(call->request)); + memcpy(&call->request, call->in.data, sizeof(call->request)); - call->wbconn = wbconn; - call->event_ctx = call->wbconn->conn->event.ctx; - - *_call = call; return NT_STATUS_OK; } @@ -216,9 +207,8 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call) return NT_STATUS_OK; } -static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_CTX *mem_ctx, DATA_BLOB *_blob) +static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call) { - DATA_BLOB blob; uint8_t *extra_data; size_t extra_data_len = 0; @@ -228,25 +218,28 @@ static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_C sizeof(call->response); } - blob = data_blob_talloc(mem_ctx, NULL, call->response.length); - NT_STATUS_HAVE_NO_MEMORY(blob.data); + call->out = data_blob_talloc(call, NULL, call->response.length); + NT_STATUS_HAVE_NO_MEMORY(call->out.data); /* don't push real pointer values into sockets */ if (extra_data) { call->response.extra_data.data = (void *)0xFFFFFFFF; } - memcpy(blob.data, &call->response, sizeof(call->response)); + memcpy(call->out.data, &call->response, sizeof(call->response)); /* set back the pointer */ call->response.extra_data.data = extra_data; if (extra_data) { - memcpy(blob.data + sizeof(call->response), extra_data, extra_data_len); + memcpy(call->out.data + sizeof(call->response), + extra_data, + extra_data_len); } - *_blob = blob; return NT_STATUS_OK; } +static void wbsrv_samba3_send_reply_done(struct tevent_req *subreq); + /* * queue a wbsrv_call reply on a wbsrv_connection * NOTE: that this implies talloc_free(call), @@ -255,38 +248,68 @@ static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_C */ NTSTATUS wbsrv_samba3_send_reply(struct wbsrv_samba3_call *call) { - struct wbsrv_connection *wbconn = call->wbconn; - DATA_BLOB rep; + struct wbsrv_connection *wbsrv_conn = call->wbconn; + struct tevent_req *subreq; NTSTATUS status; - status = wbsrv_samba3_push_reply(call, call, &rep); + status = wbsrv_samba3_push_reply(call); NT_STATUS_NOT_OK_RETURN(status); - status = packet_send(call->wbconn->packet, rep); - - talloc_free(call); - - if (!NT_STATUS_IS_OK(status)) { - wbsrv_terminate_connection(wbconn, - "failed to packet_send winbindd reply"); - return status; + call->out_iov[0].iov_base = call->out.data; + call->out_iov[0].iov_len = call->out.length; + + subreq = tstream_writev_queue_send(call, + wbsrv_conn->conn->event.ctx, + wbsrv_conn->tstream, + wbsrv_conn->send_queue, + call->out_iov, 1); + if (subreq == NULL) { + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " + "no memory for tstream_writev_queue_send"); + return NT_STATUS_NO_MEMORY; } - /* the call isn't needed any more */ + tevent_req_set_callback(subreq, wbsrv_samba3_send_reply_done, call); + return status; } -NTSTATUS wbsrv_samba3_process(void *private_data, DATA_BLOB blob) +static void wbsrv_samba3_send_reply_done(struct tevent_req *subreq) +{ + struct wbsrv_samba3_call *call = tevent_req_callback_data(subreq, + struct wbsrv_samba3_call); + int sys_errno; + int rc; + + rc = tstream_writev_queue_recv(subreq, &sys_errno); + TALLOC_FREE(subreq); + if (rc == -1) { + const char *reason; + + reason = talloc_asprintf(call, "wbsrv_samba3_send_reply_done: " + "tstream_writev_queue_recv() - %d:%s", + sys_errno, strerror(sys_errno)); + if (reason == NULL) { + reason = "wbsrv_samba3_send_reply_done: " + "tstream_writev_queue_recv() failed"; + } + + wbsrv_terminate_connection(call->wbconn, reason); + return; + } + + talloc_free(call); +} + +NTSTATUS wbsrv_samba3_process(struct wbsrv_samba3_call *call) { NTSTATUS status; - struct wbsrv_connection *wbconn = talloc_get_type(private_data, - struct wbsrv_connection); - struct wbsrv_samba3_call *call; - status = wbsrv_samba3_pull_request(blob, wbconn, &call); + + status = wbsrv_samba3_pull_request(call); if (!NT_STATUS_IS_OK(status)) { return status; } - + status = wbsrv_samba3_handle_call(call); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c index 3265aa90f0..fdf8deaa2c 100644 --- a/source4/winbind/wb_server.c +++ b/source4/winbind/wb_server.c @@ -23,6 +23,8 @@ #include "smbd/process_model.h" #include "winbind/wb_server.h" #include "lib/stream/packet.h" +#include "lib/tsocket/tsocket.h" +#include "libcli/util/tstream.h" #include "param/param.h" void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *reason) @@ -30,55 +32,139 @@ void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *rea stream_terminate_connection(wbconn->conn, reason); } -/* - called on a tcp recv error -*/ -static void wbsrv_recv_error(void *private_data, NTSTATUS status) +static void wbsrv_call_loop(struct tevent_req *subreq) { - struct wbsrv_connection *wbconn = talloc_get_type(private_data, struct wbsrv_connection); - wbsrv_terminate_connection(wbconn, nt_errstr(status)); + struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq, + struct wbsrv_connection); + struct wbsrv_samba3_call *call; + NTSTATUS status; + + call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call); + if (call == NULL) { + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " + "no memory for wbsrv_samba3_call"); + return; + } + call->wbconn = wbsrv_conn; + + status = tstream_read_pdu_blob_recv(subreq, + call, + &call->in); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + const char *reason; + + reason = talloc_asprintf(call, "wbsrv_call_loop: " + "tstream_read_pdu_blob_recv() - %s", + nt_errstr(status)); + if (!reason) { + reason = nt_errstr(status); + } + + wbsrv_terminate_connection(wbsrv_conn, reason); + return; + } + + DEBUG(10,("Received winbind TCP packet of length %lu from %s\n", + (long) call->in.length, + tsocket_address_string(wbsrv_conn->conn->remote_address, call))); + + status = wbsrv_samba3_process(call); + if (!NT_STATUS_IS_OK(status)) { + const char *reason; + + reason = talloc_asprintf(call, "wbsrv_call_loop: " + "tstream_read_pdu_blob_recv() - %s", + nt_errstr(status)); + if (!reason) { + reason = nt_errstr(status); + } + + wbsrv_terminate_connection(wbsrv_conn, reason); + return; + } + + /* + * The winbind pdu's has the length as 4 byte (initial_read_size), + * wbsrv_samba3_packet_full_request provides the pdu length then. + */ + subreq = tstream_read_pdu_blob_send(wbsrv_conn, + wbsrv_conn->conn->event.ctx, + wbsrv_conn->tstream, + 4, /* initial_read_size */ + wbsrv_samba3_packet_full_request, + wbsrv_conn); + if (subreq == NULL) { + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " + "no memory for tstream_read_pdu_blob_send"); + return; + } + tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); } static void wbsrv_accept(struct stream_connection *conn) { - struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private_data, - struct wbsrv_listen_socket); - struct wbsrv_connection *wbconn; + struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data, + struct wbsrv_listen_socket); + struct wbsrv_connection *wbsrv_conn; + struct tevent_req *subreq; + int rc; - wbconn = talloc_zero(conn, struct wbsrv_connection); - if (!wbconn) { + wbsrv_conn = talloc_zero(conn, struct wbsrv_connection); + if (wbsrv_conn == NULL) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } - wbconn->conn = conn; - wbconn->listen_socket = listen_socket; - wbconn->lp_ctx = listen_socket->service->task->lp_ctx; - conn->private_data = wbconn; - - wbconn->packet = packet_init(wbconn); - if (wbconn->packet == NULL) { - wbsrv_terminate_connection(wbconn, "wbsrv_accept: out of memory"); + + wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept"); + if (wbsrv_conn->send_queue == NULL) { + stream_terminate_connection(conn, + "wbsrv_accept: out of memory"); + return; + } + + TALLOC_FREE(conn->event.fde); + + rc = tstream_bsd_existing_socket(wbsrv_conn->tstream, + socket_get_fd(conn->socket), + &wbsrv_conn->tstream); + if (rc < 0) { + stream_terminate_connection(conn, + "wbsrv_accept: out of memory"); + return; + } + + wbsrv_conn->conn = conn; + wbsrv_conn->listen_socket = wbsrv_socket; + wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx; + conn->private_data = wbsrv_conn; + + /* + * The winbind pdu's has the length as 4 byte (initial_read_size), + * wbsrv_samba3_packet_full_request provides the pdu length then. + */ + subreq = tstream_read_pdu_blob_send(wbsrv_conn, + wbsrv_conn->conn->event.ctx, + wbsrv_conn->tstream, + 4, /* initial_read_size */ + wbsrv_samba3_packet_full_request, + wbsrv_conn); + if (subreq == NULL) { + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: " + "no memory for tstream_read_pdu_blob_send"); return; } - packet_set_private(wbconn->packet, wbconn); - packet_set_socket(wbconn->packet, conn->socket); - packet_set_callback(wbconn->packet, wbsrv_samba3_process); - packet_set_full_request(wbconn->packet, wbsrv_samba3_packet_full_request); - packet_set_error_handler(wbconn->packet, wbsrv_recv_error); - packet_set_event_context(wbconn->packet, conn->event.ctx); - packet_set_fde(wbconn->packet, conn->event.fde); - packet_set_serialise(wbconn->packet); + tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); } /* - receive some data on a winbind connection + called on a tcp recv */ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags) { - struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data, - struct wbsrv_connection); - packet_recv(wbconn->packet); - + struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data, + struct wbsrv_connection); + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_recv: called"); } /* @@ -86,9 +172,10 @@ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags) */ static void wbsrv_send(struct stream_connection *conn, uint16_t flags) { - struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data, - struct wbsrv_connection); - packet_queue_run(wbconn->packet); + struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data, + struct wbsrv_connection); + /* this should never be triggered! */ + wbsrv_terminate_connection(wbsrv_conn, "wbsrv_send: called"); } static const struct stream_server_ops wbsrv_ops = { diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h index be79872e65..b5576d0f40 100644 --- a/source4/winbind/wb_server.h +++ b/source4/winbind/wb_server.h @@ -100,7 +100,9 @@ struct wbsrv_connection { /* how many calls are pending */ uint32_t pending_calls; - struct packet_context *packet; + struct tstream_context *tstream; + + struct tevent_queue *send_queue; struct loadparm_context *lp_ctx; }; @@ -148,9 +150,6 @@ struct wbsrv_samba3_call { /* the connection the call belongs to */ struct wbsrv_connection *wbconn; - /* the backend should use this event context */ - struct tevent_context *event_ctx; - /* here the backend can store stuff like composite_context's ... */ void *private_data; @@ -159,6 +158,10 @@ struct wbsrv_samba3_call { /* the response structure of the samba3 protocol*/ struct winbindd_response response; + + DATA_BLOB in; + DATA_BLOB out; + struct iovec out_iov[1]; }; struct netr_LMSessionKey; |