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 = 2000;
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);
825 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
826 /********************************************************
827 Internal function to extract the MACHINE<0x20> name.
828 *********************************************************/
830 static void _lookup_pdc_name(char *p, char *master,char *rname)
832 int numnames = CVAL(p,0);
838 int type = CVAL(p,15);
841 trim_string(rname,NULL," ");
847 #endif /* I_HATE_WINDOWS_REPLY_CODE */
849 /********************************************************
850 Lookup a PDC name given a Domain name and IP address.
851 *********************************************************/
853 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
855 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
861 * Due to the fact win WinNT *sucks* we must do a node status
865 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
872 ret = internal_name_status(sock,"*SMBSERVER",0x20,True,
873 *pdc_ip,NULL,pdc_name,False,_lookup_pdc_name);
877 if(ret && *pdc_name) {
878 fstrcpy(ret_name, pdc_name);
884 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
886 JRA - This code is broken with BDC rollover - we need to do a full
887 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
890 int retry_time = 2000;
892 struct packet_struct p;
893 struct dgram_packet *dgram = &p.packet.dgram;
897 struct sockaddr_in sock_name;
898 int sock_len = sizeof(sock_name);
899 const char *mailslot = NET_LOGON_MAILSLOT;
903 int dgm_id = generate_trn_id();
904 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
909 /* Find out the transient UDP port we have been allocated. */
910 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
911 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
918 * Create the request data.
921 memset(buffer,'\0',sizeof(buffer));
923 SSVAL(bufp,0,QUERYFORPDC);
925 fstrcpy(bufp,srcname);
926 bufp += (strlen(bufp) + 1);
927 slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
928 mailslot_name = bufp;
929 bufp += (strlen(bufp) + 1);
930 bufp = ALIGN2(bufp, buffer);
931 bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
933 SSVAL(bufp,4,0xFFFF);
934 SSVAL(bufp,6,0xFFFF);
936 len = PTR_DIFF(bufp,buffer);
938 memset((char *)&p,'\0',sizeof(p));
940 /* DIRECT GROUP or UNIQUE datagram. */
941 dgram->header.msg_type = 0x10;
942 dgram->header.flags.node_type = M_NODE;
943 dgram->header.flags.first = True;
944 dgram->header.flags.more = False;
945 dgram->header.dgm_id = dgm_id;
946 dgram->header.source_ip = *iface_ip(*pdc_ip);
947 dgram->header.source_port = ntohs(sock_name.sin_port);
948 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
949 dgram->header.packet_offset = 0;
951 make_nmb_name(&dgram->source_name,srcname,0);
952 make_nmb_name(&dgram->dest_name,domain,0x1C);
954 ptr = &dgram->data[0];
956 /* Setup the smb part. */
957 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
959 set_message(ptr,17,17 + len,True);
962 CVAL(ptr,smb_com) = SMBtrans;
963 SSVAL(ptr,smb_vwv1,len);
964 SSVAL(ptr,smb_vwv11,len);
965 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
966 SSVAL(ptr,smb_vwv13,3);
967 SSVAL(ptr,smb_vwv14,1);
968 SSVAL(ptr,smb_vwv15,1);
969 SSVAL(ptr,smb_vwv16,2);
971 pstrcpy(p2,mailslot);
972 p2 = skip_string(p2,1);
974 memcpy(p2,buffer,len);
977 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
982 p.timestamp = time(NULL);
983 p.packet_type = DGRAM_PACKET;
987 if (!send_packet(&p)) {
988 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
996 struct timeval tval2;
997 struct packet_struct *p_ret;
999 GetTimeOfDay(&tval2);
1000 if (TvalDiff(&tval,&tval2) > retry_time) {
1003 if (!send_packet(&p)) {
1004 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1008 GetTimeOfDay(&tval);
1012 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1013 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1017 buf = &dgram2->data[0];
1020 if (CVAL(buf,smb_com) != SMBtrans) {
1021 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1022 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1027 len = SVAL(buf,smb_vwv11);
1028 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1031 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1036 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1037 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1038 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1040 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1041 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1042 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1048 /* Note this is safe as it is a bounded strcpy. */
1049 fstrcpy(ret_name, buf2);
1050 ret_name[sizeof(fstring)-1] = '\0';
1059 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1063 /********************************************************
1064 Get the IP address list of the PDC/BDC's of a Domain.
1065 *********************************************************/
1066 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
1068 return internal_resolve_name(group, 0x1C, ip_list, count);