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 Interpret a node status response.
32 ****************************************************************************/
34 static void _interpret_node_status(char *p
, char *master
,char *rname
)
36 int numnames
= CVAL(p
,0);
37 DEBUG(1,("received %d names\n",numnames
));
39 if (rname
) *rname
= 0;
40 if (master
) *master
= 0;
53 fstrcat(flags
, (p
[0] & 0x80) ? "<GROUP> " : " ");
54 if ((p
[0] & 0x60) == 0x00) fstrcat(flags
,"B ");
55 if ((p
[0] & 0x60) == 0x20) fstrcat(flags
,"P ");
56 if ((p
[0] & 0x60) == 0x40) fstrcat(flags
,"M ");
57 if ((p
[0] & 0x60) == 0x60) fstrcat(flags
,"H ");
58 if (p
[0] & 0x10) fstrcat(flags
,"<DEREGISTERING> ");
59 if (p
[0] & 0x08) fstrcat(flags
,"<CONFLICT> ");
60 if (p
[0] & 0x04) fstrcat(flags
,"<ACTIVE> ");
61 if (p
[0] & 0x02) fstrcat(flags
,"<PERMANENT> ");
63 if (master
&& !*master
&& type
== 0x1d) {
64 StrnCpy(master
,qname
,15);
65 trim_string(master
,NULL
," ");
68 if (rname
&& !*rname
&& type
== 0x20 && !(p
[0]&0x80)) {
69 StrnCpy(rname
,qname
,15);
70 trim_string(rname
,NULL
," ");
73 for (i
= strlen( qname
) ; --i
>= 0 ; ) {
74 if (!isprint((int)qname
[i
])) qname
[i
] = '.';
76 DEBUG(1,("\t%-15s <%02x> - %s\n",qname
,type
,flags
));
80 DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
81 IVAL(p
,20),IVAL(p
,24)));
84 /****************************************************************************
85 Internal function handling a netbios name status query on a host.
86 **************************************************************************/
88 static BOOL
internal_name_status(int fd
,char *name
,int name_type
,BOOL recurse
,
89 struct in_addr to_ip
,char *master
,char *rname
, BOOL verbose
,
90 void (*fn_interpret_node_status
)(char *, char *,char *),
91 void (*fn
)(struct packet_struct
*))
95 int retry_time
= 5000;
97 struct packet_struct p
;
98 struct packet_struct
*p2
;
99 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
100 static int name_trn_id
= 0;
102 memset((char *)&p
,'\0',sizeof(p
));
104 if (!name_trn_id
) name_trn_id
= ((unsigned)time(NULL
)%(unsigned)0x7FFF) +
105 ((unsigned)getpid()%(unsigned)100);
106 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
108 nmb
->header
.name_trn_id
= name_trn_id
;
109 nmb
->header
.opcode
= 0;
110 nmb
->header
.response
= False
;
111 nmb
->header
.nm_flags
.bcast
= False
;
112 nmb
->header
.nm_flags
.recursion_available
= False
;
113 nmb
->header
.nm_flags
.recursion_desired
= False
;
114 nmb
->header
.nm_flags
.trunc
= False
;
115 nmb
->header
.nm_flags
.authoritative
= False
;
116 nmb
->header
.rcode
= 0;
117 nmb
->header
.qdcount
= 1;
118 nmb
->header
.ancount
= 0;
119 nmb
->header
.nscount
= 0;
120 nmb
->header
.arcount
= 0;
122 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
);
124 nmb
->question
.question_type
= 0x21;
125 nmb
->question
.question_class
= 0x1;
130 p
.timestamp
= time(NULL
);
131 p
.packet_type
= NMB_PACKET
;
135 if (!send_packet(&p
))
141 struct timeval tval2
;
142 GetTimeOfDay(&tval2
);
143 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
146 if (!found
&& !send_packet(&p
))
152 if ((p2
=receive_packet(fd
,NMB_PACKET
,90))) {
153 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
154 debug_nmb_packet(p2
);
156 if (nmb
->header
.name_trn_id
!= nmb2
->header
.name_trn_id
||
157 !nmb2
->header
.response
) {
158 /* its not for us - maybe deal with it later */
166 if (nmb2
->header
.opcode
!= 0 ||
167 nmb2
->header
.nm_flags
.bcast
||
168 nmb2
->header
.rcode
||
169 !nmb2
->header
.ancount
||
170 nmb2
->answers
->rr_type
!= 0x21) {
171 /* XXXX what do we do with this? could be a redirect, but
172 we'll discard it for the moment */
177 if(fn_interpret_node_status
)
178 (*fn_interpret_node_status
)(&nmb2
->answers
->rdata
[0],master
,rname
);
185 DEBUG(0,("No status response (this is not unusual)\n"));
190 /****************************************************************************
191 Do a netbios name status query on a host.
192 The "master" parameter is a hack used for finding workgroups.
193 **************************************************************************/
195 BOOL
name_status(int fd
,char *name
,int name_type
,BOOL recurse
,
196 struct in_addr to_ip
,char *master
,char *rname
,
197 void (*fn
)(struct packet_struct
*))
199 return internal_name_status(fd
,name
,name_type
,recurse
,
200 to_ip
,master
,rname
,True
,
201 _interpret_node_status
, fn
);
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
, BOOL bcast
,BOOL recurse
,
211 struct in_addr to_ip
, int *count
, void (*fn
)(struct packet_struct
*))
215 int retry_time
= bcast
?250:2000;
217 struct packet_struct p
;
218 struct packet_struct
*p2
;
219 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
220 static int name_trn_id
= 0;
221 struct in_addr
*ip_list
= NULL
;
223 memset((char *)&p
,'\0',sizeof(p
));
226 if (!name_trn_id
) name_trn_id
= ((unsigned)time(NULL
)%(unsigned)0x7FFF) +
227 ((unsigned)getpid()%(unsigned)100);
228 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
230 nmb
->header
.name_trn_id
= name_trn_id
;
231 nmb
->header
.opcode
= 0;
232 nmb
->header
.response
= False
;
233 nmb
->header
.nm_flags
.bcast
= bcast
;
234 nmb
->header
.nm_flags
.recursion_available
= False
;
235 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
236 nmb
->header
.nm_flags
.trunc
= False
;
237 nmb
->header
.nm_flags
.authoritative
= False
;
238 nmb
->header
.rcode
= 0;
239 nmb
->header
.qdcount
= 1;
240 nmb
->header
.ancount
= 0;
241 nmb
->header
.nscount
= 0;
242 nmb
->header
.arcount
= 0;
244 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
);
246 nmb
->question
.question_type
= 0x20;
247 nmb
->question
.question_class
= 0x1;
252 p
.timestamp
= time(NULL
);
253 p
.packet_type
= NMB_PACKET
;
257 if (!send_packet(&p
))
264 struct timeval tval2
;
265 GetTimeOfDay(&tval2
);
266 if (TvalDiff(&tval
,&tval2
) > retry_time
)
270 if (!found
&& !send_packet(&p
))
276 if ((p2
=receive_packet(fd
,NMB_PACKET
,90)))
278 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
279 debug_nmb_packet(p2
);
281 if (nmb
->header
.name_trn_id
!= nmb2
->header
.name_trn_id
||
282 !nmb2
->header
.response
)
285 * Its not for us - maybe deal with it later
286 * (put it on the queue?).
295 if (nmb2
->header
.opcode
!= 0 ||
296 nmb2
->header
.nm_flags
.bcast
||
297 nmb2
->header
.rcode
||
298 !nmb2
->header
.ancount
)
301 * XXXX what do we do with this? Could be a redirect, but
302 * we'll discard it for the moment.
308 ip_list
= (struct in_addr
*)Realloc(ip_list
, sizeof(ip_list
[0]) *
309 ((*count
)+nmb2
->answers
->rdlength
/6));
312 DEBUG(fn
?3:2,("Got a positive name query response from %s ( ",
314 for (i
=0;i
<nmb2
->answers
->rdlength
/6;i
++)
316 putip((char *)&ip_list
[(*count
)],&nmb2
->answers
->rdata
[2+i
*6]);
317 DEBUG(fn
?3:2,("%s ",inet_ntoa(ip_list
[(*count
)])));
320 DEBUG(fn
?3:2,(")\n"));
330 * If we're doing a unicast lookup we only
331 * expect one reply. Don't wait the full 2
332 * seconds if we got one. JRA.
342 /********************************************************
343 Start parsing the lmhosts file.
344 *********************************************************/
346 FILE *startlmhosts(char *fname
)
348 FILE *fp
= sys_fopen(fname
,"r");
350 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
351 fname
, strerror(errno
)));
357 /********************************************************
358 Parse the next line in the lmhosts file.
359 *********************************************************/
361 BOOL
getlmhostsent( FILE *fp
, pstring name
, int *name_type
, struct in_addr
*ipaddr
)
365 while(!feof(fp
) && !ferror(fp
)) {
366 pstring ip
,flags
,extra
;
372 if (!fgets_slash(line
,sizeof(pstring
),fp
))
384 if (next_token(&ptr
,ip
,NULL
,sizeof(ip
)))
386 if (next_token(&ptr
,name
,NULL
, sizeof(pstring
)))
388 if (next_token(&ptr
,flags
,NULL
, sizeof(flags
)))
390 if (next_token(&ptr
,extra
,NULL
, sizeof(extra
)))
396 if (count
> 0 && count
< 2)
398 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line
));
404 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
408 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip
, name
, flags
));
410 if (strchr(flags
,'G') || strchr(flags
,'S'))
412 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
416 *ipaddr
= *interpret_addr2(ip
);
418 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
419 then only add that name type. */
420 if((ptr
= strchr(name
, '#')) != NULL
)
425 *name_type
= (int)strtol(ptr
, &endptr
, 16);
427 if(!*ptr
|| (endptr
== ptr
))
429 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name
));
433 *(--ptr
) = '\0'; /* Truncate at the '#' */
442 /********************************************************
443 Finish parsing the lmhosts file.
444 *********************************************************/
446 void endlmhosts(FILE *fp
)
451 /********************************************************
452 Resolve via "bcast" method.
453 *********************************************************/
455 static BOOL
resolve_bcast(const char *name
, int name_type
,
456 struct in_addr
**return_ip_list
, int *return_count
)
459 int num_interfaces
= iface_count();
461 *return_ip_list
= NULL
;
465 * "bcast" means do a broadcast lookup on all the local interfaces.
468 DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name
, name_type
));
470 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
471 interpret_addr(lp_socket_address()), True
);
473 if (sock
== -1) return False
;
475 set_socket_options(sock
,"SO_BROADCAST");
477 * Lookup the name on all the interfaces, return on
478 * the first successful match.
480 for( i
= num_interfaces
-1; i
>= 0; i
--) {
481 struct in_addr sendto_ip
;
482 /* Done this way to fix compiler error on IRIX 5.x */
483 sendto_ip
= *iface_bcast(*iface_n_ip(i
));
484 *return_ip_list
= name_query(sock
, name
, name_type
, True
,
485 True
, sendto_ip
, return_count
, NULL
);
486 if(*return_ip_list
!= NULL
) {
496 /********************************************************
497 Resolve via "wins" method.
498 *********************************************************/
500 static BOOL
resolve_wins(const char *name
, int name_type
,
501 struct in_addr
**return_iplist
, int *return_count
)
504 struct in_addr wins_ip
;
507 *return_iplist
= NULL
;
511 * "wins" means do a unicast lookup to the WINS server.
512 * Ignore if there is no WINS server specified or if the
513 * WINS server is one of our interfaces (if we're being
514 * called from within nmbd - we can't do this call as we
518 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name
, name_type
));
520 if(!*lp_wins_server()) {
521 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS server present.\n"));
525 wins_ip
= *interpret_addr2(lp_wins_server());
526 wins_ismyip
= ismyip(wins_ip
);
528 if((wins_ismyip
&& !global_in_nmbd
) || !wins_ismyip
) {
529 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
530 interpret_addr(lp_socket_address()), True
);
533 *return_iplist
= name_query(sock
, name
, name_type
, False
,
534 True
, wins_ip
, return_count
, NULL
);
535 if(*return_iplist
!= NULL
) {
546 /********************************************************
547 Resolve via "lmhosts" method.
548 *********************************************************/
550 static BOOL
resolve_lmhosts(const char *name
, int name_type
,
551 struct in_addr
**return_iplist
, int *return_count
)
554 * "lmhosts" means parse the local lmhosts file.
560 struct in_addr return_ip
;
562 *return_iplist
= NULL
;
565 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name
, name_type
));
567 fp
= startlmhosts( LMHOSTSFILE
);
569 while (getlmhostsent(fp
, lmhost_name
, &name_type2
, &return_ip
)) {
570 if (strequal(name
, lmhost_name
) &&
571 ((name_type2
== -1) || (name_type
== name_type2
))
574 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
575 if(*return_iplist
== NULL
) {
576 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
579 **return_iplist
= return_ip
;
590 /********************************************************
591 Resolve via "hosts" method.
592 *********************************************************/
594 static BOOL
resolve_hosts(const char *name
,
595 struct in_addr
**return_iplist
, int *return_count
)
598 * "host" means do a localhost, or dns lookup.
602 *return_iplist
= NULL
;
605 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name
));
607 if (((hp
= Get_Hostbyname(name
)) != NULL
) && (hp
->h_addr
!= NULL
)) {
608 struct in_addr return_ip
;
609 putip((char *)&return_ip
,(char *)hp
->h_addr
);
610 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
611 if(*return_iplist
== NULL
) {
612 DEBUG(3,("resolve_hosts: malloc fail !\n"));
615 **return_iplist
= return_ip
;
622 /********************************************************
623 Internal interface to resolve a name into an IP address.
624 Use this function if the string is either an IP address, DNS
625 or host name or NetBIOS name. This uses the name switch in the
626 smb.conf to determine the order of name resolution.
627 *********************************************************/
629 static BOOL
internal_resolve_name(const char *name
, int name_type
,
630 struct in_addr
**return_iplist
, int *return_count
)
632 pstring name_resolve_list
;
635 BOOL allones
= (strcmp(name
,"255.255.255.255") == 0);
636 BOOL allzeros
= (strcmp(name
,"0.0.0.0") == 0);
637 BOOL is_address
= is_ipaddress(name
);
638 *return_iplist
= NULL
;
641 if (allzeros
|| allones
|| is_address
) {
642 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
643 if(*return_iplist
== NULL
) {
644 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
648 /* if it's in the form of an IP address then get the lib to interpret it */
649 (*return_iplist
)->s_addr
= inet_addr(name
);
651 (*return_iplist
)->s_addr
= allones
? 0xFFFFFFFF : 0;
657 pstrcpy(name_resolve_list
, lp_name_resolve_order());
658 ptr
= name_resolve_list
;
662 while (next_token(&ptr
, tok
, LIST_SEP
, sizeof(tok
))) {
663 if((strequal(tok
, "host") || strequal(tok
, "hosts"))) {
664 if (name_type
== 0x20 && resolve_hosts(name
, return_iplist
, return_count
)) {
667 } else if(strequal( tok
, "lmhosts")) {
668 if (resolve_lmhosts(name
, name_type
, return_iplist
, return_count
)) {
671 } else if(strequal( tok
, "wins")) {
672 /* don't resolve 1D via WINS */
673 if (name_type
!= 0x1D &&
674 resolve_wins(name
, name_type
, return_iplist
, return_count
)) {
677 } else if(strequal( tok
, "bcast")) {
678 if (resolve_bcast(name
, name_type
, return_iplist
, return_count
)) {
682 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok
));
686 if((*return_iplist
) != NULL
) {
687 free((char *)(*return_iplist
));
688 *return_iplist
= NULL
;
693 /********************************************************
694 Internal interface to resolve a name into one IP address.
695 Use this function if the string is either an IP address, DNS
696 or host name or NetBIOS name. This uses the name switch in the
697 smb.conf to determine the order of name resolution.
698 *********************************************************/
700 BOOL
resolve_name(const char *name
, struct in_addr
*return_ip
, int name_type
)
702 struct in_addr
*ip_list
= NULL
;
705 if(internal_resolve_name(name
, name_type
, &ip_list
, &count
)) {
706 *return_ip
= ip_list
[0];
707 free((char *)ip_list
);
711 free((char *)ip_list
);
715 /********************************************************
716 Find the IP address of the master browser or DMB for a workgroup.
717 *********************************************************/
719 BOOL
find_master_ip(char *group
, struct in_addr
*master_ip
)
721 struct in_addr
*ip_list
= NULL
;
724 if (internal_resolve_name(group
, 0x1D, &ip_list
, &count
)) {
725 *master_ip
= ip_list
[0];
726 free((char *)ip_list
);
729 if(internal_resolve_name(group
, 0x1B, &ip_list
, &count
)) {
730 *master_ip
= ip_list
[0];
731 free((char *)ip_list
);
736 free((char *)ip_list
);
740 /********************************************************
741 Internal function to extract the MACHINE<0x20> name.
742 *********************************************************/
744 static void _lookup_pdc_name(char *p
, char *master
,char *rname
)
746 int numnames
= CVAL(p
,0);
752 int type
= CVAL(p
,15);
755 trim_string(rname
,NULL
," ");
762 /********************************************************
763 Lookup a PDC name given a Domain name and IP address.
764 *********************************************************/
766 BOOL
lookup_pdc_name(const char *srcname
, const char *domain
, struct in_addr
*pdc_ip
, char *ret_name
)
768 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
774 * Due to the fact win WinNT *sucks* we must do a node status
778 int sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
785 ret
= internal_name_status(sock
,"*SMBSERVER",0x20,True
,
786 *pdc_ip
,NULL
,pdc_name
,False
,
787 _lookup_pdc_name
,NULL
);
791 if(ret
&& *pdc_name
) {
792 fstrcpy(ret_name
, pdc_name
);
798 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
800 * Sigh. I *love* this code, it took me ages to get right and it's
801 * completely *USELESS* because NT 4.x refuses to send the mailslot
802 * reply back to the correct port (it always uses 138).
803 * I hate NT when it does these things... JRA.
807 int retry_time
= 2000;
809 struct packet_struct p
;
810 struct dgram_packet
*dgram
= &p
.packet
.dgram
;
814 struct sockaddr_in sock_name
;
815 int sock_len
= sizeof(sock_name
);
816 const char *mailslot
= "\\MAILSLOT\\NET\\NETLOGON";
817 static int name_trn_id
= 0;
820 int sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
825 /* Find out the transient UDP port we have been allocated. */
826 if(getsockname(sock
, (struct sockaddr
*)&sock_name
, &sock_len
)<0) {
827 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
834 * Create the request data.
837 memset(buffer
,'\0',sizeof(buffer
));
839 SSVAL(bufp
,0,QUERYFORPDC
);
841 fstrcpy(bufp
,srcname
);
842 bufp
+= (strlen(bufp
) + 1);
843 fstrcpy(bufp
,"\\MAILSLOT\\NET\\GETDC411");
844 bufp
+= (strlen(bufp
) + 1);
845 bufp
= align2(bufp
, buffer
);
846 bufp
+= dos_PutUniCode(bufp
, srcname
, sizeof(buffer
) - (bufp
- buffer
) - 1, True
);
848 SSVAL(bufp
,4,0xFFFF);
849 SSVAL(bufp
,6,0xFFFF);
851 len
= PTR_DIFF(bufp
,buffer
);
854 name_trn_id
= ((unsigned)time(NULL
)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100);
855 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
857 memset((char *)&p
,'\0',sizeof(p
));
859 /* DIRECT GROUP or UNIQUE datagram. */
860 dgram
->header
.msg_type
= 0x10;
861 dgram
->header
.flags
.node_type
= M_NODE
;
862 dgram
->header
.flags
.first
= True
;
863 dgram
->header
.flags
.more
= False
;
864 dgram
->header
.dgm_id
= name_trn_id
;
865 dgram
->header
.source_ip
= sock_name
.sin_addr
;
866 dgram
->header
.source_port
= ntohs(sock_name
.sin_port
);
867 dgram
->header
.dgm_length
= 0; /* Let build_dgram() handle this. */
868 dgram
->header
.packet_offset
= 0;
870 make_nmb_name(&dgram
->source_name
,srcname
,0);
871 make_nmb_name(&dgram
->dest_name
,domain
,0x1B);
873 ptr
= &dgram
->data
[0];
875 /* Setup the smb part. */
876 ptr
-= 4; /* XXX Ugliness because of handling of tcp SMB length. */
878 set_message(ptr
,17,17 + len
,True
);
881 CVAL(ptr
,smb_com
) = SMBtrans
;
882 SSVAL(ptr
,smb_vwv1
,len
);
883 SSVAL(ptr
,smb_vwv11
,len
);
884 SSVAL(ptr
,smb_vwv12
,70 + strlen(mailslot
));
885 SSVAL(ptr
,smb_vwv13
,3);
886 SSVAL(ptr
,smb_vwv14
,1);
887 SSVAL(ptr
,smb_vwv15
,1);
888 SSVAL(ptr
,smb_vwv16
,2);
890 pstrcpy(p2
,mailslot
);
891 p2
= skip_string(p2
,1);
893 memcpy(p2
,buffer
,len
);
896 dgram
->datasize
= PTR_DIFF(p2
,ptr
+4); /* +4 for tcp length. */
901 p
.timestamp
= time(NULL
);
902 p
.packet_type
= DGRAM_PACKET
;
906 if (!send_packet(&p
)) {
907 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
915 struct timeval tval2
;
916 struct packet_struct
*p_ret
;
918 GetTimeOfDay(&tval2
);
919 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
922 if (!send_packet(&p
)) {
923 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
931 if ((p_ret
= receive_packet(sock
,NMB_PACKET
,90))) {
932 struct nmb_packet
*nmb2
= &p_ret
->packet
.nmb
;
933 struct dgram_packet
*dgram2
= &p_ret
->packet
.dgram
;
937 debug_nmb_packet(p_ret
);
939 if (memcmp(&p
.ip
, &p_ret
->ip
, sizeof(p
.ip
))) {
943 DEBUG(0,("lookup_pdc_name: datagram return IP %s doesn't match\n", inet_ntoa(p_ret
->ip
) ));
948 buf
= &dgram2
->data
[0];
951 if (CVAL(buf
,smb_com
) != SMBtrans
) {
952 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)CVAL(buf
,smb_com
),
953 (unsigned int)SMBtrans
));
958 len
= SVAL(buf
,smb_vwv11
);
959 buf2
= smb_base(buf
) + SVAL(buf
,smb_vwv12
);
962 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len
));
967 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
968 nmb_namestr(&dgram2
->source_name
),nmb_namestr(&dgram2
->dest_name
),
969 inet_ntoa(p_ret
->ip
), smb_buf(buf
),CVAL(buf2
,0),len
));
971 if(SVAL(buf
,0) != QUERYFORPDC_R
) {
972 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
973 (unsigned int)SVAL(buf
,0), (unsigned int)QUERYFORPDC_R
));
979 /* Note this is safe as it is a bounded strcpy. */
980 fstrcpy(ret_name
, buf
);
981 ret_name
[sizeof(fstring
)-1] = '\0';
990 #endif /* I_HATE_WINDOWS_REPLY_CODE */
993 /********************************************************
994 Get the IP address list of the PDC/BDC's of a Domain.
995 *********************************************************/
997 BOOL
get_dc_list(char *group
, struct in_addr
**ip_list
, int *count
)
999 return internal_resolve_name(group
, 0x1C, ip_list
, count
);