2 * Samba Unix/Linux SMB client library
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/>.
20 #include "netlogon_ping.h"
21 #include "libcli/netlogon/netlogon_proto.h"
22 #include "libcli/ldap/ldap_ndr.h"
23 #include "libcli/ldap/ldap_message.h"
24 #include "libcli/cldap/cldap.h"
25 #include "source3/include/tldap.h"
26 #include "source3/include/tldap_util.h"
27 #include "source3/lib/tldap_tls_connect.h"
28 #include "lib/util/tevent_unix.h"
29 #include "lib/util/tevent_ntstatus.h"
30 #include "source4/lib/tls/tls.h"
31 #include "source3/libads/cldap.h"
32 #include "librpc/gen_ndr/netlogon.h"
34 #define RETURN_ON_FALSE(x) \
38 bool check_cldap_reply_required_flags(uint32_t ret_flags
, uint32_t req_flags
)
44 if (req_flags
& DS_PDC_REQUIRED
)
45 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_PDC
);
47 if (req_flags
& DS_GC_SERVER_REQUIRED
)
48 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_GC
);
50 if (req_flags
& DS_ONLY_LDAP_NEEDED
)
51 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_LDAP
);
53 if ((req_flags
& DS_DIRECTORY_SERVICE_REQUIRED
) ||
54 (req_flags
& DS_DIRECTORY_SERVICE_PREFERRED
))
55 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_DS
);
57 if (req_flags
& DS_KDC_REQUIRED
)
58 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_KDC
);
60 if (req_flags
& DS_TIMESERV_REQUIRED
)
61 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_TIMESERV
);
63 if (req_flags
& DS_WEB_SERVICE_REQUIRED
)
64 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_ADS_WEB_SERVICE
);
66 if (req_flags
& DS_WRITABLE_REQUIRED
)
67 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_WRITABLE
);
69 if (req_flags
& DS_DIRECTORY_SERVICE_6_REQUIRED
)
70 RETURN_ON_FALSE(ret_flags
&
71 (NBT_SERVER_SELECT_SECRET_DOMAIN_6
|
72 NBT_SERVER_FULL_SECRET_DOMAIN_6
));
74 if (req_flags
& DS_DIRECTORY_SERVICE_8_REQUIRED
)
75 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_DS_8
);
77 if (req_flags
& DS_DIRECTORY_SERVICE_9_REQUIRED
)
78 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_DS_9
);
80 if (req_flags
& DS_DIRECTORY_SERVICE_10_REQUIRED
)
81 RETURN_ON_FALSE(ret_flags
& NBT_SERVER_DS_10
);
86 struct ldap_netlogon_state
{
87 struct tevent_context
*ev
;
88 struct tsocket_address
*local
;
89 struct tsocket_address
*remote
;
90 enum client_netlogon_ping_protocol proto
;
93 struct tstream_context
*plain
;
94 struct tldap_context
*tldap
;
95 struct tstream_tls_params
*tls_params
;
97 struct netlogon_samlogon_response
*response
;
100 static void ldap_netlogon_connected(struct tevent_req
*subreq
);
101 static void ldap_netlogon_starttls_done(struct tevent_req
*subreq
);
102 static void ldap_netlogon_tls_set_up(struct tevent_req
*subreq
);
103 static void ldap_netlogon_search(struct tevent_req
*req
);
104 static void ldap_netlogon_searched(struct tevent_req
*subreq
);
106 static struct tevent_req
*ldap_netlogon_send(
108 struct tevent_context
*ev
,
109 const struct tsocket_address
*server
,
110 enum client_netlogon_ping_protocol proto
,
113 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
114 struct ldap_netlogon_state
*state
= NULL
;
118 req
= tevent_req_create(mem_ctx
, &state
, struct ldap_netlogon_state
);
123 state
->filter
= filter
;
124 state
->proto
= proto
;
126 state
->remote
= tsocket_address_copy(server
, state
);
127 if (tevent_req_nomem(state
->remote
, req
)) {
128 return tevent_req_post(req
, ev
);
131 port
= (proto
== CLIENT_NETLOGON_PING_LDAPS
) ? 636 : 389;
133 ret
= tsocket_address_inet_set_port(state
->remote
, port
);
135 tevent_req_nterror(req
, map_nt_error_from_unix_common(errno
));
136 return tevent_req_post(req
, ev
);
139 ret
= tsocket_address_inet_from_strings(
140 state
, "ip", NULL
, 0, &state
->local
);
142 tevent_req_nterror(req
, map_nt_error_from_unix_common(errno
));
143 return tevent_req_post(req
, ev
);
146 subreq
= tstream_inet_tcp_connect_send(state
,
150 if (tevent_req_nomem(subreq
, req
)) {
151 return tevent_req_post(req
, ev
);
153 tevent_req_set_callback(subreq
, ldap_netlogon_connected
, req
);
158 static void ldap_netlogon_connected(struct tevent_req
*subreq
)
160 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
162 struct ldap_netlogon_state
*state
= tevent_req_data(
163 req
, struct ldap_netlogon_state
);
167 ret
= tstream_inet_tcp_connect_recv(
168 subreq
, &err
, state
, &state
->plain
, NULL
);
171 tevent_req_nterror(req
, map_nt_error_from_unix_common(err
));
175 state
->tldap
= tldap_context_create_from_plain_stream(
176 state
, &state
->plain
);
177 if (tevent_req_nomem(state
->tldap
, req
)) {
181 if (state
->proto
== CLIENT_NETLOGON_PING_LDAP
) {
182 ldap_netlogon_search(req
);
186 status
= tstream_tls_params_client(state
,
192 TLS_VERIFY_PEER_NO_CHECK
,
195 if (tevent_req_nterror(req
, status
)) {
196 DBG_ERR("tstream_tls_params_client(NO_CHECK): %s\n",
201 if (state
->proto
== CLIENT_NETLOGON_PING_STARTTLS
) {
202 subreq
= tldap_extended_send(state
,
205 LDB_EXTENDED_START_TLS_OID
,
211 if (tevent_req_nomem(subreq
, req
)) {
214 tevent_req_set_callback(subreq
,
215 ldap_netlogon_starttls_done
,
220 subreq
= tldap_tls_connect_send(state
,
224 if (tevent_req_nomem(subreq
, req
)) {
227 tevent_req_set_callback(subreq
, ldap_netlogon_tls_set_up
, req
);
230 static void ldap_netlogon_starttls_done(struct tevent_req
*subreq
)
232 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
234 struct ldap_netlogon_state
*state
= tevent_req_data(
235 req
, struct ldap_netlogon_state
);
238 rc
= tldap_extended_recv(subreq
, NULL
, NULL
, NULL
);
240 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
241 tevent_req_nterror(req
, NT_STATUS_LDAP(TLDAP_RC_V(rc
)));
245 subreq
= tldap_tls_connect_send(state
,
249 if (tevent_req_nomem(subreq
, req
)) {
252 tevent_req_set_callback(subreq
, ldap_netlogon_tls_set_up
, req
);
255 static void ldap_netlogon_tls_set_up(struct tevent_req
*subreq
)
257 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
261 rc
= tldap_tls_connect_recv(subreq
);
263 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
264 tevent_req_nterror(req
, NT_STATUS_LDAP(TLDAP_RC_V(rc
)));
268 ldap_netlogon_search(req
);
271 static void ldap_netlogon_search(struct tevent_req
*req
)
273 struct ldap_netlogon_state
*state
= tevent_req_data(
274 req
, struct ldap_netlogon_state
);
275 static const char *attrs
[] = {"netlogon"};
276 struct tevent_req
*subreq
= NULL
;
278 subreq
= tldap_search_all_send(state
,
294 if (tevent_req_nomem(subreq
, req
)) {
297 tevent_req_set_callback(subreq
, ldap_netlogon_searched
, req
);
300 static void ldap_netlogon_searched(struct tevent_req
*subreq
)
302 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
304 struct ldap_netlogon_state
*state
= tevent_req_data(
305 req
, struct ldap_netlogon_state
);
306 struct tldap_message
**msgs
= NULL
;
307 DATA_BLOB blob
= {.data
= NULL
};
312 rc
= tldap_search_all_recv(subreq
, state
, &msgs
, NULL
);
314 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
315 tevent_req_nterror(req
, NT_STATUS_LDAP(TLDAP_RC_V(rc
)));
319 if (talloc_array_length(msgs
) != 1) {
320 tevent_req_nterror(req
,
321 NT_STATUS_LDAP(TLDAP_RC_V(
322 TLDAP_NO_RESULTS_RETURNED
)));
326 ok
= tldap_get_single_valueblob(msgs
[0], "netlogon", &blob
);
328 tevent_req_nterror(req
,
329 NT_STATUS_LDAP(TLDAP_RC_V(
330 TLDAP_NO_RESULTS_RETURNED
)));
334 state
->response
= talloc(state
, struct netlogon_samlogon_response
);
335 if (tevent_req_nomem(state
->response
, req
)) {
339 status
= pull_netlogon_samlogon_response(&blob
,
342 if (!NT_STATUS_IS_OK(status
)) {
343 tevent_req_nterror(req
, status
);
347 tevent_req_done(req
);
350 static NTSTATUS
ldap_netlogon_recv(
351 struct tevent_req
*req
,
353 struct netlogon_samlogon_response
**response
)
355 struct ldap_netlogon_state
*state
= tevent_req_data(
356 req
, struct ldap_netlogon_state
);
359 if (tevent_req_is_nterror(req
, &status
)) {
362 *response
= talloc_move(mem_ctx
, &state
->response
);
363 tevent_req_received(req
);
367 struct cldap_netlogon_ping_state
{
368 struct cldap_socket
*sock
;
369 struct cldap_search search
;
370 struct netlogon_samlogon_response
*response
;
373 static void cldap_netlogon_ping_done(struct tevent_req
*subreq
);
375 static struct tevent_req
*cldap_netlogon_ping_send(
377 struct tevent_context
*ev
,
378 const struct tsocket_address
*server
,
381 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
382 struct cldap_netlogon_ping_state
*state
= NULL
;
383 struct tsocket_address
*server_389
= NULL
;
384 static const char *const attr
[] = {"NetLogon", NULL
};
388 req
= tevent_req_create(mem_ctx
,
390 struct cldap_netlogon_ping_state
);
395 server_389
= tsocket_address_copy(server
, state
);
396 if (tevent_req_nomem(server_389
, req
)) {
397 return tevent_req_post(req
, ev
);
400 ret
= tsocket_address_inet_set_port(server_389
, 389);
402 tevent_req_nterror(req
, map_nt_error_from_unix_common(errno
));
403 return tevent_req_post(req
, ev
);
406 status
= cldap_socket_init(state
, NULL
, server_389
, &state
->sock
);
407 if (tevent_req_nterror(req
, status
)) {
408 return tevent_req_post(req
, ev
);
411 state
->search
= (struct cldap_search
){
413 .in
.attributes
= attr
,
418 subreq
= cldap_search_send(state
, ev
, state
->sock
, &state
->search
);
419 if (tevent_req_nomem(subreq
, req
)) {
420 return tevent_req_post(req
, ev
);
422 tevent_req_set_callback(subreq
, cldap_netlogon_ping_done
, req
);
426 static void cldap_netlogon_ping_done(struct tevent_req
*subreq
)
428 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
430 struct cldap_netlogon_ping_state
*state
= tevent_req_data(
431 req
, struct cldap_netlogon_ping_state
);
432 struct ldap_SearchResEntry
*resp
= NULL
;
435 status
= cldap_search_recv(subreq
, state
, &state
->search
);
437 if (tevent_req_nterror(req
, status
)) {
441 TALLOC_FREE(state
->sock
);
443 resp
= state
->search
.out
.response
;
446 tevent_req_nterror(req
, NT_STATUS_NOT_FOUND
);
450 if (resp
->num_attributes
!= 1 ||
451 !strequal(resp
->attributes
[0].name
, "netlogon") ||
452 resp
->attributes
[0].num_values
!= 1 ||
453 resp
->attributes
[0].values
->length
< 2)
455 tevent_req_nterror(req
, NT_STATUS_UNEXPECTED_NETWORK_ERROR
);
459 state
->response
= talloc(state
, struct netlogon_samlogon_response
);
460 if (tevent_req_nomem(state
->response
, req
)) {
464 status
= pull_netlogon_samlogon_response(resp
->attributes
[0].values
,
467 if (tevent_req_nterror(req
, status
)) {
470 tevent_req_done(req
);
473 static NTSTATUS
cldap_netlogon_ping_recv(
474 struct tevent_req
*req
,
476 struct netlogon_samlogon_response
**response
)
478 struct cldap_netlogon_ping_state
*state
= tevent_req_data(
479 req
, struct cldap_netlogon_ping_state
);
482 if (tevent_req_is_nterror(req
, &status
)) {
485 *response
= talloc_move(mem_ctx
, &state
->response
);
486 tevent_req_received(req
);
490 struct netlogon_ping_state
{
491 struct netlogon_samlogon_response
*response
;
494 static void netlogon_ping_done_cldap(struct tevent_req
*subreq
);
495 static void netlogon_ping_done_ldaps(struct tevent_req
*subreq
);
497 static struct tevent_req
*netlogon_ping_send(
499 struct tevent_context
*ev
,
500 struct tsocket_address
*server
,
501 enum client_netlogon_ping_protocol proto
,
503 struct timeval timeout
)
505 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
506 struct netlogon_ping_state
*state
= NULL
;
508 req
= tevent_req_create(mem_ctx
, &state
, struct netlogon_ping_state
);
514 case CLIENT_NETLOGON_PING_CLDAP
:
515 subreq
= cldap_netlogon_ping_send(state
, ev
, server
, filter
);
516 if (tevent_req_nomem(subreq
, req
)) {
517 return tevent_req_post(req
, ev
);
519 tevent_req_set_callback(subreq
, netlogon_ping_done_cldap
, req
);
521 case CLIENT_NETLOGON_PING_LDAP
:
522 case CLIENT_NETLOGON_PING_LDAPS
:
523 case CLIENT_NETLOGON_PING_STARTTLS
:
524 subreq
= ldap_netlogon_send(state
, ev
, server
, proto
, filter
);
525 if (tevent_req_nomem(subreq
, req
)) {
526 return tevent_req_post(req
, ev
);
528 tevent_req_set_callback(subreq
, netlogon_ping_done_ldaps
, req
);
531 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
532 return tevent_req_post(req
, ev
);
539 static void netlogon_ping_done_cldap(struct tevent_req
*subreq
)
541 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
543 struct netlogon_ping_state
*state
= tevent_req_data(
544 req
, struct netlogon_ping_state
);
547 status
= cldap_netlogon_ping_recv(subreq
, state
, &state
->response
);
548 if (tevent_req_nterror(req
, status
)) {
551 tevent_req_done(req
);
554 static void netlogon_ping_done_ldaps(struct tevent_req
*subreq
)
556 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
558 struct netlogon_ping_state
*state
= tevent_req_data(
559 req
, struct netlogon_ping_state
);
562 status
= ldap_netlogon_recv(subreq
, state
, &state
->response
);
564 if (tevent_req_nterror(req
, status
)) {
567 tevent_req_done(req
);
570 static NTSTATUS
netlogon_ping_recv(
571 struct tevent_req
*req
,
573 struct netlogon_samlogon_response
**response
)
575 struct netlogon_ping_state
*state
= tevent_req_data(
576 req
, struct netlogon_ping_state
);
579 if (tevent_req_is_nterror(req
, &status
)) {
582 *response
= talloc_move(mem_ctx
, &state
->response
);
586 struct netlogon_pings_state
{
587 struct tevent_context
*ev
;
589 struct tsocket_address
**servers
;
592 struct timeval timeout
;
593 enum client_netlogon_ping_protocol proto
;
594 uint32_t required_flags
;
599 size_t num_good_received
;
600 struct tevent_req
**reqs
;
601 struct netlogon_samlogon_response
**responses
;
604 static void netlogon_pings_next(struct tevent_req
*subreq
);
605 static void netlogon_pings_done(struct tevent_req
*subreq
);
607 struct tevent_req
*netlogon_pings_send(TALLOC_CTX
*mem_ctx
,
608 struct tevent_context
*ev
,
609 enum client_netlogon_ping_protocol proto
,
610 struct tsocket_address
**servers
,
612 struct netlogon_ping_filter filter
,
614 struct timeval timeout
)
616 struct tevent_req
*req
= NULL
;
617 struct netlogon_pings_state
*state
= NULL
;
618 char *filter_str
= NULL
;
621 req
= tevent_req_create(mem_ctx
, &state
, struct netlogon_pings_state
);
626 state
->proto
= proto
;
627 state
->servers
= servers
;
628 state
->num_servers
= num_servers
;
629 state
->min_servers
= min_servers
;
630 state
->timeout
= timeout
;
631 state
->required_flags
= filter
.required_flags
;
633 state
->reqs
= talloc_zero_array(state
,
636 if (tevent_req_nomem(state
->reqs
, req
)) {
637 return tevent_req_post(req
, ev
);
640 state
->responses
= talloc_zero_array(
641 state
, struct netlogon_samlogon_response
*, num_servers
);
642 if (tevent_req_nomem(state
->responses
, req
)) {
643 return tevent_req_post(req
, ev
);
646 filter_str
= talloc_asprintf(state
,
648 ldap_encode_ndr_uint32(state
,
650 if (filter
.domain
!= NULL
) {
651 talloc_asprintf_addbuf(&filter_str
,
655 if (filter
.acct_ctrl
!= -1) {
656 talloc_asprintf_addbuf(
659 ldap_encode_ndr_uint32(mem_ctx
, filter
.acct_ctrl
));
661 if (filter
.domain_sid
!= NULL
) {
662 talloc_asprintf_addbuf(
665 ldap_encode_ndr_dom_sid(mem_ctx
, filter
.domain_sid
));
667 if (filter
.domain_guid
!= NULL
) {
668 talloc_asprintf_addbuf(
671 ldap_encode_ndr_GUID(mem_ctx
, filter
.domain_guid
));
673 if (filter
.hostname
!= NULL
) {
674 talloc_asprintf_addbuf(&filter_str
,
678 if (filter
.user
!= NULL
) {
679 talloc_asprintf_addbuf(&filter_str
, "(User=%s)", filter
.user
);
681 talloc_asprintf_addbuf(&filter_str
, ")");
683 if (tevent_req_nomem(filter_str
, req
)) {
684 return tevent_req_post(req
, ev
);
686 state
->filter
= filter_str
;
688 for (i
= 0; i
< min_servers
; i
++) {
689 state
->reqs
[i
] = netlogon_ping_send(state
->reqs
,
695 if (tevent_req_nomem(state
->reqs
[i
], req
)) {
696 return tevent_req_post(req
, ev
);
698 tevent_req_set_callback(state
->reqs
[i
],
702 state
->num_sent
= min_servers
;
703 if (state
->num_sent
< state
->num_servers
) {
705 * After 100 milliseconds fire the next one
707 struct tevent_req
*subreq
= tevent_wakeup_send(
708 state
, state
->ev
, timeval_current_ofs(0, 100000));
709 if (tevent_req_nomem(subreq
, req
)) {
710 return tevent_req_post(req
, ev
);
712 tevent_req_set_callback(subreq
, netlogon_pings_next
, req
);
718 static void netlogon_pings_next(struct tevent_req
*subreq
)
720 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
722 struct netlogon_pings_state
*state
= tevent_req_data(
723 req
, struct netlogon_pings_state
);
726 ret
= tevent_wakeup_recv(subreq
);
729 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
733 subreq
= netlogon_ping_send(state
->reqs
,
735 state
->servers
[state
->num_sent
],
739 if (tevent_req_nomem(subreq
, req
)) {
742 tevent_req_set_callback(subreq
, netlogon_pings_done
, req
);
743 state
->reqs
[state
->num_sent
] = subreq
;
744 state
->num_sent
+= 1;
746 if (state
->num_sent
< state
->num_servers
) {
748 * After 100 milliseconds fire the next one
750 subreq
= tevent_wakeup_send(state
,
752 timeval_current_ofs(0, 100000));
753 if (tevent_req_nomem(subreq
, req
)) {
756 tevent_req_set_callback(subreq
, netlogon_pings_next
, req
);
760 static void netlogon_pings_done(struct tevent_req
*subreq
)
762 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
764 struct netlogon_pings_state
*state
= tevent_req_data(
765 req
, struct netlogon_pings_state
);
766 struct netlogon_samlogon_response
*response
= NULL
;
770 for (i
= 0; i
< state
->num_sent
; i
++) {
771 if (state
->reqs
[i
] == subreq
) {
776 if (i
== state
->num_sent
) {
778 * Got a response we did not fire...
780 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
783 state
->reqs
[i
] = NULL
;
785 status
= netlogon_ping_recv(subreq
, state
, &response
);
787 state
->num_received
+= 1;
789 if (NT_STATUS_IS_OK(status
)) {
793 switch (response
->ntver
) {
794 case NETLOGON_NT_VERSION_5EX
:
795 ret_flags
= response
->data
.nt5_ex
.server_type
;
797 case NETLOGON_NT_VERSION_5
:
798 ret_flags
= response
->data
.nt5
.server_type
;
805 ok
= check_cldap_reply_required_flags(ret_flags
,
806 state
->required_flags
);
808 state
->responses
[i
] = talloc_move(state
->responses
,
810 state
->num_good_received
+= 1;
814 if (state
->num_good_received
>= state
->min_servers
) {
815 tevent_req_done(req
);
818 if (state
->num_received
== state
->num_servers
) {
820 * Everybody replied, but we did not get enough good
821 * answers (see above)
823 tevent_req_nterror(req
, NT_STATUS_NOT_FOUND
);
827 * Wait for more answers
831 NTSTATUS
netlogon_pings_recv(struct tevent_req
*req
,
833 struct netlogon_samlogon_response
***responses
)
835 struct netlogon_pings_state
*state
= tevent_req_data(
836 req
, struct netlogon_pings_state
);
839 if (tevent_req_is_nterror(req
, &status
)) {
842 *responses
= talloc_move(mem_ctx
, &state
->responses
);
843 tevent_req_received(req
);
847 NTSTATUS
netlogon_pings(TALLOC_CTX
*mem_ctx
,
848 enum client_netlogon_ping_protocol proto
,
849 struct tsocket_address
**servers
,
851 struct netlogon_ping_filter filter
,
853 struct timeval timeout
,
854 struct netlogon_samlogon_response
***responses
)
856 TALLOC_CTX
*frame
= talloc_stackframe();
857 struct tevent_context
*ev
= NULL
;
858 struct tevent_req
*req
= NULL
;
859 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
861 ev
= samba_tevent_context_init(frame
);
865 req
= netlogon_pings_send(frame
,
876 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
879 status
= netlogon_pings_recv(req
, mem_ctx
, responses
);