LCOV - code coverage report
Current view: top level - source4/libcli/raw - clitransport.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 242 306 79.1 %
Date: 2024-05-31 13:13:24 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB client transport context management functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell 1994-2005
       6             :    Copyright (C) James Myers 2003 <myersjj@samba.org>
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/network.h"
      24             : #include "../lib/async_req/async_sock.h"
      25             : #include "../lib/util/tevent_ntstatus.h"
      26             : #include "libcli/raw/libcliraw.h"
      27             : #include "libcli/raw/raw_proto.h"
      28             : #include "lib/socket/socket.h"
      29             : #include "lib/events/events.h"
      30             : #include "librpc/gen_ndr/ndr_nbt.h"
      31             : #include "../libcli/nbt/libnbt.h"
      32             : #include "../libcli/smb/smbXcli_base.h"
      33             : #include "../libcli/smb/read_smb.h"
      34             : 
      35             : /*
      36             :   destroy a transport
      37             :  */
      38        2792 : static int transport_destructor(struct smbcli_transport *transport)
      39             : {
      40        2792 :         smbcli_transport_dead(transport, NT_STATUS_LOCAL_DISCONNECT);
      41        2792 :         return 0;
      42             : }
      43             : 
      44             : /*
      45             :   create a transport structure based on an established socket
      46             : */
      47        2837 : struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
      48             :                                                TALLOC_CTX *parent_ctx,
      49             :                                                bool primary,
      50             :                                                struct smbcli_options *options)
      51             : {
      52         141 :         struct smbcli_transport *transport;
      53         141 :         uint32_t smb1_capabilities;
      54             : 
      55        2837 :         transport = talloc_zero(parent_ctx, struct smbcli_transport);
      56        2837 :         if (!transport) return NULL;
      57             : 
      58        2837 :         transport->ev = sock->event.ctx;
      59        2837 :         transport->options = *options;
      60             : 
      61        2837 :         if (transport->options.max_protocol == PROTOCOL_DEFAULT) {
      62        2783 :                 transport->options.max_protocol = PROTOCOL_NT1;
      63             :         }
      64             : 
      65        2837 :         if (transport->options.max_protocol > PROTOCOL_NT1) {
      66           0 :                 transport->options.max_protocol = PROTOCOL_NT1;
      67             :         }
      68             : 
      69        2837 :         TALLOC_FREE(sock->event.fde);
      70        2837 :         TALLOC_FREE(sock->event.te);
      71             : 
      72        2837 :         smb1_capabilities = 0;
      73        2837 :         smb1_capabilities |= CAP_LARGE_FILES;
      74        2837 :         smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
      75        2837 :         smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
      76        2837 :         smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
      77        2837 :         smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
      78        2837 :         smb1_capabilities |= CAP_LWIO;
      79             : 
      80        2837 :         if (options->ntstatus_support) {
      81        2829 :                 smb1_capabilities |= CAP_STATUS32;
      82             :         }
      83             : 
      84        2837 :         if (options->unicode) {
      85        2837 :                 smb1_capabilities |= CAP_UNICODE;
      86             :         }
      87             : 
      88        2837 :         if (options->use_spnego) {
      89        2817 :                 smb1_capabilities |= CAP_EXTENDED_SECURITY;
      90             :         }
      91             : 
      92        2837 :         if (options->use_level2_oplocks) {
      93        2831 :                 smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
      94             :         }
      95             : 
      96        5674 :         transport->conn = smbXcli_conn_create(transport,
      97        2837 :                                               sock->sock->fd,
      98             :                                               sock->hostname,
      99             :                                               options->signing,
     100             :                                               smb1_capabilities,
     101             :                                               NULL, /* client_guid */
     102             :                                               0, /* smb2_capabilities */
     103             :                                               NULL); /* smb3_ciphers */
     104        2837 :         if (transport->conn == NULL) {
     105           0 :                 TALLOC_FREE(sock);
     106           0 :                 TALLOC_FREE(transport);
     107           0 :                 return NULL;
     108             :         }
     109        2837 :         sock->sock->fd = -1;
     110        2837 :         TALLOC_FREE(sock);
     111             : 
     112        2837 :         talloc_set_destructor(transport, transport_destructor);
     113             : 
     114        2837 :         return transport;
     115             : }
     116             : 
     117             : /*
     118             :   create a transport structure based on an established socket
     119             : */
     120          26 : NTSTATUS smbcli_transport_raw_init(TALLOC_CTX *mem_ctx,
     121             :                                    struct tevent_context *ev,
     122             :                                    struct smbXcli_conn **_conn,
     123             :                                    const struct smbcli_options *options,
     124             :                                    struct smbcli_transport **_transport)
     125             : {
     126          26 :         struct smbcli_transport *transport = NULL;
     127           0 :         NTSTATUS status;
     128             : 
     129          26 :         if (*_conn == NULL) {
     130           0 :                 return NT_STATUS_INVALID_PARAMETER;
     131             :         }
     132             : 
     133          26 :         transport = talloc_zero(mem_ctx, struct smbcli_transport);
     134          26 :         if (transport == NULL) {
     135           0 :                 return NT_STATUS_NO_MEMORY;
     136             :         }
     137             : 
     138          26 :         transport->ev = ev;
     139          26 :         transport->options = *options;
     140             : 
     141             :         /*
     142             :          * First only set the pointer without move.
     143             :          */
     144          26 :         transport->conn = *_conn;
     145          26 :         status = smb_raw_negotiate_fill_transport(transport);
     146          26 :         if (!NT_STATUS_IS_OK(status)) {
     147           0 :                 TALLOC_FREE(transport);
     148           0 :                 return status;
     149             :         }
     150             : 
     151          26 :         talloc_set_destructor(transport, transport_destructor);
     152             : 
     153             :         /*
     154             :          * Now move it away from the caller...
     155             :          */
     156          26 :         transport->conn = talloc_move(transport, _conn);
     157          26 :         *_transport = transport;
     158          26 :         return NT_STATUS_OK;
     159             : }
     160             : 
     161             : /*
     162             :   mark the transport as dead
     163             : */
     164        2802 : void smbcli_transport_dead(struct smbcli_transport *transport, NTSTATUS status)
     165             : {
     166        2802 :         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
     167           0 :                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
     168             :         }
     169        2802 :         if (NT_STATUS_IS_OK(status)) {
     170           0 :                 status = NT_STATUS_LOCAL_DISCONNECT;
     171             :         }
     172             : 
     173        2802 :         smbXcli_conn_disconnect(transport->conn, status);
     174        2802 : }
     175             : 
     176         156 : static void idle_handler(struct tevent_context *ev,
     177             :                          struct tevent_timer *te, struct timeval t, void *private_data)
     178             : {
     179         156 :         struct smbcli_transport *transport = talloc_get_type(private_data,
     180             :                                                              struct smbcli_transport);
     181           0 :         struct timeval next;
     182             : 
     183         156 :         transport->idle.func(transport, transport->idle.private_data);
     184             : 
     185         156 :         if (transport->idle.func == NULL) {
     186           3 :                 return;
     187             :         }
     188             : 
     189         156 :         if (!smbXcli_conn_is_connected(transport->conn)) {
     190           3 :                 return;
     191             :         }
     192             : 
     193         153 :         next = timeval_current_ofs_usec(transport->idle.period);
     194             : 
     195         153 :         transport->idle.te = tevent_add_timer(transport->ev,
     196             :                                               transport,
     197             :                                               next,
     198             :                                               idle_handler,
     199             :                                               transport);
     200             : }
     201             : 
     202             : /*
     203             :   setup the idle handler for a transport
     204             :   the period is in microseconds
     205             : */
     206           7 : _PUBLIC_ void smbcli_transport_idle_handler(struct smbcli_transport *transport,
     207             :                                    void (*idle_func)(struct smbcli_transport *, void *),
     208             :                                    uint64_t period,
     209             :                                    void *private_data)
     210             : {
     211           7 :         TALLOC_FREE(transport->idle.te);
     212           7 :         ZERO_STRUCT(transport->idle);
     213             : 
     214           7 :         if (idle_func == NULL) {
     215           0 :                 return;
     216             :         }
     217             : 
     218           7 :         if (!smbXcli_conn_is_connected(transport->conn)) {
     219           0 :                 return;
     220             :         }
     221             : 
     222           7 :         transport->idle.func = idle_func;
     223           7 :         transport->idle.private_data = private_data;
     224           7 :         transport->idle.period = period;
     225             : 
     226           7 :         transport->idle.te = tevent_add_timer(transport->ev,
     227             :                                               transport,
     228             :                                               timeval_current_ofs_usec(period),
     229             :                                               idle_handler,
     230             :                                               transport);
     231             : }
     232             : 
     233             : /*
     234             :   process some read/write requests that are pending
     235             :   return false if the socket is dead
     236             : */
     237         458 : _PUBLIC_ bool smbcli_transport_process(struct smbcli_transport *transport)
     238             : {
     239         458 :         struct tevent_req *subreq = NULL;
     240           0 :         int ret;
     241             : 
     242         458 :         if (!smbXcli_conn_is_connected(transport->conn)) {
     243           0 :                 return false;
     244             :         }
     245             : 
     246         458 :         if (!smbXcli_conn_has_async_calls(transport->conn)) {
     247           3 :                 return true;
     248             :         }
     249             : 
     250             :         /*
     251             :          * do not block for more than 500 micro seconds
     252             :          */
     253         455 :         subreq = tevent_wakeup_send(transport,
     254             :                                     transport->ev,
     255             :                                     timeval_current_ofs_usec(500));
     256         455 :         if (subreq == NULL) {
     257           0 :                 return false;
     258             :         }
     259             : 
     260         455 :         ret = tevent_loop_once(transport->ev);
     261         455 :         if (ret != 0) {
     262           0 :                 return false;
     263             :         }
     264             : 
     265         455 :         TALLOC_FREE(subreq);
     266             : 
     267         455 :         if (!smbXcli_conn_is_connected(transport->conn)) {
     268           0 :                 return false;
     269             :         }
     270             : 
     271         455 :         return true;
     272             : }
     273             : 
     274             : static void smbcli_transport_break_handler(struct tevent_req *subreq);
     275             : static void smbcli_request_done(struct tevent_req *subreq);
     276             : 
     277      441814 : struct tevent_req *smbcli_transport_setup_subreq(struct smbcli_request *req)
     278             : {
     279      441814 :         struct smbcli_transport *transport = req->transport;
     280        6438 :         uint8_t smb_command;
     281        6438 :         uint8_t additional_flags;
     282        6438 :         uint8_t clear_flags;
     283        6438 :         uint16_t additional_flags2;
     284        6438 :         uint16_t clear_flags2;
     285        6438 :         uint32_t pid;
     286      441814 :         struct smbXcli_tcon *tcon = NULL;
     287      441814 :         struct smbXcli_session *session = NULL;
     288      441814 :         uint32_t timeout_msec = transport->options.request_timeout * 1000;
     289      441814 :         struct iovec *bytes_iov = NULL;
     290      441814 :         struct tevent_req *subreq = NULL;
     291             : 
     292      441814 :         smb_command = SVAL(req->out.hdr, HDR_COM);
     293      441814 :         additional_flags = CVAL(req->out.hdr, HDR_FLG);
     294      441814 :         additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
     295      441814 :         pid  = SVAL(req->out.hdr, HDR_PID);
     296      441814 :         pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
     297             : 
     298      441814 :         clear_flags = ~additional_flags;
     299      441814 :         clear_flags2 = ~additional_flags2;
     300             : 
     301      441814 :         if (req->session) {
     302      441807 :                 session = req->session->smbXcli;
     303             :         }
     304             : 
     305      441814 :         if (req->tree) {
     306      432642 :                 tcon = req->tree->smbXcli;
     307             :         }
     308             : 
     309      441814 :         bytes_iov = talloc(req, struct iovec);
     310      441814 :         if (bytes_iov == NULL) {
     311           0 :                 return NULL;
     312             :         }
     313      441814 :         bytes_iov->iov_base = (void *)req->out.data;
     314      441814 :         bytes_iov->iov_len = req->out.data_size;
     315             : 
     316      448252 :         subreq = smb1cli_req_create(req,
     317             :                                     transport->ev,
     318             :                                     transport->conn,
     319             :                                     smb_command,
     320             :                                     additional_flags,
     321             :                                     clear_flags,
     322             :                                     additional_flags2,
     323             :                                     clear_flags2,
     324             :                                     timeout_msec,
     325             :                                     pid,
     326             :                                     tcon,
     327             :                                     session,
     328      441814 :                                     req->out.wct,
     329      441814 :                                     (uint16_t *)req->out.vwv,
     330             :                                     1, bytes_iov);
     331      441814 :         if (subreq == NULL) {
     332           0 :                 return NULL;
     333             :         }
     334             : 
     335      441814 :         ZERO_STRUCT(req->out);
     336             : 
     337      441814 :         return subreq;
     338             : }
     339             : 
     340             : /*
     341             :   put a request into the send queue
     342             : */
     343      441796 : void smbcli_transport_send(struct smbcli_request *req)
     344             : {
     345      441796 :         struct smbcli_transport *transport = req->transport;
     346        6435 :         NTSTATUS status;
     347      441796 :         bool need_pending_break = false;
     348      441796 :         struct tevent_req *subreq = NULL;
     349        6435 :         size_t i;
     350      441796 :         size_t num_subreqs = 0;
     351             : 
     352      441796 :         if (transport->oplock.handler) {
     353       62248 :                 need_pending_break = true;
     354             :         }
     355             : 
     356      441796 :         if (transport->break_subreq) {
     357       61895 :                 need_pending_break = false;
     358             :         }
     359             : 
     360      441786 :         if (need_pending_break) {
     361         343 :                 subreq = smb1cli_req_create(transport,
     362             :                                             transport->ev,
     363             :                                             transport->conn,
     364             :                                             0, /* smb_command */
     365             :                                             0, /* additional_flags */
     366             :                                             0, /* clear_flags */
     367             :                                             0, /* additional_flags2 */
     368             :                                             0, /* clear_flags2 */
     369             :                                             0, /* timeout_msec */
     370             :                                             0, /* pid */
     371             :                                             NULL, /* tcon */
     372             :                                             NULL, /* session */
     373             :                                             0, /* wct */
     374             :                                             NULL, /* vwv */
     375             :                                             0, /* iov_count */
     376             :                                             NULL); /* bytes_iov */
     377         343 :                 if (subreq != NULL) {
     378         343 :                         smb1cli_req_set_mid(subreq, 0xFFFF);
     379         343 :                         smbXcli_req_set_pending(subreq);
     380         343 :                         tevent_req_set_callback(subreq,
     381             :                                                 smbcli_transport_break_handler,
     382             :                                                 transport);
     383         343 :                         transport->break_subreq = subreq;
     384         343 :                         subreq = NULL;
     385             :                 }
     386             :         }
     387             : 
     388      441796 :         subreq = smbcli_transport_setup_subreq(req);
     389      441796 :         if (subreq == NULL) {
     390           0 :                 req->state = SMBCLI_REQUEST_ERROR;
     391           0 :                 req->status = NT_STATUS_NO_MEMORY;
     392           0 :                 return;
     393             :         }
     394             : 
     395      883610 :         for (i = 0; i < ARRAY_SIZE(req->subreqs); i++) {
     396      883592 :                 if (req->subreqs[i] == NULL) {
     397      883574 :                         req->subreqs[i] = subreq;
     398      883574 :                         subreq = NULL;
     399             :                 }
     400      883592 :                 if (req->subreqs[i] == NULL) {
     401      435346 :                         break;
     402             :                 }
     403             : 
     404      441814 :                 if (!tevent_req_is_in_progress(req->subreqs[i])) {
     405           0 :                         req->state = SMBCLI_REQUEST_ERROR;
     406           0 :                         req->status = NT_STATUS_INTERNAL_ERROR;
     407           0 :                         return;
     408             :                 }
     409             :         }
     410      441796 :         num_subreqs = i;
     411             : 
     412      441796 :         req->state = SMBCLI_REQUEST_RECV;
     413      441796 :         tevent_req_set_callback(req->subreqs[0], smbcli_request_done, req);
     414             : 
     415      441796 :         status = smb1cli_req_chain_submit(req->subreqs, num_subreqs);
     416      441796 :         if (!NT_STATUS_IS_OK(status)) {
     417           4 :                 req->status = status;
     418           4 :                 req->state = SMBCLI_REQUEST_ERROR;
     419           4 :                 smbXcli_conn_disconnect(transport->conn, status);
     420             :         }
     421             : }
     422             : 
     423      441577 : static void smbcli_request_done(struct tevent_req *subreq)
     424             : {
     425        6435 :         struct smbcli_request *req =
     426      441577 :                 tevent_req_callback_data(subreq,
     427             :                 struct smbcli_request);
     428      441577 :         struct smbcli_transport *transport = req->transport;
     429        6435 :         ssize_t len;
     430        6435 :         size_t i;
     431      441577 :         uint8_t *hdr = NULL;
     432      441577 :         uint8_t wct = 0;
     433      441577 :         uint16_t *vwv = NULL;
     434      441577 :         uint32_t num_bytes = 0;
     435      441577 :         uint8_t *bytes = NULL;
     436      441577 :         struct iovec *recv_iov = NULL;
     437      441577 :         uint8_t *inbuf = NULL;
     438             : 
     439      441577 :         req->status = smb1cli_req_recv(req->subreqs[0], req,
     440             :                                        &recv_iov,
     441             :                                        &hdr,
     442             :                                        &wct,
     443             :                                        &vwv,
     444             :                                        NULL, /* pvwv_offset */
     445             :                                        &num_bytes,
     446             :                                        &bytes,
     447             :                                        NULL, /* pbytes_offset */
     448             :                                        &inbuf,
     449             :                                        NULL, 0); /* expected */
     450      441577 :         TALLOC_FREE(req->subreqs[0]);
     451      441577 :         if (!NT_STATUS_IS_OK(req->status)) {
     452       92144 :                 if (recv_iov == NULL) {
     453         141 :                         req->state = SMBCLI_REQUEST_ERROR;
     454         141 :                         transport->error.e.nt_status = req->status;
     455         141 :                         transport->error.etype = ETYPE_SOCKET;
     456         141 :                         if (req->async.fn) {
     457           2 :                                 req->async.fn(req);
     458             :                         }
     459         141 :                         return;
     460             :                 }
     461             :         }
     462             : 
     463             :         /*
     464             :          * For SMBreadBraw hdr is NULL
     465             :          */
     466      441436 :         len = recv_iov[0].iov_len;
     467     1324188 :         for (i=1; hdr != NULL && i < 3; i++) {
     468      882752 :                 uint8_t *p = recv_iov[i-1].iov_base;
     469      882752 :                 uint8_t *c1 = recv_iov[i].iov_base;
     470      882752 :                 uint8_t *c2 = p + recv_iov[i-1].iov_len;
     471             : 
     472      882752 :                 len += recv_iov[i].iov_len;
     473             : 
     474      882752 :                 c2 += i;
     475      882752 :                 len += i;
     476             : 
     477      882752 :                 if (recv_iov[i].iov_len == 0) {
     478      673369 :                         continue;
     479             :                 }
     480             : 
     481      209383 :                 if (c1 != c2) {
     482           0 :                         req->state = SMBCLI_REQUEST_ERROR;
     483           0 :                         req->status = NT_STATUS_INTERNAL_ERROR;
     484           0 :                         transport->error.e.nt_status = req->status;
     485           0 :                         transport->error.etype = ETYPE_SMB;
     486           0 :                         if (req->async.fn) {
     487           0 :                                 req->async.fn(req);
     488             :                         }
     489           0 :                         return;
     490             :                 }
     491             :         }
     492             : 
     493             :         /* fill in the 'in' portion of the matching request */
     494      441436 :         req->in.buffer = inbuf;
     495      441436 :         req->in.size = NBT_HDR_SIZE + len;
     496      441436 :         req->in.allocated = req->in.size;
     497             : 
     498      441436 :         req->in.hdr = hdr;
     499      441436 :         req->in.vwv = (uint8_t *)vwv;
     500      441436 :         req->in.wct = wct;
     501      441436 :         req->in.data = bytes;
     502      441436 :         req->in.data_size = num_bytes;
     503      441436 :         req->in.ptr = req->in.data;
     504      441436 :         if (hdr != NULL) {
     505      441376 :                 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
     506             :         }
     507             : 
     508      441436 :         smb_setup_bufinfo(req);
     509             : 
     510      441436 :         transport->error.e.nt_status = req->status;
     511      441436 :         if (NT_STATUS_IS_OK(req->status)) {
     512      349433 :                 transport->error.etype = ETYPE_NONE;
     513             :         } else {
     514       92003 :                 transport->error.etype = ETYPE_SMB;
     515             :         }
     516             : 
     517      441436 :         req->state = SMBCLI_REQUEST_DONE;
     518      441436 :         if (req->async.fn) {
     519       72996 :                 req->async.fn(req);
     520             :         }
     521             : }
     522             : 
     523         154 : static void smbcli_transport_break_handler(struct tevent_req *subreq)
     524             : {
     525           0 :         struct smbcli_transport *transport =
     526         154 :                 tevent_req_callback_data(subreq,
     527             :                 struct smbcli_transport);
     528           0 :         NTSTATUS status;
     529         154 :         struct iovec *recv_iov = NULL;
     530         154 :         uint8_t *hdr = NULL;
     531         154 :         uint16_t *vwv = NULL;
     532         154 :         const struct smb1cli_req_expected_response expected[] = {
     533             :         {
     534             :                 .status = NT_STATUS_OK,
     535             :                 .wct = 8,
     536             :         }
     537             :         };
     538           0 :         uint16_t tid;
     539           0 :         uint16_t fnum;
     540           0 :         uint8_t level;
     541             : 
     542         154 :         transport->break_subreq = NULL;
     543             : 
     544         154 :         status = smb1cli_req_recv(subreq, transport,
     545             :                                   &recv_iov,
     546             :                                   &hdr,
     547             :                                   NULL, /* pwct */
     548             :                                   &vwv,
     549             :                                   NULL, /* pvwv_offset */
     550             :                                   NULL, /* pnum_bytes */
     551             :                                   NULL, /* pbytes */
     552             :                                   NULL, /* pbytes_offset */
     553             :                                   NULL, /* pinbuf */
     554             :                                   expected,
     555             :                                   ARRAY_SIZE(expected));
     556         154 :         TALLOC_FREE(subreq);
     557         154 :         if (!NT_STATUS_IS_OK(status)) {
     558           0 :                 TALLOC_FREE(recv_iov);
     559           0 :                 smbcli_transport_dead(transport, status);
     560           0 :                 return;
     561             :         }
     562             : 
     563             :         /*
     564             :          * Setup the subreq to handle the
     565             :          * next incoming SMB2 Break.
     566             :          */
     567         154 :         subreq = smb1cli_req_create(transport,
     568             :                                     transport->ev,
     569             :                                     transport->conn,
     570             :                                     0, /* smb_command */
     571             :                                     0, /* additional_flags */
     572             :                                     0, /* clear_flags */
     573             :                                     0, /* additional_flags2 */
     574             :                                     0, /* clear_flags2 */
     575             :                                     0, /* timeout_msec */
     576             :                                     0, /* pid */
     577             :                                     NULL, /* tcon */
     578             :                                     NULL, /* session */
     579             :                                     0, /* wct */
     580             :                                     NULL, /* vwv */
     581             :                                     0, /* iov_count */
     582             :                                     NULL); /* bytes_iov */
     583         154 :         if (subreq != NULL) {
     584         154 :                 smb1cli_req_set_mid(subreq, 0xFFFF);
     585         154 :                 smbXcli_req_set_pending(subreq);
     586         154 :                 tevent_req_set_callback(subreq,
     587             :                                         smbcli_transport_break_handler,
     588             :                                         transport);
     589         154 :                 transport->break_subreq = subreq;
     590             :         }
     591             : 
     592         154 :         tid = SVAL(hdr, HDR_TID);
     593         154 :         fnum = SVAL(vwv+2, 0);
     594         154 :         level = CVAL(vwv+3, 1);
     595             : 
     596         154 :         TALLOC_FREE(recv_iov);
     597             : 
     598         154 :         if (transport->oplock.handler) {
     599         154 :                 transport->oplock.handler(transport, tid, fnum, level,
     600             :                                           transport->oplock.private_data);
     601             :         } else {
     602           0 :                 DEBUG(5,("Got SMB oplock break with no handler\n"));
     603             :         }
     604             : 
     605             : }
     606             : 
     607             : 
     608             : /****************************************************************************
     609             :  Send an SMBecho (async send)
     610             : *****************************************************************************/
     611           7 : _PUBLIC_ struct smbcli_request *smb_raw_echo_send(struct smbcli_transport *transport,
     612             :                                          struct smb_echo *p)
     613             : {
     614           0 :         struct smbcli_request *req;
     615             : 
     616           7 :         req = smbcli_request_setup_transport(transport, SMBecho, 1, p->in.size);
     617           7 :         if (!req) return NULL;
     618             : 
     619           7 :         SSVAL(req->out.vwv, VWV(0), p->in.repeat_count);
     620             : 
     621           7 :         memcpy(req->out.data, p->in.data, p->in.size);
     622             : 
     623           7 :         ZERO_STRUCT(p->out);
     624             : 
     625           7 :         if (!smbcli_request_send(req)) {
     626           0 :                 smbcli_request_destroy(req);
     627           0 :                 return NULL;
     628             :         }
     629             : 
     630           7 :         return req;
     631             : }
     632             : 
     633             : /****************************************************************************
     634             :  raw echo interface (async recv)
     635             : ****************************************************************************/
     636           0 : NTSTATUS smb_raw_echo_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
     637             :                            struct smb_echo *p)
     638             : {
     639           0 :         if (!smbcli_request_receive(req) ||
     640           0 :             smbcli_request_is_error(req)) {
     641           0 :                 goto failed;
     642             :         }
     643             : 
     644           0 :         SMBCLI_CHECK_WCT(req, 1);
     645           0 :         p->out.count++;
     646           0 :         p->out.sequence_number = SVAL(req->in.vwv, VWV(0));
     647           0 :         p->out.size = req->in.data_size;
     648           0 :         talloc_free(p->out.data);
     649           0 :         p->out.data = talloc_array(mem_ctx, uint8_t, p->out.size);
     650           0 :         NT_STATUS_HAVE_NO_MEMORY(p->out.data);
     651             : 
     652           0 :         if (!smbcli_raw_pull_data(&req->in.bufinfo, req->in.data, p->out.size, p->out.data)) {
     653           0 :                 req->status = NT_STATUS_BUFFER_TOO_SMALL;
     654             :         }
     655             : 
     656           0 :         if (p->out.count == p->in.repeat_count) {
     657           0 :                 return smbcli_request_destroy(req);
     658             :         }
     659             : 
     660           0 :         return NT_STATUS_OK;
     661             : 
     662           0 : failed:
     663           0 :         return smbcli_request_destroy(req);
     664             : }
     665             : 
     666             : /****************************************************************************
     667             :  Send a echo (sync interface)
     668             : *****************************************************************************/
     669           7 : NTSTATUS smb_raw_echo(struct smbcli_transport *transport, struct smb_echo *p)
     670             : {
     671           7 :         struct smbcli_request *req = smb_raw_echo_send(transport, p);
     672           7 :         return smbcli_request_simple_recv(req);
     673             : }

Generated by: LCOV version 1.14