r873: converted samba4 to use real 64 bit integers instead of
[kamenim/samba.git] / source4 / libcli / raw / rawrequest.c
index 52349d415c75d842183021989c947cd006912670..085b445fbabeb6ee2a0b3aa651b7c3c5aa764f9d 100644 (file)
@@ -40,9 +40,11 @@ NTSTATUS cli_request_destroy(struct cli_request *req)
           _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_requests, req);
+       }
 
        /* ahh, its so nice to destroy a complex structure in such a
           simple way! */
@@ -269,13 +271,17 @@ static void cli_req_grow_data(struct cli_request *req, unsigned new_size)
 */
 BOOL cli_request_send(struct cli_request *req)
 {
+       uint_t ret;
+
        if (IVAL(req->out.buffer, 0) == 0) {
                _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
        }
 
        cli_request_calculate_sign_mac(req);
 
-       if (req->out.size != cli_sock_write(req->transport->socket, req->out.buffer, req->out.size)) {
+       ret = cli_sock_write(req->transport->socket, req->out.buffer, req->out.size);
+
+       if (req->out.size != ret) {
                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",
@@ -302,10 +308,15 @@ BOOL cli_request_receive(struct cli_request *req)
        /* keep receiving packets until this one is replied to */
        while (!req->in.buffer) {
                if (!cli_transport_select(req->transport)) {
+                       req->status = NT_STATUS_UNSUCCESSFUL;
                        return False;
                }
 
-               cli_request_receive_next(req->transport);
+               if (!cli_request_receive_next(req->transport)) {
+                       cli_transport_dead(req->transport);
+                       req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+                       return False;
+               }
        }
 
        return True;
@@ -332,7 +343,7 @@ static BOOL handle_oplock_break(struct cli_transport *transport, uint_t len, con
        if (transport->oplock.handler) {
                uint16 tid = SVAL(hdr, HDR_TID);
                uint16 fnum = SVAL(vwv,VWV(2));
-               uint8 level = CVAL(vwv,VWV(3));
+               uint8 level = CVAL(vwv,VWV(3)+1);
                transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private);
        }
 
@@ -754,7 +765,7 @@ size_t cli_req_pull_string(struct cli_request *req, TALLOC_CTX *mem_ctx,
                           char **dest, const char *src, int byte_len, unsigned flags)
 {
        if (!(flags & STR_ASCII) && 
-           ((flags & STR_UNICODE || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
+           (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
                return cli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
        }
 
@@ -820,11 +831,9 @@ BOOL cli_raw_pull_data(struct cli_request *req, const char *src, int len, char *
 /*
   put a NTTIME into a packet
 */
-
-void cli_push_nttime(void *base, uint16 offset, NTTIME *t)
+void cli_push_nttime(void *base, uint16 offset, NTTIME t)
 {
-       SIVAL(base, offset,   t->low);
-       SIVAL(base, offset+4, t->high);
+       SBVAL(base, offset, t);
 }
 
 /*
@@ -832,9 +841,7 @@ void cli_push_nttime(void *base, uint16 offset, NTTIME *t)
 */
 NTTIME cli_pull_nttime(void *base, uint16 offset)
 {
-       NTTIME ret;
-       ret.low = IVAL(base, offset);
-       ret.high = IVAL(base, offset+4);
+       NTTIME ret = BVAL(base, offset);
        return ret;
 }
 
@@ -963,8 +970,9 @@ size_t cli_blob_pull_string(struct cli_session *session,
                            uint16 len_offset, uint16 str_offset, 
                            unsigned flags)
 {
+       int extra;
        dest->s = NULL;
-
+       
        if (len_offset > blob->length-4) {
                return 0;
        }
@@ -973,21 +981,77 @@ size_t cli_blob_pull_string(struct cli_session *session,
        } else {
                dest->private_length = IVAL(blob->data, len_offset);
        }
+       extra = 0;
        dest->s = 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->s, 
+                                                         blob->data+str_offset+align, 
+                                                         dest->private_length, flags);
+       }
+
+       if (flags & STR_LEN_NOTERM) {
+               extra = 1;
+       }
+
+       return extra + cli_blob_pull_ascii(mem_ctx, blob, &dest->s, 
+                                          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 str_offset, 
+                           unsigned 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)) {
-                       str_offset++;
+                       align = 1;
                }
-               return cli_blob_pull_ucs2(mem_ctx, blob, &dest->s, 
-                                         blob->data+str_offset, dest->private_length, flags);
+               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 cli_blob_pull_ascii(mem_ctx, blob, &dest->s, 
-                                  blob->data+str_offset, dest->private_length, flags);
+       return extra + cli_blob_pull_ascii(mem_ctx, blob, dest,
+                                          blob->data+str_offset, -1, flags);
 }
 
+
 /*
   append a string into a blob
 */