_send() call fails completely */
if (!req) return NT_STATUS_UNSUCCESSFUL;
- /* remove it from the list of pending requests (a null op if
- its not in the list) */
- DLIST_REMOVE(req->transport->pending_requests, req);
+ if (req->transport) {
+ /* remove it from the list of pending requests (a null op if
+ its not in the list) */
+ DLIST_REMOVE(req->transport->pending_recv, req);
+ }
/* ahh, its so nice to destroy a complex structure in such a
simple way! */
ZERO_STRUCTP(req);
/* setup the request context */
+ req->state = CLI_REQUEST_INIT;
req->mem_ctx = mem_ctx;
req->transport = transport;
req->session = NULL;
setup a SMB packet at transport level
*/
struct cli_request *cli_request_setup_transport(struct cli_transport *transport,
- uint8 command, unsigned wct, unsigned buflen)
+ uint8_t command, uint_t wct, uint_t buflen)
{
struct cli_request *req;
way. This interface is used before a session is setup.
*/
struct cli_request *cli_request_setup_session(struct cli_session *session,
- uint8 command, unsigned wct, unsigned buflen)
+ uint8_t command, uint_t wct, uint_t buflen)
{
struct cli_request *req;
- uint16 flags2;
- uint32 capabilities;
+ uint16_t flags2;
+ uint32_t capabilities;
req = cli_request_setup_transport(session->transport, command, wct, buflen);
setup a request for tree based commands
*/
struct cli_request *cli_request_setup(struct cli_tree *tree,
- uint8 command,
- unsigned wct, unsigned buflen)
+ uint8_t command,
+ uint_t wct, uint_t buflen)
{
struct cli_request *req;
To cope with this req->out.ptr is supplied. This will be updated to
point at the same offset into the packet as before this call
*/
-static void cli_req_grow_allocation(struct cli_request *req, unsigned new_size)
+static void cli_req_grow_allocation(struct cli_request *req, uint_t new_size)
{
int delta;
char *buf2;
To cope with this req->out.ptr is supplied. This will be updated to
point at the same offset into the packet as before this call
*/
-static void cli_req_grow_data(struct cli_request *req, unsigned new_size)
+static void cli_req_grow_data(struct cli_request *req, uint_t new_size)
{
int delta;
SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
}
+
/*
send a message
*/
cli_request_calculate_sign_mac(req);
- if (req->out.size != cli_sock_write(req->transport->socket, req->out.buffer, req->out.size)) {
- req->transport->error.etype = ETYPE_SOCKET;
- req->transport->error.e.socket_error = SOCKET_WRITE_ERROR;
- DEBUG(0,("Error writing %d bytes to server - %s\n",
- (int)req->out.size, strerror(errno)));
- return False;
- }
+ cli_transport_send(req);
- /* add it to the list of pending requests */
- DLIST_ADD(req->transport->pending_requests, req);
-
return True;
}
if (!req) return False;
/* keep receiving packets until this one is replied to */
- while (!req->in.buffer) {
- if (!cli_transport_select(req->transport)) {
- return False;
- }
-
- cli_request_receive_next(req->transport);
+ while (req->state <= CLI_REQUEST_RECV) {
+ event_loop_once(req->transport->event.ctx);
}
return True;
handle oplock break requests from the server - return True if the request was
an oplock break
*/
-static BOOL handle_oplock_break(struct cli_transport *transport, uint_t len, const char *hdr, const char *vwv)
+BOOL handle_oplock_break(struct cli_transport *transport, uint_t len, const char *hdr, const char *vwv)
{
/* we must be very fussy about what we consider an oplock break to avoid
matching readbraw replies */
}
if (transport->oplock.handler) {
- uint16 tid = SVAL(hdr, HDR_TID);
- uint16 fnum = SVAL(vwv,VWV(2));
- uint8 level = CVAL(vwv,VWV(3));
+ uint16_t tid = SVAL(hdr, HDR_TID);
+ uint16_t fnum = SVAL(vwv,VWV(2));
+ uint8_t level = CVAL(vwv,VWV(3)+1);
transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
}
return True;
}
-
-/*
- receive an async message from the server
- this function assumes that the caller already knows that the socket is readable
- and that there is a packet waiting
-
- The packet is not actually returned by this function, instead any
- registered async message handlers are called
-
- return True if a packet was successfully received and processed
- return False if the socket appears to be dead
-*/
-BOOL cli_request_receive_next(struct cli_transport *transport)
-{
- BOOL ret;
- int len;
- char header[NBT_HDR_SIZE];
- char *buffer, *hdr, *vwv;
- TALLOC_CTX *mem_ctx;
- struct cli_request *req;
- uint16 wct, mid = 0;
-
- len = cli_sock_read(transport->socket, header, 4);
- if (len != 4) {
- return False;
- }
-
- len = smb_len(header);
-
- mem_ctx = talloc_init("cli_request_receive_next");
-
- /* allocate the incoming buffer at the right size */
- buffer = talloc(mem_ctx, len+NBT_HDR_SIZE);
- if (!buffer) {
- talloc_destroy(mem_ctx);
- return False;
- }
-
- /* fill in the already received header */
- memcpy(buffer, header, NBT_HDR_SIZE);
-
- ret = cli_sock_read(transport->socket, buffer + NBT_HDR_SIZE, len);
- /* If the server is not responding, note that now */
- if (ret != len) {
- return False;
- }
-
- hdr = buffer+NBT_HDR_SIZE;
- vwv = hdr + HDR_VWV;
-
- /* see if it could be an oplock break request */
- if (handle_oplock_break(transport, len, hdr, vwv)) {
- goto done;
- }
-
- /* at this point we need to check for a readbraw reply, as these can be any length */
- if (transport->readbraw_pending) {
- transport->readbraw_pending = 0;
-
- /* it must match the first entry in the pending queue as the client is not allowed
- to have outstanding readbraw requests */
- req = transport->pending_requests;
- if (!req) goto done;
-
- req->in.buffer = buffer;
- talloc_steal(mem_ctx, req->mem_ctx, buffer);
- req->in.size = len + NBT_HDR_SIZE;
- req->in.allocated = req->in.size;
- goto async;
- }
-
- if (len >= MIN_SMB_SIZE) {
- /* extract the mid for matching to pending requests */
- mid = SVAL(hdr, HDR_MID);
- wct = CVAL(hdr, HDR_WCT);
- }
-
- /* match the incoming request against the list of pending requests */
- for (req=transport->pending_requests; req; req=req->next) {
- if (req->mid == mid) break;
- }
-
- if (!req) {
- DEBUG(3,("Discarding unmatched reply with mid %d\n", mid));
- goto done;
- }
-
- /* fill in the 'in' portion of the matching request */
- req->in.buffer = buffer;
- talloc_steal(mem_ctx, req->mem_ctx, buffer);
- req->in.size = len + NBT_HDR_SIZE;
- req->in.allocated = req->in.size;
-
- /* handle non-SMB replies */
- if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE) {
- goto done;
- }
-
- if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
- DEBUG(2,("bad reply size for mid %d\n", mid));
- req->status = NT_STATUS_UNSUCCESSFUL;
- goto done;
- }
-
- req->in.hdr = hdr;
- req->in.vwv = vwv;
- req->in.wct = wct;
- if (req->in.size >= NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) {
- req->in.data = req->in.vwv + VWV(wct) + 2;
- req->in.data_size = SVAL(req->in.vwv, VWV(wct));
- if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + req->in.data_size) {
- DEBUG(3,("bad data size for mid %d\n", mid));
- /* blergh - w2k3 gives a bogus data size values in some
- openX replies */
- req->in.data_size = req->in.size - (NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct));
- }
- }
- req->in.ptr = req->in.data;
- req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
-
- if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
- transport->error.etype = ETYPE_DOS;
- transport->error.e.dos.eclass = CVAL(req->in.hdr,HDR_RCLS);
- transport->error.e.dos.ecode = SVAL(req->in.hdr,HDR_ERR);
- req->status = dos_to_ntstatus(transport->error.e.dos.eclass,
- transport->error.e.dos.ecode);
- } else {
- transport->error.etype = ETYPE_NT;
- transport->error.e.nt_status = NT_STATUS(IVAL(req->in.hdr, HDR_RCLS));
- req->status = transport->error.e.nt_status;
- }
-
- if (!cli_request_check_sign_mac(req)) {
- transport->error.etype = ETYPE_SOCKET;
- transport->error.e.socket_error = SOCKET_READ_BAD_SIG;
- return False;
- };
-
-async:
- /* if this request has an async handler then call that to
- notify that the reply has been received. This might destroy
- the request so it must happen last */
- if (req->async.fn) {
- req->async.fn(req);
- }
-
-done:
- talloc_destroy(mem_ctx);
- return True;
-}
-
-
/*
wait for a reply to be received for a packet that just returns an error
code and nothing more
return the number of bytes added to the packet
*/
-size_t cli_req_append_string(struct cli_request *req, const char *str, unsigned flags)
+size_t cli_req_append_string(struct cli_request *req, const char *str, uint_t flags)
{
size_t len;
this is used in places where the non-terminated string byte length is
placed in the packet as a separate field
*/
-size_t cli_req_append_string_len(struct cli_request *req, const char *str, unsigned flags, int *len)
+size_t cli_req_append_string_len(struct cli_request *req, const char *str, uint_t flags, int *len)
{
int diff = 0;
size_t ret;
if dest_len is -1 then no limit applies
*/
-size_t cli_req_append_ascii4(struct cli_request *req, const char *str, unsigned flags)
+size_t cli_req_append_ascii4(struct cli_request *req, const char *str, uint_t flags)
{
size_t size;
- cli_req_append_bytes(req, (const uint8 *)"\4", 1);
+ cli_req_append_bytes(req, (const uint8_t *)"\4", 1);
size = cli_req_append_string(req, str, flags);
return size + 1;
}
append raw bytes into the data portion of the request packet
return the number of bytes added
*/
-size_t cli_req_append_bytes(struct cli_request *req, const uint8 *bytes, size_t byte_len)
+size_t cli_req_append_bytes(struct cli_request *req, const uint8_t *bytes, size_t byte_len)
{
cli_req_grow_allocation(req, byte_len + req->out.data_size);
memcpy(req->out.data + req->out.data_size, bytes, byte_len);
append variable block (type 5 buffer) into the data portion of the request packet
return the number of bytes added
*/
-size_t cli_req_append_var_block(struct cli_request *req, const uint8 *bytes, uint16 byte_len)
+size_t cli_req_append_var_block(struct cli_request *req, const uint8_t *bytes, uint16_t byte_len)
{
cli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
SCVAL(req->out.data + req->out.data_size, 0, 5);
of bytes consumed in the packet is returned
*/
static size_t cli_req_pull_ucs2(struct cli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, unsigned flags)
+ char **dest, const char *src, int byte_len, uint_t flags)
{
int src_len, src_len2, alignment=0;
ssize_t ret;
of bytes consumed in the packet is returned
*/
size_t cli_req_pull_ascii(struct cli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, unsigned flags)
+ char **dest, const char *src, int byte_len, uint_t flags)
{
int src_len, src_len2;
ssize_t ret;
of bytes consumed in the packet is returned
*/
size_t cli_req_pull_string(struct cli_request *req, TALLOC_CTX *mem_ctx,
- char **dest, const char *src, int byte_len, unsigned flags)
+ char **dest, const char *src, int byte_len, uint_t flags)
{
if (!(flags & STR_ASCII) &&
(((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
/* check that a lump of data in a request is within the bounds of the data section of
the packet */
-static BOOL cli_req_data_oob(struct cli_request *req, const char *ptr, uint32 count)
+static BOOL cli_req_data_oob(struct cli_request *req, const char *ptr, uint32_t count)
{
/* be careful with wraparound! */
if (ptr < req->in.data ||
/*
put a NTTIME into a packet
*/
-
-void cli_push_nttime(void *base, uint16 offset, NTTIME *t)
+void cli_push_nttime(void *base, uint16_t offset, NTTIME t)
{
- SIVAL(base, offset, t->low);
- SIVAL(base, offset+4, t->high);
+ SBVAL(base, offset, t);
}
/*
pull a NTTIME from a packet
*/
-NTTIME cli_pull_nttime(void *base, uint16 offset)
+NTTIME cli_pull_nttime(void *base, uint16_t offset)
{
- NTTIME ret;
- ret.low = IVAL(base, offset);
- ret.high = IVAL(base, offset+4);
+ NTTIME ret = BVAL(base, offset);
return ret;
}
*/
static size_t cli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
DATA_BLOB *blob, const char **dest,
- const char *src, int byte_len, unsigned flags)
+ const char *src, int byte_len, uint_t flags)
{
int src_len, src_len2, alignment=0;
ssize_t ret;
*/
static size_t cli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
DATA_BLOB *blob, const char **dest,
- const char *src, int byte_len, unsigned flags)
+ const char *src, int byte_len, uint_t flags)
{
int src_len, src_len2;
ssize_t ret;
TALLOC_CTX *mem_ctx,
DATA_BLOB *blob,
WIRE_STRING *dest,
- uint16 len_offset, uint16 str_offset,
- unsigned flags)
+ uint16_t len_offset, uint16_t str_offset,
+ uint_t flags)
{
int extra;
dest->s = NULL;
blob->data+str_offset, dest->private_length, flags);
}
+/*
+ pull a string from a blob, returning a talloced char *
+
+ Currently only used by the UNIX search info level.
+
+ the string length is limited by 2 things:
+ - the data size in the blob
+ - the end of string (null termination)
+
+ on failure zero is returned and dest->s is set to NULL, otherwise the number
+ of bytes consumed in the blob is returned
+*/
+size_t cli_blob_pull_unix_string(struct cli_session *session,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *blob,
+ const char **dest,
+ uint16_t str_offset,
+ uint_t flags)
+{
+ int extra = 0;
+ *dest = NULL;
+
+ if (!(flags & STR_ASCII) &&
+ ((flags & STR_UNICODE) ||
+ (session->transport->negotiate.capabilities & CAP_UNICODE))) {
+ int align = 0;
+ if ((str_offset&1) && !(flags & STR_NOALIGN)) {
+ align = 1;
+ }
+ if (flags & STR_LEN_NOTERM) {
+ extra = 2;
+ }
+ return align + extra + cli_blob_pull_ucs2(mem_ctx, blob, dest,
+ blob->data+str_offset+align,
+ -1, flags);
+ }
+
+ if (flags & STR_LEN_NOTERM) {
+ extra = 1;
+ }
+
+ return extra + cli_blob_pull_ascii(mem_ctx, blob, dest,
+ blob->data+str_offset, -1, flags);
+}
+
+
/*
append a string into a blob
*/
size_t cli_blob_append_string(struct cli_session *session,
TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
- const char *str, unsigned flags)
+ const char *str, uint_t flags)
{
size_t max_len;
int len;