2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "system/network.h"
24 #include "system/time.h"
26 /* A netbios node status array element. */
34 /* nmbd.c sets this to True. */
35 BOOL global_in_nmbd = False;
37 /****************************************************************************
38 generate a random trn_id
39 ****************************************************************************/
40 static int generate_trn_id(void)
45 sys_srandom(getpid());
48 trn_id = sys_random();
50 return trn_id % (uint_t)0x7FFF;
54 /****************************************************************************
55 parse a node status response into an array of structures
56 ****************************************************************************/
57 static struct node_status *parse_node_status(char *p, int *num_names)
59 struct node_status *ret;
62 *num_names = CVAL(p,0);
64 if (*num_names == 0) return NULL;
66 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
67 if (!ret) return NULL;
70 for (i=0;i< *num_names;i++) {
71 StrnCpy(ret[i].name,p,15);
72 trim_string(ret[i].name,NULL," ");
73 ret[i].type = CVAL(p,15);
76 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
77 ret[i].type, ret[i].flags));
83 /****************************************************************************
84 do a NBT node status query on an open socket and return an array of
85 structures holding the returned names or NULL if the query failed
86 **************************************************************************/
87 struct node_status *node_status_query(int fd,struct nmb_name *name,
88 struct ipv4_addr to_ip, int *num_names)
92 int retry_time = 2000;
94 struct packet_struct p;
95 struct packet_struct *p2;
96 struct nmb_packet *nmb = &p.packet.nmb;
97 struct node_status *ret;
101 nmb->header.name_trn_id = generate_trn_id();
102 nmb->header.opcode = 0;
103 nmb->header.response = False;
104 nmb->header.nm_flags.bcast = False;
105 nmb->header.nm_flags.recursion_available = False;
106 nmb->header.nm_flags.recursion_desired = False;
107 nmb->header.nm_flags.trunc = False;
108 nmb->header.nm_flags.authoritative = False;
109 nmb->header.rcode = 0;
110 nmb->header.qdcount = 1;
111 nmb->header.ancount = 0;
112 nmb->header.nscount = 0;
113 nmb->header.arcount = 0;
114 nmb->question.question_name = *name;
115 nmb->question.question_type = 0x21;
116 nmb->question.question_class = 0x1;
121 p.timestamp = time(NULL);
122 p.packet_type = NMB_PACKET;
126 if (!send_packet(&p))
132 struct timeval tval2;
133 GetTimeOfDay(&tval2);
134 if (TvalDiff(&tval,&tval2) > retry_time) {
137 if (!found && !send_packet(&p))
143 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
144 struct nmb_packet *nmb2 = &p2->packet.nmb;
145 debug_nmb_packet(p2);
147 if (nmb2->header.opcode != 0 ||
148 nmb2->header.nm_flags.bcast ||
149 nmb2->header.rcode ||
150 !nmb2->header.ancount ||
151 nmb2->answers->rr_type != 0x21) {
152 /* XXXX what do we do with this? could be a
153 redirect, but we'll discard it for the
159 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
169 /****************************************************************************
170 find the first type XX name in a node status reply - used for finding
171 a servers name given its IP
172 return the matched name in *name
173 **************************************************************************/
175 BOOL name_status_find(const char *q_name, int q_type, int type, struct ipv4_addr to_ip, char *name)
177 struct node_status *status = NULL;
178 struct nmb_name nname;
183 if (lp_disable_netbios()) {
184 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
188 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
189 q_type, sys_inet_ntoa(to_ip)));
191 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
195 /* W2K PDC's seem not to respond to '*'#0. JRA */
196 make_nmb_name(&nname, q_name, q_type);
197 status = node_status_query(sock, &nname, to_ip, &count);
202 for (i=0;i<count;i++) {
203 if (status[i].type == type)
209 pull_ascii(name, status[i].name, 16, 15, STR_TERMINATE);
215 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
218 DEBUGADD(10, (", ip address is %s", sys_inet_ntoa(to_ip)));
227 comparison function used by sort_ip_list
229 int ip_compare(struct ipv4_addr *ip1, struct ipv4_addr *ip2)
231 int max_bits1=0, max_bits2=0;
232 int num_interfaces = iface_count();
235 for (i=0;i<num_interfaces;i++) {
238 ip = *iface_n_bcast(i);
239 bits1 = matching_quad_bits((uint8_t *)&ip1->s_addr, (uint8_t *)&ip.s_addr);
240 bits2 = matching_quad_bits((uint8_t *)&ip2->s_addr, (uint8_t *)&ip.s_addr);
241 max_bits1 = MAX(bits1, max_bits1);
242 max_bits2 = MAX(bits2, max_bits2);
245 /* bias towards directly reachable IPs */
246 if (iface_local(*ip1)) {
249 if (iface_local(*ip2)) {
253 return max_bits2 - max_bits1;
257 sort an IP list so that names that are close to one of our interfaces
258 are at the top. This prevents the problem where a WINS server returns an IP that
259 is not reachable from our subnet as the first match
261 static void sort_ip_list(struct ipv4_addr *iplist, int count)
267 qsort(iplist, count, sizeof(struct ipv4_addr), QSORT_CAST ip_compare);
271 /****************************************************************************
272 Do a netbios name query to find someones IP.
273 Returns an array of IP addresses or NULL if none.
274 *count will be set to the number of addresses returned.
275 *timed_out is set if we failed by timing out
276 ****************************************************************************/
277 struct ipv4_addr *name_query(int fd,const char *name,int name_type,
278 BOOL bcast,BOOL recurse,
279 struct ipv4_addr to_ip, int *count, int *flags,
284 int retry_time = bcast?250:2000;
286 struct packet_struct p;
287 struct packet_struct *p2;
288 struct nmb_packet *nmb = &p.packet.nmb;
289 struct ipv4_addr *ip_list = NULL;
291 if (lp_disable_netbios()) {
292 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
300 memset((char *)&p,'\0',sizeof(p));
304 nmb->header.name_trn_id = generate_trn_id();
305 nmb->header.opcode = 0;
306 nmb->header.response = False;
307 nmb->header.nm_flags.bcast = bcast;
308 nmb->header.nm_flags.recursion_available = False;
309 nmb->header.nm_flags.recursion_desired = recurse;
310 nmb->header.nm_flags.trunc = False;
311 nmb->header.nm_flags.authoritative = False;
312 nmb->header.rcode = 0;
313 nmb->header.qdcount = 1;
314 nmb->header.ancount = 0;
315 nmb->header.nscount = 0;
316 nmb->header.arcount = 0;
318 make_nmb_name(&nmb->question.question_name,name,name_type);
320 nmb->question.question_type = 0x20;
321 nmb->question.question_class = 0x1;
326 p.timestamp = time(NULL);
327 p.packet_type = NMB_PACKET;
331 if (!send_packet(&p))
337 struct timeval tval2;
338 struct ipv4_addr *tmp_ip_list;
340 GetTimeOfDay(&tval2);
341 if (TvalDiff(&tval,&tval2) > retry_time) {
344 if (!found && !send_packet(&p))
350 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
351 struct nmb_packet *nmb2 = &p2->packet.nmb;
352 debug_nmb_packet(p2);
354 /* If we get a Negative Name Query Response from a WINS
355 * server, we should report it and give up.
357 if( 0 == nmb2->header.opcode /* A query response */
358 && !(bcast) /* from a WINS server */
359 && nmb2->header.rcode /* Error returned */
363 /* Only executed if DEBUGLEVEL >= 3 */
364 DEBUG(3,("Negative name query response, rcode 0x%02x: ", nmb2->header.rcode ));
365 switch( nmb2->header.rcode ) {
367 DEBUG(3,("Request was invalidly formatted.\n" ));
370 DEBUG(3,("Problem with NBNS, cannot process name.\n"));
373 DEBUG(3,("The name requested does not exist.\n" ));
376 DEBUG(3,("Unsupported request error.\n" ));
379 DEBUG(3,("Query refused error.\n" ));
382 DEBUG(3,("Unrecognized error code.\n" ));
390 if (nmb2->header.opcode != 0 ||
391 nmb2->header.nm_flags.bcast ||
392 nmb2->header.rcode ||
393 !nmb2->header.ancount) {
395 * XXXX what do we do with this? Could be a
396 * redirect, but we'll discard it for the
403 tmp_ip_list = (struct ipv4_addr *)Realloc( ip_list, sizeof( ip_list[0] )
404 * ( (*count) + nmb2->answers->rdlength/6 ) );
407 DEBUG(0,("name_query: Realloc failed.\n"));
411 ip_list = tmp_ip_list;
414 DEBUG(2,("Got a positive name query response from %s ( ", sys_inet_ntoa(p2->ip)));
415 for (i=0;i<nmb2->answers->rdlength/6;i++) {
416 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
417 DEBUGADD(2,("%s ",sys_inet_ntoa(ip_list[(*count)])));
425 /* We add the flags back ... */
426 if (nmb2->header.response)
427 (*flags) |= NM_FLAGS_RS;
428 if (nmb2->header.nm_flags.authoritative)
429 (*flags) |= NM_FLAGS_AA;
430 if (nmb2->header.nm_flags.trunc)
431 (*flags) |= NM_FLAGS_TC;
432 if (nmb2->header.nm_flags.recursion_desired)
433 (*flags) |= NM_FLAGS_RD;
434 if (nmb2->header.nm_flags.recursion_available)
435 (*flags) |= NM_FLAGS_RA;
436 if (nmb2->header.nm_flags.bcast)
437 (*flags) |= NM_FLAGS_B;
440 * If we're doing a unicast lookup we only
441 * expect one reply. Don't wait the full 2
442 * seconds if we got one. JRA.
453 /* sort the ip list so we choose close servers first if possible */
454 sort_ip_list(ip_list, *count);
459 /********************************************************
460 Start parsing the lmhosts file.
461 *********************************************************/
463 XFILE *startlmhosts(char *fname)
465 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
467 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
468 fname, strerror(errno)));
474 /********************************************************
475 Parse the next line in the lmhosts file.
476 *********************************************************/
478 BOOL getlmhostsent( TALLOC_CTX *mem_ctx,
479 XFILE *fp, pstring name, int *name_type, struct ipv4_addr *ipaddr)
483 while(!x_feof(fp) && !x_ferror(fp)) {
484 pstring ip,flags,extra;
491 if (!fgets_slash(line,sizeof(pstring),fp))
503 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
505 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
507 if (next_token(&ptr,flags,NULL, sizeof(flags)))
509 if (next_token(&ptr,extra,NULL, sizeof(extra)))
515 if (count > 0 && count < 2)
517 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
523 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
527 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
529 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
531 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
535 *ipaddr = interpret_addr2(ip);
537 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
538 then only add that name type. */
539 if((ptr1 = strchr_m(name, '#')) != NULL)
544 *name_type = (int)strtol(ptr1, &endptr, 16);
546 if(!*ptr1 || (endptr == ptr1))
548 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
552 *(--ptr1) = '\0'; /* Truncate at the '#' */
561 /********************************************************
562 Finish parsing the lmhosts file.
563 *********************************************************/
565 void endlmhosts(XFILE *fp)
571 /********************************************************
572 Resolve via "bcast" method.
573 *********************************************************/
575 BOOL name_resolve_bcast(const char *name, int name_type,
576 struct ipv4_addr **return_ip_list, int *return_count)
579 int num_interfaces = iface_count();
581 if (lp_disable_netbios()) {
582 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
586 *return_ip_list = NULL;
590 * "bcast" means do a broadcast lookup on all the local interfaces.
593 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
595 sock = open_socket_in( SOCK_DGRAM, 0, 3,
596 interpret_addr(lp_socket_address()), True );
598 if (sock == -1) return False;
600 set_socket_options(sock,"SO_BROADCAST");
602 * Lookup the name on all the interfaces, return on
603 * the first successful match.
605 for( i = num_interfaces-1; i >= 0; i--) {
606 struct ipv4_addr sendto_ip;
608 /* Done this way to fix compiler error on IRIX 5.x */
609 sendto_ip = *iface_n_bcast(i);
610 *return_ip_list = name_query(sock, name, name_type, True,
611 True, sendto_ip, return_count, &flags, NULL);
612 if(*return_ip_list != NULL) {
622 /********************************************************
623 Resolve via "wins" method.
624 *********************************************************/
625 BOOL resolve_wins(TALLOC_CTX *mem_ctx, const char *name, int name_type,
626 struct ipv4_addr **return_iplist, int *return_count)
630 struct ipv4_addr src_ip;
632 if (lp_disable_netbios()) {
633 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
637 *return_iplist = NULL;
640 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
642 if (wins_srv_count() < 1) {
643 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
647 /* we try a lookup on each of the WINS tags in turn */
648 wins_tags = wins_srv_tags();
651 /* huh? no tags?? give up in disgust */
655 /* the address we will be sending from */
656 src_ip = interpret_addr2(lp_socket_address());
658 /* in the worst case we will try every wins server with every
660 for (t=0; wins_tags && wins_tags[t]; t++) {
661 int srv_count = wins_srv_count_tag(wins_tags[t]);
662 for (i=0; i<srv_count; i++) {
663 struct ipv4_addr wins_ip;
667 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
669 if (global_in_nmbd && ismyip(wins_ip)) {
670 /* yikes! we'll loop forever */
674 /* skip any that have been unresponsive lately */
675 if (wins_srv_is_dead(wins_ip, src_ip)) {
679 DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", sys_inet_ntoa(wins_ip), wins_tags[t]));
681 sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
686 *return_iplist = name_query(sock,name,name_type, False,
687 True, wins_ip, return_count, &flags,
689 if (*return_iplist != NULL) {
695 /* Timed out wating for WINS server to respond. Mark it dead. */
696 wins_srv_died(wins_ip, src_ip);
698 /* The name definately isn't in this
699 group of WINS servers. goto the next group */
705 wins_srv_tags_free(wins_tags);
709 wins_srv_tags_free(wins_tags);
714 /********************************************************
715 Resolve via "hosts" method.
716 *********************************************************/
718 static BOOL resolve_hosts(const char *name,
719 struct ipv4_addr **return_iplist, int *return_count)
722 * "host" means do a localhost, or dns lookup.
726 *return_iplist = NULL;
729 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
731 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
732 struct ipv4_addr return_ip;
733 putip((char *)&return_ip,(char *)hp->h_addr);
734 *return_iplist = (struct ipv4_addr *)malloc(sizeof(struct ipv4_addr));
735 if(*return_iplist == NULL) {
736 DEBUG(3,("resolve_hosts: malloc fail !\n"));
739 **return_iplist = return_ip;
746 /********************************************************
747 Internal interface to resolve a name into an IP address.
748 Use this function if the string is either an IP address, DNS
749 or host name or NetBIOS name. This uses the name switch in the
750 smb.conf to determine the order of name resolution.
751 *********************************************************/
753 static BOOL internal_resolve_name(TALLOC_CTX *mem_ctx, const char *name, int name_type,
754 struct ipv4_addr **return_iplist, int *return_count)
756 char *name_resolve_list;
759 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
760 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
761 BOOL is_address = is_ipaddress(name);
763 struct ipv4_addr *nodupes_iplist;
766 *return_iplist = NULL;
769 DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
771 if (allzeros || allones || is_address) {
772 *return_iplist = (struct ipv4_addr *)malloc(sizeof(struct ipv4_addr));
773 if(*return_iplist == NULL) {
774 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
778 /* if it's in the form of an IP address then get the lib to interpret it */
779 if (((*return_iplist)->s_addr = inet_addr(name)) == 0xFFFFFFFF ){
780 DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
784 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
790 /* Check netbios name cache */
792 if (namecache_fetch(mem_ctx, name, name_type, return_iplist, return_count)) {
794 /* This could be a negative response */
796 return (*return_count > 0);
799 name_resolve_list = talloc_strdup(mem_ctx, lp_name_resolve_order());
800 ptr = name_resolve_list;
804 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
805 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
806 if (name_type == 0x20) {
807 if (resolve_hosts(name, return_iplist, return_count)) {
812 } else if(strequal( tok, "lmhosts")) {
813 /* REWRITE: add back in? */
814 DEBUG(2,("resolve_name: REWRITE: add lmhosts back?? %s\n", tok));
815 } else if(strequal( tok, "wins")) {
816 /* don't resolve 1D via WINS */
817 if (name_type != 0x1D &&
818 resolve_wins(mem_ctx, name, name_type, return_iplist, return_count)) {
822 } else if(strequal( tok, "bcast")) {
823 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
828 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
832 /* All of the resolve_* functions above have returned false. */
834 SAFE_FREE(*return_iplist);
841 /* Remove duplicate entries. Some queries, notably #1c (domain
842 controllers) return the PDC in iplist[0] and then all domain
843 controllers including the PDC in iplist[1..n]. Iterating over
844 the iplist when the PDC is down will cause two sets of timeouts. */
846 if (*return_count && (nodupes_iplist = (struct ipv4_addr *)
847 malloc(sizeof(struct ipv4_addr) * (*return_count)))) {
848 int nodupes_count = 0;
850 /* Iterate over return_iplist looking for duplicates */
852 for (i = 0; i < *return_count; i++) {
853 BOOL is_dupe = False;
856 for (j = i + 1; j < *return_count; j++) {
857 if (ip_equal((*return_iplist)[i],
858 (*return_iplist)[j])) {
866 /* This one not a duplicate */
868 nodupes_iplist[nodupes_count] = (*return_iplist)[i];
873 /* Switcheroo with original list */
875 free(*return_iplist);
877 *return_iplist = nodupes_iplist;
878 *return_count = nodupes_count;
881 /* Save in name cache */
882 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
883 DEBUG(100, ("Storing name %s of type %d (ip: %s)\n", name,
884 name_type, sys_inet_ntoa((*return_iplist)[i])));
886 namecache_store(mem_ctx, name, name_type, *return_count, *return_iplist);
888 /* Display some debugging info */
890 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
893 for (i = 0; i < *return_count; i++)
894 DEBUGADD(10, ("%s ", sys_inet_ntoa((*return_iplist)[i])));
901 /********************************************************
902 Internal interface to resolve a name into one IP address.
903 Use this function if the string is either an IP address, DNS
904 or host name or NetBIOS name. This uses the name switch in the
905 smb.conf to determine the order of name resolution.
906 *********************************************************/
907 BOOL resolve_name(TALLOC_CTX *mem_ctx, const char *name, struct ipv4_addr *return_ip, int name_type)
909 struct ipv4_addr *ip_list = NULL;
912 if (is_ipaddress(name)) {
913 *return_ip = interpret_addr2(name);
917 if (internal_resolve_name(mem_ctx, name, name_type, &ip_list, &count)) {
919 /* only return valid addresses for TCP connections */
920 for (i=0; i<count; i++) {
921 const char *ip_str = sys_inet_ntoa(ip_list[i]);
923 strcmp(ip_str, "255.255.255.255") != 0 &&
924 strcmp(ip_str, "0.0.0.0") != 0) {
925 *return_ip = ip_list[i];
935 /********************************************************
936 Find the IP address of the master browser or DMB for a workgroup.
937 *********************************************************/
939 BOOL find_master_ip(TALLOC_CTX *mem_ctx, const char *group, struct ipv4_addr *master_ip)
941 struct ipv4_addr *ip_list = NULL;
944 if (lp_disable_netbios()) {
945 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
949 if (internal_resolve_name(mem_ctx, group, 0x1D, &ip_list, &count)) {
950 *master_ip = ip_list[0];
954 if(internal_resolve_name(mem_ctx, group, 0x1B, &ip_list, &count)) {
955 *master_ip = ip_list[0];
964 /********************************************************
965 Lookup a DC name given a Domain name and IP address.
966 *********************************************************/
968 BOOL lookup_dc_name(const char *srcname, const char *domain,
969 struct ipv4_addr *dc_ip, char *ret_name)
971 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
975 if (lp_disable_netbios()) {
976 DEBUG(5,("lookup_dc_name(%s): netbios is disabled\n", domain));
981 * Due to the fact win WinNT *sucks* we must do a node status
987 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
989 if(ret && *dc_name) {
990 fstrcpy(ret_name, dc_name);
996 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
998 JRA - This code is broken with BDC rollover - we need to do a full
999 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1002 int retry_time = 2000;
1003 struct timeval tval;
1004 struct packet_struct p;
1005 struct dgram_packet *dgram = &p.packet.dgram;
1009 struct sockaddr_in sock_name;
1010 int sock_len = sizeof(sock_name);
1011 const char *mailslot = NET_LOGON_MAILSLOT;
1012 char *mailslot_name;
1015 int dgm_id = generate_trn_id();
1016 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1021 /* Find out the transient UDP port we have been allocated. */
1022 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1023 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1030 * Create the request data.
1033 memset(buffer,'\0',sizeof(buffer));
1035 SSVAL(bufp,0,QUERYFORPDC);
1037 fstrcpy(bufp,srcname);
1038 bufp += (strlen(bufp) + 1);
1039 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1040 mailslot_name = bufp;
1041 bufp += (strlen(bufp) + 1);
1042 bufp = ALIGN2(bufp, buffer);
1043 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1046 SSVAL(bufp,4,0xFFFF);
1047 SSVAL(bufp,6,0xFFFF);
1049 len = PTR_DIFF(bufp,buffer);
1051 memset((char *)&p,'\0',sizeof(p));
1053 /* DIRECT GROUP or UNIQUE datagram. */
1054 dgram->header.msg_type = 0x10;
1055 dgram->header.flags.node_type = M_NODE;
1056 dgram->header.flags.first = True;
1057 dgram->header.flags.more = False;
1058 dgram->header.dgm_id = dgm_id;
1059 dgram->header.source_ip = *iface_ip(*pdc_ip);
1060 dgram->header.source_port = ntohs(sock_name.sin_port);
1061 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1062 dgram->header.packet_offset = 0;
1064 make_nmb_name(&dgram->source_name,srcname,0);
1065 make_nmb_name(&dgram->dest_name,domain,0x1C);
1067 ptr = &dgram->data[0];
1069 /* Setup the smb part. */
1070 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1072 set_message(ptr,17,17 + len,True);
1075 CVAL(ptr,smb_com) = SMBtrans;
1076 SSVAL(ptr,smb_vwv1,len);
1077 SSVAL(ptr,smb_vwv11,len);
1078 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1079 SSVAL(ptr,smb_vwv13,3);
1080 SSVAL(ptr,smb_vwv14,1);
1081 SSVAL(ptr,smb_vwv15,1);
1082 SSVAL(ptr,smb_vwv16,2);
1084 pstrcpy(p2,mailslot);
1085 p2 = skip_string(p2,1);
1087 memcpy(p2,buffer,len);
1090 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1093 p.port = DGRAM_PORT;
1095 p.timestamp = time(NULL);
1096 p.packet_type = DGRAM_PACKET;
1098 GetTimeOfDay(&tval);
1100 if (!send_packet(&p)) {
1101 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1109 struct timeval tval2;
1110 struct packet_struct *p_ret;
1112 GetTimeOfDay(&tval2);
1113 if (TvalDiff(&tval,&tval2) > retry_time) {
1116 if (!send_packet(&p)) {
1117 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1121 GetTimeOfDay(&tval);
1125 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1126 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1130 buf = &dgram2->data[0];
1133 if (CVAL(buf,smb_com) != SMBtrans) {
1134 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (uint_t)
1135 CVAL(buf,smb_com), (uint_t)SMBtrans ));
1140 len = SVAL(buf,smb_vwv11);
1141 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1144 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1149 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1150 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1151 sys_inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1153 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1154 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1155 (uint_t)SVAL(buf,0), (uint_t)QUERYFORPDC_R ));
1161 /* Note this is safe as it is a bounded strcpy. */
1162 fstrcpy(ret_name, buf2);
1163 ret_name[sizeof(fstring)-1] = '\0';
1172 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1175 /********************************************************
1176 Get the IP address list of the primary domain controller
1178 *********************************************************/
1180 BOOL get_pdc_ip(TALLOC_CTX *mem_ctx, const char *domain, struct ipv4_addr *ip)
1182 struct ipv4_addr *ip_list;
1186 /* Look up #1B name */
1188 if (!internal_resolve_name(mem_ctx, domain, 0x1b, &ip_list, &count))
1191 /* if we get more than 1 IP back we have to assume it is a
1192 multi-homed PDC and not a mess up */
1195 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
1197 /* look for a local net */
1198 for ( i=0; i<count; i++ ) {
1199 if ( is_local_net( ip_list[i] ) )
1203 /* if we hit then end then just grab the first
1204 one from the list */
1217 /********************************************************
1218 Get the IP address list of the domain controllers for
1220 *********************************************************/
1222 BOOL get_dc_list(TALLOC_CTX *mem_ctx, const char *domain, struct ipv4_addr **ip_list, int *count, int *ordered)
1227 /* If it's our domain then use the 'password server' parameter. */
1229 if (strequal(domain, lp_workgroup())) {
1231 const char *pserver = lp_passwordserver(); /* UNIX charset. */
1233 int num_addresses = 0;
1234 int local_count, i, j;
1235 struct ipv4_addr *return_iplist = NULL;
1236 struct ipv4_addr *auto_ip_list = NULL;
1237 BOOL done_auto_lookup = False;
1242 return internal_resolve_name(mem_ctx,
1243 domain, 0x1C, ip_list, count);
1248 * if '*' appears in the "password server" list then add
1249 * an auto lookup to the list of manually configured
1250 * DC's. If any DC is listed by name, then the list should be
1251 * considered to be ordered
1254 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1255 if (strequal(name, "*")) {
1256 if ( internal_resolve_name(mem_ctx, domain, 0x1C, &auto_ip_list, &auto_count) )
1257 num_addresses += auto_count;
1258 done_auto_lookup = True;
1259 DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
1265 /* if we have no addresses and haven't done the auto lookup, then
1266 just return the list of DC's */
1268 if ( (num_addresses == 0) && !done_auto_lookup )
1269 return internal_resolve_name(mem_ctx, domain, 0x1C, ip_list, count);
1271 return_iplist = (struct ipv4_addr *)malloc(num_addresses * sizeof(struct ipv4_addr));
1273 if (return_iplist == NULL) {
1274 DEBUG(3,("get_dc_list: malloc fail !\n"));
1281 /* fill in the return list now with real IP's */
1283 while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
1284 struct ipv4_addr name_ip;
1286 /* copy any addersses from the auto lookup */
1288 if ( strequal(name, "*") ) {
1289 for ( j=0; j<auto_count; j++ )
1290 return_iplist[local_count++] = auto_ip_list[j];
1294 /* explicit lookup; resolve_name() will handle names & IP addresses */
1296 if ( resolve_name( mem_ctx, name, &name_ip, 0x20) ) {
1297 return_iplist[local_count++] = name_ip;
1303 SAFE_FREE(auto_ip_list);
1305 /* need to remove duplicates in the list if we have
1306 any explicit password servers */
1309 /* one loop to remove duplicates */
1310 for ( i=0; i<local_count; i++ ) {
1311 if ( is_zero_ip(return_iplist[i]) )
1314 for ( j=i+1; j<local_count; j++ ) {
1315 if ( ip_equal( return_iplist[i], return_iplist[j]) )
1316 zero_ip(&return_iplist[j]);
1320 /* one loop to clean up any holes we left */
1321 /* first ip should never be a zero_ip() */
1322 for (i = 0; i<local_count; ) {
1323 if ( is_zero_ip(return_iplist[i]) ) {
1324 if (i != local_count-1 )
1325 memmove(&return_iplist[i], &return_iplist[i+1],
1326 (local_count - i - 1)*sizeof(return_iplist[i]));
1334 *ip_list = return_iplist;
1335 *count = local_count;
1337 DEBUG(8,("get_dc_list: return %d ip addresses\n", *count));
1339 return (*count != 0);
1342 return internal_resolve_name(mem_ctx, domain, 0x1C, ip_list, count);