From 1c07c25322802eef7b57dda3975baca6c9114c83 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 9 Nov 2005 08:13:41 +0000 Subject: r11596: switched the libcli/raw/ code over to using the lib/stream/ generic packet parsing code. This simplifies the logic in the raw client library a fair bit (This used to be commit f8d43f1f67876360e1295d85a3c3702d1d60ed7b) --- source4/lib/basic.mk | 1 + source4/lib/tls/tls.h | 4 ++ source4/libcli/config.mk | 1 + source4/libcli/raw/clitransport.c | 122 +++++++++++++++----------------------- source4/libcli/raw/libcliraw.h | 9 +-- source4/ntvfs/cifs/vfs_cifs.c | 27 --------- 6 files changed, 55 insertions(+), 109 deletions(-) (limited to 'source4') diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index 383892eb9c..a531145060 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -15,6 +15,7 @@ include cmdline/config.mk include socket_wrapper/config.mk include appweb/config.mk include replace/config.mk +include stream/config.mk ############################## # Start SUBSYSTEM LIBNETIF diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h index a046b91637..df67bad0e4 100644 --- a/source4/lib/tls/tls.h +++ b/source4/lib/tls/tls.h @@ -20,6 +20,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef _TLS_H_ +#define _TLS_H_ + /* call tls_initialise() once per task to startup the tls subsystem */ @@ -72,3 +75,4 @@ BOOL tls_support(struct tls_params *parms); */ NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending); +#endif diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index a7a2862da5..ea93b12a03 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -121,3 +121,4 @@ OBJ_FILES = raw/rawfile.o \ raw/rawacl.o \ raw/rawdate.o \ raw/rawlpq.o +REQUIRED_SUBSYSTEMS = LIBPACKET diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index b07bd630e9..15959ce272 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -25,9 +25,9 @@ #include "lib/socket/socket.h" #include "dlinklist.h" #include "lib/events/events.h" +#include "lib/stream/packet.h" -static void smbcli_transport_process_recv(struct smbcli_transport *transport); static void smbcli_transport_process_send(struct smbcli_transport *transport); /* @@ -40,7 +40,7 @@ static void smbcli_transport_event_handler(struct event_context *ev, struct smbcli_transport *transport = talloc_get_type(private, struct smbcli_transport); if (flags & EVENT_FD_READ) { - smbcli_transport_process_recv(transport); + packet_recv(transport->packet); return; } if (flags & EVENT_FD_WRITE) { @@ -59,6 +59,18 @@ static int transport_destructor(void *ptr) return 0; } + +/* + handle receive errors +*/ +static void smbcli_transport_error(void *private, NTSTATUS status) +{ + struct smbcli_transport *transport = talloc_get_type(private, struct smbcli_transport); + smbcli_transport_dead(transport); +} + +static NTSTATUS smbcli_transport_finish_recv(void *private, DATA_BLOB blob); + /* create a transport structure based on an established socket */ @@ -82,7 +94,20 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock, transport->options.request_timeout = SMB_REQUEST_TIMEOUT; transport->negotiate.max_xmit = transport->options.max_xmit; - + + /* setup the stream -> packet parser */ + transport->packet = packet_init(transport); + if (transport->packet == NULL) { + talloc_free(transport); + return NULL; + } + packet_set_private(transport->packet, transport); + packet_set_socket(transport->packet, transport->socket->sock); + packet_set_callback(transport->packet, smbcli_transport_finish_recv); + packet_set_full_request(transport->packet, packet_full_request_nbt); + packet_set_error_handler(transport->packet, smbcli_transport_error); + packet_set_event_context(transport->packet, transport->socket->event.ctx); + smbcli_init_signing(transport); ZERO_STRUCT(transport->called); @@ -381,17 +406,17 @@ static void smbcli_transport_process_send(struct smbcli_transport *transport) we have a full request in our receive buffer - match it to a pending request and process */ -static void smbcli_transport_finish_recv(struct smbcli_transport *transport) +static NTSTATUS smbcli_transport_finish_recv(void *private, DATA_BLOB blob) { + struct smbcli_transport *transport = talloc_get_type(private, + struct smbcli_transport); uint8_t *buffer, *hdr, *vwv; int len; uint16_t wct=0, mid = 0, op = 0; struct smbcli_request *req; - buffer = transport->recv_buffer.buffer; - len = transport->recv_buffer.req_size; - - ZERO_STRUCT(transport->recv_buffer); + buffer = blob.data; + len = blob.length; hdr = buffer+NBT_HDR_SIZE; vwv = hdr + HDR_VWV; @@ -399,7 +424,7 @@ static void smbcli_transport_finish_recv(struct smbcli_transport *transport) /* see if it could be an oplock break request */ if (handle_oplock_break(transport, len, hdr, vwv)) { talloc_free(buffer); - return; + return NT_STATUS_OK; } /* at this point we need to check for a readbraw reply, as @@ -514,77 +539,14 @@ async: if (req->async.fn) { req->async.fn(req); } - return; + return NT_STATUS_OK; error: if (req) { DLIST_REMOVE(transport->pending_recv, req); req->state = SMBCLI_REQUEST_ERROR; } -} - -/* - process some pending receives -*/ -static void smbcli_transport_process_recv(struct smbcli_transport *transport) -{ - /* a incoming packet goes through 2 stages - first we read the - 4 byte header, which tells us how much more is coming. Then - we read the rest */ - if (transport->recv_buffer.received < NBT_HDR_SIZE) { - NTSTATUS status; - size_t nread; - status = smbcli_sock_read(transport->socket, - transport->recv_buffer.header + - transport->recv_buffer.received, - NBT_HDR_SIZE - transport->recv_buffer.received, - &nread); - if (NT_STATUS_IS_ERR(status)) { - smbcli_transport_dead(transport); - return; - } - if (!NT_STATUS_IS_OK(status)) { - return; - } - - transport->recv_buffer.received += nread; - - if (transport->recv_buffer.received == NBT_HDR_SIZE) { - /* we've got a full header */ - transport->recv_buffer.req_size = smb_len(transport->recv_buffer.header) + NBT_HDR_SIZE; - transport->recv_buffer.buffer = talloc_size(transport, - NBT_HDR_SIZE+transport->recv_buffer.req_size); - if (transport->recv_buffer.buffer == NULL) { - smbcli_transport_dead(transport); - return; - } - memcpy(transport->recv_buffer.buffer, transport->recv_buffer.header, NBT_HDR_SIZE); - } - } - - if (transport->recv_buffer.received < transport->recv_buffer.req_size) { - NTSTATUS status; - size_t nread; - status = smbcli_sock_read(transport->socket, - transport->recv_buffer.buffer + - transport->recv_buffer.received, - transport->recv_buffer.req_size - - transport->recv_buffer.received, - &nread); - if (NT_STATUS_IS_ERR(status)) { - smbcli_transport_dead(transport); - return; - } - if (!NT_STATUS_IS_OK(status)) { - return; - } - transport->recv_buffer.received += nread; - } - - if (transport->recv_buffer.received != 0 && - transport->recv_buffer.received == transport->recv_buffer.req_size) { - smbcli_transport_finish_recv(transport); - } + return NT_STATUS_OK; } /* @@ -593,8 +555,18 @@ static void smbcli_transport_process_recv(struct smbcli_transport *transport) */ BOOL smbcli_transport_process(struct smbcli_transport *transport) { + NTSTATUS status; + size_t npending; + smbcli_transport_process_send(transport); - smbcli_transport_process_recv(transport); + if (transport->socket->sock == NULL) { + return False; + } + + status = socket_pending(transport->socket->sock, &npending); + if (NT_STATUS_IS_OK(status) && npending > 0) { + packet_recv(transport->packet); + } if (transport->socket->sock == NULL) { return False; } diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h index bb13210e74..a853bd177c 100644 --- a/source4/libcli/raw/libcliraw.h +++ b/source4/libcli/raw/libcliraw.h @@ -154,13 +154,8 @@ struct smbcli_transport { know the server name */ struct nbt_name called; - /* a buffer for partially received SMB packets. */ - struct { - uint8_t header[NBT_HDR_SIZE]; - size_t req_size; - size_t received; - uint8_t *buffer; - } recv_buffer; + /* context of the stream -> packet parser */ + struct packet_context *packet; }; /* this is the context for the user */ diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 44c31d91ad..b0d0d06552 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -63,21 +63,6 @@ static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin return req_send_oplock_break(private->tcon, fnum, level); } - /* - a handler for read events on a connection to a backend server -*/ -static void cifs_socket_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) -{ - struct cvfs_private *cvfs = talloc_get_type(private, struct cvfs_private); - struct smbsrv_tcon *tcon = cvfs->tcon; - - if (!smbcli_transport_process(cvfs->transport)) { - /* the connection to our server is dead */ - talloc_free(tcon); - } -} - /* connect to a share - used when a tree_connect operation comes in. */ @@ -90,7 +75,6 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, const char *host, *user, *pass, *domain, *remote_share; struct smb_composite_connect io; struct composite_context *creq; - struct fd_event *fde; struct cli_credentials *credentials; BOOL machine_account; @@ -180,17 +164,6 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, /* we need to receive oplock break requests from the server */ smbcli_oplock_handler(private->transport, oplock_handler, private); - /* take over event handling for this socket */ - talloc_free(private->transport->socket->event.fde); - fde = event_add_fd(private->transport->socket->event.ctx, - private, - socket_get_fd(private->transport->socket->sock), - EVENT_FD_READ | EVENT_FD_WRITE, - cifs_socket_handler, - private); - private->transport->socket->event.fde = fde; - - private->map_generic = lp_parm_bool(req->tcon->service, "cifs", "mapgeneric", False); -- cgit