s3: Use resolve_wins_send/recv in resolve_wins
[Samba.git] / source3 / libsmb / namequery.c
blobdc062fb0a0c767f483b738cd753aba24861b6f3f
1 /*
2 Unix SMB/CIFS implementation.
3 name query routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2007.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "libads/sitename_cache.h"
24 #include "libads/dns.h"
25 #include "../libcli/netlogon/netlogon.h"
26 #include "lib/async_req/async_sock.h"
27 #include "libsmb/nmblib.h"
29 /* nmbd.c sets this to True. */
30 bool global_in_nmbd = False;
32 /****************************
33 * SERVER AFFINITY ROUTINES *
34 ****************************/
36 /* Server affinity is the concept of preferring the last domain
37 controller with whom you had a successful conversation */
39 /****************************************************************************
40 ****************************************************************************/
41 #define SAFKEY_FMT "SAF/DOMAIN/%s"
42 #define SAF_TTL 900
43 #define SAFJOINKEY_FMT "SAFJOIN/DOMAIN/%s"
44 #define SAFJOIN_TTL 3600
46 static char *saf_key(const char *domain)
48 char *keystr;
50 asprintf_strupper_m(&keystr, SAFKEY_FMT, domain);
52 return keystr;
55 static char *saf_join_key(const char *domain)
57 char *keystr;
59 asprintf_strupper_m(&keystr, SAFJOINKEY_FMT, domain);
61 return keystr;
64 /****************************************************************************
65 ****************************************************************************/
67 bool saf_store( const char *domain, const char *servername )
69 char *key;
70 time_t expire;
71 bool ret = False;
73 if ( !domain || !servername ) {
74 DEBUG(2,("saf_store: "
75 "Refusing to store empty domain or servername!\n"));
76 return False;
79 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
80 DEBUG(0,("saf_store: "
81 "refusing to store 0 length domain or servername!\n"));
82 return False;
85 key = saf_key( domain );
86 expire = time( NULL ) + lp_parm_int(-1, "saf","ttl", SAF_TTL);
88 DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
89 domain, servername, (unsigned int)expire ));
91 ret = gencache_set( key, servername, expire );
93 SAFE_FREE( key );
95 return ret;
98 bool saf_join_store( const char *domain, const char *servername )
100 char *key;
101 time_t expire;
102 bool ret = False;
104 if ( !domain || !servername ) {
105 DEBUG(2,("saf_join_store: Refusing to store empty domain or servername!\n"));
106 return False;
109 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
110 DEBUG(0,("saf_join_store: refusing to store 0 length domain or servername!\n"));
111 return False;
114 key = saf_join_key( domain );
115 expire = time( NULL ) + lp_parm_int(-1, "saf","join ttl", SAFJOIN_TTL);
117 DEBUG(10,("saf_join_store: domain = [%s], server = [%s], expire = [%u]\n",
118 domain, servername, (unsigned int)expire ));
120 ret = gencache_set( key, servername, expire );
122 SAFE_FREE( key );
124 return ret;
127 bool saf_delete( const char *domain )
129 char *key;
130 bool ret = False;
132 if ( !domain ) {
133 DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
134 return False;
137 key = saf_join_key(domain);
138 ret = gencache_del(key);
139 SAFE_FREE(key);
141 if (ret) {
142 DEBUG(10,("saf_delete[join]: domain = [%s]\n", domain ));
145 key = saf_key(domain);
146 ret = gencache_del(key);
147 SAFE_FREE(key);
149 if (ret) {
150 DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
153 return ret;
156 /****************************************************************************
157 ****************************************************************************/
159 char *saf_fetch( const char *domain )
161 char *server = NULL;
162 time_t timeout;
163 bool ret = False;
164 char *key = NULL;
166 if ( !domain || strlen(domain) == 0) {
167 DEBUG(2,("saf_fetch: Empty domain name!\n"));
168 return NULL;
171 key = saf_join_key( domain );
173 ret = gencache_get( key, &server, &timeout );
175 SAFE_FREE( key );
177 if ( ret ) {
178 DEBUG(5,("saf_fetch[join]: Returning \"%s\" for \"%s\" domain\n",
179 server, domain ));
180 return server;
183 key = saf_key( domain );
185 ret = gencache_get( key, &server, &timeout );
187 SAFE_FREE( key );
189 if ( !ret ) {
190 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n",
191 domain ));
192 } else {
193 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n",
194 server, domain ));
197 return server;
200 static void set_socket_addr_v4(struct sockaddr_storage *addr)
202 if (!interpret_string_addr(addr, lp_socket_address(),
203 AI_NUMERICHOST|AI_PASSIVE)) {
204 zero_sockaddr(addr);
206 if (addr->ss_family != AF_INET) {
207 zero_sockaddr(addr);
211 static struct in_addr my_socket_addr_v4(void)
213 struct sockaddr_storage my_addr;
214 struct sockaddr_in *in_addr = (struct sockaddr_in *)((char *)&my_addr);
216 set_socket_addr_v4(&my_addr);
217 return in_addr->sin_addr;
220 /****************************************************************************
221 Generate a random trn_id.
222 ****************************************************************************/
224 static int generate_trn_id(void)
226 uint16 id;
228 generate_random_buffer((uint8 *)&id, sizeof(id));
230 return id % (unsigned)0x7FFF;
233 /****************************************************************************
234 Parse a node status response into an array of structures.
235 ****************************************************************************/
237 static struct node_status *parse_node_status(TALLOC_CTX *mem_ctx, char *p,
238 int *num_names,
239 struct node_status_extra *extra)
241 struct node_status *ret;
242 int i;
244 *num_names = CVAL(p,0);
246 if (*num_names == 0)
247 return NULL;
249 ret = talloc_array(mem_ctx, struct node_status,*num_names);
250 if (!ret)
251 return NULL;
253 p++;
254 for (i=0;i< *num_names;i++) {
255 StrnCpy(ret[i].name,p,15);
256 trim_char(ret[i].name,'\0',' ');
257 ret[i].type = CVAL(p,15);
258 ret[i].flags = p[16];
259 p += 18;
260 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
261 ret[i].type, ret[i].flags));
264 * Also, pick up the MAC address ...
266 if (extra) {
267 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
269 return ret;
272 struct sock_packet_read_state {
273 struct tevent_context *ev;
274 enum packet_type type;
275 int trn_id;
277 struct nb_packet_reader *reader;
278 struct tevent_req *reader_req;
280 int sock;
281 struct tevent_req *socket_req;
282 uint8_t buf[1024];
283 struct sockaddr_storage addr;
284 socklen_t addr_len;
286 bool (*validator)(struct packet_struct *p,
287 void *private_data);
288 void *private_data;
290 struct packet_struct *packet;
293 static int sock_packet_read_state_destructor(struct sock_packet_read_state *s);
294 static void sock_packet_read_got_packet(struct tevent_req *subreq);
295 static void sock_packet_read_got_socket(struct tevent_req *subreq);
297 static struct tevent_req *sock_packet_read_send(
298 TALLOC_CTX *mem_ctx,
299 struct tevent_context *ev,
300 int sock, /* dgram socket */
301 struct nb_packet_reader *reader,
302 enum packet_type type,
303 int trn_id,
304 bool (*validator)(struct packet_struct *p, void *private_data),
305 void *private_data)
307 struct tevent_req *req;
308 struct sock_packet_read_state *state;
310 req = tevent_req_create(mem_ctx, &state,
311 struct sock_packet_read_state);
312 if (req == NULL) {
313 return NULL;
315 talloc_set_destructor(state, sock_packet_read_state_destructor);
316 state->ev = ev;
317 state->reader = reader;
318 state->sock = sock;
319 state->type = type;
320 state->trn_id = trn_id;
321 state->validator = validator;
322 state->private_data = private_data;
324 if (reader != NULL) {
325 state->reader_req = nb_packet_read_send(state, ev, reader);
326 if (tevent_req_nomem(state->reader_req, req)) {
327 return tevent_req_post(req, ev);
329 tevent_req_set_callback(
330 state->reader_req, sock_packet_read_got_packet, req);
333 state->addr_len = sizeof(state->addr);
334 state->socket_req = recvfrom_send(state, ev, sock,
335 state->buf, sizeof(state->buf), 0,
336 &state->addr, &state->addr_len);
337 if (tevent_req_nomem(state->socket_req, req)) {
338 return tevent_req_post(req, ev);
340 tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
341 req);
343 return req;
346 static int sock_packet_read_state_destructor(struct sock_packet_read_state *s)
348 if (s->packet != NULL) {
349 free_packet(s->packet);
350 s->packet = NULL;
352 return 0;
355 static void sock_packet_read_got_packet(struct tevent_req *subreq)
357 struct tevent_req *req = tevent_req_callback_data(
358 subreq, struct tevent_req);
359 struct sock_packet_read_state *state = tevent_req_data(
360 req, struct sock_packet_read_state);
361 NTSTATUS status;
363 status = nb_packet_read_recv(subreq, &state->packet);
365 TALLOC_FREE(state->reader_req);
367 if (!NT_STATUS_IS_OK(status)) {
368 if (state->socket_req != NULL) {
370 * Still waiting for socket
372 return;
375 * Both socket and packet reader failed
377 tevent_req_nterror(req, status);
378 return;
381 if ((state->validator != NULL) &&
382 !state->validator(state->packet, state->private_data)) {
383 DEBUG(10, ("validator failed\n"));
385 free_packet(state->packet);
386 state->packet = NULL;
388 state->reader_req = nb_packet_read_send(state, state->ev,
389 state->reader);
390 if (tevent_req_nomem(state->reader_req, req)) {
391 return;
393 tevent_req_set_callback(
394 state->reader_req, sock_packet_read_got_packet, req);
395 return;
398 TALLOC_FREE(state->socket_req);
399 tevent_req_done(req);
402 static void sock_packet_read_got_socket(struct tevent_req *subreq)
404 struct tevent_req *req = tevent_req_callback_data(
405 subreq, struct tevent_req);
406 struct sock_packet_read_state *state = tevent_req_data(
407 req, struct sock_packet_read_state);
408 struct sockaddr_in *in_addr;
409 ssize_t received;
410 int err;
412 received = recvfrom_recv(subreq, &err);
414 TALLOC_FREE(state->socket_req);
416 if (received == -1) {
417 if (state->reader_req != NULL) {
419 * Still waiting for reader
421 return;
424 * Both socket and reader failed
426 tevent_req_nterror(req, map_nt_error_from_unix(err));
427 return;
429 if (state->addr.ss_family != AF_INET) {
430 goto retry;
432 in_addr = (struct sockaddr_in *)(void *)&state->addr;
434 state->packet = parse_packet((char *)state->buf, received, state->type,
435 in_addr->sin_addr, in_addr->sin_port);
436 if (state->packet == NULL) {
437 DEBUG(10, ("parse_packet failed\n"));
438 goto retry;
440 if ((state->trn_id != -1) &&
441 (state->trn_id != packet_trn_id(state->packet))) {
442 DEBUG(10, ("Expected transaction id %d, got %d\n",
443 state->trn_id, packet_trn_id(state->packet)));
444 goto retry;
447 if ((state->validator != NULL) &&
448 !state->validator(state->packet, state->private_data)) {
449 DEBUG(10, ("validator failed\n"));
450 goto retry;
453 tevent_req_done(req);
454 return;
456 retry:
457 if (state->packet != NULL) {
458 free_packet(state->packet);
459 state->packet = NULL;
461 state->socket_req = recvfrom_send(state, state->ev, state->sock,
462 state->buf, sizeof(state->buf), 0,
463 &state->addr, &state->addr_len);
464 if (tevent_req_nomem(state->socket_req, req)) {
465 return;
467 tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
468 req);
471 static NTSTATUS sock_packet_read_recv(struct tevent_req *req,
472 struct packet_struct **ppacket)
474 struct sock_packet_read_state *state = tevent_req_data(
475 req, struct sock_packet_read_state);
476 NTSTATUS status;
478 if (tevent_req_is_nterror(req, &status)) {
479 return status;
481 *ppacket = state->packet;
482 state->packet = NULL;
483 return NT_STATUS_OK;
486 struct nb_trans_state {
487 struct tevent_context *ev;
488 int sock;
489 struct nb_packet_reader *reader;
491 const struct sockaddr_storage *dst_addr;
492 uint8_t *buf;
493 size_t buflen;
494 enum packet_type type;
495 int trn_id;
497 bool (*validator)(struct packet_struct *p,
498 void *private_data);
499 void *private_data;
501 struct packet_struct *packet;
504 static int nb_trans_state_destructor(struct nb_trans_state *s);
505 static void nb_trans_got_reader(struct tevent_req *subreq);
506 static void nb_trans_done(struct tevent_req *subreq);
507 static void nb_trans_sent(struct tevent_req *subreq);
508 static void nb_trans_send_next(struct tevent_req *subreq);
510 static struct tevent_req *nb_trans_send(
511 TALLOC_CTX *mem_ctx,
512 struct tevent_context *ev,
513 const struct sockaddr_storage *my_addr,
514 const struct sockaddr_storage *dst_addr,
515 bool bcast,
516 uint8_t *buf, size_t buflen,
517 enum packet_type type, int trn_id,
518 bool (*validator)(struct packet_struct *p,
519 void *private_data),
520 void *private_data)
522 struct tevent_req *req, *subreq;
523 struct nb_trans_state *state;
525 req = tevent_req_create(mem_ctx, &state, struct nb_trans_state);
526 if (req == NULL) {
527 return NULL;
529 talloc_set_destructor(state, nb_trans_state_destructor);
530 state->ev = ev;
531 state->dst_addr = dst_addr;
532 state->buf = buf;
533 state->buflen = buflen;
534 state->type = type;
535 state->trn_id = trn_id;
536 state->validator = validator;
537 state->private_data = private_data;
539 state->sock = open_socket_in(SOCK_DGRAM, 0, 3, my_addr, True);
540 if (state->sock == -1) {
541 tevent_req_nterror(req, map_nt_error_from_unix(errno));
542 DEBUG(10, ("open_socket_in failed: %s\n", strerror(errno)));
543 return tevent_req_post(req, ev);
546 if (bcast) {
547 set_socket_options(state->sock,"SO_BROADCAST");
550 subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
551 if (tevent_req_nomem(subreq, req)) {
552 return tevent_req_post(req, ev);
554 tevent_req_set_callback(subreq, nb_trans_got_reader, req);
555 return req;
558 static int nb_trans_state_destructor(struct nb_trans_state *s)
560 if (s->sock != -1) {
561 close(s->sock);
562 s->sock = -1;
564 if (s->packet != NULL) {
565 free_packet(s->packet);
566 s->packet = NULL;
568 return 0;
571 static void nb_trans_got_reader(struct tevent_req *subreq)
573 struct tevent_req *req = tevent_req_callback_data(
574 subreq, struct tevent_req);
575 struct nb_trans_state *state = tevent_req_data(
576 req, struct nb_trans_state);
577 NTSTATUS status;
579 status = nb_packet_reader_recv(subreq, state, &state->reader);
580 TALLOC_FREE(subreq);
582 if (!NT_STATUS_IS_OK(status)) {
583 DEBUG(10, ("nmbd not around\n"));
584 state->reader = NULL;
587 subreq = sock_packet_read_send(
588 state, state->ev, state->sock,
589 state->reader, state->type, state->trn_id,
590 state->validator, state->private_data);
591 if (tevent_req_nomem(subreq, req)) {
592 return;
594 tevent_req_set_callback(subreq, nb_trans_done, req);
596 subreq = sendto_send(state, state->ev, state->sock,
597 state->buf, state->buflen, 0, state->dst_addr);
598 if (tevent_req_nomem(subreq, req)) {
599 return;
601 tevent_req_set_callback(subreq, nb_trans_sent, req);
604 static void nb_trans_sent(struct tevent_req *subreq)
606 struct tevent_req *req = tevent_req_callback_data(
607 subreq, struct tevent_req);
608 struct nb_trans_state *state = tevent_req_data(
609 req, struct nb_trans_state);
610 ssize_t sent;
611 int err;
613 sent = sendto_recv(subreq, &err);
614 TALLOC_FREE(subreq);
615 if (sent == -1) {
616 DEBUG(10, ("sendto failed: %s\n", strerror(err)));
617 tevent_req_nterror(req, map_nt_error_from_unix(err));
618 return;
620 subreq = tevent_wakeup_send(state, state->ev,
621 timeval_current_ofs(1, 0));
622 if (tevent_req_nomem(subreq, req)) {
623 return;
625 tevent_req_set_callback(subreq, nb_trans_send_next, req);
628 static void nb_trans_send_next(struct tevent_req *subreq)
630 struct tevent_req *req = tevent_req_callback_data(
631 subreq, struct tevent_req);
632 struct nb_trans_state *state = tevent_req_data(
633 req, struct nb_trans_state);
634 bool ret;
636 ret = tevent_wakeup_recv(subreq);
637 TALLOC_FREE(subreq);
638 if (!ret) {
639 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
640 return;
642 subreq = sendto_send(state, state->ev, state->sock,
643 state->buf, state->buflen, 0, state->dst_addr);
644 if (tevent_req_nomem(subreq, req)) {
645 return;
647 tevent_req_set_callback(subreq, nb_trans_sent, req);
650 static void nb_trans_done(struct tevent_req *subreq)
652 struct tevent_req *req = tevent_req_callback_data(
653 subreq, struct tevent_req);
654 struct nb_trans_state *state = tevent_req_data(
655 req, struct nb_trans_state);
656 NTSTATUS status;
658 status = sock_packet_read_recv(subreq, &state->packet);
659 TALLOC_FREE(subreq);
660 if (tevent_req_nterror(req, status)) {
661 return;
663 tevent_req_done(req);
666 static NTSTATUS nb_trans_recv(struct tevent_req *req,
667 struct packet_struct **ppacket)
669 struct nb_trans_state *state = tevent_req_data(
670 req, struct nb_trans_state);
671 NTSTATUS status;
673 if (tevent_req_is_nterror(req, &status)) {
674 return status;
676 *ppacket = state->packet;
677 state->packet = NULL;
678 return NT_STATUS_OK;
681 /****************************************************************************
682 Do a NBT node status query on an open socket and return an array of
683 structures holding the returned names or NULL if the query failed.
684 **************************************************************************/
686 struct node_status_query_state {
687 struct sockaddr_storage my_addr;
688 struct sockaddr_storage addr;
689 uint8_t buf[1024];
690 ssize_t buflen;
691 struct packet_struct *packet;
694 static int node_status_query_state_destructor(
695 struct node_status_query_state *s);
696 static bool node_status_query_validator(struct packet_struct *p,
697 void *private_data);
698 static void node_status_query_done(struct tevent_req *subreq);
700 struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
701 struct tevent_context *ev,
702 struct nmb_name *name,
703 const struct sockaddr_storage *addr)
705 struct tevent_req *req, *subreq;
706 struct node_status_query_state *state;
707 struct packet_struct p;
708 struct nmb_packet *nmb = &p.packet.nmb;
709 struct sockaddr_in *in_addr;
711 req = tevent_req_create(mem_ctx, &state,
712 struct node_status_query_state);
713 if (req == NULL) {
714 return NULL;
716 talloc_set_destructor(state, node_status_query_state_destructor);
718 if (addr->ss_family != AF_INET) {
719 /* Can't do node status to IPv6 */
720 tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
721 return tevent_req_post(req, ev);
724 state->addr = *addr;
725 in_addr = (struct sockaddr_in *)(void *)&state->addr;
726 in_addr->sin_port = htons(NMB_PORT);
728 set_socket_addr_v4(&state->my_addr);
730 ZERO_STRUCT(p);
731 nmb->header.name_trn_id = generate_trn_id();
732 nmb->header.opcode = 0;
733 nmb->header.response = false;
734 nmb->header.nm_flags.bcast = false;
735 nmb->header.nm_flags.recursion_available = false;
736 nmb->header.nm_flags.recursion_desired = false;
737 nmb->header.nm_flags.trunc = false;
738 nmb->header.nm_flags.authoritative = false;
739 nmb->header.rcode = 0;
740 nmb->header.qdcount = 1;
741 nmb->header.ancount = 0;
742 nmb->header.nscount = 0;
743 nmb->header.arcount = 0;
744 nmb->question.question_name = *name;
745 nmb->question.question_type = 0x21;
746 nmb->question.question_class = 0x1;
748 state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
749 &p);
750 if (state->buflen == 0) {
751 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
752 DEBUG(10, ("build_packet failed\n"));
753 return tevent_req_post(req, ev);
756 subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, false,
757 state->buf, state->buflen,
758 NMB_PACKET, nmb->header.name_trn_id,
759 node_status_query_validator, NULL);
760 if (tevent_req_nomem(subreq, req)) {
761 DEBUG(10, ("nb_trans_send failed\n"));
762 return tevent_req_post(req, ev);
764 if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(10, 0))) {
765 return tevent_req_post(req, ev);
767 tevent_req_set_callback(subreq, node_status_query_done, req);
768 return req;
771 static bool node_status_query_validator(struct packet_struct *p,
772 void *private_data)
774 struct nmb_packet *nmb = &p->packet.nmb;
775 debug_nmb_packet(p);
777 if (nmb->header.opcode != 0 ||
778 nmb->header.nm_flags.bcast ||
779 nmb->header.rcode ||
780 !nmb->header.ancount ||
781 nmb->answers->rr_type != 0x21) {
783 * XXXX what do we do with this? could be a redirect,
784 * but we'll discard it for the moment
786 return false;
788 return true;
791 static int node_status_query_state_destructor(
792 struct node_status_query_state *s)
794 if (s->packet != NULL) {
795 free_packet(s->packet);
796 s->packet = NULL;
798 return 0;
801 static void node_status_query_done(struct tevent_req *subreq)
803 struct tevent_req *req = tevent_req_callback_data(
804 subreq, struct tevent_req);
805 struct node_status_query_state *state = tevent_req_data(
806 req, struct node_status_query_state);
807 NTSTATUS status;
809 status = nb_trans_recv(subreq, &state->packet);
810 TALLOC_FREE(subreq);
811 if (tevent_req_nterror(req, status)) {
812 return;
814 tevent_req_done(req);
817 NTSTATUS node_status_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
818 struct node_status **pnode_status,
819 int *pnum_names,
820 struct node_status_extra *extra)
822 struct node_status_query_state *state = tevent_req_data(
823 req, struct node_status_query_state);
824 struct node_status *node_status;
825 int num_names;
826 NTSTATUS status;
828 if (tevent_req_is_nterror(req, &status)) {
829 return status;
831 node_status = parse_node_status(
832 mem_ctx, &state->packet->packet.nmb.answers->rdata[0],
833 &num_names, extra);
834 if (node_status == NULL) {
835 return NT_STATUS_NO_MEMORY;
837 *pnode_status = node_status;
838 *pnum_names = num_names;
839 return NT_STATUS_OK;
842 NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
843 const struct sockaddr_storage *addr,
844 struct node_status **pnode_status,
845 int *pnum_names,
846 struct node_status_extra *extra)
848 TALLOC_CTX *frame = talloc_stackframe();
849 struct tevent_context *ev;
850 struct tevent_req *req;
851 NTSTATUS status = NT_STATUS_NO_MEMORY;
853 ev = tevent_context_init(frame);
854 if (ev == NULL) {
855 goto fail;
857 req = node_status_query_send(ev, ev, name, addr);
858 if (req == NULL) {
859 goto fail;
861 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
862 goto fail;
864 status = node_status_query_recv(req, mem_ctx, pnode_status,
865 pnum_names, extra);
866 fail:
867 TALLOC_FREE(frame);
868 return status;
871 /****************************************************************************
872 Find the first type XX name in a node status reply - used for finding
873 a servers name given its IP. Return the matched name in *name.
874 **************************************************************************/
876 bool name_status_find(const char *q_name,
877 int q_type,
878 int type,
879 const struct sockaddr_storage *to_ss,
880 fstring name)
882 char addr[INET6_ADDRSTRLEN];
883 struct sockaddr_storage ss;
884 struct node_status *addrs = NULL;
885 struct nmb_name nname;
886 int count, i;
887 bool result = false;
888 NTSTATUS status;
890 if (lp_disable_netbios()) {
891 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n",
892 q_name, q_type));
893 return False;
896 print_sockaddr(addr, sizeof(addr), to_ss);
898 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
899 q_type, addr));
901 /* Check the cache first. */
903 if (namecache_status_fetch(q_name, q_type, type, to_ss, name)) {
904 return True;
907 if (to_ss->ss_family != AF_INET) {
908 /* Can't do node status to IPv6 */
909 return false;
912 set_socket_addr_v4(&ss);
914 /* W2K PDC's seem not to respond to '*'#0. JRA */
915 make_nmb_name(&nname, q_name, q_type);
916 status = node_status_query(talloc_tos(), &nname, to_ss,
917 &addrs, &count, NULL);
918 if (!NT_STATUS_IS_OK(status)) {
919 goto done;
922 for (i=0;i<count;i++) {
923 /* Find first one of the requested type that's not a GROUP. */
924 if (addrs[i].type == type && ! (addrs[i].flags & 0x80))
925 break;
927 if (i == count)
928 goto done;
930 pull_ascii_nstring(name, sizeof(fstring), addrs[i].name);
932 /* Store the result in the cache. */
933 /* but don't store an entry for 0x1c names here. Here we have
934 a single host and DOMAIN<0x1c> names should be a list of hosts */
936 if ( q_type != 0x1c ) {
937 namecache_status_store(q_name, q_type, type, to_ss, name);
940 result = true;
942 done:
943 TALLOC_FREE(addrs);
945 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
947 if (result)
948 DEBUGADD(10, (", name %s ip address is %s", name, addr));
950 DEBUG(10, ("\n"));
952 return result;
956 comparison function used by sort_addr_list
959 static int addr_compare(const struct sockaddr_storage *ss1,
960 const struct sockaddr_storage *ss2)
962 int max_bits1=0, max_bits2=0;
963 int num_interfaces = iface_count();
964 int i;
966 /* Sort IPv4 addresses first. */
967 if (ss1->ss_family != ss2->ss_family) {
968 if (ss2->ss_family == AF_INET) {
969 return 1;
970 } else {
971 return -1;
975 /* Here we know both addresses are of the same
976 * family. */
978 for (i=0;i<num_interfaces;i++) {
979 const struct sockaddr_storage *pss = iface_n_bcast(i);
980 const unsigned char *p_ss1 = NULL;
981 const unsigned char *p_ss2 = NULL;
982 const unsigned char *p_if = NULL;
983 size_t len = 0;
984 int bits1, bits2;
986 if (pss->ss_family != ss1->ss_family) {
987 /* Ignore interfaces of the wrong type. */
988 continue;
990 if (pss->ss_family == AF_INET) {
991 p_if = (const unsigned char *)
992 &((const struct sockaddr_in *)pss)->sin_addr;
993 p_ss1 = (const unsigned char *)
994 &((const struct sockaddr_in *)ss1)->sin_addr;
995 p_ss2 = (const unsigned char *)
996 &((const struct sockaddr_in *)ss2)->sin_addr;
997 len = 4;
999 #if defined(HAVE_IPV6)
1000 if (pss->ss_family == AF_INET6) {
1001 p_if = (const unsigned char *)
1002 &((const struct sockaddr_in6 *)pss)->sin6_addr;
1003 p_ss1 = (const unsigned char *)
1004 &((const struct sockaddr_in6 *)ss1)->sin6_addr;
1005 p_ss2 = (const unsigned char *)
1006 &((const struct sockaddr_in6 *)ss2)->sin6_addr;
1007 len = 16;
1009 #endif
1010 if (!p_ss1 || !p_ss2 || !p_if || len == 0) {
1011 continue;
1013 bits1 = matching_len_bits(p_ss1, p_if, len);
1014 bits2 = matching_len_bits(p_ss2, p_if, len);
1015 max_bits1 = MAX(bits1, max_bits1);
1016 max_bits2 = MAX(bits2, max_bits2);
1019 /* Bias towards directly reachable IPs */
1020 if (iface_local((const struct sockaddr *)ss1)) {
1021 if (ss1->ss_family == AF_INET) {
1022 max_bits1 += 32;
1023 } else {
1024 max_bits1 += 128;
1027 if (iface_local((const struct sockaddr *)ss2)) {
1028 if (ss2->ss_family == AF_INET) {
1029 max_bits2 += 32;
1030 } else {
1031 max_bits2 += 128;
1034 return max_bits2 - max_bits1;
1037 /*******************************************************************
1038 compare 2 ldap IPs by nearness to our interfaces - used in qsort
1039 *******************************************************************/
1041 int ip_service_compare(struct ip_service *ss1, struct ip_service *ss2)
1043 int result;
1045 if ((result = addr_compare(&ss1->ss, &ss2->ss)) != 0) {
1046 return result;
1049 if (ss1->port > ss2->port) {
1050 return 1;
1053 if (ss1->port < ss2->port) {
1054 return -1;
1057 return 0;
1061 sort an IP list so that names that are close to one of our interfaces
1062 are at the top. This prevents the problem where a WINS server returns an IP
1063 that is not reachable from our subnet as the first match
1066 static void sort_addr_list(struct sockaddr_storage *sslist, int count)
1068 if (count <= 1) {
1069 return;
1072 TYPESAFE_QSORT(sslist, count, addr_compare);
1075 static void sort_service_list(struct ip_service *servlist, int count)
1077 if (count <= 1) {
1078 return;
1081 TYPESAFE_QSORT(servlist, count, ip_service_compare);
1084 /**********************************************************************
1085 Remove any duplicate address/port pairs in the list
1086 *********************************************************************/
1088 static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
1090 int i, j;
1092 DEBUG(10,("remove_duplicate_addrs2: "
1093 "looking for duplicate address/port pairs\n"));
1095 /* one loop to remove duplicates */
1096 for ( i=0; i<count; i++ ) {
1097 if ( is_zero_addr(&iplist[i].ss)) {
1098 continue;
1101 for ( j=i+1; j<count; j++ ) {
1102 if (sockaddr_equal((struct sockaddr *)&iplist[i].ss, (struct sockaddr *)&iplist[j].ss) &&
1103 iplist[i].port == iplist[j].port) {
1104 zero_sockaddr(&iplist[j].ss);
1109 /* one loop to clean up any holes we left */
1110 /* first ip should never be a zero_ip() */
1111 for (i = 0; i<count; ) {
1112 if (is_zero_addr(&iplist[i].ss) ) {
1113 if (i != count-1) {
1114 memmove(&iplist[i], &iplist[i+1],
1115 (count - i - 1)*sizeof(iplist[i]));
1117 count--;
1118 continue;
1120 i++;
1123 return count;
1126 static bool prioritize_ipv4_list(struct ip_service *iplist, int count)
1128 TALLOC_CTX *frame = talloc_stackframe();
1129 struct ip_service *iplist_new = talloc_array(frame, struct ip_service, count);
1130 int i, j;
1132 if (iplist_new == NULL) {
1133 TALLOC_FREE(frame);
1134 return false;
1137 j = 0;
1139 /* Copy IPv4 first. */
1140 for (i = 0; i < count; i++) {
1141 if (iplist[i].ss.ss_family == AF_INET) {
1142 iplist_new[j++] = iplist[i];
1146 /* Copy IPv6. */
1147 for (i = 0; i < count; i++) {
1148 if (iplist[i].ss.ss_family != AF_INET) {
1149 iplist_new[j++] = iplist[i];
1153 memcpy(iplist, iplist_new, sizeof(struct ip_service)*count);
1154 TALLOC_FREE(frame);
1155 return true;
1158 /****************************************************************************
1159 Do a netbios name query to find someones IP.
1160 Returns an array of IP addresses or NULL if none.
1161 *count will be set to the number of addresses returned.
1162 *timed_out is set if we failed by timing out
1163 ****************************************************************************/
1165 struct name_query_state {
1166 struct sockaddr_storage my_addr;
1167 struct sockaddr_storage addr;
1168 bool bcast;
1171 uint8_t buf[1024];
1172 ssize_t buflen;
1174 NTSTATUS validate_error;
1175 uint8_t flags;
1177 struct sockaddr_storage *addrs;
1178 int num_addrs;
1181 static bool name_query_validator(struct packet_struct *p, void *private_data);
1182 static void name_query_done(struct tevent_req *subreq);
1184 struct tevent_req *name_query_send(TALLOC_CTX *mem_ctx,
1185 struct tevent_context *ev,
1186 const char *name, int name_type,
1187 bool bcast, bool recurse,
1188 const struct sockaddr_storage *addr)
1190 struct tevent_req *req, *subreq;
1191 struct name_query_state *state;
1192 struct packet_struct p;
1193 struct nmb_packet *nmb = &p.packet.nmb;
1194 struct sockaddr_in *in_addr;
1196 req = tevent_req_create(mem_ctx, &state, struct name_query_state);
1197 if (req == NULL) {
1198 return NULL;
1200 state->bcast = bcast;
1202 if (addr->ss_family != AF_INET) {
1203 /* Can't do node status to IPv6 */
1204 tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
1205 return tevent_req_post(req, ev);
1208 if (lp_disable_netbios()) {
1209 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n",
1210 name, name_type));
1211 tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
1212 return tevent_req_post(req, ev);
1215 state->addr = *addr;
1216 in_addr = (struct sockaddr_in *)(void *)&state->addr;
1217 in_addr->sin_port = htons(NMB_PORT);
1219 set_socket_addr_v4(&state->my_addr);
1221 ZERO_STRUCT(p);
1222 nmb->header.name_trn_id = generate_trn_id();
1223 nmb->header.opcode = 0;
1224 nmb->header.response = false;
1225 nmb->header.nm_flags.bcast = bcast;
1226 nmb->header.nm_flags.recursion_available = false;
1227 nmb->header.nm_flags.recursion_desired = recurse;
1228 nmb->header.nm_flags.trunc = false;
1229 nmb->header.nm_flags.authoritative = false;
1230 nmb->header.rcode = 0;
1231 nmb->header.qdcount = 1;
1232 nmb->header.ancount = 0;
1233 nmb->header.nscount = 0;
1234 nmb->header.arcount = 0;
1236 make_nmb_name(&nmb->question.question_name,name,name_type);
1238 nmb->question.question_type = 0x20;
1239 nmb->question.question_class = 0x1;
1241 state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
1242 &p);
1243 if (state->buflen == 0) {
1244 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1245 DEBUG(10, ("build_packet failed\n"));
1246 return tevent_req_post(req, ev);
1249 subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, bcast,
1250 state->buf, state->buflen,
1251 NMB_PACKET, nmb->header.name_trn_id,
1252 name_query_validator, state);
1253 if (tevent_req_nomem(subreq, req)) {
1254 DEBUG(10, ("nb_trans_send failed\n"));
1255 return tevent_req_post(req, ev);
1257 tevent_req_set_callback(subreq, name_query_done, req);
1258 return req;
1261 static bool name_query_validator(struct packet_struct *p, void *private_data)
1263 struct name_query_state *state = talloc_get_type_abort(
1264 private_data, struct name_query_state);
1265 struct nmb_packet *nmb = &p->packet.nmb;
1266 struct sockaddr_storage *tmp_addrs;
1267 bool got_unique_netbios_name = false;
1268 int i;
1270 debug_nmb_packet(p);
1273 * If we get a Negative Name Query Response from a WINS
1274 * server, we should report it and give up.
1276 if( 0 == nmb->header.opcode /* A query response */
1277 && !state->bcast /* from a WINS server */
1278 && nmb->header.rcode /* Error returned */
1281 if( DEBUGLVL( 3 ) ) {
1282 /* Only executed if DEBUGLEVEL >= 3 */
1283 dbgtext( "Negative name query "
1284 "response, rcode 0x%02x: ",
1285 nmb->header.rcode );
1286 switch( nmb->header.rcode ) {
1287 case 0x01:
1288 dbgtext("Request was invalidly formatted.\n");
1289 break;
1290 case 0x02:
1291 dbgtext("Problem with NBNS, cannot process "
1292 "name.\n");
1293 break;
1294 case 0x03:
1295 dbgtext("The name requested does not "
1296 "exist.\n");
1297 break;
1298 case 0x04:
1299 dbgtext("Unsupported request error.\n");
1300 break;
1301 case 0x05:
1302 dbgtext("Query refused error.\n");
1303 break;
1304 default:
1305 dbgtext("Unrecognized error code.\n" );
1306 break;
1311 * We accept this packet as valid, but tell the upper
1312 * layers that it's a negative response.
1314 state->validate_error = NT_STATUS_NOT_FOUND;
1315 return true;
1318 if (nmb->header.opcode != 0 ||
1319 nmb->header.nm_flags.bcast ||
1320 nmb->header.rcode ||
1321 !nmb->header.ancount) {
1323 * XXXX what do we do with this? Could be a redirect,
1324 * but we'll discard it for the moment.
1326 return false;
1329 tmp_addrs = talloc_realloc(
1330 state, state->addrs, struct sockaddr_storage,
1331 state->num_addrs + nmb->answers->rdlength/6);
1332 if (tmp_addrs == NULL) {
1333 state->validate_error = NT_STATUS_NO_MEMORY;
1334 return true;
1336 state->addrs = tmp_addrs;
1338 DEBUG(2,("Got a positive name query response "
1339 "from %s ( ", inet_ntoa(p->ip)));
1341 for (i=0; i<nmb->answers->rdlength/6; i++) {
1342 uint16_t flags;
1343 struct in_addr ip;
1344 struct sockaddr_storage addr;
1345 int j;
1347 flags = RSVAL(&nmb->answers->rdata[i*6], 0);
1348 got_unique_netbios_name |= ((flags & 0x8000) == 0);
1350 putip((char *)&ip,&nmb->answers->rdata[2+i*6]);
1351 in_addr_to_sockaddr_storage(&addr, ip);
1353 for (j=0; j<state->num_addrs; j++) {
1354 if (sockaddr_equal(
1355 (struct sockaddr *)&addr,
1356 (struct sockaddr *)&state->addrs[j])) {
1357 break;
1360 if (j < state->num_addrs) {
1361 /* Already got it */
1362 continue;
1365 DEBUGADD(2,("%s ",inet_ntoa(ip)));
1367 state->addrs[state->num_addrs] = addr;
1368 state->num_addrs += 1;
1370 DEBUGADD(2,(")\n"));
1372 /* We add the flags back ... */
1373 if (nmb->header.response)
1374 state->flags |= NM_FLAGS_RS;
1375 if (nmb->header.nm_flags.authoritative)
1376 state->flags |= NM_FLAGS_AA;
1377 if (nmb->header.nm_flags.trunc)
1378 state->flags |= NM_FLAGS_TC;
1379 if (nmb->header.nm_flags.recursion_desired)
1380 state->flags |= NM_FLAGS_RD;
1381 if (nmb->header.nm_flags.recursion_available)
1382 state->flags |= NM_FLAGS_RA;
1383 if (nmb->header.nm_flags.bcast)
1384 state->flags |= NM_FLAGS_B;
1386 if (state->bcast) {
1388 * We have to collect all entries coming in from broadcast
1389 * queries. If we got a unique name, we're done.
1391 return got_unique_netbios_name;
1394 * WINS responses are accepted when they are received
1396 return true;
1399 static void name_query_done(struct tevent_req *subreq)
1401 struct tevent_req *req = tevent_req_callback_data(
1402 subreq, struct tevent_req);
1403 struct name_query_state *state = tevent_req_data(
1404 req, struct name_query_state);
1405 NTSTATUS status;
1406 struct packet_struct *p = NULL;
1408 status = nb_trans_recv(subreq, &p);
1409 TALLOC_FREE(subreq);
1410 if (tevent_req_nterror(req, status)) {
1411 return;
1413 if (!NT_STATUS_IS_OK(state->validate_error)) {
1414 tevent_req_nterror(req, state->validate_error);
1415 return;
1417 if (p != NULL) {
1419 * Free the packet here, we've collected the response in the
1420 * validator
1422 free_packet(p);
1424 tevent_req_done(req);
1427 NTSTATUS name_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1428 struct sockaddr_storage **addrs, int *num_addrs,
1429 uint8_t *flags)
1431 struct name_query_state *state = tevent_req_data(
1432 req, struct name_query_state);
1433 NTSTATUS status;
1435 if (tevent_req_is_nterror(req, &status)) {
1436 if (state->bcast &&
1437 NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1439 * In the broadcast case we collect replies until the
1440 * timeout.
1442 status = NT_STATUS_OK;
1444 if (!NT_STATUS_IS_OK(status)) {
1445 return status;
1448 if (state->num_addrs == 0) {
1449 return NT_STATUS_NOT_FOUND;
1451 *addrs = talloc_move(mem_ctx, &state->addrs);
1452 sort_addr_list(*addrs, state->num_addrs);
1453 *num_addrs = state->num_addrs;
1454 if (flags != NULL) {
1455 *flags = state->flags;
1457 return NT_STATUS_OK;
1460 NTSTATUS name_query(const char *name, int name_type,
1461 bool bcast, bool recurse,
1462 const struct sockaddr_storage *to_ss,
1463 TALLOC_CTX *mem_ctx,
1464 struct sockaddr_storage **addrs,
1465 int *num_addrs, uint8_t *flags)
1467 TALLOC_CTX *frame = talloc_stackframe();
1468 struct tevent_context *ev;
1469 struct tevent_req *req;
1470 struct timeval timeout;
1471 NTSTATUS status = NT_STATUS_NO_MEMORY;
1473 ev = tevent_context_init(frame);
1474 if (ev == NULL) {
1475 goto fail;
1477 req = name_query_send(ev, ev, name, name_type, bcast, recurse, to_ss);
1478 if (req == NULL) {
1479 goto fail;
1481 if (bcast) {
1482 timeout = timeval_current_ofs(0, 250000);
1483 } else {
1484 timeout = timeval_current_ofs(2, 0);
1486 if (!tevent_req_set_endtime(req, ev, timeout)) {
1487 goto fail;
1489 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1490 goto fail;
1492 status = name_query_recv(req, mem_ctx, addrs, num_addrs, flags);
1493 fail:
1494 TALLOC_FREE(frame);
1495 return status;
1498 /********************************************************
1499 convert an array if struct sockaddr_storage to struct ip_service
1500 return false on failure. Port is set to PORT_NONE;
1501 *********************************************************/
1503 static bool convert_ss2service(struct ip_service **return_iplist,
1504 const struct sockaddr_storage *ss_list,
1505 int count)
1507 int i;
1509 if ( count==0 || !ss_list )
1510 return False;
1512 /* copy the ip address; port will be PORT_NONE */
1513 if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) ==
1514 NULL) {
1515 DEBUG(0,("convert_ip2service: malloc failed "
1516 "for %d enetries!\n", count ));
1517 return False;
1520 for ( i=0; i<count; i++ ) {
1521 (*return_iplist)[i].ss = ss_list[i];
1522 (*return_iplist)[i].port = PORT_NONE;
1525 return true;
1528 struct name_queries_state {
1529 struct tevent_context *ev;
1530 const char *name;
1531 int name_type;
1532 bool bcast;
1533 bool recurse;
1534 const struct sockaddr_storage *addrs;
1535 int num_addrs;
1536 int wait_msec;
1537 int timeout_msec;
1539 struct tevent_req **subreqs;
1540 int num_received;
1541 int num_sent;
1543 int received_index;
1544 struct sockaddr_storage *result_addrs;
1545 int num_result_addrs;
1546 uint8_t flags;
1549 static void name_queries_done(struct tevent_req *subreq);
1550 static void name_queries_next(struct tevent_req *subreq);
1553 * Send a name query to multiple destinations with a wait time in between
1556 static struct tevent_req *name_queries_send(
1557 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
1558 const char *name, int name_type,
1559 bool bcast, bool recurse,
1560 const struct sockaddr_storage *addrs,
1561 int num_addrs, int wait_msec, int timeout_msec)
1563 struct tevent_req *req, *subreq;
1564 struct name_queries_state *state;
1566 req = tevent_req_create(mem_ctx, &state,
1567 struct name_queries_state);
1568 if (req == NULL) {
1569 return NULL;
1571 state->ev = ev;
1572 state->name = name;
1573 state->name_type = name_type;
1574 state->bcast = bcast;
1575 state->recurse = recurse;
1576 state->addrs = addrs;
1577 state->num_addrs = num_addrs;
1578 state->wait_msec = wait_msec;
1579 state->timeout_msec = timeout_msec;
1581 state->subreqs = talloc_zero_array(
1582 state, struct tevent_req *, num_addrs);
1583 if (tevent_req_nomem(state->subreqs, req)) {
1584 return tevent_req_post(req, ev);
1586 state->num_sent = 0;
1588 subreq = name_query_send(
1589 state->subreqs, state->ev, name, name_type, bcast, recurse,
1590 &state->addrs[state->num_sent]);
1591 if (tevent_req_nomem(subreq, req)) {
1592 return tevent_req_post(req, ev);
1594 if (!tevent_req_set_endtime(
1595 subreq, state->ev,
1596 timeval_current_ofs(0, state->timeout_msec * 1000))) {
1597 tevent_req_nomem(NULL, req);
1598 return tevent_req_post(req, ev);
1600 tevent_req_set_callback(subreq, name_queries_done, req);
1602 state->subreqs[state->num_sent] = subreq;
1603 state->num_sent += 1;
1605 if (state->num_sent < state->num_addrs) {
1606 subreq = tevent_wakeup_send(
1607 state, state->ev,
1608 timeval_current_ofs(0, state->wait_msec * 1000));
1609 if (tevent_req_nomem(subreq, req)) {
1610 return tevent_req_post(req, ev);
1612 tevent_req_set_callback(subreq, name_queries_next, req);
1614 return req;
1617 static void name_queries_done(struct tevent_req *subreq)
1619 struct tevent_req *req = tevent_req_callback_data(
1620 subreq, struct tevent_req);
1621 struct name_queries_state *state = tevent_req_data(
1622 req, struct name_queries_state);
1623 int i;
1624 NTSTATUS status;
1626 status = name_query_recv(subreq, state, &state->result_addrs,
1627 &state->num_result_addrs, &state->flags);
1629 for (i=0; i<state->num_sent; i++) {
1630 if (state->subreqs[i] == subreq) {
1631 break;
1634 if (i == state->num_sent) {
1635 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1636 return;
1638 TALLOC_FREE(state->subreqs[i]);
1640 state->num_received += 1;
1642 if (!NT_STATUS_IS_OK(status)) {
1644 if (state->num_received >= state->num_addrs) {
1645 tevent_req_nterror(req, status);
1646 return;
1649 * Still outstanding requests, just wait
1651 return;
1653 state->received_index = i;
1654 tevent_req_done(req);
1657 static void name_queries_next(struct tevent_req *subreq)
1659 struct tevent_req *req = tevent_req_callback_data(
1660 subreq, struct tevent_req);
1661 struct name_queries_state *state = tevent_req_data(
1662 req, struct name_queries_state);
1664 if (!tevent_wakeup_recv(subreq)) {
1665 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1666 return;
1669 subreq = name_query_send(
1670 state->subreqs, state->ev,
1671 state->name, state->name_type, state->bcast, state->recurse,
1672 &state->addrs[state->num_sent]);
1673 if (tevent_req_nomem(subreq, req)) {
1674 return;
1676 tevent_req_set_callback(subreq, name_queries_done, req);
1677 if (!tevent_req_set_endtime(
1678 subreq, state->ev,
1679 timeval_current_ofs(0, state->timeout_msec * 1000))) {
1680 tevent_req_nomem(NULL, req);
1681 return;
1683 state->subreqs[state->num_sent] = subreq;
1684 state->num_sent += 1;
1686 if (state->num_sent < state->num_addrs) {
1687 subreq = tevent_wakeup_send(
1688 state, state->ev,
1689 timeval_current_ofs(0, state->wait_msec * 1000));
1690 if (tevent_req_nomem(subreq, req)) {
1691 return;
1693 tevent_req_set_callback(subreq, name_queries_next, req);
1697 static NTSTATUS name_queries_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1698 struct sockaddr_storage **result_addrs,
1699 int *num_result_addrs, uint8_t *flags,
1700 int *received_index)
1702 struct name_queries_state *state = tevent_req_data(
1703 req, struct name_queries_state);
1704 NTSTATUS status;
1706 if (tevent_req_is_nterror(req, &status)) {
1707 return status;
1710 if (result_addrs != NULL) {
1711 *result_addrs = talloc_move(mem_ctx, &state->result_addrs);
1713 if (num_result_addrs != NULL) {
1714 *num_result_addrs = state->num_result_addrs;
1716 if (flags != NULL) {
1717 *flags = state->flags;
1719 if (received_index != NULL) {
1720 *received_index = state->received_index;
1722 return NT_STATUS_OK;
1725 static NTSTATUS name_queries(const char *name, int name_type,
1726 bool bcast, bool recurse,
1727 const struct sockaddr_storage *addrs,
1728 int num_addrs, int wait_msec, int timeout_msec,
1729 TALLOC_CTX *mem_ctx,
1730 struct sockaddr_storage **result_addrs,
1731 int *num_result_addrs, uint8_t *flags,
1732 int *received_index)
1734 TALLOC_CTX *frame = talloc_stackframe();
1735 struct event_context *ev;
1736 struct tevent_req *req;
1737 NTSTATUS status = NT_STATUS_NO_MEMORY;
1739 ev = event_context_init(frame);
1740 if (ev == NULL) {
1741 goto fail;
1743 req = name_queries_send(frame, ev, name, name_type, bcast,
1744 recurse, addrs, num_addrs, wait_msec,
1745 timeout_msec);
1746 if (req == NULL) {
1747 goto fail;
1749 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1750 goto fail;
1752 status = name_queries_recv(req, mem_ctx, result_addrs,
1753 num_result_addrs, flags, received_index);
1754 fail:
1755 TALLOC_FREE(frame);
1756 return status;
1759 /********************************************************
1760 Resolve via "bcast" method.
1761 *********************************************************/
1763 NTSTATUS name_resolve_bcast(const char *name,
1764 int name_type,
1765 TALLOC_CTX *mem_ctx,
1766 struct sockaddr_storage **return_iplist,
1767 int *return_count)
1769 struct sockaddr_storage *bcast_addrs;
1770 int i, num_addrs, num_bcast_addrs;
1772 if (lp_disable_netbios()) {
1773 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n",
1774 name, name_type));
1775 return NT_STATUS_INVALID_PARAMETER;
1779 * "bcast" means do a broadcast lookup on all the local interfaces.
1782 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup "
1783 "for name %s<0x%x>\n", name, name_type));
1785 num_addrs = iface_count();
1786 bcast_addrs = talloc_array(talloc_tos(), struct sockaddr_storage,
1787 num_addrs);
1788 if (bcast_addrs == NULL) {
1789 return NT_STATUS_NO_MEMORY;
1793 * Lookup the name on all the interfaces, return on
1794 * the first successful match.
1796 num_bcast_addrs = 0;
1798 for (i=0; i<num_addrs; i++) {
1799 const struct sockaddr_storage *pss = iface_n_bcast(i);
1801 if (pss->ss_family != AF_INET) {
1802 continue;
1804 bcast_addrs[num_bcast_addrs] = *pss;
1805 num_bcast_addrs += 1;
1808 return name_queries(name, name_type, true, true,
1809 bcast_addrs, num_bcast_addrs, 0, 1000,
1810 mem_ctx, return_iplist, return_count,
1811 NULL, NULL);
1814 struct query_wins_list_state {
1815 struct tevent_context *ev;
1816 const char *name;
1817 uint8_t name_type;
1818 struct in_addr *servers;
1819 uint32_t num_servers;
1820 struct sockaddr_storage server;
1821 uint32_t num_sent;
1823 struct sockaddr_storage *addrs;
1824 int num_addrs;
1825 uint8_t flags;
1828 static void query_wins_list_done(struct tevent_req *subreq);
1831 * Query a list of (replicating) wins servers in sequence, call them
1832 * dead if they don't reply
1835 static struct tevent_req *query_wins_list_send(
1836 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
1837 struct in_addr src_ip, const char *name, uint8_t name_type,
1838 struct in_addr *servers, int num_servers)
1840 struct tevent_req *req, *subreq;
1841 struct query_wins_list_state *state;
1843 req = tevent_req_create(mem_ctx, &state,
1844 struct query_wins_list_state);
1845 if (req == NULL) {
1846 return NULL;
1848 state->ev = ev;
1849 state->name = name;
1850 state->name_type = name_type;
1851 state->servers = servers;
1852 state->num_servers = num_servers;
1854 if (state->num_servers == 0) {
1855 tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
1856 return tevent_req_post(req, ev);
1859 in_addr_to_sockaddr_storage(
1860 &state->server, state->servers[state->num_sent]);
1862 subreq = name_query_send(state, state->ev,
1863 state->name, state->name_type,
1864 false, true, &state->server);
1865 state->num_sent += 1;
1866 if (tevent_req_nomem(subreq, req)) {
1867 return tevent_req_post(req, ev);
1869 if (!tevent_req_set_endtime(subreq, state->ev,
1870 timeval_current_ofs(2, 0))) {
1871 tevent_req_nomem(NULL, req);
1872 return tevent_req_post(req, ev);
1874 tevent_req_set_callback(subreq, query_wins_list_done, req);
1875 return req;
1878 static void query_wins_list_done(struct tevent_req *subreq)
1880 struct tevent_req *req = tevent_req_callback_data(
1881 subreq, struct tevent_req);
1882 struct query_wins_list_state *state = tevent_req_data(
1883 req, struct query_wins_list_state);
1884 NTSTATUS status;
1886 status = name_query_recv(subreq, state,
1887 &state->addrs, &state->num_addrs,
1888 &state->flags);
1889 TALLOC_FREE(subreq);
1890 if (NT_STATUS_IS_OK(status)) {
1891 tevent_req_done(req);
1892 return;
1894 if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1895 tevent_req_nterror(req, status);
1896 return;
1898 wins_srv_died(state->servers[state->num_sent-1],
1899 my_socket_addr_v4());
1901 if (state->num_sent == state->num_servers) {
1902 tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
1903 return;
1906 in_addr_to_sockaddr_storage(
1907 &state->server, state->servers[state->num_sent]);
1909 subreq = name_query_send(state, state->ev,
1910 state->name, state->name_type,
1911 false, true, &state->server);
1912 state->num_sent += 1;
1913 if (tevent_req_nomem(subreq, req)) {
1914 return;
1916 if (!tevent_req_set_endtime(subreq, state->ev,
1917 timeval_current_ofs(2, 0))) {
1918 tevent_req_nomem(NULL, req);
1919 return;
1921 tevent_req_set_callback(subreq, query_wins_list_done, req);
1924 static NTSTATUS query_wins_list_recv(struct tevent_req *req,
1925 TALLOC_CTX *mem_ctx,
1926 struct sockaddr_storage **addrs,
1927 int *num_addrs,
1928 uint8_t *flags)
1930 struct query_wins_list_state *state = tevent_req_data(
1931 req, struct query_wins_list_state);
1932 NTSTATUS status;
1934 if (tevent_req_is_nterror(req, &status)) {
1935 return status;
1937 if (addrs != NULL) {
1938 *addrs = talloc_move(mem_ctx, &state->addrs);
1940 if (num_addrs != NULL) {
1941 *num_addrs = state->num_addrs;
1943 if (flags != NULL) {
1944 *flags = state->flags;
1946 return NT_STATUS_OK;
1949 struct resolve_wins_state {
1950 int num_sent;
1951 int num_received;
1953 struct sockaddr_storage *addrs;
1954 int num_addrs;
1955 uint8_t flags;
1958 static void resolve_wins_done(struct tevent_req *subreq);
1960 struct tevent_req *resolve_wins_send(TALLOC_CTX *mem_ctx,
1961 struct tevent_context *ev,
1962 const char *name,
1963 int name_type)
1965 struct tevent_req *req, *subreq;
1966 struct resolve_wins_state *state;
1967 char **wins_tags = NULL;
1968 struct sockaddr_storage src_ss;
1969 struct in_addr src_ip;
1970 int i, num_wins_tags;
1972 req = tevent_req_create(mem_ctx, &state,
1973 struct resolve_wins_state);
1974 if (req == NULL) {
1975 return NULL;
1978 if (wins_srv_count() < 1) {
1979 DEBUG(3,("resolve_wins: WINS server resolution selected "
1980 "and no WINS servers listed.\n"));
1981 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1982 goto fail;
1985 /* the address we will be sending from */
1986 if (!interpret_string_addr(&src_ss, lp_socket_address(),
1987 AI_NUMERICHOST|AI_PASSIVE)) {
1988 zero_sockaddr(&src_ss);
1991 if (src_ss.ss_family != AF_INET) {
1992 char addr[INET6_ADDRSTRLEN];
1993 print_sockaddr(addr, sizeof(addr), &src_ss);
1994 DEBUG(3,("resolve_wins: cannot receive WINS replies "
1995 "on IPv6 address %s\n",
1996 addr));
1997 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1998 goto fail;
2001 src_ip = ((const struct sockaddr_in *)(void *)&src_ss)->sin_addr;
2003 wins_tags = wins_srv_tags();
2004 if (wins_tags == NULL) {
2005 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2006 goto fail;
2009 num_wins_tags = 0;
2010 while (wins_tags[num_wins_tags] != NULL) {
2011 num_wins_tags += 1;
2014 for (i=0; i<num_wins_tags; i++) {
2015 int num_servers, num_alive;
2016 struct in_addr *servers, *alive;
2017 int j;
2019 if (!wins_server_tag_ips(wins_tags[i], talloc_tos(),
2020 &servers, &num_servers)) {
2021 DEBUG(10, ("wins_server_tag_ips failed for tag %s\n",
2022 wins_tags[i]));
2023 continue;
2026 alive = talloc_array(state, struct in_addr, num_servers);
2027 if (tevent_req_nomem(alive, req)) {
2028 goto fail;
2031 num_alive = 0;
2032 for (j=0; j<num_servers; j++) {
2033 struct in_addr wins_ip = servers[j];
2035 if (global_in_nmbd && ismyip_v4(wins_ip)) {
2036 /* yikes! we'll loop forever */
2037 continue;
2039 /* skip any that have been unresponsive lately */
2040 if (wins_srv_is_dead(wins_ip, src_ip)) {
2041 continue;
2043 DEBUG(3, ("resolve_wins: using WINS server %s "
2044 "and tag '%s'\n",
2045 inet_ntoa(wins_ip), wins_tags[i]));
2046 alive[num_alive] = wins_ip;
2047 num_alive += 1;
2049 TALLOC_FREE(servers);
2051 if (num_alive == 0) {
2052 continue;
2055 subreq = query_wins_list_send(
2056 state, ev, src_ip, name, name_type,
2057 alive, num_alive);
2058 if (tevent_req_nomem(subreq, req)) {
2059 goto fail;
2061 tevent_req_set_callback(subreq, resolve_wins_done, req);
2062 state->num_sent += 1;
2065 if (state->num_sent == 0) {
2066 tevent_req_nterror(req, NT_STATUS_NOT_FOUND);
2067 goto fail;
2070 wins_srv_tags_free(wins_tags);
2071 return req;
2072 fail:
2073 wins_srv_tags_free(wins_tags);
2074 return tevent_req_post(req, ev);
2077 static void resolve_wins_done(struct tevent_req *subreq)
2079 struct tevent_req *req = tevent_req_callback_data(
2080 subreq, struct tevent_req);
2081 struct resolve_wins_state *state = tevent_req_data(
2082 req, struct resolve_wins_state);
2083 NTSTATUS status;
2085 status = query_wins_list_recv(subreq, state, &state->addrs,
2086 &state->num_addrs, &state->flags);
2087 if (NT_STATUS_IS_OK(status)) {
2088 tevent_req_done(req);
2089 return;
2092 state->num_received += 1;
2094 if (state->num_received < state->num_sent) {
2096 * Wait for the others
2098 return;
2100 tevent_req_nterror(req, status);
2103 NTSTATUS resolve_wins_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2104 struct sockaddr_storage **addrs,
2105 int *num_addrs, uint8_t *flags)
2107 struct resolve_wins_state *state = tevent_req_data(
2108 req, struct resolve_wins_state);
2109 NTSTATUS status;
2111 if (tevent_req_is_nterror(req, &status)) {
2112 return status;
2114 if (addrs != NULL) {
2115 *addrs = talloc_move(mem_ctx, &state->addrs);
2117 if (num_addrs != NULL) {
2118 *num_addrs = state->num_addrs;
2120 if (flags != NULL) {
2121 *flags = state->flags;
2123 return NT_STATUS_OK;
2126 /********************************************************
2127 Resolve via "wins" method.
2128 *********************************************************/
2130 NTSTATUS resolve_wins(const char *name,
2131 int name_type,
2132 TALLOC_CTX *mem_ctx,
2133 struct sockaddr_storage **return_iplist,
2134 int *return_count)
2136 struct tevent_context *ev;
2137 struct tevent_req *req;
2138 NTSTATUS status = NT_STATUS_NO_MEMORY;
2140 ev = tevent_context_init(talloc_tos());
2141 if (ev == NULL) {
2142 goto fail;
2144 req = resolve_wins_send(ev, ev, name, name_type);
2145 if (req == NULL) {
2146 goto fail;
2148 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2149 goto fail;
2151 status = resolve_wins_recv(req, mem_ctx, return_iplist, return_count,
2152 NULL);
2153 fail:
2154 TALLOC_FREE(ev);
2155 return status;
2158 /********************************************************
2159 Resolve via "lmhosts" method.
2160 *********************************************************/
2162 static NTSTATUS resolve_lmhosts(const char *name, int name_type,
2163 struct ip_service **return_iplist,
2164 int *return_count)
2167 * "lmhosts" means parse the local lmhosts file.
2169 struct sockaddr_storage *ss_list;
2170 NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2171 TALLOC_CTX *ctx = NULL;
2173 *return_iplist = NULL;
2174 *return_count = 0;
2176 DEBUG(3,("resolve_lmhosts: "
2177 "Attempting lmhosts lookup for name %s<0x%x>\n",
2178 name, name_type));
2180 ctx = talloc_init("resolve_lmhosts");
2181 if (!ctx) {
2182 return NT_STATUS_NO_MEMORY;
2185 status = resolve_lmhosts_file_as_sockaddr(get_dyn_LMHOSTSFILE(),
2186 name, name_type,
2187 ctx,
2188 &ss_list,
2189 return_count);
2190 if (NT_STATUS_IS_OK(status)) {
2191 if (convert_ss2service(return_iplist,
2192 ss_list,
2193 *return_count)) {
2194 talloc_free(ctx);
2195 return NT_STATUS_OK;
2196 } else {
2197 talloc_free(ctx);
2198 return NT_STATUS_NO_MEMORY;
2201 talloc_free(ctx);
2202 return status;
2206 /********************************************************
2207 Resolve via "hosts" method.
2208 *********************************************************/
2210 static NTSTATUS resolve_hosts(const char *name, int name_type,
2211 struct ip_service **return_iplist,
2212 int *return_count)
2215 * "host" means do a localhost, or dns lookup.
2217 struct addrinfo hints;
2218 struct addrinfo *ailist = NULL;
2219 struct addrinfo *res = NULL;
2220 int ret = -1;
2221 int i = 0;
2222 const char *dns_hosts_file;
2224 if ( name_type != 0x20 && name_type != 0x0) {
2225 DEBUG(5, ("resolve_hosts: not appropriate "
2226 "for name type <0x%x>\n",
2227 name_type));
2228 return NT_STATUS_INVALID_PARAMETER;
2231 *return_iplist = NULL;
2232 *return_count = 0;
2234 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n",
2235 name, name_type));
2237 ZERO_STRUCT(hints);
2238 /* By default make sure it supports TCP. */
2239 hints.ai_socktype = SOCK_STREAM;
2240 hints.ai_flags = AI_ADDRCONFIG;
2242 #if !defined(HAVE_IPV6)
2243 /* Unless we have IPv6, we really only want IPv4 addresses back. */
2244 hints.ai_family = AF_INET;
2245 #endif
2247 dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
2248 if (dns_hosts_file) {
2249 struct sockaddr_storage *ss_list;
2250 NTSTATUS status;
2251 TALLOC_CTX *ctx = talloc_stackframe();
2252 if (!ctx) {
2253 return NT_STATUS_NO_MEMORY;
2256 status = resolve_dns_hosts_file_as_sockaddr(dns_hosts_file, name, false,
2257 ctx, &ss_list, return_count);
2258 if (NT_STATUS_IS_OK(status)) {
2259 if (convert_ss2service(return_iplist,
2260 ss_list,
2261 *return_count)) {
2262 talloc_free(ctx);
2263 return NT_STATUS_OK;
2264 } else {
2265 talloc_free(ctx);
2266 return NT_STATUS_NO_MEMORY;
2269 talloc_free(ctx);
2270 return NT_STATUS_UNSUCCESSFUL;
2273 ret = getaddrinfo(name,
2274 NULL,
2275 &hints,
2276 &ailist);
2277 if (ret) {
2278 DEBUG(3,("resolve_hosts: getaddrinfo failed for name %s [%s]\n",
2279 name,
2280 gai_strerror(ret) ));
2283 for (res = ailist; res; res = res->ai_next) {
2284 struct sockaddr_storage ss;
2286 if (!res->ai_addr || res->ai_addrlen == 0) {
2287 continue;
2290 ZERO_STRUCT(ss);
2291 memcpy(&ss, res->ai_addr, res->ai_addrlen);
2293 *return_count += 1;
2295 *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
2296 struct ip_service,
2297 *return_count);
2298 if (!*return_iplist) {
2299 DEBUG(3,("resolve_hosts: malloc fail !\n"));
2300 freeaddrinfo(ailist);
2301 return NT_STATUS_NO_MEMORY;
2303 (*return_iplist)[i].ss = ss;
2304 (*return_iplist)[i].port = PORT_NONE;
2305 i++;
2307 if (ailist) {
2308 freeaddrinfo(ailist);
2310 if (*return_count) {
2311 return NT_STATUS_OK;
2313 return NT_STATUS_UNSUCCESSFUL;
2316 /********************************************************
2317 Resolve via "ADS" method.
2318 *********************************************************/
2320 /* Special name type used to cause a _kerberos DNS lookup. */
2321 #define KDC_NAME_TYPE 0xDCDC
2323 static NTSTATUS resolve_ads(const char *name,
2324 int name_type,
2325 const char *sitename,
2326 struct ip_service **return_iplist,
2327 int *return_count)
2329 int i, j;
2330 NTSTATUS status;
2331 TALLOC_CTX *ctx;
2332 struct dns_rr_srv *dcs = NULL;
2333 int numdcs = 0;
2334 int numaddrs = 0;
2336 if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE) &&
2337 (name_type != 0x1b)) {
2338 return NT_STATUS_INVALID_PARAMETER;
2341 if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
2342 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
2343 return NT_STATUS_NO_MEMORY;
2346 /* The DNS code needs fixing to find IPv6 addresses... JRA. */
2348 switch (name_type) {
2349 case 0x1b:
2350 DEBUG(5,("resolve_ads: Attempting to resolve "
2351 "PDC for %s using DNS\n", name));
2352 status = ads_dns_query_pdc(ctx, name, &dcs, &numdcs);
2353 break;
2355 case 0x1c:
2356 DEBUG(5,("resolve_ads: Attempting to resolve "
2357 "DCs for %s using DNS\n", name));
2358 status = ads_dns_query_dcs(ctx, name, sitename, &dcs,
2359 &numdcs);
2360 break;
2361 case KDC_NAME_TYPE:
2362 DEBUG(5,("resolve_ads: Attempting to resolve "
2363 "KDCs for %s using DNS\n", name));
2364 status = ads_dns_query_kdcs(ctx, name, sitename, &dcs,
2365 &numdcs);
2366 break;
2367 default:
2368 status = NT_STATUS_INVALID_PARAMETER;
2369 break;
2372 if ( !NT_STATUS_IS_OK( status ) ) {
2373 talloc_destroy(ctx);
2374 return status;
2377 for (i=0;i<numdcs;i++) {
2378 numaddrs += MAX(dcs[i].num_ips,1);
2381 if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) ==
2382 NULL ) {
2383 DEBUG(0,("resolve_ads: malloc failed for %d entries\n",
2384 numaddrs ));
2385 talloc_destroy(ctx);
2386 return NT_STATUS_NO_MEMORY;
2389 /* now unroll the list of IP addresses */
2391 *return_count = 0;
2392 i = 0;
2393 j = 0;
2394 while ( i < numdcs && (*return_count<numaddrs) ) {
2395 struct ip_service *r = &(*return_iplist)[*return_count];
2397 r->port = dcs[i].port;
2399 /* If we don't have an IP list for a name, lookup it up */
2401 if (!dcs[i].ss_s) {
2402 interpret_string_addr(&r->ss, dcs[i].hostname, 0);
2403 i++;
2404 j = 0;
2405 } else {
2406 /* use the IP addresses from the SRV sresponse */
2408 if ( j >= dcs[i].num_ips ) {
2409 i++;
2410 j = 0;
2411 continue;
2414 r->ss = dcs[i].ss_s[j];
2415 j++;
2418 /* make sure it is a valid IP. I considered checking the
2419 * negative connection cache, but this is the wrong place
2420 * for it. Maybe only as a hack. After think about it, if
2421 * all of the IP addresses returned from DNS are dead, what
2422 * hope does a netbios name lookup have ? The standard reason
2423 * for falling back to netbios lookups is that our DNS server
2424 * doesn't know anything about the DC's -- jerry */
2426 if (!is_zero_addr(&r->ss)) {
2427 (*return_count)++;
2431 talloc_destroy(ctx);
2432 return NT_STATUS_OK;
2435 /*******************************************************************
2436 Internal interface to resolve a name into an IP address.
2437 Use this function if the string is either an IP address, DNS
2438 or host name or NetBIOS name. This uses the name switch in the
2439 smb.conf to determine the order of name resolution.
2441 Added support for ip addr/port to support ADS ldap servers.
2442 the only place we currently care about the port is in the
2443 resolve_hosts() when looking up DC's via SRV RR entries in DNS
2444 **********************************************************************/
2446 NTSTATUS internal_resolve_name(const char *name,
2447 int name_type,
2448 const char *sitename,
2449 struct ip_service **return_iplist,
2450 int *return_count,
2451 const char *resolve_order)
2453 char *tok;
2454 const char *ptr;
2455 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2456 int i;
2457 TALLOC_CTX *frame = NULL;
2459 *return_iplist = NULL;
2460 *return_count = 0;
2462 DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
2463 name, name_type, sitename ? sitename : "(null)"));
2465 if (is_ipaddress(name)) {
2466 if ((*return_iplist = SMB_MALLOC_P(struct ip_service)) ==
2467 NULL) {
2468 DEBUG(0,("internal_resolve_name: malloc fail !\n"));
2469 return NT_STATUS_NO_MEMORY;
2472 /* ignore the port here */
2473 (*return_iplist)->port = PORT_NONE;
2475 /* if it's in the form of an IP address then get the lib to interpret it */
2476 if (!interpret_string_addr(&(*return_iplist)->ss,
2477 name, AI_NUMERICHOST)) {
2478 DEBUG(1,("internal_resolve_name: interpret_string_addr "
2479 "failed on %s\n",
2480 name));
2481 SAFE_FREE(*return_iplist);
2482 return NT_STATUS_INVALID_PARAMETER;
2484 *return_count = 1;
2485 return NT_STATUS_OK;
2488 /* Check name cache */
2490 if (namecache_fetch(name, name_type, return_iplist, return_count)) {
2491 /* This could be a negative response */
2492 if (*return_count > 0) {
2493 return NT_STATUS_OK;
2494 } else {
2495 return NT_STATUS_UNSUCCESSFUL;
2499 /* set the name resolution order */
2501 if (strcmp( resolve_order, "NULL") == 0) {
2502 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
2503 return NT_STATUS_INVALID_PARAMETER;
2506 if (!resolve_order[0]) {
2507 ptr = "host";
2508 } else {
2509 ptr = resolve_order;
2512 /* iterate through the name resolution backends */
2514 frame = talloc_stackframe();
2515 while (next_token_talloc(frame, &ptr, &tok, LIST_SEP)) {
2516 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
2517 status = resolve_hosts(name, name_type, return_iplist,
2518 return_count);
2519 if (NT_STATUS_IS_OK(status)) {
2520 goto done;
2522 } else if(strequal( tok, "kdc")) {
2523 /* deal with KDC_NAME_TYPE names here.
2524 * This will result in a SRV record lookup */
2525 status = resolve_ads(name, KDC_NAME_TYPE, sitename,
2526 return_iplist, return_count);
2527 if (NT_STATUS_IS_OK(status)) {
2528 /* Ensure we don't namecache
2529 * this with the KDC port. */
2530 name_type = KDC_NAME_TYPE;
2531 goto done;
2533 } else if(strequal( tok, "ads")) {
2534 /* deal with 0x1c and 0x1b names here.
2535 * This will result in a SRV record lookup */
2536 status = resolve_ads(name, name_type, sitename,
2537 return_iplist, return_count);
2538 if (NT_STATUS_IS_OK(status)) {
2539 goto done;
2541 } else if(strequal( tok, "lmhosts")) {
2542 status = resolve_lmhosts(name, name_type,
2543 return_iplist, return_count);
2544 if (NT_STATUS_IS_OK(status)) {
2545 goto done;
2547 } else if(strequal( tok, "wins")) {
2548 /* don't resolve 1D via WINS */
2549 struct sockaddr_storage *ss_list;
2550 if (name_type != 0x1D) {
2551 status = resolve_wins(name, name_type,
2552 talloc_tos(),
2553 &ss_list,
2554 return_count);
2555 if (NT_STATUS_IS_OK(status)) {
2556 if (!convert_ss2service(return_iplist,
2557 ss_list,
2558 *return_count)) {
2559 status = NT_STATUS_NO_MEMORY;
2561 goto done;
2564 } else if(strequal( tok, "bcast")) {
2565 struct sockaddr_storage *ss_list;
2566 status = name_resolve_bcast(
2567 name, name_type, talloc_tos(),
2568 &ss_list, return_count);
2569 if (NT_STATUS_IS_OK(status)) {
2570 if (!convert_ss2service(return_iplist,
2571 ss_list,
2572 *return_count)) {
2573 status = NT_STATUS_NO_MEMORY;
2575 goto done;
2577 } else {
2578 DEBUG(0,("resolve_name: unknown name switch type %s\n",
2579 tok));
2583 /* All of the resolve_* functions above have returned false. */
2585 TALLOC_FREE(frame);
2586 SAFE_FREE(*return_iplist);
2587 *return_count = 0;
2589 return NT_STATUS_UNSUCCESSFUL;
2591 done:
2593 /* Remove duplicate entries. Some queries, notably #1c (domain
2594 controllers) return the PDC in iplist[0] and then all domain
2595 controllers including the PDC in iplist[1..n]. Iterating over
2596 the iplist when the PDC is down will cause two sets of timeouts. */
2598 if ( *return_count ) {
2599 *return_count = remove_duplicate_addrs2(*return_iplist,
2600 *return_count );
2603 /* Save in name cache */
2604 if ( DEBUGLEVEL >= 100 ) {
2605 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) {
2606 char addr[INET6_ADDRSTRLEN];
2607 print_sockaddr(addr, sizeof(addr),
2608 &(*return_iplist)[i].ss);
2609 DEBUG(100, ("Storing name %s of type %d (%s:%d)\n",
2610 name,
2611 name_type,
2612 addr,
2613 (*return_iplist)[i].port));
2617 namecache_store(name, name_type, *return_count, *return_iplist);
2619 /* Display some debugging info */
2621 if ( DEBUGLEVEL >= 10 ) {
2622 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
2623 *return_count));
2625 for (i = 0; i < *return_count; i++) {
2626 char addr[INET6_ADDRSTRLEN];
2627 print_sockaddr(addr, sizeof(addr),
2628 &(*return_iplist)[i].ss);
2629 DEBUGADD(10, ("%s:%d ",
2630 addr,
2631 (*return_iplist)[i].port));
2633 DEBUG(10, ("\n"));
2636 TALLOC_FREE(frame);
2637 return status;
2640 /********************************************************
2641 Internal interface to resolve a name into one IP address.
2642 Use this function if the string is either an IP address, DNS
2643 or host name or NetBIOS name. This uses the name switch in the
2644 smb.conf to determine the order of name resolution.
2645 *********************************************************/
2647 bool resolve_name(const char *name,
2648 struct sockaddr_storage *return_ss,
2649 int name_type,
2650 bool prefer_ipv4)
2652 struct ip_service *ss_list = NULL;
2653 char *sitename = NULL;
2654 int count = 0;
2656 if (is_ipaddress(name)) {
2657 return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
2660 sitename = sitename_fetch(lp_realm()); /* wild guess */
2662 if (NT_STATUS_IS_OK(internal_resolve_name(name, name_type, sitename,
2663 &ss_list, &count,
2664 lp_name_resolve_order()))) {
2665 int i;
2667 if (prefer_ipv4) {
2668 for (i=0; i<count; i++) {
2669 if (!is_zero_addr(&ss_list[i].ss) &&
2670 !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss) &&
2671 (ss_list[i].ss.ss_family == AF_INET)) {
2672 *return_ss = ss_list[i].ss;
2673 SAFE_FREE(ss_list);
2674 SAFE_FREE(sitename);
2675 return True;
2680 /* only return valid addresses for TCP connections */
2681 for (i=0; i<count; i++) {
2682 if (!is_zero_addr(&ss_list[i].ss) &&
2683 !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
2684 *return_ss = ss_list[i].ss;
2685 SAFE_FREE(ss_list);
2686 SAFE_FREE(sitename);
2687 return True;
2692 SAFE_FREE(ss_list);
2693 SAFE_FREE(sitename);
2694 return False;
2697 /********************************************************
2698 Internal interface to resolve a name into a list of IP addresses.
2699 Use this function if the string is either an IP address, DNS
2700 or host name or NetBIOS name. This uses the name switch in the
2701 smb.conf to determine the order of name resolution.
2702 *********************************************************/
2704 NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
2705 const char *name,
2706 int name_type,
2707 struct sockaddr_storage **return_ss_arr,
2708 unsigned int *p_num_entries)
2710 struct ip_service *ss_list = NULL;
2711 char *sitename = NULL;
2712 int count = 0;
2713 int i;
2714 unsigned int num_entries;
2715 NTSTATUS status;
2717 *p_num_entries = 0;
2718 *return_ss_arr = NULL;
2720 if (is_ipaddress(name)) {
2721 *return_ss_arr = talloc(ctx, struct sockaddr_storage);
2722 if (!*return_ss_arr) {
2723 return NT_STATUS_NO_MEMORY;
2725 if (!interpret_string_addr(*return_ss_arr, name, AI_NUMERICHOST)) {
2726 TALLOC_FREE(*return_ss_arr);
2727 return NT_STATUS_BAD_NETWORK_NAME;
2729 *p_num_entries = 1;
2730 return NT_STATUS_OK;
2733 sitename = sitename_fetch(lp_realm()); /* wild guess */
2735 status = internal_resolve_name(name, name_type, sitename,
2736 &ss_list, &count,
2737 lp_name_resolve_order());
2738 SAFE_FREE(sitename);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 return status;
2744 /* only return valid addresses for TCP connections */
2745 for (i=0, num_entries = 0; i<count; i++) {
2746 if (!is_zero_addr(&ss_list[i].ss) &&
2747 !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
2748 num_entries++;
2751 if (num_entries == 0) {
2752 SAFE_FREE(ss_list);
2753 return NT_STATUS_BAD_NETWORK_NAME;
2756 *return_ss_arr = talloc_array(ctx,
2757 struct sockaddr_storage,
2758 num_entries);
2759 if (!(*return_ss_arr)) {
2760 SAFE_FREE(ss_list);
2761 return NT_STATUS_NO_MEMORY;
2764 for (i=0, num_entries = 0; i<count; i++) {
2765 if (!is_zero_addr(&ss_list[i].ss) &&
2766 !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
2767 (*return_ss_arr)[num_entries++] = ss_list[i].ss;
2771 status = NT_STATUS_OK;
2772 *p_num_entries = num_entries;
2774 SAFE_FREE(ss_list);
2775 return NT_STATUS_OK;
2778 /********************************************************
2779 Find the IP address of the master browser or DMB for a workgroup.
2780 *********************************************************/
2782 bool find_master_ip(const char *group, struct sockaddr_storage *master_ss)
2784 struct ip_service *ip_list = NULL;
2785 int count = 0;
2786 NTSTATUS status;
2788 if (lp_disable_netbios()) {
2789 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
2790 return false;
2793 status = internal_resolve_name(group, 0x1D, NULL, &ip_list, &count,
2794 lp_name_resolve_order());
2795 if (NT_STATUS_IS_OK(status)) {
2796 *master_ss = ip_list[0].ss;
2797 SAFE_FREE(ip_list);
2798 return true;
2801 status = internal_resolve_name(group, 0x1B, NULL, &ip_list, &count,
2802 lp_name_resolve_order());
2803 if (NT_STATUS_IS_OK(status)) {
2804 *master_ss = ip_list[0].ss;
2805 SAFE_FREE(ip_list);
2806 return true;
2809 SAFE_FREE(ip_list);
2810 return false;
2813 /********************************************************
2814 Get the IP address list of the primary domain controller
2815 for a domain.
2816 *********************************************************/
2818 bool get_pdc_ip(const char *domain, struct sockaddr_storage *pss)
2820 struct ip_service *ip_list = NULL;
2821 int count = 0;
2822 NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2824 /* Look up #1B name */
2826 if (lp_security() == SEC_ADS) {
2827 status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
2828 &count, "ads");
2831 if (!NT_STATUS_IS_OK(status) || count == 0) {
2832 status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
2833 &count,
2834 lp_name_resolve_order());
2835 if (!NT_STATUS_IS_OK(status)) {
2836 return false;
2840 /* if we get more than 1 IP back we have to assume it is a
2841 multi-homed PDC and not a mess up */
2843 if ( count > 1 ) {
2844 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
2845 sort_service_list(ip_list, count);
2848 *pss = ip_list[0].ss;
2849 SAFE_FREE(ip_list);
2850 return true;
2853 /* Private enum type for lookups. */
2855 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
2857 /********************************************************
2858 Get the IP address list of the domain controllers for
2859 a domain.
2860 *********************************************************/
2862 static NTSTATUS get_dc_list(const char *domain,
2863 const char *sitename,
2864 struct ip_service **ip_list,
2865 int *count,
2866 enum dc_lookup_type lookup_type,
2867 bool *ordered)
2869 char *resolve_order = NULL;
2870 char *saf_servername = NULL;
2871 char *pserver = NULL;
2872 const char *p;
2873 char *port_str = NULL;
2874 int port;
2875 char *name;
2876 int num_addresses = 0;
2877 int local_count, i, j;
2878 struct ip_service *return_iplist = NULL;
2879 struct ip_service *auto_ip_list = NULL;
2880 bool done_auto_lookup = false;
2881 int auto_count = 0;
2882 NTSTATUS status;
2883 TALLOC_CTX *ctx = talloc_init("get_dc_list");
2885 *ip_list = NULL;
2886 *count = 0;
2888 if (!ctx) {
2889 return NT_STATUS_NO_MEMORY;
2892 *ordered = False;
2894 /* if we are restricted to solely using DNS for looking
2895 up a domain controller, make sure that host lookups
2896 are enabled for the 'name resolve order'. If host lookups
2897 are disabled and ads_only is True, then set the string to
2898 NULL. */
2900 resolve_order = talloc_strdup(ctx, lp_name_resolve_order());
2901 if (!resolve_order) {
2902 status = NT_STATUS_NO_MEMORY;
2903 goto out;
2905 strlower_m(resolve_order);
2906 if (lookup_type == DC_ADS_ONLY) {
2907 if (strstr( resolve_order, "host")) {
2908 resolve_order = talloc_strdup(ctx, "ads");
2910 /* DNS SRV lookups used by the ads resolver
2911 are already sorted by priority and weight */
2912 *ordered = true;
2913 } else {
2914 resolve_order = talloc_strdup(ctx, "NULL");
2916 } else if (lookup_type == DC_KDC_ONLY) {
2917 /* DNS SRV lookups used by the ads/kdc resolver
2918 are already sorted by priority and weight */
2919 *ordered = true;
2920 resolve_order = talloc_strdup(ctx, "kdc");
2922 if (!resolve_order) {
2923 status = NT_STATUS_NO_MEMORY;
2924 goto out;
2927 /* fetch the server we have affinity for. Add the
2928 'password server' list to a search for our domain controllers */
2930 saf_servername = saf_fetch( domain);
2932 if (strequal(domain, lp_workgroup()) || strequal(domain, lp_realm())) {
2933 pserver = talloc_asprintf(ctx, "%s, %s",
2934 saf_servername ? saf_servername : "",
2935 lp_passwordserver());
2936 } else {
2937 pserver = talloc_asprintf(ctx, "%s, *",
2938 saf_servername ? saf_servername : "");
2941 SAFE_FREE(saf_servername);
2942 if (!pserver) {
2943 status = NT_STATUS_NO_MEMORY;
2944 goto out;
2947 /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
2949 if (!*pserver ) {
2950 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
2951 status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
2952 count, resolve_order);
2953 goto out;
2956 DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
2959 * if '*' appears in the "password server" list then add
2960 * an auto lookup to the list of manually configured
2961 * DC's. If any DC is listed by name, then the list should be
2962 * considered to be ordered
2965 p = pserver;
2966 while (next_token_talloc(ctx, &p, &name, LIST_SEP)) {
2967 if (!done_auto_lookup && strequal(name, "*")) {
2968 status = internal_resolve_name(domain, 0x1C, sitename,
2969 &auto_ip_list,
2970 &auto_count,
2971 resolve_order);
2972 if (NT_STATUS_IS_OK(status)) {
2973 num_addresses += auto_count;
2975 done_auto_lookup = true;
2976 DEBUG(8,("Adding %d DC's from auto lookup\n",
2977 auto_count));
2978 } else {
2979 num_addresses++;
2983 /* if we have no addresses and haven't done the auto lookup, then
2984 just return the list of DC's. Or maybe we just failed. */
2986 if ((num_addresses == 0)) {
2987 if (done_auto_lookup) {
2988 DEBUG(4,("get_dc_list: no servers found\n"));
2989 status = NT_STATUS_NO_LOGON_SERVERS;
2990 goto out;
2992 status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
2993 count, resolve_order);
2994 goto out;
2997 if ((return_iplist = SMB_MALLOC_ARRAY(struct ip_service,
2998 num_addresses)) == NULL) {
2999 DEBUG(3,("get_dc_list: malloc fail !\n"));
3000 status = NT_STATUS_NO_MEMORY;
3001 goto out;
3004 p = pserver;
3005 local_count = 0;
3007 /* fill in the return list now with real IP's */
3009 while ((local_count<num_addresses) &&
3010 next_token_talloc(ctx, &p, &name, LIST_SEP)) {
3011 struct sockaddr_storage name_ss;
3013 /* copy any addersses from the auto lookup */
3015 if (strequal(name, "*")) {
3016 for (j=0; j<auto_count; j++) {
3017 char addr[INET6_ADDRSTRLEN];
3018 print_sockaddr(addr,
3019 sizeof(addr),
3020 &auto_ip_list[j].ss);
3021 /* Check for and don't copy any
3022 * known bad DC IP's. */
3023 if(!NT_STATUS_IS_OK(check_negative_conn_cache(
3024 domain,
3025 addr))) {
3026 DEBUG(5,("get_dc_list: "
3027 "negative entry %s removed "
3028 "from DC list\n",
3029 addr));
3030 continue;
3032 return_iplist[local_count].ss =
3033 auto_ip_list[j].ss;
3034 return_iplist[local_count].port =
3035 auto_ip_list[j].port;
3036 local_count++;
3038 continue;
3041 /* added support for address:port syntax for ads
3042 * (not that I think anyone will ever run the LDAP
3043 * server in an AD domain on something other than
3044 * port 389 */
3046 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
3047 if ((port_str=strchr(name, ':')) != NULL) {
3048 *port_str = '\0';
3049 port_str++;
3050 port = atoi(port_str);
3053 /* explicit lookup; resolve_name() will
3054 * handle names & IP addresses */
3055 if (resolve_name( name, &name_ss, 0x20, true )) {
3056 char addr[INET6_ADDRSTRLEN];
3057 print_sockaddr(addr,
3058 sizeof(addr),
3059 &name_ss);
3061 /* Check for and don't copy any known bad DC IP's. */
3062 if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain,
3063 addr)) ) {
3064 DEBUG(5,("get_dc_list: negative entry %s "
3065 "removed from DC list\n",
3066 name ));
3067 continue;
3070 return_iplist[local_count].ss = name_ss;
3071 return_iplist[local_count].port = port;
3072 local_count++;
3073 *ordered = true;
3077 /* need to remove duplicates in the list if we have any
3078 explicit password servers */
3080 if (local_count) {
3081 local_count = remove_duplicate_addrs2(return_iplist,
3082 local_count );
3085 /* For DC's we always prioritize IPv4 due to W2K3 not
3086 * supporting LDAP, KRB5 or CLDAP over IPv6. */
3088 if (local_count && return_iplist) {
3089 prioritize_ipv4_list(return_iplist, local_count);
3092 if ( DEBUGLEVEL >= 4 ) {
3093 DEBUG(4,("get_dc_list: returning %d ip addresses "
3094 "in an %sordered list\n",
3095 local_count,
3096 *ordered ? "":"un"));
3097 DEBUG(4,("get_dc_list: "));
3098 for ( i=0; i<local_count; i++ ) {
3099 char addr[INET6_ADDRSTRLEN];
3100 print_sockaddr(addr,
3101 sizeof(addr),
3102 &return_iplist[i].ss);
3103 DEBUGADD(4,("%s:%d ", addr, return_iplist[i].port ));
3105 DEBUGADD(4,("\n"));
3108 *ip_list = return_iplist;
3109 *count = local_count;
3111 status = ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
3113 out:
3115 if (!NT_STATUS_IS_OK(status)) {
3116 SAFE_FREE(return_iplist);
3117 *ip_list = NULL;
3118 *count = 0;
3121 SAFE_FREE(auto_ip_list);
3122 TALLOC_FREE(ctx);
3123 return status;
3126 /*********************************************************************
3127 Small wrapper function to get the DC list and sort it if neccessary.
3128 *********************************************************************/
3130 NTSTATUS get_sorted_dc_list( const char *domain,
3131 const char *sitename,
3132 struct ip_service **ip_list,
3133 int *count,
3134 bool ads_only )
3136 bool ordered = false;
3137 NTSTATUS status;
3138 enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
3140 *ip_list = NULL;
3141 *count = 0;
3143 DEBUG(8,("get_sorted_dc_list: attempting lookup "
3144 "for name %s (sitename %s) using [%s]\n",
3145 domain,
3146 sitename ? sitename : "NULL",
3147 (ads_only ? "ads" : lp_name_resolve_order())));
3149 if (ads_only) {
3150 lookup_type = DC_ADS_ONLY;
3153 status = get_dc_list(domain, sitename, ip_list,
3154 count, lookup_type, &ordered);
3155 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_LOGON_SERVERS)
3156 && sitename) {
3157 DEBUG(3,("get_sorted_dc_list: no server for name %s available"
3158 " in site %s, fallback to all servers\n",
3159 domain, sitename));
3160 status = get_dc_list(domain, NULL, ip_list,
3161 count, lookup_type, &ordered);
3164 if (!NT_STATUS_IS_OK(status)) {
3165 SAFE_FREE(*ip_list);
3166 *count = 0;
3167 return status;
3170 /* only sort if we don't already have an ordered list */
3171 if (!ordered) {
3172 sort_service_list(*ip_list, *count);
3175 return NT_STATUS_OK;
3178 /*********************************************************************
3179 Get the KDC list - re-use all the logic in get_dc_list.
3180 *********************************************************************/
3182 NTSTATUS get_kdc_list( const char *realm,
3183 const char *sitename,
3184 struct ip_service **ip_list,
3185 int *count)
3187 bool ordered;
3188 NTSTATUS status;
3190 *count = 0;
3191 *ip_list = NULL;
3193 status = get_dc_list(realm, sitename, ip_list,
3194 count, DC_KDC_ONLY, &ordered);
3196 if (!NT_STATUS_IS_OK(status)) {
3197 SAFE_FREE(*ip_list);
3198 *count = 0;
3199 return status;
3202 /* only sort if we don't already have an ordered list */
3203 if ( !ordered ) {
3204 sort_service_list(*ip_list, *count);
3207 return NT_STATUS_OK;