ctdb-scripts: Don't set arp_filter=1 by default in 10.interface
[samba4-gss.git] / source4 / libcli / raw / clitransport.c
blob04761d62cf2cdeb2cd542f95f0a08f4dcf0acecd
1 /*
2 Unix SMB/CIFS implementation.
3 SMB client transport context management functions
5 Copyright (C) Andrew Tridgell 1994-2005
6 Copyright (C) James Myers 2003 <myersjj@samba.org>
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.
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.
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/>.
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"
36 destroy a transport
38 static int transport_destructor(struct smbcli_transport *transport)
40 smbcli_transport_dead(transport, NT_STATUS_LOCAL_DISCONNECT);
41 return 0;
45 create a transport structure based on an established socket
47 struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
48 TALLOC_CTX *parent_ctx,
49 bool primary,
50 struct smbcli_options *options)
52 struct smbcli_transport *transport;
53 uint32_t smb1_capabilities;
55 transport = talloc_zero(parent_ctx, struct smbcli_transport);
56 if (!transport) return NULL;
58 transport->ev = sock->event.ctx;
59 transport->options = *options;
61 if (transport->options.max_protocol == PROTOCOL_DEFAULT) {
62 transport->options.max_protocol = PROTOCOL_NT1;
65 if (transport->options.max_protocol > PROTOCOL_NT1) {
66 transport->options.max_protocol = PROTOCOL_NT1;
69 TALLOC_FREE(sock->event.fde);
70 TALLOC_FREE(sock->event.te);
72 smb1_capabilities = 0;
73 smb1_capabilities |= CAP_LARGE_FILES;
74 smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
75 smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND;
76 smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS;
77 smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX;
78 smb1_capabilities |= CAP_LWIO;
80 if (options->ntstatus_support) {
81 smb1_capabilities |= CAP_STATUS32;
84 if (options->unicode) {
85 smb1_capabilities |= CAP_UNICODE;
88 if (options->use_spnego) {
89 smb1_capabilities |= CAP_EXTENDED_SECURITY;
92 if (options->use_level2_oplocks) {
93 smb1_capabilities |= CAP_LEVEL_II_OPLOCKS;
96 transport->conn = smbXcli_conn_create(transport,
97 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 if (transport->conn == NULL) {
105 TALLOC_FREE(sock);
106 TALLOC_FREE(transport);
107 return NULL;
109 sock->sock->fd = -1;
110 TALLOC_FREE(sock);
112 talloc_set_destructor(transport, transport_destructor);
114 return transport;
118 create a transport structure based on an established socket
120 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)
126 struct smbcli_transport *transport = NULL;
127 NTSTATUS status;
129 if (*_conn == NULL) {
130 return NT_STATUS_INVALID_PARAMETER;
133 transport = talloc_zero(mem_ctx, struct smbcli_transport);
134 if (transport == NULL) {
135 return NT_STATUS_NO_MEMORY;
138 transport->ev = ev;
139 transport->options = *options;
142 * First only set the pointer without move.
144 transport->conn = *_conn;
145 status = smb_raw_negotiate_fill_transport(transport);
146 if (!NT_STATUS_IS_OK(status)) {
147 TALLOC_FREE(transport);
148 return status;
151 talloc_set_destructor(transport, transport_destructor);
154 * Now move it away from the caller...
156 transport->conn = talloc_move(transport, _conn);
157 *_transport = transport;
158 return NT_STATUS_OK;
162 mark the transport as dead
164 void smbcli_transport_dead(struct smbcli_transport *transport, NTSTATUS status)
166 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
167 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
169 if (NT_STATUS_IS_OK(status)) {
170 status = NT_STATUS_LOCAL_DISCONNECT;
173 smbXcli_conn_disconnect(transport->conn, status);
176 static void idle_handler(struct tevent_context *ev,
177 struct tevent_timer *te, struct timeval t, void *private_data)
179 struct smbcli_transport *transport = talloc_get_type(private_data,
180 struct smbcli_transport);
181 struct timeval next;
183 transport->idle.func(transport, transport->idle.private_data);
185 if (transport->idle.func == NULL) {
186 return;
189 if (!smbXcli_conn_is_connected(transport->conn)) {
190 return;
193 next = timeval_current_ofs_usec(transport->idle.period);
195 transport->idle.te = tevent_add_timer(transport->ev,
196 transport,
197 next,
198 idle_handler,
199 transport);
203 setup the idle handler for a transport
204 the period is in microseconds
206 _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)
211 TALLOC_FREE(transport->idle.te);
212 ZERO_STRUCT(transport->idle);
214 if (idle_func == NULL) {
215 return;
218 if (!smbXcli_conn_is_connected(transport->conn)) {
219 return;
222 transport->idle.func = idle_func;
223 transport->idle.private_data = private_data;
224 transport->idle.period = period;
226 transport->idle.te = tevent_add_timer(transport->ev,
227 transport,
228 timeval_current_ofs_usec(period),
229 idle_handler,
230 transport);
234 process some read/write requests that are pending
235 return false if the socket is dead
237 _PUBLIC_ bool smbcli_transport_process(struct smbcli_transport *transport)
239 struct tevent_req *subreq = NULL;
240 int ret;
242 if (!smbXcli_conn_is_connected(transport->conn)) {
243 return false;
246 if (!smbXcli_conn_has_async_calls(transport->conn)) {
247 return true;
251 * do not block for more than 500 micro seconds
253 subreq = tevent_wakeup_send(transport,
254 transport->ev,
255 timeval_current_ofs_usec(500));
256 if (subreq == NULL) {
257 return false;
260 ret = tevent_loop_once(transport->ev);
261 if (ret != 0) {
262 return false;
265 TALLOC_FREE(subreq);
267 if (!smbXcli_conn_is_connected(transport->conn)) {
268 return false;
271 return true;
274 static void smbcli_transport_break_handler(struct tevent_req *subreq);
275 static void smbcli_request_done(struct tevent_req *subreq);
277 struct tevent_req *smbcli_transport_setup_subreq(struct smbcli_request *req)
279 struct smbcli_transport *transport = req->transport;
280 uint8_t smb_command;
281 uint8_t additional_flags;
282 uint8_t clear_flags;
283 uint16_t additional_flags2;
284 uint16_t clear_flags2;
285 uint32_t pid;
286 struct smbXcli_tcon *tcon = NULL;
287 struct smbXcli_session *session = NULL;
288 uint32_t timeout_msec = transport->options.request_timeout * 1000;
289 struct iovec *bytes_iov = NULL;
290 struct tevent_req *subreq = NULL;
292 smb_command = SVAL(req->out.hdr, HDR_COM);
293 additional_flags = CVAL(req->out.hdr, HDR_FLG);
294 additional_flags2 = SVAL(req->out.hdr, HDR_FLG2);
295 pid = SVAL(req->out.hdr, HDR_PID);
296 pid |= SVAL(req->out.hdr, HDR_PIDHIGH)<<16;
298 clear_flags = ~additional_flags;
299 clear_flags2 = ~additional_flags2;
301 if (req->session) {
302 session = req->session->smbXcli;
305 if (req->tree) {
306 tcon = req->tree->smbXcli;
309 bytes_iov = talloc(req, struct iovec);
310 if (bytes_iov == NULL) {
311 return NULL;
313 bytes_iov->iov_base = (void *)req->out.data;
314 bytes_iov->iov_len = req->out.data_size;
316 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 req->out.wct,
329 (uint16_t *)req->out.vwv,
330 1, bytes_iov);
331 if (subreq == NULL) {
332 return NULL;
335 ZERO_STRUCT(req->out);
337 return subreq;
341 put a request into the send queue
343 void smbcli_transport_send(struct smbcli_request *req)
345 struct smbcli_transport *transport = req->transport;
346 NTSTATUS status;
347 bool need_pending_break = false;
348 struct tevent_req *subreq = NULL;
349 size_t i;
350 size_t num_subreqs = 0;
352 if (transport->oplock.handler) {
353 need_pending_break = true;
356 if (transport->break_subreq) {
357 need_pending_break = false;
360 if (need_pending_break) {
361 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 if (subreq != NULL) {
378 smb1cli_req_set_mid(subreq, 0xFFFF);
379 smbXcli_req_set_pending(subreq);
380 tevent_req_set_callback(subreq,
381 smbcli_transport_break_handler,
382 transport);
383 transport->break_subreq = subreq;
384 subreq = NULL;
388 subreq = smbcli_transport_setup_subreq(req);
389 if (subreq == NULL) {
390 req->state = SMBCLI_REQUEST_ERROR;
391 req->status = NT_STATUS_NO_MEMORY;
392 return;
395 for (i = 0; i < ARRAY_SIZE(req->subreqs); i++) {
396 if (req->subreqs[i] == NULL) {
397 req->subreqs[i] = subreq;
398 subreq = NULL;
400 if (req->subreqs[i] == NULL) {
401 break;
404 if (!tevent_req_is_in_progress(req->subreqs[i])) {
405 req->state = SMBCLI_REQUEST_ERROR;
406 req->status = NT_STATUS_INTERNAL_ERROR;
407 return;
410 num_subreqs = i;
412 req->state = SMBCLI_REQUEST_RECV;
413 tevent_req_set_callback(req->subreqs[0], smbcli_request_done, req);
415 status = smb1cli_req_chain_submit(req->subreqs, num_subreqs);
416 if (!NT_STATUS_IS_OK(status)) {
417 req->status = status;
418 req->state = SMBCLI_REQUEST_ERROR;
419 smbXcli_conn_disconnect(transport->conn, status);
423 static void smbcli_request_done(struct tevent_req *subreq)
425 struct smbcli_request *req =
426 tevent_req_callback_data(subreq,
427 struct smbcli_request);
428 struct smbcli_transport *transport = req->transport;
429 ssize_t len;
430 size_t i;
431 uint8_t *hdr = NULL;
432 uint8_t wct = 0;
433 uint16_t *vwv = NULL;
434 uint32_t num_bytes = 0;
435 uint8_t *bytes = NULL;
436 struct iovec *recv_iov = NULL;
437 uint8_t *inbuf = NULL;
439 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 TALLOC_FREE(req->subreqs[0]);
451 if (!NT_STATUS_IS_OK(req->status)) {
452 if (recv_iov == NULL) {
453 req->state = SMBCLI_REQUEST_ERROR;
454 transport->error.e.nt_status = req->status;
455 transport->error.etype = ETYPE_SOCKET;
456 if (req->async.fn) {
457 req->async.fn(req);
459 return;
464 * For SMBreadBraw hdr is NULL
466 len = recv_iov[0].iov_len;
467 for (i=1; hdr != NULL && i < 3; i++) {
468 uint8_t *p = recv_iov[i-1].iov_base;
469 uint8_t *c1 = recv_iov[i].iov_base;
470 uint8_t *c2 = p + recv_iov[i-1].iov_len;
472 len += recv_iov[i].iov_len;
474 c2 += i;
475 len += i;
477 if (recv_iov[i].iov_len == 0) {
478 continue;
481 if (c1 != c2) {
482 req->state = SMBCLI_REQUEST_ERROR;
483 req->status = NT_STATUS_INTERNAL_ERROR;
484 transport->error.e.nt_status = req->status;
485 transport->error.etype = ETYPE_SMB;
486 if (req->async.fn) {
487 req->async.fn(req);
489 return;
493 /* fill in the 'in' portion of the matching request */
494 req->in.buffer = inbuf;
495 req->in.size = NBT_HDR_SIZE + len;
496 req->in.allocated = req->in.size;
498 req->in.hdr = hdr;
499 req->in.vwv = (uint8_t *)vwv;
500 req->in.wct = wct;
501 req->in.data = bytes;
502 req->in.data_size = num_bytes;
503 req->in.ptr = req->in.data;
504 if (hdr != NULL) {
505 req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
508 smb_setup_bufinfo(req);
510 transport->error.e.nt_status = req->status;
511 if (NT_STATUS_IS_OK(req->status)) {
512 transport->error.etype = ETYPE_NONE;
513 } else {
514 transport->error.etype = ETYPE_SMB;
517 req->state = SMBCLI_REQUEST_DONE;
518 if (req->async.fn) {
519 req->async.fn(req);
523 static void smbcli_transport_break_handler(struct tevent_req *subreq)
525 struct smbcli_transport *transport =
526 tevent_req_callback_data(subreq,
527 struct smbcli_transport);
528 NTSTATUS status;
529 struct iovec *recv_iov = NULL;
530 uint8_t *hdr = NULL;
531 uint16_t *vwv = NULL;
532 const struct smb1cli_req_expected_response expected[] = {
534 .status = NT_STATUS_OK,
535 .wct = 8,
538 uint16_t tid;
539 uint16_t fnum;
540 uint8_t level;
542 transport->break_subreq = NULL;
544 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 TALLOC_FREE(subreq);
557 if (!NT_STATUS_IS_OK(status)) {
558 TALLOC_FREE(recv_iov);
559 smbcli_transport_dead(transport, status);
560 return;
564 * Setup the subreq to handle the
565 * next incoming SMB2 Break.
567 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 if (subreq != NULL) {
584 smb1cli_req_set_mid(subreq, 0xFFFF);
585 smbXcli_req_set_pending(subreq);
586 tevent_req_set_callback(subreq,
587 smbcli_transport_break_handler,
588 transport);
589 transport->break_subreq = subreq;
592 tid = SVAL(hdr, HDR_TID);
593 fnum = SVAL(vwv+2, 0);
594 level = CVAL(vwv+3, 1);
596 TALLOC_FREE(recv_iov);
598 if (transport->oplock.handler) {
599 transport->oplock.handler(transport, tid, fnum, level,
600 transport->oplock.private_data);
601 } else {
602 DEBUG(5,("Got SMB oplock break with no handler\n"));
608 /****************************************************************************
609 Send an SMBecho (async send)
610 *****************************************************************************/
611 _PUBLIC_ struct smbcli_request *smb_raw_echo_send(struct smbcli_transport *transport,
612 struct smb_echo *p)
614 struct smbcli_request *req;
616 req = smbcli_request_setup_transport(transport, SMBecho, 1, p->in.size);
617 if (!req) return NULL;
619 SSVAL(req->out.vwv, VWV(0), p->in.repeat_count);
621 memcpy(req->out.data, p->in.data, p->in.size);
623 ZERO_STRUCT(p->out);
625 if (!smbcli_request_send(req)) {
626 smbcli_request_destroy(req);
627 return NULL;
630 return req;
633 /****************************************************************************
634 raw echo interface (async recv)
635 ****************************************************************************/
636 NTSTATUS smb_raw_echo_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
637 struct smb_echo *p)
639 if (!smbcli_request_receive(req) ||
640 smbcli_request_is_error(req)) {
641 goto failed;
644 SMBCLI_CHECK_WCT(req, 1);
645 p->out.count++;
646 p->out.sequence_number = SVAL(req->in.vwv, VWV(0));
647 p->out.size = req->in.data_size;
648 talloc_free(p->out.data);
649 p->out.data = talloc_array(mem_ctx, uint8_t, p->out.size);
650 NT_STATUS_HAVE_NO_MEMORY(p->out.data);
652 if (!smbcli_raw_pull_data(&req->in.bufinfo, req->in.data, p->out.size, p->out.data)) {
653 req->status = NT_STATUS_BUFFER_TOO_SMALL;
656 if (p->out.count == p->in.repeat_count) {
657 return smbcli_request_destroy(req);
660 return NT_STATUS_OK;
662 failed:
663 return smbcli_request_destroy(req);
666 /****************************************************************************
667 Send a echo (sync interface)
668 *****************************************************************************/
669 NTSTATUS smb_raw_echo(struct smbcli_transport *transport, struct smb_echo *p)
671 struct smbcli_request *req = smb_raw_echo_send(transport, p);
672 return smbcli_request_simple_recv(req);