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
*info3
,
70 DATA_BLOB session_key
)
72 struct tevent_req
*req
;
73 struct tstream_npa_connect_state
*state
;
74 struct tevent_req
*subreq
;
76 enum ndr_err_code ndr_err
;
78 req
= tevent_req_create(mem_ctx
, &state
,
79 struct tstream_npa_connect_state
);
84 state
->caller
.ev
= ev
;
85 state
->caller
.smb_iconv_c
= smb_iconv_c
;
87 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
90 if (tevent_req_nomem(state
->unix_path
, req
)) {
94 ret
= tsocket_address_unix_from_path(state
,
98 tevent_req_error(req
, errno
);
102 ret
= tsocket_address_unix_from_path(state
,
106 tevent_req_error(req
, errno
);
110 ZERO_STRUCT(state
->auth_req
);
112 struct named_pipe_auth_req_info2
*info2
;
115 tevent_req_error(req
, EINVAL
);
119 state
->auth_req
.level
= 2;
120 info2
= &state
->auth_req
.info
.info2
;
122 info2
->client_name
= client_name_in
;
123 info2
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
124 if (!info2
->client_addr
) {
125 /* errno might be EINVAL */
126 tevent_req_error(req
, errno
);
129 info2
->client_port
= tsocket_address_inet_port(client
);
130 if (!info2
->client_name
) {
131 info2
->client_name
= info2
->client_addr
;
134 info2
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
135 if (!info2
->server_addr
) {
136 /* errno might be EINVAL */
137 tevent_req_error(req
, errno
);
140 info2
->server_port
= tsocket_address_inet_port(server
);
141 if (!info2
->server_name
) {
142 info2
->server_name
= info2
->server_addr
;
145 info2
->sam_info3
= discard_const_p(struct netr_SamInfo3
, info3
);
146 info2
->session_key_length
= session_key
.length
;
147 info2
->session_key
= session_key
.data
;
149 state
->auth_req
.level
= 1;
150 state
->auth_req
.info
.info1
= *info3
;
152 state
->auth_req
.level
= 0;
156 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
159 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
160 state
, smb_iconv_c
, &state
->auth_req
,
161 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
162 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
163 tevent_req_error(req
, EINVAL
);
167 state
->auth_req_iov
.iov_base
= state
->auth_req_blob
.data
;
168 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
170 subreq
= tstream_unix_connect_send(state
,
174 if (tevent_req_nomem(subreq
, req
)) {
177 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
182 tevent_req_post(req
, ev
);
186 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
188 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
190 struct tevent_req
*req
=
191 tevent_req_callback_data(subreq
,
193 struct tstream_npa_connect_state
*state
=
195 struct tstream_npa_connect_state
);
199 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
200 state
, &state
->unix_stream
);
203 tevent_req_error(req
, sys_errno
);
207 subreq
= tstream_writev_send(state
,
210 &state
->auth_req_iov
, 1);
211 if (tevent_req_nomem(subreq
, req
)) {
214 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
217 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
220 struct iovec
**_vector
,
222 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
224 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
226 struct tevent_req
*req
=
227 tevent_req_callback_data(subreq
,
229 struct tstream_npa_connect_state
*state
=
231 struct tstream_npa_connect_state
);
235 ret
= tstream_writev_recv(subreq
, &sys_errno
);
238 tevent_req_error(req
, sys_errno
);
242 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
244 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
246 tstream_npa_connect_next_vector
,
248 if (tevent_req_nomem(subreq
, req
)) {
251 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
254 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
257 struct iovec
**_vector
,
260 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
261 struct tstream_npa_connect_state
);
262 struct iovec
*vector
;
266 if (state
->auth_rep_blob
.length
== 0) {
267 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
268 if (!state
->auth_rep_blob
.data
) {
271 } else if (state
->auth_rep_blob
.length
== 4) {
276 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
278 if (msg_len
> 0x00FFFFFF) {
290 state
->auth_rep_blob
.data
= talloc_realloc(state
,
291 state
->auth_rep_blob
.data
,
293 if (!state
->auth_rep_blob
.data
) {
296 state
->auth_rep_blob
.length
= msg_len
;
303 /* we need to get a message header */
304 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
308 vector
[0].iov_base
= state
->auth_rep_blob
.data
+ ofs
;
309 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
317 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
319 struct tevent_req
*req
=
320 tevent_req_callback_data(subreq
,
322 struct tstream_npa_connect_state
*state
=
324 struct tstream_npa_connect_state
);
327 enum ndr_err_code ndr_err
;
329 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
332 tevent_req_error(req
, sys_errno
);
336 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
337 (uint32_t)state
->auth_rep_blob
.length
));
338 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
340 ndr_err
= ndr_pull_struct_blob(
341 &state
->auth_rep_blob
, state
,
342 state
->caller
.smb_iconv_c
, &state
->auth_rep
,
343 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
345 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
346 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
347 ndr_map_error2string(ndr_err
)));
348 tevent_req_error(req
, EIO
);
353 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
356 if (state
->auth_rep
.length
< 16) {
357 DEBUG(0, ("req invalid length: %u < 16\n",
358 state
->auth_rep
.length
));
359 tevent_req_error(req
, EIO
);
363 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
364 DEBUG(0, ("req invalid magic: %s != %s\n",
365 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
366 tevent_req_error(req
, EIO
);
370 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
371 DEBUG(0, ("req failed: %s\n",
372 nt_errstr(state
->auth_rep
.status
)));
373 tevent_req_error(req
, EACCES
);
377 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
378 DEBUG(0, ("req invalid level: %u != %u\n",
379 state
->auth_rep
.level
, state
->auth_req
.level
));
380 tevent_req_error(req
, EIO
);
384 tevent_req_done(req
);
387 int _tstream_npa_connect_recv(struct tevent_req
*req
,
390 struct tstream_context
**_stream
,
391 uint16_t *_file_type
,
392 uint16_t *_device_state
,
393 uint64_t *_allocation_size
,
394 const char *location
)
396 struct tstream_npa_connect_state
*state
=
398 struct tstream_npa_connect_state
);
399 struct tstream_context
*stream
;
400 struct tstream_npa
*npas
;
401 uint16_t device_state
= 0;
402 uint64_t allocation_size
= 0;
404 if (tevent_req_is_unix_error(req
, perrno
)) {
405 tevent_req_received(req
);
409 stream
= tstream_context_create(mem_ctx
,
419 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
420 switch (state
->auth_rep
.level
) {
423 npas
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
424 device_state
= 0x00ff;
425 allocation_size
= 2048;
428 npas
->file_type
= state
->auth_rep
.info
.info2
.file_type
;
429 device_state
= state
->auth_rep
.info
.info2
.device_state
;
430 allocation_size
= state
->auth_rep
.info
.info2
.allocation_size
;
435 *_file_type
= npas
->file_type
;
436 *_device_state
= device_state
;
437 *_allocation_size
= allocation_size
;
438 tevent_req_received(req
);
442 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
444 struct tstream_npa
*npas
= tstream_context_data(stream
,
448 if (!npas
->unix_stream
) {
453 switch (npas
->file_type
) {
454 case FILE_TYPE_BYTE_MODE_PIPE
:
455 ret
= tstream_pending_bytes(npas
->unix_stream
);
458 case FILE_TYPE_MESSAGE_MODE_PIPE
:
459 ret
= npas
->pending
.iov_len
;
469 struct tstream_npa_readv_state
{
470 struct tstream_context
*stream
;
472 struct iovec
*vector
;
475 /* the header for message mode */
482 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
483 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
486 struct iovec
**_vector
,
488 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
490 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
491 struct tevent_context
*ev
,
492 struct tstream_context
*stream
,
493 struct iovec
*vector
,
496 struct tevent_req
*req
;
497 struct tstream_npa_readv_state
*state
;
498 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
499 struct tevent_req
*subreq
;
504 req
= tevent_req_create(mem_ctx
, &state
,
505 struct tstream_npa_readv_state
);
510 state
->stream
= stream
;
513 if (!npas
->unix_stream
) {
514 tevent_req_error(req
, ENOTCONN
);
518 switch (npas
->file_type
) {
519 case FILE_TYPE_BYTE_MODE_PIPE
:
520 state
->vector
= vector
;
521 state
->count
= count
;
523 subreq
= tstream_readv_send(state
,
528 if (tevent_req_nomem(subreq
,req
)) {
531 tevent_req_set_callback(subreq
,
532 tstream_npa_readv_byte_mode_handler
,
537 case FILE_TYPE_MESSAGE_MODE_PIPE
:
539 * we make a copy of the vector and prepend a header
542 state
->vector
= talloc_array(state
, struct iovec
, count
);
543 if (tevent_req_nomem(state
->vector
, req
)) {
546 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
547 state
->count
= count
;
550 * copy the pending buffer first
553 left
= npas
->pending
.iov_len
;
554 pbase
= (uint8_t *)npas
->pending
.iov_base
;
556 while (left
> 0 && state
->count
> 0) {
558 base
= (uint8_t *)state
->vector
[0].iov_base
;
559 if (left
< state
->vector
[0].iov_len
) {
560 memcpy(base
, pbase
+ ofs
, left
);
563 state
->vector
[0].iov_base
= base
;
564 state
->vector
[0].iov_len
-= left
;
569 ZERO_STRUCT(npas
->pending
);
572 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
574 ofs
+= state
->vector
[0].iov_len
;
575 left
-= state
->vector
[0].iov_len
;
581 ZERO_STRUCT(npas
->pending
);
587 memmove(pbase
, pbase
+ ofs
, left
);
588 npas
->pending
.iov_base
= pbase
;
589 npas
->pending
.iov_len
= left
;
591 * this cannot fail and even if it
592 * fails we can handle it
594 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
596 npas
->pending
.iov_base
= pbase
;
603 if (state
->count
== 0) {
604 tevent_req_done(req
);
608 ZERO_STRUCT(state
->hdr
);
609 state
->wait_for_hdr
= false;
611 subreq
= tstream_readv_pdu_send(state
,
614 tstream_npa_readv_next_vector
,
616 if (tevent_req_nomem(subreq
, req
)) {
619 tevent_req_set_callback(subreq
,
620 tstream_npa_readv_msg_mode_handler
,
626 /* this can't happen */
627 tevent_req_error(req
, EINVAL
);
631 tevent_req_post(req
, ev
);
635 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
637 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
639 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
640 struct tstream_npa_readv_state
);
644 ret
= tstream_readv_recv(subreq
, &sys_errno
);
647 tevent_req_error(req
, sys_errno
);
653 tevent_req_done(req
);
656 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
659 struct iovec
**_vector
,
662 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
663 struct tstream_npa_readv_state
);
664 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
666 struct iovec
*vector
;
671 if (state
->count
== 0) {
677 if (!state
->wait_for_hdr
) {
678 /* we need to get a message header */
679 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
683 ZERO_STRUCT(state
->hdr
);
684 vector
[0].iov_base
= state
->hdr
;
685 vector
[0].iov_len
= sizeof(state
->hdr
);
689 state
->wait_for_hdr
= true;
696 /* and now fill the callers buffers and maybe the pending buffer */
697 state
->wait_for_hdr
= false;
699 msg_len
= SVAL(state
->hdr
, 0);
706 state
->wait_for_hdr
= false;
708 /* +1 because we may need to fill the pending buffer */
709 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
716 while (left
> 0 && state
->count
> 0) {
717 if (left
< state
->vector
[0].iov_len
) {
719 base
= (uint8_t *)state
->vector
[0].iov_base
;
720 vector
[count
].iov_base
= base
;
721 vector
[count
].iov_len
= left
;
724 state
->vector
[0].iov_base
= base
;
725 state
->vector
[0].iov_len
-= left
;
728 vector
[count
] = state
->vector
[0];
730 left
-= state
->vector
[0].iov_len
;
737 * if the message if longer than the buffers the caller
738 * requested, we need to consume the rest of the message
739 * into the pending buffer, where the next readv can
742 npas
->pending
.iov_base
= talloc_array(npas
, uint8_t, left
);
743 if (!npas
->pending
.iov_base
) {
746 npas
->pending
.iov_len
= left
;
748 vector
[count
] = npas
->pending
;
752 state
->ret
+= (msg_len
- left
);
759 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
761 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
766 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
769 tevent_req_error(req
, sys_errno
);
774 * we do not set state->ret here as ret includes the headr size.
775 * we set it in tstream_npa_readv_pdu_next_vector()
778 tevent_req_done(req
);
781 static int tstream_npa_readv_recv(struct tevent_req
*req
,
784 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
785 struct tstream_npa_readv_state
);
788 ret
= tsocket_simple_int_recv(req
, perrno
);
793 tevent_req_received(req
);
797 struct tstream_npa_writev_state
{
798 const struct iovec
*vector
;
801 /* the header for message mode */
807 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
809 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
810 struct tevent_context
*ev
,
811 struct tstream_context
*stream
,
812 const struct iovec
*vector
,
815 struct tevent_req
*req
;
816 struct tstream_npa_writev_state
*state
;
817 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
818 struct tevent_req
*subreq
;
821 struct iovec
*new_vector
;
823 req
= tevent_req_create(mem_ctx
, &state
,
824 struct tstream_npa_writev_state
);
831 if (!npas
->unix_stream
) {
832 tevent_req_error(req
, ENOTCONN
);
836 switch (npas
->file_type
) {
837 case FILE_TYPE_BYTE_MODE_PIPE
:
838 state
->vector
= vector
;
839 state
->count
= count
;
842 case FILE_TYPE_MESSAGE_MODE_PIPE
:
844 * we make a copy of the vector and prepend a header
847 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
848 if (tevent_req_nomem(new_vector
, req
)) {
851 new_vector
[0].iov_base
= state
->hdr
;
852 new_vector
[0].iov_len
= sizeof(state
->hdr
);
853 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
855 state
->vector
= new_vector
;
856 state
->count
= count
+ 1;
859 for (i
=0; i
< count
; i
++) {
860 msg_len
+= vector
[i
].iov_len
;
863 if (msg_len
> UINT16_MAX
) {
864 tevent_req_error(req
, EMSGSIZE
);
868 SSVAL(state
->hdr
, 0, msg_len
);
872 subreq
= tstream_writev_send(state
,
877 if (tevent_req_nomem(subreq
, req
)) {
880 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
885 tevent_req_post(req
, ev
);
889 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
891 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
893 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
894 struct tstream_npa_writev_state
);
898 ret
= tstream_writev_recv(subreq
, &sys_errno
);
901 tevent_req_error(req
, sys_errno
);
907 tevent_req_done(req
);
910 static int tstream_npa_writev_recv(struct tevent_req
*req
,
913 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
914 struct tstream_npa_writev_state
);
917 ret
= tsocket_simple_int_recv(req
, perrno
);
922 tevent_req_received(req
);
926 struct tstream_npa_disconnect_state
{
927 struct tstream_context
*stream
;
930 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
932 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
933 struct tevent_context
*ev
,
934 struct tstream_context
*stream
)
936 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
937 struct tevent_req
*req
;
938 struct tstream_npa_disconnect_state
*state
;
939 struct tevent_req
*subreq
;
941 req
= tevent_req_create(mem_ctx
, &state
,
942 struct tstream_npa_disconnect_state
);
947 state
->stream
= stream
;
949 if (!npas
->unix_stream
) {
950 tevent_req_error(req
, ENOTCONN
);
954 subreq
= tstream_disconnect_send(state
,
957 if (tevent_req_nomem(subreq
, req
)) {
960 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
965 tevent_req_post(req
, ev
);
969 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
971 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
973 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
974 struct tstream_npa_disconnect_state
);
975 struct tstream_context
*stream
= state
->stream
;
976 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
980 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
983 tevent_req_error(req
, sys_errno
);
987 TALLOC_FREE(npas
->unix_stream
);
989 tevent_req_done(req
);
992 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
997 ret
= tsocket_simple_int_recv(req
, perrno
);
999 tevent_req_received(req
);
1003 static const struct tstream_context_ops tstream_npa_ops
= {
1006 .pending_bytes
= tstream_npa_pending_bytes
,
1008 .readv_send
= tstream_npa_readv_send
,
1009 .readv_recv
= tstream_npa_readv_recv
,
1011 .writev_send
= tstream_npa_writev_send
,
1012 .writev_recv
= tstream_npa_writev_recv
,
1014 .disconnect_send
= tstream_npa_disconnect_send
,
1015 .disconnect_recv
= tstream_npa_disconnect_recv
,
1018 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1021 struct tstream_context
**_stream
,
1022 const char *location
)
1024 struct tstream_context
*stream
;
1025 struct tstream_npa
*npas
;
1028 switch (file_type
) {
1029 case FILE_TYPE_BYTE_MODE_PIPE
:
1031 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1038 stream
= tstream_context_create(mem_ctx
,
1048 npas
->file_type
= file_type
;
1050 ret
= tstream_bsd_existing_socket(stream
, fd
,
1051 &npas
->unix_stream
);
1053 int saved_errno
= errno
;
1054 talloc_free(stream
);
1055 errno
= saved_errno
;