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( "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.
354 /********************************************************
355 Start parsing the lmhosts file.
356 *********************************************************/
358 FILE *startlmhosts(char *fname)
360 FILE *fp = sys_fopen(fname,"r");
362 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
363 fname, strerror(errno)));
369 /********************************************************
370 Parse the next line in the lmhosts file.
371 *********************************************************/
373 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
377 while(!feof(fp) && !ferror(fp)) {
378 pstring ip,flags,extra;
384 if (!fgets_slash(line,sizeof(pstring),fp))
396 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
398 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
400 if (next_token(&ptr,flags,NULL, sizeof(flags)))
402 if (next_token(&ptr,extra,NULL, sizeof(extra)))
408 if (count > 0 && count < 2)
410 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
416 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
420 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
422 if (strchr(flags,'G') || strchr(flags,'S'))
424 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
428 *ipaddr = *interpret_addr2(ip);
430 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
431 then only add that name type. */
432 if((ptr = strchr(name, '#')) != NULL)
437 *name_type = (int)strtol(ptr, &endptr, 16);
439 if(!*ptr || (endptr == ptr))
441 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
445 *(--ptr) = '\0'; /* Truncate at the '#' */
454 /********************************************************
455 Finish parsing the lmhosts file.
456 *********************************************************/
458 void endlmhosts(FILE *fp)
463 /********************************************************
464 Resolve via "bcast" method.
465 *********************************************************/
467 static BOOL resolve_bcast(const char *name, int name_type,
468 struct in_addr **return_ip_list, int *return_count)
471 int num_interfaces = iface_count();
473 *return_ip_list = NULL;
477 * "bcast" means do a broadcast lookup on all the local interfaces.
480 DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
482 sock = open_socket_in( SOCK_DGRAM, 0, 3,
483 interpret_addr(lp_socket_address()), True );
485 if (sock == -1) return False;
487 set_socket_options(sock,"SO_BROADCAST");
489 * Lookup the name on all the interfaces, return on
490 * the first successful match.
492 for( i = num_interfaces-1; i >= 0; i--) {
493 struct in_addr sendto_ip;
494 /* Done this way to fix compiler error on IRIX 5.x */
495 sendto_ip = *iface_bcast(*iface_n_ip(i));
496 *return_ip_list = name_query(sock, name, name_type, True,
497 True, sendto_ip, return_count);
498 if(*return_ip_list != NULL) {
508 /********************************************************
509 Resolve via "wins" method.
510 *********************************************************/
512 static BOOL resolve_wins(const char *name, int name_type,
513 struct in_addr **return_iplist, int *return_count)
516 struct in_addr wins_ip;
519 *return_iplist = NULL;
523 * "wins" means do a unicast lookup to the WINS server.
524 * Ignore if there is no WINS server specified or if the
525 * WINS server is one of our interfaces (if we're being
526 * called from within nmbd - we can't do this call as we
530 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
532 if( wins_srv_count() < 1 ) {
533 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
537 wins_ip = wins_srv_ip();
538 wins_ismyip = ismyip(wins_ip);
540 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
541 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
542 sock = open_socket_in( SOCK_DGRAM, 0, 3,
543 interpret_addr(lp_socket_address()),
546 *return_iplist = name_query( sock, name,
550 if(*return_iplist != NULL) {
561 /********************************************************
562 Resolve via "lmhosts" method.
563 *********************************************************/
565 static BOOL resolve_lmhosts(const char *name, int name_type,
566 struct in_addr **return_iplist, int *return_count)
569 * "lmhosts" means parse the local lmhosts file.
575 struct in_addr return_ip;
577 *return_iplist = NULL;
580 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
582 fp = startlmhosts( LMHOSTSFILE );
584 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
585 if (strequal(name, lmhost_name) &&
586 ((name_type2 == -1) || (name_type == name_type2))
589 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
590 if(*return_iplist == NULL) {
591 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
594 **return_iplist = return_ip;
605 /********************************************************
606 Resolve via "hosts" method.
607 *********************************************************/
609 static BOOL resolve_hosts(const char *name,
610 struct in_addr **return_iplist, int *return_count)
613 * "host" means do a localhost, or dns lookup.
617 *return_iplist = NULL;
620 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
622 if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
623 struct in_addr return_ip;
624 putip((char *)&return_ip,(char *)hp->h_addr);
625 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
626 if(*return_iplist == NULL) {
627 DEBUG(3,("resolve_hosts: malloc fail !\n"));
630 **return_iplist = return_ip;
637 /********************************************************
638 Resolve a name into an IP address. Use this function if
639 the string is either an IP address, DNS or host name
640 or NetBIOS name. This uses the name switch in the
641 smb.conf to determine the order of name resolution.
642 *********************************************************/
643 BOOL is_ip_address(const char *name)
646 for (i=0; name[i]; i++)
647 if (!(isdigit((int)name[i]) || name[i] == '.'))
654 /********************************************************
655 Internal interface to resolve a name into an IP address.
656 Use this function if the string is either an IP address, DNS
657 or host name or NetBIOS name. This uses the name switch in the
658 smb.conf to determine the order of name resolution.
659 *********************************************************/
661 static BOOL internal_resolve_name(const char *name, int name_type,
662 struct in_addr **return_iplist, int *return_count)
664 pstring name_resolve_list;
667 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
668 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
669 BOOL is_address = is_ipaddress(name);
670 *return_iplist = NULL;
673 if (allzeros || allones || is_address) {
674 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
675 if(*return_iplist == NULL) {
676 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
680 /* if it's in the form of an IP address then get the lib to interpret it */
681 (*return_iplist)->s_addr = inet_addr(name);
683 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
689 pstrcpy(name_resolve_list, lp_name_resolve_order());
690 ptr = name_resolve_list;
694 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
695 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
696 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
699 } else if(strequal( tok, "lmhosts")) {
700 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
703 } else if(strequal( tok, "wins")) {
704 /* don't resolve 1D via WINS */
705 if (name_type != 0x1D &&
706 resolve_wins(name, name_type, return_iplist, return_count)) {
709 } else if(strequal( tok, "bcast")) {
710 if (resolve_bcast(name, name_type, return_iplist, return_count)) {
714 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
718 if((*return_iplist) != NULL) {
719 free((char *)(*return_iplist));
720 *return_iplist = NULL;
725 /********************************************************
726 Internal interface to resolve a name into one IP address.
727 Use this function if the string is either an IP address, DNS
728 or host name or NetBIOS name. This uses the name switch in the
729 smb.conf to determine the order of name resolution.
730 *********************************************************/
732 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
734 struct in_addr *ip_list = NULL;
737 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
738 *return_ip = ip_list[0];
739 free((char *)ip_list);
743 free((char *)ip_list);
748 /********************************************************
749 resolve a name of format \\server_name or \\ipaddress
750 into a name. also, cut the \\ from the front for us.
751 *********************************************************/
753 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
757 const char *sv_name = srv_name;
759 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
761 if (srv_name == NULL || strequal("\\\\.", srv_name))
763 extern pstring global_myname;
764 fstrcpy(dest_host, global_myname);
765 ip = interpret_addr2("127.0.0.1");
769 if (strnequal("\\\\", srv_name, 2))
771 sv_name = &srv_name[2];
774 fstrcpy(dest_host, sv_name);
775 /* treat the '*' name specially - it is a magic name for the PDC */
776 if (strcmp(dest_host,"*") == 0) {
777 extern pstring global_myname;
778 ret = resolve_name(lp_workgroup(), ip, 0x1B);
779 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
781 ret = resolve_name(dest_host, ip, 0x20);
784 if (is_ip_address(dest_host))
786 fstrcpy(dest_host, "*SMBSERVER");
793 /********************************************************
794 Find the IP address of the master browser or DMB for a workgroup.
795 *********************************************************/
797 BOOL find_master_ip(char *group, struct in_addr *master_ip)
799 struct in_addr *ip_list = NULL;
802 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
803 *master_ip = ip_list[0];
804 free((char *)ip_list);
807 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
808 *master_ip = ip_list[0];
809 free((char *)ip_list);
814 free((char *)ip_list);
819 /********************************************************
820 Lookup a PDC name given a Domain name and IP address.
821 *********************************************************/
822 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
825 int retry_time = 2000;
827 struct packet_struct p;
828 struct dgram_packet *dgram = &p.packet.dgram;
832 struct sockaddr_in sock_name;
833 int sock_len = sizeof(sock_name);
834 const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
838 int dgm_id = generate_trn_id();
839 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
844 /* Find out the transient UDP port we have been allocated. */
845 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
846 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
853 * Create the request data.
856 memset(buffer,'\0',sizeof(buffer));
858 SSVAL(bufp,0,QUERYFORPDC);
860 fstrcpy(bufp,srcname);
861 bufp += (strlen(bufp) + 1);
862 slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
863 mailslot_name = bufp;
864 bufp += (strlen(bufp) + 1);
865 bufp = ALIGN2(bufp, buffer);
866 bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
868 SSVAL(bufp,4,0xFFFF);
869 SSVAL(bufp,6,0xFFFF);
871 len = PTR_DIFF(bufp,buffer);
873 memset((char *)&p,'\0',sizeof(p));
875 /* DIRECT GROUP or UNIQUE datagram. */
876 dgram->header.msg_type = 0x10;
877 dgram->header.flags.node_type = M_NODE;
878 dgram->header.flags.first = True;
879 dgram->header.flags.more = False;
880 dgram->header.dgm_id = dgm_id;
881 dgram->header.source_ip = *iface_ip(*pdc_ip);
882 dgram->header.source_port = ntohs(sock_name.sin_port);
883 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
884 dgram->header.packet_offset = 0;
886 make_nmb_name(&dgram->source_name,srcname,0);
887 make_nmb_name(&dgram->dest_name,domain,0x1B);
889 ptr = &dgram->data[0];
891 /* Setup the smb part. */
892 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
894 set_message(ptr,17,17 + len,True);
897 CVAL(ptr,smb_com) = SMBtrans;
898 SSVAL(ptr,smb_vwv1,len);
899 SSVAL(ptr,smb_vwv11,len);
900 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
901 SSVAL(ptr,smb_vwv13,3);
902 SSVAL(ptr,smb_vwv14,1);
903 SSVAL(ptr,smb_vwv15,1);
904 SSVAL(ptr,smb_vwv16,2);
906 pstrcpy(p2,mailslot);
907 p2 = skip_string(p2,1);
909 memcpy(p2,buffer,len);
912 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
917 p.timestamp = time(NULL);
918 p.packet_type = DGRAM_PACKET;
922 if (!send_packet(&p)) {
923 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
931 struct timeval tval2;
932 struct packet_struct *p_ret;
934 GetTimeOfDay(&tval2);
935 if (TvalDiff(&tval,&tval2) > retry_time) {
938 if (!send_packet(&p)) {
939 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
947 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
948 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
952 buf = &dgram2->data[0];
955 if (CVAL(buf,smb_com) != SMBtrans) {
956 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
957 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
962 len = SVAL(buf,smb_vwv11);
963 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
966 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
971 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
972 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
973 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
975 if(SVAL(buf2,0) != QUERYFORPDC_R) {
976 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
977 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
983 /* Note this is safe as it is a bounded strcpy. */
984 fstrcpy(ret_name, buf2);
985 ret_name[sizeof(fstring)-1] = '\0';
997 /********************************************************
998 Get the IP address list of the PDC/BDC's of a Domain.
999 *********************************************************/
1000 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
1002 return internal_resolve_name(group, 0x1C, ip_list, count);