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.
25 extern int DEBUGLEVEL;
27 /* nmbd.c sets this to True. */
28 BOOL global_in_nmbd = False;
30 /****************************************************************************
31 generate a random trn_id
32 ****************************************************************************/
33 static int generate_trn_id(void)
38 sys_srandom(sys_getpid());
41 trn_id = sys_random();
43 return trn_id % (unsigned)0x7FFF;
47 /****************************************************************************
48 Interpret a node status response.
49 ****************************************************************************/
51 static void _interpret_node_status(char *p, char *master,char *rname)
53 int numnames = CVAL(p,0);
54 DEBUG(1,("received %d names\n",numnames));
56 if (rname) *rname = 0;
57 if (master) *master = 0;
70 fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : " ");
71 if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B ");
72 if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P ");
73 if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M ");
74 if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H ");
75 if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> ");
76 if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> ");
77 if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> ");
78 if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> ");
80 if (master && !*master && type == 0x1d) {
81 StrnCpy(master,qname,15);
82 trim_string(master,NULL," ");
85 if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
86 StrnCpy(rname,qname,15);
87 trim_string(rname,NULL," ");
90 for (i = strlen( qname) ; --i >= 0 ; ) {
91 if (!isprint((int)qname[i])) qname[i] = '.';
93 DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
97 DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
98 IVAL(p,20),IVAL(p,24)));
101 /****************************************************************************
102 Internal function handling a netbios name status query on a host.
103 **************************************************************************/
104 static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse,
105 struct in_addr to_ip,char *master,
106 char *rname, BOOL verbose,
107 void (*fn_interpret_node_status)(char *, char *,char *))
111 int retry_time = 5000;
113 struct packet_struct p;
114 struct packet_struct *p2;
115 struct nmb_packet *nmb = &p.packet.nmb;
117 memset((char *)&p,'\0',sizeof(p));
119 nmb->header.name_trn_id = generate_trn_id();
120 nmb->header.opcode = 0;
121 nmb->header.response = False;
122 nmb->header.nm_flags.bcast = False;
123 nmb->header.nm_flags.recursion_available = False;
124 nmb->header.nm_flags.recursion_desired = False;
125 nmb->header.nm_flags.trunc = False;
126 nmb->header.nm_flags.authoritative = False;
127 nmb->header.rcode = 0;
128 nmb->header.qdcount = 1;
129 nmb->header.ancount = 0;
130 nmb->header.nscount = 0;
131 nmb->header.arcount = 0;
133 make_nmb_name(&nmb->question.question_name,name,name_type);
135 nmb->question.question_type = 0x21;
136 nmb->question.question_class = 0x1;
141 p.timestamp = time(NULL);
142 p.packet_type = NMB_PACKET;
146 if (!send_packet(&p))
152 struct timeval tval2;
153 GetTimeOfDay(&tval2);
154 if (TvalDiff(&tval,&tval2) > retry_time) {
157 if (!found && !send_packet(&p))
163 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
164 struct nmb_packet *nmb2 = &p2->packet.nmb;
165 debug_nmb_packet(p2);
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
173 redirect, but we'll discard it for the
179 if(fn_interpret_node_status)
180 (*fn_interpret_node_status)(&nmb2->answers->rdata[0],master,rname);
187 DEBUG(0,("No status response (this is not unusual)\n"));
192 /****************************************************************************
193 Do a netbios name status query on a host.
194 The "master" parameter is a hack used for finding workgroups.
195 **************************************************************************/
196 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
197 struct in_addr to_ip,char *master,char *rname)
199 return internal_name_status(fd,name,name_type,recurse,
200 to_ip,master,rname,True,
201 _interpret_node_status);
204 /****************************************************************************
205 Do a netbios name query to find someones IP.
206 Returns an array of IP addresses or NULL if none.
207 *count will be set to the number of addresses returned.
208 ****************************************************************************/
210 struct in_addr *name_query(int fd,const char *name,int name_type,
211 BOOL bcast,BOOL recurse,
212 struct in_addr to_ip, int *count)
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 struct in_addr *ip_list = NULL;
223 memset((char *)&p,'\0',sizeof(p));
226 nmb->header.name_trn_id = generate_trn_id();
227 nmb->header.opcode = 0;
228 nmb->header.response = False;
229 nmb->header.nm_flags.bcast = bcast;
230 nmb->header.nm_flags.recursion_available = False;
231 nmb->header.nm_flags.recursion_desired = recurse;
232 nmb->header.nm_flags.trunc = False;
233 nmb->header.nm_flags.authoritative = False;
234 nmb->header.rcode = 0;
235 nmb->header.qdcount = 1;
236 nmb->header.ancount = 0;
237 nmb->header.nscount = 0;
238 nmb->header.arcount = 0;
240 make_nmb_name(&nmb->question.question_name,name,name_type);
242 nmb->question.question_type = 0x20;
243 nmb->question.question_class = 0x1;
248 p.timestamp = time(NULL);
249 p.packet_type = NMB_PACKET;
253 if (!send_packet(&p))
260 struct timeval tval2;
261 GetTimeOfDay(&tval2);
262 if (TvalDiff(&tval,&tval2) > retry_time) {
265 if (!found && !send_packet(&p))
271 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
272 struct nmb_packet *nmb2 = &p2->packet.nmb;
273 debug_nmb_packet(p2);
275 /* If we get a Negative Name Query Response from a WINS
276 * server, we should report it and give up.
278 if( 0 == nmb2->header.opcode /* A query response */
279 && !(bcast) /* from a WINS server */
280 && nmb2->header.rcode /* Error returned */
283 if( DEBUGLVL( 3 ) ) {
284 /* Only executed if DEBUGLEVEL >= 3 */
285 dbgtext( "Negative name query response, rcode 0x%02x: ",
286 nmb2->header.rcode );
287 switch( nmb2->header.rcode ) {
289 dbgtext( "Request was invalidly formatted.\n" );
292 dbgtext( "Problem with NBNS, cannot process name.\n");
295 dbgtext( "The name requested does not exist.\n" );
298 dbgtext( "Unsupported request error.\n" );
301 dbgtext( "Query refused error.\n" );
304 dbgtext( "Unrecognized error code.\n" );
312 if (nmb2->header.opcode != 0 ||
313 nmb2->header.nm_flags.bcast ||
314 nmb2->header.rcode ||
315 !nmb2->header.ancount) {
317 * XXXX what do we do with this? Could be a
318 * redirect, but we'll discard it for the
324 ip_list = (struct in_addr *)Realloc( ip_list,
326 * ( (*count) + nmb2->answers->rdlength/6 ) );
328 DEBUG(2,("Got a positive name query response from %s ( ",
330 for (i=0;i<nmb2->answers->rdlength/6;i++) {
331 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
332 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
342 * If we're doing a unicast lookup we only
343 * expect one reply. Don't wait the full 2
344 * seconds if we got one. JRA.
351 /* Reach here if we've timed out waiting for replies.. */
352 if( !bcast && !found )
354 /* Timed out wating for WINS server to respond. Mark it dead. */
355 wins_srv_died( to_ip );
361 /********************************************************
362 Start parsing the lmhosts file.
363 *********************************************************/
365 FILE *startlmhosts(char *fname)
367 FILE *fp = sys_fopen(fname,"r");
369 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
370 fname, strerror(errno)));
376 /********************************************************
377 Parse the next line in the lmhosts file.
378 *********************************************************/
380 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
384 while(!feof(fp) && !ferror(fp)) {
385 pstring ip,flags,extra;
391 if (!fgets_slash(line,sizeof(pstring),fp))
403 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
405 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
407 if (next_token(&ptr,flags,NULL, sizeof(flags)))
409 if (next_token(&ptr,extra,NULL, sizeof(extra)))
415 if (count > 0 && count < 2)
417 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
423 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
427 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
429 if (strchr(flags,'G') || strchr(flags,'S'))
431 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
435 *ipaddr = *interpret_addr2(ip);
437 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
438 then only add that name type. */
439 if((ptr = strchr(name, '#')) != NULL)
444 *name_type = (int)strtol(ptr, &endptr, 16);
446 if(!*ptr || (endptr == ptr))
448 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
452 *(--ptr) = '\0'; /* Truncate at the '#' */
461 /********************************************************
462 Finish parsing the lmhosts file.
463 *********************************************************/
465 void endlmhosts(FILE *fp)
470 /********************************************************
471 Resolve via "bcast" method.
472 *********************************************************/
474 static BOOL resolve_bcast(const char *name, int name_type,
475 struct in_addr **return_ip_list, int *return_count)
478 int num_interfaces = iface_count();
480 *return_ip_list = NULL;
484 * "bcast" means do a broadcast lookup on all the local interfaces.
487 DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
489 sock = open_socket_in( SOCK_DGRAM, 0, 3,
490 interpret_addr(lp_socket_address()), True );
492 if (sock == -1) return False;
494 set_socket_options(sock,"SO_BROADCAST");
496 * Lookup the name on all the interfaces, return on
497 * the first successful match.
499 for( i = num_interfaces-1; i >= 0; i--) {
500 struct in_addr sendto_ip;
501 /* Done this way to fix compiler error on IRIX 5.x */
502 sendto_ip = *iface_bcast(*iface_n_ip(i));
503 *return_ip_list = name_query(sock, name, name_type, True,
504 True, sendto_ip, return_count);
505 if(*return_ip_list != NULL) {
515 /********************************************************
516 Resolve via "wins" method.
517 *********************************************************/
519 static BOOL resolve_wins(const char *name, int name_type,
520 struct in_addr **return_iplist, int *return_count)
523 struct in_addr wins_ip;
526 *return_iplist = NULL;
530 * "wins" means do a unicast lookup to the WINS server.
531 * Ignore if there is no WINS server specified or if the
532 * WINS server is one of our interfaces (if we're being
533 * called from within nmbd - we can't do this call as we
537 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
539 if( wins_srv_count() < 1 ) {
540 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
544 wins_ip = wins_srv_ip();
545 wins_ismyip = ismyip(wins_ip);
547 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
548 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
549 sock = open_socket_in( SOCK_DGRAM, 0, 3,
550 interpret_addr(lp_socket_address()),
553 *return_iplist = name_query( sock, name,
557 if(*return_iplist != NULL) {
568 /********************************************************
569 Resolve via "lmhosts" method.
570 *********************************************************/
572 static BOOL resolve_lmhosts(const char *name, int name_type,
573 struct in_addr **return_iplist, int *return_count)
576 * "lmhosts" means parse the local lmhosts file.
582 struct in_addr return_ip;
584 *return_iplist = NULL;
587 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
589 fp = startlmhosts( LMHOSTSFILE );
591 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
592 if (strequal(name, lmhost_name) &&
593 ((name_type2 == -1) || (name_type == name_type2))
596 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
597 if(*return_iplist == NULL) {
598 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
601 **return_iplist = return_ip;
612 /********************************************************
613 Resolve via "hosts" method.
614 *********************************************************/
616 static BOOL resolve_hosts(const char *name,
617 struct in_addr **return_iplist, int *return_count)
620 * "host" means do a localhost, or dns lookup.
624 *return_iplist = NULL;
627 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
629 if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
630 struct in_addr return_ip;
631 putip((char *)&return_ip,(char *)hp->h_addr);
632 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
633 if(*return_iplist == NULL) {
634 DEBUG(3,("resolve_hosts: malloc fail !\n"));
637 **return_iplist = return_ip;
644 /********************************************************
645 Resolve a name into an IP address. Use this function if
646 the string is either an IP address, DNS or host name
647 or NetBIOS name. This uses the name switch in the
648 smb.conf to determine the order of name resolution.
649 *********************************************************/
650 BOOL is_ip_address(const char *name)
653 for (i=0; name[i]; i++)
654 if (!(isdigit((int)name[i]) || name[i] == '.'))
661 /********************************************************
662 Internal interface to resolve a name into an IP address.
663 Use this function if the string is either an IP address, DNS
664 or host name or NetBIOS name. This uses the name switch in the
665 smb.conf to determine the order of name resolution.
666 *********************************************************/
668 static BOOL internal_resolve_name(const char *name, int name_type,
669 struct in_addr **return_iplist, int *return_count)
671 pstring name_resolve_list;
674 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
675 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
676 BOOL is_address = is_ipaddress(name);
677 *return_iplist = NULL;
680 if (allzeros || allones || is_address) {
681 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
682 if(*return_iplist == NULL) {
683 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
687 /* if it's in the form of an IP address then get the lib to interpret it */
688 (*return_iplist)->s_addr = inet_addr(name);
690 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
696 pstrcpy(name_resolve_list, lp_name_resolve_order());
697 ptr = name_resolve_list;
701 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
702 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
703 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
706 } else if(strequal( tok, "lmhosts")) {
707 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
710 } else if(strequal( tok, "wins")) {
711 /* don't resolve 1D via WINS */
712 if (name_type != 0x1D &&
713 resolve_wins(name, name_type, return_iplist, return_count)) {
716 } else if(strequal( tok, "bcast")) {
717 if (resolve_bcast(name, name_type, return_iplist, return_count)) {
721 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
725 if((*return_iplist) != NULL) {
726 free((char *)(*return_iplist));
727 *return_iplist = NULL;
732 /********************************************************
733 Internal interface to resolve a name into one IP address.
734 Use this function if the string is either an IP address, DNS
735 or host name or NetBIOS name. This uses the name switch in the
736 smb.conf to determine the order of name resolution.
737 *********************************************************/
739 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
741 struct in_addr *ip_list = NULL;
744 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
745 *return_ip = ip_list[0];
746 free((char *)ip_list);
750 free((char *)ip_list);
755 /********************************************************
756 resolve a name of format \\server_name or \\ipaddress
757 into a name. also, cut the \\ from the front for us.
758 *********************************************************/
760 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
764 const char *sv_name = srv_name;
766 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
768 if (srv_name == NULL || strequal("\\\\.", srv_name))
770 extern pstring global_myname;
771 fstrcpy(dest_host, global_myname);
772 ip = interpret_addr2("127.0.0.1");
776 if (strnequal("\\\\", srv_name, 2))
778 sv_name = &srv_name[2];
781 fstrcpy(dest_host, sv_name);
782 /* treat the '*' name specially - it is a magic name for the PDC */
783 if (strcmp(dest_host,"*") == 0) {
784 extern pstring global_myname;
785 ret = resolve_name(lp_workgroup(), ip, 0x1B);
786 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
788 ret = resolve_name(dest_host, ip, 0x20);
791 if (is_ip_address(dest_host))
793 fstrcpy(dest_host, "*SMBSERVER");
800 /********************************************************
801 Find the IP address of the master browser or DMB for a workgroup.
802 *********************************************************/
804 BOOL find_master_ip(char *group, struct in_addr *master_ip)
806 struct in_addr *ip_list = NULL;
809 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
810 *master_ip = ip_list[0];
811 free((char *)ip_list);
814 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
815 *master_ip = ip_list[0];
816 free((char *)ip_list);
821 free((char *)ip_list);
826 /********************************************************
827 Lookup a PDC name given a Domain name and IP address.
828 *********************************************************/
829 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
832 int retry_time = 2000;
834 struct packet_struct p;
835 struct dgram_packet *dgram = &p.packet.dgram;
839 struct sockaddr_in sock_name;
840 int sock_len = sizeof(sock_name);
841 const char *mailslot = NET_LOGON_MAILSLOT;
845 int dgm_id = generate_trn_id();
846 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
851 /* Find out the transient UDP port we have been allocated. */
852 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
853 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
860 * Create the request data.
863 memset(buffer,'\0',sizeof(buffer));
865 SSVAL(bufp,0,QUERYFORPDC);
867 fstrcpy(bufp,srcname);
868 bufp += (strlen(bufp) + 1);
869 slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
870 mailslot_name = bufp;
871 bufp += (strlen(bufp) + 1);
872 bufp = ALIGN2(bufp, buffer);
873 bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
875 SSVAL(bufp,4,0xFFFF);
876 SSVAL(bufp,6,0xFFFF);
878 len = PTR_DIFF(bufp,buffer);
880 memset((char *)&p,'\0',sizeof(p));
882 /* DIRECT GROUP or UNIQUE datagram. */
883 dgram->header.msg_type = 0x10;
884 dgram->header.flags.node_type = M_NODE;
885 dgram->header.flags.first = True;
886 dgram->header.flags.more = False;
887 dgram->header.dgm_id = dgm_id;
888 dgram->header.source_ip = *iface_ip(*pdc_ip);
889 dgram->header.source_port = ntohs(sock_name.sin_port);
890 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
891 dgram->header.packet_offset = 0;
893 make_nmb_name(&dgram->source_name,srcname,0);
894 make_nmb_name(&dgram->dest_name,domain,0x1B);
896 ptr = &dgram->data[0];
898 /* Setup the smb part. */
899 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
901 set_message(ptr,17,17 + len,True);
904 CVAL(ptr,smb_com) = SMBtrans;
905 SSVAL(ptr,smb_vwv1,len);
906 SSVAL(ptr,smb_vwv11,len);
907 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
908 SSVAL(ptr,smb_vwv13,3);
909 SSVAL(ptr,smb_vwv14,1);
910 SSVAL(ptr,smb_vwv15,1);
911 SSVAL(ptr,smb_vwv16,2);
913 pstrcpy(p2,mailslot);
914 p2 = skip_string(p2,1);
916 memcpy(p2,buffer,len);
919 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
924 p.timestamp = time(NULL);
925 p.packet_type = DGRAM_PACKET;
929 if (!send_packet(&p)) {
930 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
938 struct timeval tval2;
939 struct packet_struct *p_ret;
941 GetTimeOfDay(&tval2);
942 if (TvalDiff(&tval,&tval2) > retry_time) {
945 if (!send_packet(&p)) {
946 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
954 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
955 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
959 buf = &dgram2->data[0];
962 if (CVAL(buf,smb_com) != SMBtrans) {
963 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
964 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
969 len = SVAL(buf,smb_vwv11);
970 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
973 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
978 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
979 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
980 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
982 if(SVAL(buf2,0) != QUERYFORPDC_R) {
983 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
984 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
990 /* Note this is safe as it is a bounded strcpy. */
991 fstrcpy(ret_name, buf2);
992 ret_name[sizeof(fstring)-1] = '\0';
1004 /********************************************************
1005 Get the IP address list of the PDC/BDC's of a Domain.
1006 *********************************************************/
1007 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
1009 return internal_resolve_name(group, 0x1C, ip_list, count);