2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL;
28 /* nmbd.c sets this to True. */
29 BOOL global_in_nmbd = False;
31 /****************************************************************************
32 Interpret a node status response.
33 ****************************************************************************/
35 static void _interpret_node_status(char *p, char *master,char *rname)
37 int numnames = CVAL(p,0);
38 DEBUG(1,("received %d names\n",numnames));
40 if (rname) *rname = 0;
41 if (master) *master = 0;
54 fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : " ");
55 if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B ");
56 if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P ");
57 if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M ");
58 if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H ");
59 if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> ");
60 if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> ");
61 if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> ");
62 if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> ");
64 if (master && !*master && type == 0x1d) {
65 StrnCpy(master,qname,15);
66 trim_string(master,NULL," ");
69 if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
70 StrnCpy(rname,qname,15);
71 trim_string(rname,NULL," ");
74 for (i = strlen( qname) ; --i >= 0 ; ) {
75 if (!isprint((int)qname[i])) qname[i] = '.';
77 DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
81 DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
82 IVAL(p,20),IVAL(p,24)));
85 /****************************************************************************
86 Internal function handling a netbios name status query on a host.
87 **************************************************************************/
89 static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse,
90 struct in_addr to_ip,char *master,char *rname, BOOL verbose,
91 void (*fn_interpret_node_status)(char *, char *,char *),
92 void (*fn)(struct packet_struct *))
96 int retry_time = 5000;
98 struct packet_struct p;
99 struct packet_struct *p2;
100 struct nmb_packet *nmb = &p.packet.nmb;
101 static int name_trn_id = 0;
103 memset((char *)&p,'\0',sizeof(p));
105 if (!name_trn_id) name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
106 ((unsigned)getpid()%(unsigned)100);
107 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
109 nmb->header.name_trn_id = name_trn_id;
110 nmb->header.opcode = 0;
111 nmb->header.response = False;
112 nmb->header.nm_flags.bcast = False;
113 nmb->header.nm_flags.recursion_available = False;
114 nmb->header.nm_flags.recursion_desired = False;
115 nmb->header.nm_flags.trunc = False;
116 nmb->header.nm_flags.authoritative = False;
117 nmb->header.rcode = 0;
118 nmb->header.qdcount = 1;
119 nmb->header.ancount = 0;
120 nmb->header.nscount = 0;
121 nmb->header.arcount = 0;
123 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
125 nmb->question.question_type = 0x21;
126 nmb->question.question_class = 0x1;
131 p.timestamp = time(NULL);
132 p.packet_type = NMB_PACKET;
136 if (!send_packet(&p))
142 struct timeval tval2;
143 GetTimeOfDay(&tval2);
144 if (TvalDiff(&tval,&tval2) > retry_time) {
147 if (!found && !send_packet(&p))
153 if ((p2=receive_packet(fd,NMB_PACKET,90))) {
154 struct nmb_packet *nmb2 = &p2->packet.nmb;
155 debug_nmb_packet(p2);
157 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
158 !nmb2->header.response) {
159 /* its not for us - maybe deal with it later */
167 if (nmb2->header.opcode != 0 ||
168 nmb2->header.nm_flags.bcast ||
169 nmb2->header.rcode ||
170 !nmb2->header.ancount ||
171 nmb2->answers->rr_type != 0x21) {
172 /* XXXX what do we do with this? could be a redirect, but
173 we'll discard it for the moment */
178 if(fn_interpret_node_status)
179 (*fn_interpret_node_status)(&nmb2->answers->rdata[0],master,rname);
186 DEBUG(0,("No status response (this is not unusual)\n"));
191 /****************************************************************************
192 Do a netbios name status query on a host.
193 The "master" parameter is a hack used for finding workgroups.
194 **************************************************************************/
196 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
197 struct in_addr to_ip,char *master,char *rname,
198 void (*fn)(struct packet_struct *))
200 return internal_name_status(fd,name,name_type,recurse,
201 to_ip,master,rname,True,
202 _interpret_node_status, fn);
205 /****************************************************************************
206 Do a netbios name query to find someones IP.
207 Returns an array of IP addresses or NULL if none.
208 *count will be set to the number of addresses returned.
209 ****************************************************************************/
211 struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOOL recurse,
212 struct in_addr to_ip, int *count, void (*fn)(struct packet_struct *))
216 int retry_time = bcast?250:2000;
218 struct packet_struct p;
219 struct packet_struct *p2;
220 struct nmb_packet *nmb = &p.packet.nmb;
221 static int name_trn_id = 0;
222 struct in_addr *ip_list = NULL;
224 memset((char *)&p,'\0',sizeof(p));
227 if (!name_trn_id) name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
228 ((unsigned)getpid()%(unsigned)100);
229 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
231 nmb->header.name_trn_id = name_trn_id;
232 nmb->header.opcode = 0;
233 nmb->header.response = False;
234 nmb->header.nm_flags.bcast = bcast;
235 nmb->header.nm_flags.recursion_available = False;
236 nmb->header.nm_flags.recursion_desired = recurse;
237 nmb->header.nm_flags.trunc = False;
238 nmb->header.nm_flags.authoritative = False;
239 nmb->header.rcode = 0;
240 nmb->header.qdcount = 1;
241 nmb->header.ancount = 0;
242 nmb->header.nscount = 0;
243 nmb->header.arcount = 0;
245 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
247 nmb->question.question_type = 0x20;
248 nmb->question.question_class = 0x1;
253 p.timestamp = time(NULL);
254 p.packet_type = NMB_PACKET;
258 if (!send_packet(&p))
265 struct timeval tval2;
266 GetTimeOfDay(&tval2);
267 if (TvalDiff(&tval,&tval2) > retry_time)
271 if (!found && !send_packet(&p))
277 if ((p2=receive_packet(fd,NMB_PACKET,90)))
279 struct nmb_packet *nmb2 = &p2->packet.nmb;
280 debug_nmb_packet(p2);
282 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
283 !nmb2->header.response)
286 * Its not for us - maybe deal with it later
287 * (put it on the queue?).
296 if (nmb2->header.opcode != 0 ||
297 nmb2->header.nm_flags.bcast ||
298 nmb2->header.rcode ||
299 !nmb2->header.ancount)
302 * XXXX what do we do with this? Could be a redirect, but
303 * we'll discard it for the moment.
309 ip_list = (struct in_addr *)Realloc(ip_list, sizeof(ip_list[0]) *
310 ((*count)+nmb2->answers->rdlength/6));
313 DEBUG(fn?3:2,("Got a positive name query response from %s ( ",
315 for (i=0;i<nmb2->answers->rdlength/6;i++)
317 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
318 DEBUG(fn?3:2,("%s ",inet_ntoa(ip_list[(*count)])));
321 DEBUG(fn?3:2,(")\n"));
331 * If we're doing a unicast lookup we only
332 * expect one reply. Don't wait the full 2
333 * seconds if we got one. JRA.
343 /********************************************************
344 Start parsing the lmhosts file.
345 *********************************************************/
347 FILE *startlmhosts(char *fname)
349 FILE *fp = sys_fopen(fname,"r");
351 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
352 fname, strerror(errno)));
358 /********************************************************
359 Parse the next line in the lmhosts file.
360 *********************************************************/
362 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
366 while(!feof(fp) && !ferror(fp)) {
367 pstring ip,flags,extra;
373 if (!fgets_slash(line,sizeof(pstring),fp))
385 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
387 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
389 if (next_token(&ptr,flags,NULL, sizeof(flags)))
391 if (next_token(&ptr,extra,NULL, sizeof(extra)))
397 if (count > 0 && count < 2)
399 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
405 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
409 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
411 if (strchr(flags,'G') || strchr(flags,'S'))
413 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
417 *ipaddr = *interpret_addr2(ip);
419 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
420 then only add that name type. */
421 if((ptr = strchr(name, '#')) != NULL)
426 *name_type = (int)strtol(ptr, &endptr, 16);
428 if(!*ptr || (endptr == ptr))
430 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
434 *(--ptr) = '\0'; /* Truncate at the '#' */
443 /********************************************************
444 Finish parsing the lmhosts file.
445 *********************************************************/
447 void endlmhosts(FILE *fp)
452 /********************************************************
453 Resolve via "bcast" method.
454 *********************************************************/
456 static BOOL resolve_bcast(const char *name, int name_type,
457 struct in_addr **return_ip_list, int *return_count)
460 int num_interfaces = iface_count();
462 *return_ip_list = NULL;
466 * "bcast" means do a broadcast lookup on all the local interfaces.
469 DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
471 sock = open_socket_in( SOCK_DGRAM, 0, 3,
472 interpret_addr(lp_socket_address()), True );
474 if (sock == -1) return False;
476 set_socket_options(sock,"SO_BROADCAST");
478 * Lookup the name on all the interfaces, return on
479 * the first successful match.
481 for( i = num_interfaces-1; i >= 0; i--) {
482 struct in_addr sendto_ip;
483 /* Done this way to fix compiler error on IRIX 5.x */
484 sendto_ip = *iface_bcast(*iface_n_ip(i));
485 *return_ip_list = name_query(sock, name, name_type, True,
486 True, sendto_ip, return_count, NULL);
487 if(*return_ip_list != NULL) {
497 /********************************************************
498 Resolve via "wins" method.
499 *********************************************************/
501 static BOOL resolve_wins(const char *name, int name_type,
502 struct in_addr **return_iplist, int *return_count)
505 struct in_addr wins_ip;
508 *return_iplist = NULL;
512 * "wins" means do a unicast lookup to the WINS server.
513 * Ignore if there is no WINS server specified or if the
514 * WINS server is one of our interfaces (if we're being
515 * called from within nmbd - we can't do this call as we
519 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
521 if(!*lp_wins_server()) {
522 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS server present.\n"));
526 wins_ip = *interpret_addr2(lp_wins_server());
527 wins_ismyip = ismyip(wins_ip);
529 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
530 sock = open_socket_in( SOCK_DGRAM, 0, 3,
531 interpret_addr(lp_socket_address()), True );
534 *return_iplist = name_query(sock, name, name_type, False,
535 True, wins_ip, return_count, NULL);
536 if(*return_iplist != NULL) {
547 /********************************************************
548 Resolve via "lmhosts" method.
549 *********************************************************/
551 static BOOL resolve_lmhosts(const char *name, int name_type,
552 struct in_addr **return_iplist, int *return_count)
555 * "lmhosts" means parse the local lmhosts file.
561 struct in_addr return_ip;
563 *return_iplist = NULL;
566 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
568 fp = startlmhosts( LMHOSTSFILE );
570 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
571 if (strequal(name, lmhost_name) &&
572 ((name_type2 == -1) || (name_type == name_type2))
575 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
576 if(*return_iplist == NULL) {
577 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
580 **return_iplist = return_ip;
591 /********************************************************
592 Resolve via "hosts" method.
593 *********************************************************/
595 static BOOL resolve_hosts(const char *name,
596 struct in_addr **return_iplist, int *return_count)
599 * "host" means do a localhost, or dns lookup.
603 *return_iplist = NULL;
606 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
608 if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
609 struct in_addr return_ip;
610 putip((char *)&return_ip,(char *)hp->h_addr);
611 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
612 if(*return_iplist == NULL) {
613 DEBUG(3,("resolve_hosts: malloc fail !\n"));
616 **return_iplist = return_ip;
623 /********************************************************
624 Internal interface to resolve a name into an IP address.
625 Use this function if the string is either an IP address, DNS
626 or host name or NetBIOS name. This uses the name switch in the
627 smb.conf to determine the order of name resolution.
628 *********************************************************/
630 static BOOL internal_resolve_name(const char *name, int name_type,
631 struct in_addr **return_iplist, int *return_count)
633 pstring name_resolve_list;
636 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
637 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
638 BOOL is_address = is_ipaddress(name);
639 *return_iplist = NULL;
642 if (allzeros || allones || is_address) {
643 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
644 if(*return_iplist == NULL) {
645 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
649 /* if it's in the form of an IP address then get the lib to interpret it */
650 (*return_iplist)->s_addr = inet_addr(name);
652 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
658 pstrcpy(name_resolve_list, lp_name_resolve_order());
659 ptr = name_resolve_list;
663 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
664 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
665 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
668 } else if(strequal( tok, "lmhosts")) {
669 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
672 } else if(strequal( tok, "wins")) {
673 /* don't resolve 1D via WINS */
674 if (name_type != 0x1D &&
675 resolve_wins(name, name_type, return_iplist, return_count)) {
678 } else if(strequal( tok, "bcast")) {
679 if (resolve_bcast(name, name_type, return_iplist, return_count)) {
683 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
687 if((*return_iplist) != NULL) {
688 free((char *)(*return_iplist));
689 *return_iplist = NULL;
694 /********************************************************
695 Internal interface to resolve a name into one IP address.
696 Use this function if the string is either an IP address, DNS
697 or host name or NetBIOS name. This uses the name switch in the
698 smb.conf to determine the order of name resolution.
699 *********************************************************/
701 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
703 struct in_addr *ip_list = NULL;
706 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
707 *return_ip = ip_list[0];
708 free((char *)ip_list);
712 free((char *)ip_list);
716 /********************************************************
717 Find the IP address of the master browser or DMB for a workgroup.
718 *********************************************************/
720 BOOL find_master_ip(char *group, struct in_addr *master_ip)
722 struct in_addr *ip_list = NULL;
725 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
726 *master_ip = ip_list[0];
727 free((char *)ip_list);
730 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
731 *master_ip = ip_list[0];
732 free((char *)ip_list);
737 free((char *)ip_list);
741 /********************************************************
742 Internal function to extract the MACHINE<0x20> name.
743 *********************************************************/
745 static void _lookup_pdc_name(char *p, char *master,char *rname)
747 int numnames = CVAL(p,0);
753 int type = CVAL(p,15);
756 trim_string(rname,NULL," ");
763 /********************************************************
764 Lookup a PDC name given a Domain name and IP address.
765 *********************************************************/
767 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
769 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
775 * Due to the fact win WinNT *sucks* we must do a node status
779 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
786 ret = internal_name_status(sock,"*SMBSERVER",0x20,True,
787 *pdc_ip,NULL,pdc_name,False,
788 _lookup_pdc_name,NULL);
792 if(ret && *pdc_name) {
793 fstrcpy(ret_name, pdc_name);
799 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
801 * Sigh. I *love* this code, it took me ages to get right and it's
802 * completely *USELESS* because NT 4.x refuses to send the mailslot
803 * reply back to the correct port (it always uses 138).
804 * I hate NT when it does these things... JRA.
808 int retry_time = 2000;
810 struct packet_struct p;
811 struct dgram_packet *dgram = &p.packet.dgram;
815 struct sockaddr_in sock_name;
816 int sock_len = sizeof(sock_name);
817 const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
818 static int name_trn_id = 0;
821 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
826 /* Find out the transient UDP port we have been allocated. */
827 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
828 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
835 * Create the request data.
838 memset(buffer,'\0',sizeof(buffer));
840 SSVAL(bufp,0,QUERYFORPDC);
842 fstrcpy(bufp,srcname);
843 bufp += (strlen(bufp) + 1);
844 fstrcpy(bufp,"\\MAILSLOT\\NET\\GETDC411");
845 bufp += (strlen(bufp) + 1);
846 bufp = align2(bufp, buffer);
847 dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1);
848 bufp = skip_unicode_string(bufp, 1);
850 SSVAL(bufp,4,0xFFFF);
851 SSVAL(bufp,6,0xFFFF);
853 len = PTR_DIFF(bufp,buffer);
856 name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100);
857 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
859 memset((char *)&p,'\0',sizeof(p));
861 /* DIRECT GROUP or UNIQUE datagram. */
862 dgram->header.msg_type = 0x10;
863 dgram->header.flags.node_type = M_NODE;
864 dgram->header.flags.first = True;
865 dgram->header.flags.more = False;
866 dgram->header.dgm_id = name_trn_id;
867 dgram->header.source_ip = sock_name.sin_addr;
868 dgram->header.source_port = ntohs(sock_name.sin_port);
869 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
870 dgram->header.packet_offset = 0;
872 make_nmb_name(&dgram->source_name,srcname,0,scope);
873 make_nmb_name(&dgram->dest_name,domain,0x1B,scope);
875 ptr = &dgram->data[0];
877 /* Setup the smb part. */
878 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
880 set_message(ptr,17,17 + len,True);
883 CVAL(ptr,smb_com) = SMBtrans;
884 SSVAL(ptr,smb_vwv1,len);
885 SSVAL(ptr,smb_vwv11,len);
886 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
887 SSVAL(ptr,smb_vwv13,3);
888 SSVAL(ptr,smb_vwv14,1);
889 SSVAL(ptr,smb_vwv15,1);
890 SSVAL(ptr,smb_vwv16,2);
892 pstrcpy(p2,mailslot);
893 p2 = skip_string(p2,1);
895 memcpy(p2,buffer,len);
898 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
903 p.timestamp = time(NULL);
904 p.packet_type = DGRAM_PACKET;
908 if (!send_packet(&p)) {
909 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
917 struct timeval tval2;
918 struct packet_struct *p_ret;
920 GetTimeOfDay(&tval2);
921 if (TvalDiff(&tval,&tval2) > retry_time) {
924 if (!send_packet(&p)) {
925 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
933 if ((p_ret = receive_packet(sock,NMB_PACKET,90))) {
934 struct nmb_packet *nmb2 = &p_ret->packet.nmb;
935 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
939 debug_nmb_packet(p_ret);
941 if (memcmp(&p.ip, &p_ret->ip, sizeof(p.ip))) {
945 DEBUG(0,("lookup_pdc_name: datagram return IP %s doesn't match\n", inet_ntoa(p_ret->ip) ));
950 buf = &dgram2->data[0];
953 if (CVAL(buf,smb_com) != SMBtrans) {
954 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)CVAL(buf,smb_com),
955 (unsigned int)SMBtrans ));
960 len = SVAL(buf,smb_vwv11);
961 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
964 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
969 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
970 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
971 inet_ntoa(p_ret->ip), smb_buf(buf),CVAL(buf2,0),len));
973 if(SVAL(buf,0) != QUERYFORPDC_R) {
974 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
975 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
981 /* Note this is safe as it is a bounded strcpy. */
982 fstrcpy(ret_name, buf);
983 ret_name[sizeof(fstring)-1] = '\0';
992 #endif /* I_HATE_WINDOWS_REPLY_CODE */
995 /********************************************************
996 Get the IP address list of the PDC/BDC's of a Domain.
997 *********************************************************/
999 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
1001 return internal_resolve_name(group, 0x1C, ip_list, count);