s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / rpc_client / local_np.c
blob5b1a818c88d1381f49a56a69644f57868d70f4c5
1 /*
2 * Unix SMB/CIFS implementation.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "source3/include/includes.h"
19 #include <spawn.h>
20 #include "local_np.h"
21 #include "lib/async_req/async_sock.h"
22 #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
23 #include "libcli/named_pipe_auth/npa_tstream.h"
24 #include "libcli/named_pipe_auth/tstream_u32_read.h"
25 #include "lib/util/tevent_unix.h"
26 #include "auth/auth_util.h"
28 /**
29 * @file local_np.c
31 * Connect to a local named pipe by connecting to
32 * samba-dcerpcd. Start samba-dcerpcd if it isn't
33 * already running.
36 extern bool override_logfile;
38 struct np_sock_connect_state {
39 struct tevent_context *ev;
40 struct samba_sockaddr addr;
41 const struct named_pipe_auth_req *npa_req;
42 struct named_pipe_auth_rep *npa_rep;
44 DATA_BLOB npa_blob;
45 struct iovec iov;
47 int sock;
48 struct tevent_req *subreq;
49 struct tstream_context *transport;
50 struct tstream_context *npa_stream;
53 static void np_sock_connect_cleanup(
54 struct tevent_req *req, enum tevent_req_state req_state);
55 static void np_sock_connect_before(void *private_data);
56 static void np_sock_connect_after(void *private_data);
57 static void np_sock_connect_connected(struct tevent_req *subreq);
58 static void np_sock_connect_written(struct tevent_req *subreq);
59 static void np_sock_connect_read_done(struct tevent_req *subreq);
61 static struct tevent_req *np_sock_connect_send(
62 TALLOC_CTX *mem_ctx,
63 struct tevent_context *ev,
64 const char *sockpath,
65 const struct named_pipe_auth_req *npa_req)
67 struct tevent_req *req = NULL;
68 struct np_sock_connect_state *state = NULL;
69 size_t len;
70 int ret;
71 bool ok;
73 req = tevent_req_create(mem_ctx, &state, struct np_sock_connect_state);
74 if (req == NULL) {
75 return NULL;
77 state->ev = ev;
78 state->npa_req = npa_req;
79 state->sock = -1;
80 state->addr.u.un.sun_family = AF_UNIX;
82 state->npa_rep = talloc_zero(state, struct named_pipe_auth_rep);
83 if (tevent_req_nomem(state->npa_rep, req)) {
84 return tevent_req_post(req, ev);
87 tevent_req_set_cleanup_fn(req, np_sock_connect_cleanup);
89 state->addr.sa_socklen = sizeof(struct sockaddr_un);
90 len = strlcpy(state->addr.u.un.sun_path,
91 sockpath,
92 sizeof(state->addr.u.un.sun_path));
93 if (len >= sizeof(state->addr.u.un.sun_path)) {
94 tevent_req_error(req, ENAMETOOLONG);
95 return tevent_req_post(req, ev);
98 state->sock = socket(AF_UNIX, SOCK_STREAM, 0);
99 if (state->sock == -1) {
100 tevent_req_error(req, errno);
101 return tevent_req_post(req, ev);
104 ret = set_blocking(state->sock, false);
105 if (ret == -1) {
106 tevent_req_error(req, errno);
107 return tevent_req_post(req, ev);
109 ok = set_close_on_exec(state->sock);
110 if (!ok) {
111 tevent_req_error(req, errno);
112 return tevent_req_post(req, ev);
115 state->subreq = async_connect_send(
116 state,
118 state->sock,
119 &state->addr.u.sa,
120 state->addr.sa_socklen,
121 np_sock_connect_before,
122 np_sock_connect_after,
123 NULL);
124 if (tevent_req_nomem(state->subreq, req)) {
125 return tevent_req_post(req, ev);
127 tevent_req_set_callback(state->subreq, np_sock_connect_connected, req);
129 return req;
132 static void np_sock_connect_cleanup(
133 struct tevent_req *req, enum tevent_req_state req_state)
135 struct np_sock_connect_state *state = tevent_req_data(
136 req, struct np_sock_connect_state);
138 TALLOC_FREE(state->subreq);
139 TALLOC_FREE(state->transport);
141 if (state->sock != -1) {
142 close(state->sock);
143 state->sock = -1;
147 static void np_sock_connect_before(void *private_data)
149 become_root();
152 static void np_sock_connect_after(void *private_data)
154 unbecome_root();
157 static void np_sock_connect_connected(struct tevent_req *subreq)
159 struct tevent_req *req = tevent_req_callback_data(
160 subreq, struct tevent_req);
161 struct np_sock_connect_state *state = tevent_req_data(
162 req, struct np_sock_connect_state);
163 enum ndr_err_code ndr_err;
164 int ret, err;
166 SMB_ASSERT(subreq == state->subreq);
168 ret = async_connect_recv(subreq, &err);
169 TALLOC_FREE(subreq);
170 state->subreq = NULL;
171 if (ret == -1) {
172 DBG_DEBUG("async_connect_recv returned %s\n", strerror(err));
173 tevent_req_error(req, err);
174 return;
177 ret = tstream_bsd_existing_socket(
178 state, state->sock, &state->transport);
179 if (ret == -1) {
180 err = errno;
181 DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
182 strerror(err));
183 tevent_req_error(req, err);
184 return;
186 state->sock = -1;
188 ndr_err = ndr_push_struct_blob(
189 &state->npa_blob,
190 state,
191 state->npa_req,
192 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
193 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
194 DBG_DEBUG("ndr_push_struct_blob failed: %s\n",
195 ndr_errstr(ndr_err));
196 tevent_req_error(req, ndr_map_error2errno(ndr_err));
197 return;
199 state->iov = (struct iovec) {
200 .iov_base = state->npa_blob.data,
201 .iov_len = state->npa_blob.length,
204 subreq = tstream_writev_send(
205 state, state->ev, state->transport, &state->iov, 1);
206 if (tevent_req_nomem(subreq, req)) {
207 return;
209 tevent_req_set_callback(subreq, np_sock_connect_written, req);
212 static void np_sock_connect_written(struct tevent_req *subreq)
214 struct tevent_req *req = tevent_req_callback_data(
215 subreq, struct tevent_req);
216 struct np_sock_connect_state *state = tevent_req_data(
217 req, struct np_sock_connect_state);
218 int ret, err;
220 ret = tstream_writev_recv(subreq, &err);
221 TALLOC_FREE(subreq);
222 if (ret == -1) {
223 DBG_DEBUG("tstream_writev_recv returned %s\n", strerror(err));
224 tevent_req_error(req, err);
225 return;
228 subreq = tstream_u32_read_send(
229 state, state->ev, 0x00FFFFFF, state->transport);
230 if (tevent_req_nomem(subreq, req)) {
231 return;
233 tevent_req_set_callback(subreq, np_sock_connect_read_done, req);
236 static void np_sock_connect_read_done(struct tevent_req *subreq)
238 struct tevent_req *req = tevent_req_callback_data(
239 subreq, struct tevent_req);
240 struct np_sock_connect_state *state = tevent_req_data(
241 req, struct np_sock_connect_state);
242 DATA_BLOB in;
243 int ret;
244 enum ndr_err_code ndr_err;
246 ret = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
247 TALLOC_FREE(subreq);
248 if (tevent_req_error(req, ret)) {
249 return;
252 ndr_err = ndr_pull_struct_blob_all(
253 &in,
254 state->npa_rep,
255 state->npa_rep,
256 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
257 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
258 DBG_DEBUG("ndr_pull_named_pipe_auth_rep failed: %s\n",
259 ndr_errstr(ndr_err));
260 tevent_req_error(req, ndr_map_error2errno(ndr_err));
261 return;
263 if (state->npa_rep->level != 5) {
264 DBG_DEBUG("npa level = %"PRIu32", expected 5\n",
265 state->npa_rep->level);
266 tevent_req_error(req, EIO);
267 return;
270 ret = tstream_npa_existing_stream(
271 state,
272 &state->transport,
273 state->npa_rep->info.info5.file_type,
274 &state->npa_stream);
275 if (ret == -1) {
276 ret = errno;
277 DBG_DEBUG("tstream_npa_existing_stream failed: %s\n",
278 strerror(ret));
279 tevent_req_error(req, ret);
280 return;
283 tevent_req_done(req);
286 static int np_sock_connect_recv(
287 struct tevent_req *req,
288 TALLOC_CTX *mem_ctx,
289 struct tstream_context **stream)
291 struct np_sock_connect_state *state = tevent_req_data(
292 req, struct np_sock_connect_state);
293 int err;
295 if (tevent_req_is_unix_error(req, &err)) {
296 tevent_req_received(req);
297 return err;
299 *stream = talloc_move(mem_ctx, &state->npa_stream);
300 tevent_req_received(req);
301 return 0;
304 struct start_rpc_host_state {
305 int ready_fd;
306 struct tevent_req *read_ready_req;
309 static void start_rpc_host_cleanup(
310 struct tevent_req *req, enum tevent_req_state req_state);
311 static void start_rpc_host_ready(struct tevent_req *subreq);
314 * Start samba-dcerpcd and wait for it to report ready.
316 static struct tevent_req *start_rpc_host_send(
317 TALLOC_CTX *mem_ctx, struct tevent_context *ev)
319 struct tevent_req *req = NULL, *subreq = NULL;
320 struct start_rpc_host_state *state = NULL;
321 int ret;
322 int ready_fds[2] = { -1, -1 };
323 char **argv = NULL;
324 pid_t pid;
325 bool ok;
327 req = tevent_req_create(
328 mem_ctx, &state, struct start_rpc_host_state);
329 if (req == NULL) {
330 return NULL;
333 ret = pipe(ready_fds);
334 if (ret == -1) {
335 ret = errno;
336 DBG_DEBUG("pipe() failed: %s\n", strerror(ret));
337 goto fail;
340 ok = smb_set_close_on_exec(ready_fds[0]);
341 if (!ok) {
342 ret = errno;
343 DBG_DEBUG("smb_set_close_on_exec failed: %s\n",
344 strerror(ret));
345 goto fail;
348 argv = str_list_make_empty(mem_ctx);
349 str_list_add_printf(
350 &argv, "%s/samba-dcerpcd", get_dyn_SAMBA_LIBEXECDIR());
351 if (!is_default_dyn_CONFIGFILE()) {
352 str_list_add_printf(
353 &argv, "--configfile=%s", get_dyn_CONFIGFILE());
355 str_list_add_printf(&argv, "--libexec-rpcds");
356 str_list_add_printf(&argv, "--ready-signal-fd=%d", ready_fds[1]);
357 str_list_add_printf(&argv, "--np-helper");
358 str_list_add_printf(
359 &argv, "--debuglevel=%d", debuglevel_get_class(DBGC_RPC_SRV));
360 if (!is_default_dyn_LOGFILEBASE()) {
361 str_list_add_printf(
362 &argv, "--log-basename=%s", get_dyn_LOGFILEBASE());
364 if (argv == NULL) {
365 errno = ENOMEM;
366 goto fail;
369 become_root();
370 ret = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
371 unbecome_root();
372 if (ret != 0) {
373 DBG_DEBUG("posix_spawn() failed: %s\n", strerror(ret));
374 goto fail;
377 state->ready_fd = ready_fds[0];
378 ready_fds[0] = -1;
379 tevent_req_set_cleanup_fn(req, start_rpc_host_cleanup);
381 close(ready_fds[1]);
382 ready_fds[1] = -1;
384 subreq = read_packet_send(state, ev, state->ready_fd, 1, NULL, NULL);
385 if (tevent_req_nomem(subreq, req)) {
386 return tevent_req_post(req, ev);
388 tevent_req_set_callback(subreq, start_rpc_host_ready, req);
389 return req;
391 fail:
392 if (ready_fds[0] == -1) {
393 close(ready_fds[0]);
394 ready_fds[0] = -1;
396 if (ready_fds[1] == -1) {
397 close(ready_fds[1]);
398 ready_fds[1] = -1;
400 tevent_req_error(req, ret);
401 return tevent_req_post(req, ev);
404 static void start_rpc_host_cleanup(
405 struct tevent_req *req, enum tevent_req_state req_state)
407 struct start_rpc_host_state *state = tevent_req_data(
408 req, struct start_rpc_host_state);
410 if (state->ready_fd != -1) {
411 close(state->ready_fd);
412 state->ready_fd = -1;
416 static void start_rpc_host_ready(struct tevent_req *subreq)
418 struct tevent_req *req = tevent_req_callback_data(
419 subreq, struct tevent_req);
420 struct start_rpc_host_state *state = tevent_req_data(
421 req, struct start_rpc_host_state);
422 uint8_t *buf;
423 int err;
424 ssize_t nread;
426 nread = read_packet_recv(subreq, state, &buf, &err);
427 TALLOC_FREE(subreq);
428 if (nread == -1) {
429 tevent_req_error(req, err);
430 return;
433 close(state->ready_fd);
434 state->ready_fd = -1;
436 tevent_req_done(req);
439 static int start_rpc_host_recv(struct tevent_req *req)
441 return tevent_req_simple_recv_unix(req);
444 struct local_np_connect_state {
445 struct tevent_context *ev;
446 const char *socketpath;
447 struct named_pipe_auth_req *npa_req;
448 struct tstream_context *npa_stream;
451 static void local_np_connect_connected(struct tevent_req *subreq);
452 static void local_np_connect_started(struct tevent_req *subreq);
453 static void local_np_connect_retried(struct tevent_req *subreq);
456 * @brief Async connect to a local named pipe RPC interface
458 * Start "samba-dcerpcd" on demand if it does not exist
460 * @param[in] mem_ctx The memory context to use.
461 * @param[in] ev The tevent context to use.
463 * @param[in] pipename The raw pipename to connect to without path
464 * @param[in] remote_client_name The client name to transmit
465 * @param[in] remote_client_addr The client addr to transmit
466 * @param[in] local_server_name The server name to transmit
467 * @param[in] local_server_addr The server addr to transmit
468 * @param[in] session_info The authorization info to use
469 * @param[in] need_idle_server Does this need to be an exclusive server?
470 * @return The tevent_req that was started
473 struct tevent_req *local_np_connect_send(
474 TALLOC_CTX *mem_ctx,
475 struct tevent_context *ev,
476 const char *pipename,
477 enum dcerpc_transport_t transport,
478 const char *remote_client_name,
479 const struct tsocket_address *remote_client_addr,
480 const char *local_server_name,
481 const struct tsocket_address *local_server_addr,
482 const struct auth_session_info *session_info,
483 bool need_idle_server)
485 struct tevent_req *req = NULL, *subreq = NULL;
486 struct local_np_connect_state *state = NULL;
487 struct named_pipe_auth_req_info5 *i5 = NULL;
488 const char *socket_dir = NULL;
489 char *lower_case_pipename = NULL;
491 req = tevent_req_create(
492 mem_ctx, &state, struct local_np_connect_state);
493 if (req == NULL) {
494 return NULL;
496 state->ev = ev;
498 socket_dir = lp_parm_const_string(
499 GLOBAL_SECTION_SNUM, "external_rpc_pipe", "socket_dir",
500 lp_ncalrpc_dir());
501 if (socket_dir == NULL) {
502 DBG_DEBUG("external_rpc_pipe:socket_dir not set\n");
503 tevent_req_error(req, EINVAL);
504 return tevent_req_post(req, ev);
507 lower_case_pipename = strlower_talloc(state, pipename);
508 if (tevent_req_nomem(lower_case_pipename, req)) {
509 return tevent_req_post(req, ev);
512 state->socketpath = talloc_asprintf(
513 state, "%s/np/%s", socket_dir, lower_case_pipename);
514 if (tevent_req_nomem(state->socketpath, req)) {
515 return tevent_req_post(req, ev);
517 TALLOC_FREE(lower_case_pipename);
519 state->npa_req = talloc_zero(state, struct named_pipe_auth_req);
520 if (tevent_req_nomem(state->npa_req, req)) {
521 return tevent_req_post(req, ev);
523 state->npa_req->level = 5;
525 i5 = &state->npa_req->info.info5;
527 i5->transport = transport;
529 /* we don't have "int" in IDL, make sure we don't overflow */
530 SMB_ASSERT(i5->transport == transport);
532 if (remote_client_name == NULL) {
533 remote_client_name = get_myname(state->npa_req);
534 if (remote_client_name == NULL) {
535 tevent_req_error(req, errno);
536 return tevent_req_post(req, ev);
539 i5->remote_client_name = remote_client_name;
541 if (remote_client_addr == NULL) {
542 struct tsocket_address *addr = NULL;
543 int ret = tsocket_address_inet_from_strings(
544 state->npa_req, "ip", NULL, 0, &addr);
545 if (ret != 0) {
546 tevent_req_error(req, errno);
547 return tevent_req_post(req, ev);
549 remote_client_addr = addr;
551 i5->remote_client_addr = tsocket_address_inet_addr_string(
552 remote_client_addr, state->npa_req);
553 if (i5->remote_client_addr == NULL) {
554 tevent_req_error(req, errno);
555 return tevent_req_post(req, ev);
557 i5->remote_client_port = tsocket_address_inet_port(remote_client_addr);
559 if (local_server_name == NULL) {
560 local_server_name = remote_client_name;
562 i5->local_server_name = local_server_name;
564 if (local_server_addr == NULL) {
565 struct tsocket_address *addr = NULL;
566 int ret = tsocket_address_inet_from_strings(
567 state->npa_req, "ip", NULL, 0, &addr);
568 if (ret != 0) {
569 tevent_req_error(req, errno);
570 return tevent_req_post(req, ev);
572 local_server_addr = addr;
574 i5->local_server_addr = tsocket_address_inet_addr_string(
575 local_server_addr, state->npa_req);
576 if (i5->local_server_addr == NULL) {
577 tevent_req_error(req, errno);
578 return tevent_req_post(req, ev);
580 i5->local_server_port = tsocket_address_inet_port(local_server_addr);
582 i5->session_info = talloc_zero(
583 state->npa_req, struct auth_session_info_transport);
584 if (tevent_req_nomem(i5->session_info, req)) {
585 return tevent_req_post(req, ev);
588 i5->session_info->session_info = copy_session_info(
589 i5->session_info, session_info);
590 if (tevent_req_nomem(i5->session_info->session_info, req)) {
591 return tevent_req_post(req, ev);
594 i5->need_idle_server = need_idle_server;
596 subreq = np_sock_connect_send(
597 state, state->ev, state->socketpath, state->npa_req);
598 if (tevent_req_nomem(subreq, req)) {
599 return tevent_req_post(req, ev);
601 tevent_req_set_callback(subreq, local_np_connect_connected, req);
603 return req;
606 static void local_np_connect_connected(struct tevent_req *subreq)
608 struct tevent_req *req = tevent_req_callback_data(
609 subreq, struct tevent_req);
610 struct local_np_connect_state *state = tevent_req_data(
611 req, struct local_np_connect_state);
612 int ret;
614 ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
615 TALLOC_FREE(subreq);
617 if (ret == 0) {
618 tevent_req_done(req);
619 return;
622 DBG_DEBUG("np_sock_connect failed: %s\n", strerror(ret));
624 if (!lp_rpc_start_on_demand_helpers()) {
626 * samba-dcerpcd should already be started in
627 * daemon/standalone mode when "rpc start on demand
628 * helpers = false". We are prohibited from starting
629 * on demand as a named-pipe helper.
631 DBG_ERR("Can't connect to a running samba-dcerpcd. smb.conf "
632 "config prohibits starting as named pipe helper as "
633 "the [global] section contains "
634 "\"rpc start on demand helpers = false\".\n");
635 tevent_req_error(req, ret);
636 return;
640 * samba-dcerpcd isn't running. We need to start it.
641 * Note if it doesn't start we treat this as a fatal
642 * error for connecting to the named pipe and don't
643 * keep trying to restart for this connection.
645 subreq = start_rpc_host_send(state, state->ev);
646 if (tevent_req_nomem(subreq, req)) {
647 return;
649 tevent_req_set_callback(subreq, local_np_connect_started, req);
652 static void local_np_connect_started(struct tevent_req *subreq)
654 struct tevent_req *req = tevent_req_callback_data(
655 subreq, struct tevent_req);
656 struct local_np_connect_state *state = tevent_req_data(
657 req, struct local_np_connect_state);
658 int ret;
660 ret = start_rpc_host_recv(subreq);
661 TALLOC_FREE(subreq);
662 if (tevent_req_error(req, ret)) {
663 DBG_DEBUG("start_rpc_host_recv failed: %s\n",
664 strerror(ret));
665 return;
668 subreq = np_sock_connect_send(
669 state, state->ev, state->socketpath, state->npa_req);
670 if (tevent_req_nomem(subreq, req)) {
671 return;
673 tevent_req_set_callback(subreq, local_np_connect_retried, req);
676 static void local_np_connect_retried(struct tevent_req *subreq)
678 struct tevent_req *req = tevent_req_callback_data(
679 subreq, struct tevent_req);
680 struct local_np_connect_state *state = tevent_req_data(
681 req, struct local_np_connect_state);
682 int ret;
684 ret = np_sock_connect_recv(subreq, state, &state->npa_stream);
685 TALLOC_FREE(subreq);
686 if (tevent_req_error(req, ret)) {
687 return;
689 tevent_req_done(req);
693 * @brief Receive handle to a local named pipe RPC interface
695 * @param[in] req The tevent_req that started the operation
696 * @param[in] ev The tevent context to use.
697 * @param[in] mem_ctx The memory context to put pstream on
698 * @param[out] pstream The established connection to the RPC server
700 * @return 0/errno
703 int local_np_connect_recv(
704 struct tevent_req *req,
705 TALLOC_CTX *mem_ctx,
706 struct tstream_context **pstream)
708 struct local_np_connect_state *state = tevent_req_data(
709 req, struct local_np_connect_state);
710 int err;
712 if (tevent_req_is_unix_error(req, &err)) {
713 tevent_req_received(req);
714 return err;
717 *pstream = talloc_move(mem_ctx, &state->npa_stream);
718 return 0;
722 * @brief Sync connect to a local named pipe RPC interface
724 * Start "samba-dcerpcd" on demand if it does not exist
726 * @param[in] pipename The raw pipename to connect to without path
727 * @param[in] remote_client_name The client name to transmit
728 * @param[in] remote_client_addr The client addr to transmit
729 * @param[in] local_server_name The server name to transmit
730 * @param[in] local_server_addr The server addr to transmit
731 * @param[in] session_info The authorization info to use
732 * @param[in] need_idle_server Does this need to be an exclusive server?
733 * @param[in] mem_ctx The memory context to use.
734 * @param[out] pstream The established connection to the RPC server
735 * @return 0/errno
738 int local_np_connect(
739 const char *pipename,
740 enum dcerpc_transport_t transport,
741 const char *remote_client_name,
742 const struct tsocket_address *remote_client_addr,
743 const char *local_server_name,
744 const struct tsocket_address *local_server_addr,
745 const struct auth_session_info *session_info,
746 bool need_idle_server,
747 TALLOC_CTX *mem_ctx,
748 struct tstream_context **pstream)
750 struct tevent_context *ev = NULL;
751 struct tevent_req *req = NULL;
752 int ret = ENOMEM;
754 ev = samba_tevent_context_init(mem_ctx);
755 if (ev == NULL) {
756 goto fail;
758 req = local_np_connect_send(
761 pipename,
762 transport,
763 remote_client_name,
764 remote_client_addr,
765 local_server_name,
766 local_server_addr,
767 session_info,
768 need_idle_server);
769 if (req == NULL) {
770 goto fail;
772 if (!tevent_req_poll_unix(req, ev, &ret)) {
773 goto fail;
775 ret = local_np_connect_recv(req, mem_ctx, pstream);
776 fail:
777 TALLOC_FREE(req);
778 TALLOC_FREE(ev);
779 return ret;