2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "../util/tevent_unix.h"
23 #include "../lib/tsocket/tsocket.h"
24 #include "../lib/tsocket/tsocket_internal.h"
25 #include "../librpc/gen_ndr/ndr_named_pipe_auth.h"
26 #include "../libcli/named_pipe_auth/npa_tstream.h"
27 #include "libcli/raw/smb.h"
29 static const struct tstream_context_ops tstream_npa_ops
;
32 struct tstream_context
*unix_stream
;
39 struct tstream_npa_connect_state
{
41 struct tevent_context
*ev
;
42 struct smb_iconv_convenience
*smb_iconv_c
;
45 const char *unix_path
;
46 struct tsocket_address
*unix_laddr
;
47 struct tsocket_address
*unix_raddr
;
48 struct tstream_context
*unix_stream
;
50 struct named_pipe_auth_req auth_req
;
51 DATA_BLOB auth_req_blob
;
52 struct iovec auth_req_iov
;
54 struct named_pipe_auth_rep auth_rep
;
55 DATA_BLOB auth_rep_blob
;
58 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
);
60 struct tevent_req
*tstream_npa_connect_send(TALLOC_CTX
*mem_ctx
,
61 struct tevent_context
*ev
,
62 struct smb_iconv_convenience
*smb_iconv_c
,
63 const char *directory
,
65 const struct tsocket_address
*client
,
66 const char *client_name_in
,
67 const struct tsocket_address
*server
,
68 const char *server_name
,
69 const struct netr_SamInfo3
*sam_info3
,
70 DATA_BLOB session_key
,
71 DATA_BLOB delegated_creds
)
73 struct tevent_req
*req
;
74 struct tstream_npa_connect_state
*state
;
75 struct tevent_req
*subreq
;
77 enum ndr_err_code ndr_err
;
79 req
= tevent_req_create(mem_ctx
, &state
,
80 struct tstream_npa_connect_state
);
85 state
->caller
.ev
= ev
;
86 state
->caller
.smb_iconv_c
= smb_iconv_c
;
88 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
91 if (tevent_req_nomem(state
->unix_path
, req
)) {
95 ret
= tsocket_address_unix_from_path(state
,
99 tevent_req_error(req
, errno
);
103 ret
= tsocket_address_unix_from_path(state
,
107 tevent_req_error(req
, errno
);
111 ZERO_STRUCT(state
->auth_req
);
113 struct named_pipe_auth_req_info3
*info3
;
116 tevent_req_error(req
, EINVAL
);
120 state
->auth_req
.level
= 3;
121 info3
= &state
->auth_req
.info
.info3
;
123 info3
->client_name
= client_name_in
;
124 info3
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
125 if (!info3
->client_addr
) {
126 /* errno might be EINVAL */
127 tevent_req_error(req
, errno
);
130 info3
->client_port
= tsocket_address_inet_port(client
);
131 if (!info3
->client_name
) {
132 info3
->client_name
= info3
->client_addr
;
135 info3
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
136 if (!info3
->server_addr
) {
137 /* errno might be EINVAL */
138 tevent_req_error(req
, errno
);
141 info3
->server_port
= tsocket_address_inet_port(server
);
142 if (!info3
->server_name
) {
143 info3
->server_name
= info3
->server_addr
;
146 info3
->sam_info3
= discard_const_p(struct netr_SamInfo3
, sam_info3
);
147 info3
->session_key_length
= session_key
.length
;
148 info3
->session_key
= session_key
.data
;
149 info3
->gssapi_delegated_creds_length
= delegated_creds
.length
;
150 info3
->gssapi_delegated_creds
= delegated_creds
.data
;
152 } else if (sam_info3
) {
153 state
->auth_req
.level
= 1;
154 state
->auth_req
.info
.info1
= *sam_info3
;
156 state
->auth_req
.level
= 0;
160 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
163 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
164 state
, smb_iconv_c
, &state
->auth_req
,
165 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
166 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
167 tevent_req_error(req
, EINVAL
);
171 state
->auth_req_iov
.iov_base
= state
->auth_req_blob
.data
;
172 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
174 subreq
= tstream_unix_connect_send(state
,
178 if (tevent_req_nomem(subreq
, req
)) {
181 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
186 tevent_req_post(req
, ev
);
190 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
192 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
194 struct tevent_req
*req
=
195 tevent_req_callback_data(subreq
,
197 struct tstream_npa_connect_state
*state
=
199 struct tstream_npa_connect_state
);
203 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
204 state
, &state
->unix_stream
);
207 tevent_req_error(req
, sys_errno
);
211 subreq
= tstream_writev_send(state
,
214 &state
->auth_req_iov
, 1);
215 if (tevent_req_nomem(subreq
, req
)) {
218 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
221 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
224 struct iovec
**_vector
,
226 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
228 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
230 struct tevent_req
*req
=
231 tevent_req_callback_data(subreq
,
233 struct tstream_npa_connect_state
*state
=
235 struct tstream_npa_connect_state
);
239 ret
= tstream_writev_recv(subreq
, &sys_errno
);
242 tevent_req_error(req
, sys_errno
);
246 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
248 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
250 tstream_npa_connect_next_vector
,
252 if (tevent_req_nomem(subreq
, req
)) {
255 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
258 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
261 struct iovec
**_vector
,
264 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
265 struct tstream_npa_connect_state
);
266 struct iovec
*vector
;
270 if (state
->auth_rep_blob
.length
== 0) {
271 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
272 if (!state
->auth_rep_blob
.data
) {
275 } else if (state
->auth_rep_blob
.length
== 4) {
280 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
282 if (msg_len
> 0x00FFFFFF) {
294 state
->auth_rep_blob
.data
= talloc_realloc(state
,
295 state
->auth_rep_blob
.data
,
297 if (!state
->auth_rep_blob
.data
) {
300 state
->auth_rep_blob
.length
= msg_len
;
307 /* we need to get a message header */
308 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
312 vector
[0].iov_base
= state
->auth_rep_blob
.data
+ ofs
;
313 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
321 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
323 struct tevent_req
*req
=
324 tevent_req_callback_data(subreq
,
326 struct tstream_npa_connect_state
*state
=
328 struct tstream_npa_connect_state
);
331 enum ndr_err_code ndr_err
;
333 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
336 tevent_req_error(req
, sys_errno
);
340 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
341 (uint32_t)state
->auth_rep_blob
.length
));
342 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
344 ndr_err
= ndr_pull_struct_blob(
345 &state
->auth_rep_blob
, state
,
346 state
->caller
.smb_iconv_c
, &state
->auth_rep
,
347 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
349 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
350 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
351 ndr_map_error2string(ndr_err
)));
352 tevent_req_error(req
, EIO
);
357 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
360 if (state
->auth_rep
.length
< 16) {
361 DEBUG(0, ("req invalid length: %u < 16\n",
362 state
->auth_rep
.length
));
363 tevent_req_error(req
, EIO
);
367 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
368 DEBUG(0, ("req invalid magic: %s != %s\n",
369 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
370 tevent_req_error(req
, EIO
);
374 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
375 DEBUG(0, ("req failed: %s\n",
376 nt_errstr(state
->auth_rep
.status
)));
377 tevent_req_error(req
, EACCES
);
381 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
382 DEBUG(0, ("req invalid level: %u != %u\n",
383 state
->auth_rep
.level
, state
->auth_req
.level
));
384 tevent_req_error(req
, EIO
);
388 tevent_req_done(req
);
391 int _tstream_npa_connect_recv(struct tevent_req
*req
,
394 struct tstream_context
**_stream
,
395 uint16_t *_file_type
,
396 uint16_t *_device_state
,
397 uint64_t *_allocation_size
,
398 const char *location
)
400 struct tstream_npa_connect_state
*state
=
402 struct tstream_npa_connect_state
);
403 struct tstream_context
*stream
;
404 struct tstream_npa
*npas
;
405 uint16_t device_state
= 0;
406 uint64_t allocation_size
= 0;
408 if (tevent_req_is_unix_error(req
, perrno
)) {
409 tevent_req_received(req
);
413 stream
= tstream_context_create(mem_ctx
,
423 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
424 switch (state
->auth_rep
.level
) {
427 npas
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
428 device_state
= 0x00ff;
429 allocation_size
= 2048;
432 npas
->file_type
= state
->auth_rep
.info
.info2
.file_type
;
433 device_state
= state
->auth_rep
.info
.info2
.device_state
;
434 allocation_size
= state
->auth_rep
.info
.info2
.allocation_size
;
437 npas
->file_type
= state
->auth_rep
.info
.info3
.file_type
;
438 device_state
= state
->auth_rep
.info
.info3
.device_state
;
439 allocation_size
= state
->auth_rep
.info
.info3
.allocation_size
;
444 *_file_type
= npas
->file_type
;
445 *_device_state
= device_state
;
446 *_allocation_size
= allocation_size
;
447 tevent_req_received(req
);
451 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
453 struct tstream_npa
*npas
= tstream_context_data(stream
,
457 if (!npas
->unix_stream
) {
462 switch (npas
->file_type
) {
463 case FILE_TYPE_BYTE_MODE_PIPE
:
464 ret
= tstream_pending_bytes(npas
->unix_stream
);
467 case FILE_TYPE_MESSAGE_MODE_PIPE
:
468 ret
= npas
->pending
.iov_len
;
478 struct tstream_npa_readv_state
{
479 struct tstream_context
*stream
;
481 struct iovec
*vector
;
484 /* the header for message mode */
491 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
492 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
495 struct iovec
**_vector
,
497 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
499 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
500 struct tevent_context
*ev
,
501 struct tstream_context
*stream
,
502 struct iovec
*vector
,
505 struct tevent_req
*req
;
506 struct tstream_npa_readv_state
*state
;
507 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
508 struct tevent_req
*subreq
;
513 req
= tevent_req_create(mem_ctx
, &state
,
514 struct tstream_npa_readv_state
);
519 state
->stream
= stream
;
522 if (!npas
->unix_stream
) {
523 tevent_req_error(req
, ENOTCONN
);
527 switch (npas
->file_type
) {
528 case FILE_TYPE_BYTE_MODE_PIPE
:
529 state
->vector
= vector
;
530 state
->count
= count
;
532 subreq
= tstream_readv_send(state
,
537 if (tevent_req_nomem(subreq
,req
)) {
540 tevent_req_set_callback(subreq
,
541 tstream_npa_readv_byte_mode_handler
,
546 case FILE_TYPE_MESSAGE_MODE_PIPE
:
548 * we make a copy of the vector and prepend a header
551 state
->vector
= talloc_array(state
, struct iovec
, count
);
552 if (tevent_req_nomem(state
->vector
, req
)) {
555 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
556 state
->count
= count
;
559 * copy the pending buffer first
562 left
= npas
->pending
.iov_len
;
563 pbase
= (uint8_t *)npas
->pending
.iov_base
;
565 while (left
> 0 && state
->count
> 0) {
567 base
= (uint8_t *)state
->vector
[0].iov_base
;
568 if (left
< state
->vector
[0].iov_len
) {
569 memcpy(base
, pbase
+ ofs
, left
);
572 state
->vector
[0].iov_base
= base
;
573 state
->vector
[0].iov_len
-= left
;
578 ZERO_STRUCT(npas
->pending
);
581 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
583 ofs
+= state
->vector
[0].iov_len
;
584 left
-= state
->vector
[0].iov_len
;
590 ZERO_STRUCT(npas
->pending
);
596 memmove(pbase
, pbase
+ ofs
, left
);
597 npas
->pending
.iov_base
= pbase
;
598 npas
->pending
.iov_len
= left
;
600 * this cannot fail and even if it
601 * fails we can handle it
603 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
605 npas
->pending
.iov_base
= pbase
;
612 if (state
->count
== 0) {
613 tevent_req_done(req
);
617 ZERO_STRUCT(state
->hdr
);
618 state
->wait_for_hdr
= false;
620 subreq
= tstream_readv_pdu_send(state
,
623 tstream_npa_readv_next_vector
,
625 if (tevent_req_nomem(subreq
, req
)) {
628 tevent_req_set_callback(subreq
,
629 tstream_npa_readv_msg_mode_handler
,
635 /* this can't happen */
636 tevent_req_error(req
, EINVAL
);
640 tevent_req_post(req
, ev
);
644 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
646 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
648 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
649 struct tstream_npa_readv_state
);
653 ret
= tstream_readv_recv(subreq
, &sys_errno
);
656 tevent_req_error(req
, sys_errno
);
662 tevent_req_done(req
);
665 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
668 struct iovec
**_vector
,
671 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
672 struct tstream_npa_readv_state
);
673 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
675 struct iovec
*vector
;
680 if (state
->count
== 0) {
686 if (!state
->wait_for_hdr
) {
687 /* we need to get a message header */
688 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
692 ZERO_STRUCT(state
->hdr
);
693 vector
[0].iov_base
= state
->hdr
;
694 vector
[0].iov_len
= sizeof(state
->hdr
);
698 state
->wait_for_hdr
= true;
705 /* and now fill the callers buffers and maybe the pending buffer */
706 state
->wait_for_hdr
= false;
708 msg_len
= SVAL(state
->hdr
, 0);
715 state
->wait_for_hdr
= false;
717 /* +1 because we may need to fill the pending buffer */
718 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
725 while (left
> 0 && state
->count
> 0) {
726 if (left
< state
->vector
[0].iov_len
) {
728 base
= (uint8_t *)state
->vector
[0].iov_base
;
729 vector
[count
].iov_base
= base
;
730 vector
[count
].iov_len
= left
;
733 state
->vector
[0].iov_base
= base
;
734 state
->vector
[0].iov_len
-= left
;
737 vector
[count
] = state
->vector
[0];
739 left
-= state
->vector
[0].iov_len
;
746 * if the message if longer than the buffers the caller
747 * requested, we need to consume the rest of the message
748 * into the pending buffer, where the next readv can
751 npas
->pending
.iov_base
= talloc_array(npas
, uint8_t, left
);
752 if (!npas
->pending
.iov_base
) {
755 npas
->pending
.iov_len
= left
;
757 vector
[count
] = npas
->pending
;
761 state
->ret
+= (msg_len
- left
);
768 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
770 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
775 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
778 tevent_req_error(req
, sys_errno
);
783 * we do not set state->ret here as ret includes the headr size.
784 * we set it in tstream_npa_readv_pdu_next_vector()
787 tevent_req_done(req
);
790 static int tstream_npa_readv_recv(struct tevent_req
*req
,
793 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
794 struct tstream_npa_readv_state
);
797 ret
= tsocket_simple_int_recv(req
, perrno
);
802 tevent_req_received(req
);
806 struct tstream_npa_writev_state
{
807 const struct iovec
*vector
;
810 /* the header for message mode */
816 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
818 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
819 struct tevent_context
*ev
,
820 struct tstream_context
*stream
,
821 const struct iovec
*vector
,
824 struct tevent_req
*req
;
825 struct tstream_npa_writev_state
*state
;
826 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
827 struct tevent_req
*subreq
;
830 struct iovec
*new_vector
;
832 req
= tevent_req_create(mem_ctx
, &state
,
833 struct tstream_npa_writev_state
);
840 if (!npas
->unix_stream
) {
841 tevent_req_error(req
, ENOTCONN
);
845 switch (npas
->file_type
) {
846 case FILE_TYPE_BYTE_MODE_PIPE
:
847 state
->vector
= vector
;
848 state
->count
= count
;
851 case FILE_TYPE_MESSAGE_MODE_PIPE
:
853 * we make a copy of the vector and prepend a header
856 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
857 if (tevent_req_nomem(new_vector
, req
)) {
860 new_vector
[0].iov_base
= state
->hdr
;
861 new_vector
[0].iov_len
= sizeof(state
->hdr
);
862 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
864 state
->vector
= new_vector
;
865 state
->count
= count
+ 1;
868 for (i
=0; i
< count
; i
++) {
869 msg_len
+= vector
[i
].iov_len
;
872 if (msg_len
> UINT16_MAX
) {
873 tevent_req_error(req
, EMSGSIZE
);
877 SSVAL(state
->hdr
, 0, msg_len
);
881 subreq
= tstream_writev_send(state
,
886 if (tevent_req_nomem(subreq
, req
)) {
889 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
894 tevent_req_post(req
, ev
);
898 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
900 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
902 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
903 struct tstream_npa_writev_state
);
907 ret
= tstream_writev_recv(subreq
, &sys_errno
);
910 tevent_req_error(req
, sys_errno
);
916 tevent_req_done(req
);
919 static int tstream_npa_writev_recv(struct tevent_req
*req
,
922 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
923 struct tstream_npa_writev_state
);
926 ret
= tsocket_simple_int_recv(req
, perrno
);
931 tevent_req_received(req
);
935 struct tstream_npa_disconnect_state
{
936 struct tstream_context
*stream
;
939 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
941 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
942 struct tevent_context
*ev
,
943 struct tstream_context
*stream
)
945 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
946 struct tevent_req
*req
;
947 struct tstream_npa_disconnect_state
*state
;
948 struct tevent_req
*subreq
;
950 req
= tevent_req_create(mem_ctx
, &state
,
951 struct tstream_npa_disconnect_state
);
956 state
->stream
= stream
;
958 if (!npas
->unix_stream
) {
959 tevent_req_error(req
, ENOTCONN
);
963 subreq
= tstream_disconnect_send(state
,
966 if (tevent_req_nomem(subreq
, req
)) {
969 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
974 tevent_req_post(req
, ev
);
978 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
980 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
982 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
983 struct tstream_npa_disconnect_state
);
984 struct tstream_context
*stream
= state
->stream
;
985 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
989 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
992 tevent_req_error(req
, sys_errno
);
996 TALLOC_FREE(npas
->unix_stream
);
998 tevent_req_done(req
);
1001 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
1006 ret
= tsocket_simple_int_recv(req
, perrno
);
1008 tevent_req_received(req
);
1012 static const struct tstream_context_ops tstream_npa_ops
= {
1015 .pending_bytes
= tstream_npa_pending_bytes
,
1017 .readv_send
= tstream_npa_readv_send
,
1018 .readv_recv
= tstream_npa_readv_recv
,
1020 .writev_send
= tstream_npa_writev_send
,
1021 .writev_recv
= tstream_npa_writev_recv
,
1023 .disconnect_send
= tstream_npa_disconnect_send
,
1024 .disconnect_recv
= tstream_npa_disconnect_recv
,
1027 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1030 struct tstream_context
**_stream
,
1031 const char *location
)
1033 struct tstream_context
*stream
;
1034 struct tstream_npa
*npas
;
1037 switch (file_type
) {
1038 case FILE_TYPE_BYTE_MODE_PIPE
:
1040 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1047 stream
= tstream_context_create(mem_ctx
,
1057 npas
->file_type
= file_type
;
1059 ret
= tstream_bsd_existing_socket(stream
, fd
,
1060 &npas
->unix_stream
);
1062 int saved_errno
= errno
;
1063 talloc_free(stream
);
1064 errno
= saved_errno
;