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 /* nmbd.c sets this to True. */
26 BOOL global_in_nmbd
= False
;
28 /****************************************************************************
29 generate a random trn_id
30 ****************************************************************************/
31 static int generate_trn_id(void)
36 sys_srandom(sys_getpid());
39 trn_id
= sys_random();
41 return trn_id
% (unsigned)0x7FFF;
45 /****************************************************************************
46 parse a node status response into an array of structures
47 ****************************************************************************/
48 static struct node_status
*parse_node_status(char *p
, int *num_names
)
50 struct node_status
*ret
;
53 *num_names
= CVAL(p
,0);
55 if (*num_names
== 0) return NULL
;
57 ret
= (struct node_status
*)malloc(sizeof(struct node_status
)* (*num_names
));
58 if (!ret
) return NULL
;
61 for (i
=0;i
< *num_names
;i
++) {
62 StrnCpy(ret
[i
].name
,p
,15);
63 trim_string(ret
[i
].name
,NULL
," ");
64 ret
[i
].type
= CVAL(p
,15);
72 /****************************************************************************
73 do a NBT node status query on an open socket and return an array of
74 structures holding the returned names or NULL if the query failed
75 **************************************************************************/
76 struct node_status
*node_status_query(int fd
,struct nmb_name
*name
,
77 struct in_addr to_ip
, int *num_names
)
81 int retry_time
= 2000;
83 struct packet_struct p
;
84 struct packet_struct
*p2
;
85 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
86 struct node_status
*ret
;
90 nmb
->header
.name_trn_id
= generate_trn_id();
91 nmb
->header
.opcode
= 0;
92 nmb
->header
.response
= False
;
93 nmb
->header
.nm_flags
.bcast
= False
;
94 nmb
->header
.nm_flags
.recursion_available
= False
;
95 nmb
->header
.nm_flags
.recursion_desired
= False
;
96 nmb
->header
.nm_flags
.trunc
= False
;
97 nmb
->header
.nm_flags
.authoritative
= False
;
98 nmb
->header
.rcode
= 0;
99 nmb
->header
.qdcount
= 1;
100 nmb
->header
.ancount
= 0;
101 nmb
->header
.nscount
= 0;
102 nmb
->header
.arcount
= 0;
103 nmb
->question
.question_name
= *name
;
104 nmb
->question
.question_type
= 0x21;
105 nmb
->question
.question_class
= 0x1;
110 p
.timestamp
= time(NULL
);
111 p
.packet_type
= NMB_PACKET
;
115 if (!send_packet(&p
))
121 struct timeval tval2
;
122 GetTimeOfDay(&tval2
);
123 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
126 if (!found
&& !send_packet(&p
))
132 if ((p2
=receive_nmb_packet(fd
,90,nmb
->header
.name_trn_id
))) {
133 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
134 debug_nmb_packet(p2
);
136 if (nmb2
->header
.opcode
!= 0 ||
137 nmb2
->header
.nm_flags
.bcast
||
138 nmb2
->header
.rcode
||
139 !nmb2
->header
.ancount
||
140 nmb2
->answers
->rr_type
!= 0x21) {
141 /* XXXX what do we do with this? could be a
142 redirect, but we'll discard it for the
148 ret
= parse_node_status(&nmb2
->answers
->rdata
[0], num_names
);
158 /****************************************************************************
159 find the first type XX name in a node status reply - used for finding
160 a servers name given its IP
161 return the matched name in *name
162 **************************************************************************/
164 BOOL
name_status_find(const char *q_name
, int q_type
, int type
, struct in_addr to_ip
, char *name
)
166 struct node_status
*status
;
167 struct nmb_name nname
;
171 sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
175 /* W2K PDC's seem not to respond to '*'#0. JRA */
176 make_nmb_name(&nname
, q_name
, q_type
);
177 status
= node_status_query(sock
, &nname
, to_ip
, &count
);
182 for (i
=0;i
<count
;i
++) {
183 if (status
[i
].type
== type
)
189 StrnCpy(name
, status
[i
].name
, 15);
191 dos_to_unix(name
, True
);
197 /****************************************************************************
198 Do a NetBIOS name registation to try to claim a name ...
199 ***************************************************************************/
200 BOOL
name_register(int fd
, const char *name
, int name_type
,
201 struct in_addr name_ip
, int opcode
,
203 struct in_addr to_ip
, int *count
)
207 struct packet_struct p
;
208 struct packet_struct
*p2
;
209 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
210 struct in_addr register_ip
;
212 DEBUG(4, ("name_register: %s as %s on %s\n", name
, inet_ntoa(name_ip
), inet_ntoa(to_ip
)));
214 register_ip
.s_addr
= name_ip
.s_addr
; /* Fix this ... */
216 memset((char *)&p
, '\0', sizeof(p
));
220 nmb
->header
.name_trn_id
= generate_trn_id();
221 nmb
->header
.opcode
= opcode
;
222 nmb
->header
.response
= False
;
223 nmb
->header
.nm_flags
.bcast
= False
;
224 nmb
->header
.nm_flags
.recursion_available
= False
;
225 nmb
->header
.nm_flags
.recursion_desired
= True
; /* ? */
226 nmb
->header
.nm_flags
.trunc
= False
;
227 nmb
->header
.nm_flags
.authoritative
= True
;
229 nmb
->header
.qdcount
= 1;
230 nmb
->header
.ancount
= 0;
231 nmb
->header
.nscount
= 0;
232 nmb
->header
.arcount
= 1;
234 make_nmb_name(&nmb
->question
.question_name
, name
, name_type
);
236 nmb
->question
.question_type
= 0x20;
237 nmb
->question
.question_class
= 0x1;
239 /* Now, create the additional stuff for a registration request */
241 if ((nmb
->additional
= (struct res_rec
*)malloc(sizeof(struct res_rec
))) == NULL
) {
243 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
248 memset((char *)nmb
->additional
, '\0', sizeof(struct res_rec
));
250 nmb
->additional
->rr_name
= nmb
->question
.question_name
;
251 nmb
->additional
->rr_type
= RR_TYPE_NB
;
252 nmb
->additional
->rr_class
= RR_CLASS_IN
;
254 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
255 if (nmb
->header
.nm_flags
.bcast
)
256 nmb
->additional
->ttl
= PERMANENT_TTL
;
258 nmb
->additional
->ttl
= lp_max_ttl();
260 nmb
->additional
->rdlength
= 6;
262 nmb
->additional
->rdata
[0] = NB_MFLAG
& 0xFF;
264 /* Set the address for the name we are registering. */
265 putip(&nmb
->additional
->rdata
[2], ®ister_ip
);
270 p
.timestamp
= time(NULL
);
271 p
.packet_type
= NMB_PACKET
;
275 if (!send_packet(&p
))
280 if ((p2
= receive_nmb_packet(fd
, 10, nmb
->header
.name_trn_id
))) {
281 debug_nmb_packet(p2
);
282 SAFE_FREE(p2
); /* No memory leaks ... */
288 /****************************************************************************
289 Do a netbios name query to find someones IP.
290 Returns an array of IP addresses or NULL if none.
291 *count will be set to the number of addresses returned.
292 ****************************************************************************/
293 struct in_addr
*name_query(int fd
,const char *name
,int name_type
,
294 BOOL bcast
,BOOL recurse
,
295 struct in_addr to_ip
, int *count
)
299 int retry_time
= bcast
?250:2000;
301 struct packet_struct p
;
302 struct packet_struct
*p2
;
303 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
304 struct in_addr
*ip_list
= NULL
;
306 memset((char *)&p
,'\0',sizeof(p
));
309 nmb
->header
.name_trn_id
= generate_trn_id();
310 nmb
->header
.opcode
= 0;
311 nmb
->header
.response
= False
;
312 nmb
->header
.nm_flags
.bcast
= bcast
;
313 nmb
->header
.nm_flags
.recursion_available
= False
;
314 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
315 nmb
->header
.nm_flags
.trunc
= False
;
316 nmb
->header
.nm_flags
.authoritative
= False
;
317 nmb
->header
.rcode
= 0;
318 nmb
->header
.qdcount
= 1;
319 nmb
->header
.ancount
= 0;
320 nmb
->header
.nscount
= 0;
321 nmb
->header
.arcount
= 0;
323 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
);
325 nmb
->question
.question_type
= 0x20;
326 nmb
->question
.question_class
= 0x1;
331 p
.timestamp
= time(NULL
);
332 p
.packet_type
= NMB_PACKET
;
336 if (!send_packet(&p
))
342 struct timeval tval2
;
343 struct in_addr
*tmp_ip_list
;
345 GetTimeOfDay(&tval2
);
346 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
349 if (!found
&& !send_packet(&p
))
355 if ((p2
=receive_nmb_packet(fd
,90,nmb
->header
.name_trn_id
))) {
356 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
357 debug_nmb_packet(p2
);
359 /* If we get a Negative Name Query Response from a WINS
360 * server, we should report it and give up.
362 if( 0 == nmb2
->header
.opcode
/* A query response */
363 && !(bcast
) /* from a WINS server */
364 && nmb2
->header
.rcode
/* Error returned */
367 if( DEBUGLVL( 3 ) ) {
368 /* Only executed if DEBUGLEVEL >= 3 */
369 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2
->header
.rcode
);
370 switch( nmb2
->header
.rcode
) {
372 dbgtext( "Request was invalidly formatted.\n" );
375 dbgtext( "Problem with NBNS, cannot process name.\n");
378 dbgtext( "The name requested does not exist.\n" );
381 dbgtext( "Unsupported request error.\n" );
384 dbgtext( "Query refused error.\n" );
387 dbgtext( "Unrecognized error code.\n" );
396 if (nmb2
->header
.opcode
!= 0 ||
397 nmb2
->header
.nm_flags
.bcast
||
398 nmb2
->header
.rcode
||
399 !nmb2
->header
.ancount
) {
401 * XXXX what do we do with this? Could be a
402 * redirect, but we'll discard it for the
409 tmp_ip_list
= (struct in_addr
*)Realloc( ip_list
, sizeof( ip_list
[0] )
410 * ( (*count
) + nmb2
->answers
->rdlength
/6 ) );
413 DEBUG(0,("name_query: Realloc failed.\n"));
417 ip_list
= tmp_ip_list
;
420 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2
->ip
)));
421 for (i
=0;i
<nmb2
->answers
->rdlength
/6;i
++) {
422 putip((char *)&ip_list
[(*count
)],&nmb2
->answers
->rdata
[2+i
*6]);
423 DEBUGADD(2,("%s ",inet_ntoa(ip_list
[(*count
)])));
434 * If we're doing a unicast lookup we only
435 * expect one reply. Don't wait the full 2
436 * seconds if we got one. JRA.
443 /* Reach here if we've timed out waiting for replies.. */
444 if( !bcast
&& !found
) {
445 /* Timed out wating for WINS server to respond. Mark it dead. */
446 wins_srv_died( to_ip
);
452 /********************************************************
453 Start parsing the lmhosts file.
454 *********************************************************/
456 FILE *startlmhosts(char *fname
)
458 FILE *fp
= sys_fopen(fname
,"r");
460 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
461 fname
, strerror(errno
)));
467 /********************************************************
468 Parse the next line in the lmhosts file.
469 *********************************************************/
471 BOOL
getlmhostsent( FILE *fp
, pstring name
, int *name_type
, struct in_addr
*ipaddr
)
475 while(!feof(fp
) && !ferror(fp
)) {
476 pstring ip
,flags
,extra
;
482 if (!fgets_slash(line
,sizeof(pstring
),fp
))
494 if (next_token(&ptr
,ip
,NULL
,sizeof(ip
)))
496 if (next_token(&ptr
,name
,NULL
, sizeof(pstring
)))
498 if (next_token(&ptr
,flags
,NULL
, sizeof(flags
)))
500 if (next_token(&ptr
,extra
,NULL
, sizeof(extra
)))
506 if (count
> 0 && count
< 2)
508 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line
));
514 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
518 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip
, name
, flags
));
520 if (strchr(flags
,'G') || strchr(flags
,'S'))
522 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
526 *ipaddr
= *interpret_addr2(ip
);
528 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
529 then only add that name type. */
530 if((ptr
= strchr(name
, '#')) != NULL
)
535 *name_type
= (int)strtol(ptr
, &endptr
, 16);
537 if(!*ptr
|| (endptr
== ptr
))
539 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name
));
543 *(--ptr
) = '\0'; /* Truncate at the '#' */
552 /********************************************************
553 Finish parsing the lmhosts file.
554 *********************************************************/
556 void endlmhosts(FILE *fp
)
561 BOOL
name_register_wins(const char *name
, int name_type
)
563 int sock
, i
, return_count
;
564 int num_interfaces
= iface_count();
565 struct in_addr sendto_ip
;
568 * Check if we have any interfaces, prevents a segfault later
571 if (num_interfaces
<= 0)
572 return False
; /* Should return some indication of the problem */
575 * Do a broadcast register ...
578 if (!lp_wins_server())
581 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name
, lp_wins_server()));
583 sock
= open_socket_in(SOCK_DGRAM
, 0, 3,
584 interpret_addr("0.0.0.0"), True
);
586 if (sock
== -1) return False
;
588 set_socket_options(sock
, "SO_BROADCAST");
590 sendto_ip
.s_addr
= inet_addr(lp_wins_server());
592 if (num_interfaces
> 1) {
594 for (i
= 0; i
< num_interfaces
; i
++) {
596 if (!name_register(sock
, name
, name_type
, *iface_n_ip(i
),
597 NMB_NAME_MULTIHOMED_REG_OPCODE
,
598 True
, sendto_ip
, &return_count
)) {
610 if (!name_register(sock
, name
, name_type
, *iface_n_ip(0),
612 True
, sendto_ip
, &return_count
)) {
627 /********************************************************
628 Resolve via "bcast" method.
629 *********************************************************/
631 BOOL
name_resolve_bcast(const char *name
, int name_type
,
632 struct in_addr
**return_ip_list
, int *return_count
)
635 int num_interfaces
= iface_count();
637 *return_ip_list
= NULL
;
641 * "bcast" means do a broadcast lookup on all the local interfaces.
644 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name
, name_type
));
646 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
647 interpret_addr(lp_socket_address()), True
);
649 if (sock
== -1) return False
;
651 set_socket_options(sock
,"SO_BROADCAST");
653 * Lookup the name on all the interfaces, return on
654 * the first successful match.
656 for( i
= num_interfaces
-1; i
>= 0; i
--) {
657 struct in_addr sendto_ip
;
658 /* Done this way to fix compiler error on IRIX 5.x */
659 sendto_ip
= *iface_bcast(*iface_n_ip(i
));
660 *return_ip_list
= name_query(sock
, name
, name_type
, True
,
661 True
, sendto_ip
, return_count
);
662 if(*return_ip_list
!= NULL
) {
672 /********************************************************
673 Resolve via "wins" method.
674 *********************************************************/
676 static BOOL
resolve_wins(const char *name
, int name_type
,
677 struct in_addr
**return_iplist
, int *return_count
)
680 struct in_addr wins_ip
;
683 *return_iplist
= NULL
;
687 * "wins" means do a unicast lookup to the WINS server.
688 * Ignore if there is no WINS server specified or if the
689 * WINS server is one of our interfaces (if we're being
690 * called from within nmbd - we can't do this call as we
694 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name
, name_type
));
696 if (lp_wins_support()) {
698 * We're providing WINS support. Call ourselves so
699 * long as we're not nmbd.
701 extern struct in_addr loopback_ip
;
702 wins_ip
= loopback_ip
;
704 } else if( wins_srv_count() < 1 ) {
705 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
708 wins_ip
= wins_srv_ip();
709 wins_ismyip
= ismyip(wins_ip
);
712 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip
)) );
713 if((wins_ismyip
&& !global_in_nmbd
) || !wins_ismyip
) {
714 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
715 interpret_addr(lp_socket_address()),
718 *return_iplist
= name_query( sock
, name
,
722 if(*return_iplist
!= NULL
) {
733 /********************************************************
734 Resolve via "lmhosts" method.
735 *********************************************************/
737 static BOOL
resolve_lmhosts(const char *name
, int name_type
,
738 struct in_addr
**return_iplist
, int *return_count
)
741 * "lmhosts" means parse the local lmhosts file.
747 struct in_addr return_ip
;
749 *return_iplist
= NULL
;
752 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name
, name_type
));
754 fp
= startlmhosts( LMHOSTSFILE
);
756 while (getlmhostsent(fp
, lmhost_name
, &name_type2
, &return_ip
)) {
757 if (strequal(name
, lmhost_name
) &&
758 ((name_type2
== -1) || (name_type
== name_type2
))
761 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
762 if(*return_iplist
== NULL
) {
763 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
766 **return_iplist
= return_ip
;
777 /********************************************************
778 Resolve via "hosts" method.
779 *********************************************************/
781 static BOOL
resolve_hosts(const char *name
,
782 struct in_addr
**return_iplist
, int *return_count
)
785 * "host" means do a localhost, or dns lookup.
789 *return_iplist
= NULL
;
792 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name
));
794 if (((hp
= sys_gethostbyname(name
)) != NULL
) && (hp
->h_addr
!= NULL
)) {
795 struct in_addr return_ip
;
796 putip((char *)&return_ip
,(char *)hp
->h_addr
);
797 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
798 if(*return_iplist
== NULL
) {
799 DEBUG(3,("resolve_hosts: malloc fail !\n"));
802 **return_iplist
= return_ip
;
809 /********************************************************
810 Internal interface to resolve a name into an IP address.
811 Use this function if the string is either an IP address, DNS
812 or host name or NetBIOS name. This uses the name switch in the
813 smb.conf to determine the order of name resolution.
814 *********************************************************/
816 static BOOL
internal_resolve_name(const char *name
, int name_type
,
817 struct in_addr
**return_iplist
, int *return_count
)
819 pstring name_resolve_list
;
822 BOOL allones
= (strcmp(name
,"255.255.255.255") == 0);
823 BOOL allzeros
= (strcmp(name
,"0.0.0.0") == 0);
824 BOOL is_address
= is_ipaddress(name
);
825 *return_iplist
= NULL
;
828 if (allzeros
|| allones
|| is_address
) {
829 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
830 if(*return_iplist
== NULL
) {
831 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
835 /* if it's in the form of an IP address then get the lib to interpret it */
836 (*return_iplist
)->s_addr
= inet_addr(name
);
838 (*return_iplist
)->s_addr
= allones
? 0xFFFFFFFF : 0;
844 pstrcpy(name_resolve_list
, lp_name_resolve_order());
845 ptr
= name_resolve_list
;
849 while (next_token(&ptr
, tok
, LIST_SEP
, sizeof(tok
))) {
850 if((strequal(tok
, "host") || strequal(tok
, "hosts"))) {
851 if (name_type
== 0x20 && resolve_hosts(name
, return_iplist
, return_count
)) {
854 } else if(strequal( tok
, "lmhosts")) {
855 if (resolve_lmhosts(name
, name_type
, return_iplist
, return_count
)) {
858 } else if(strequal( tok
, "wins")) {
859 /* don't resolve 1D via WINS */
860 if (name_type
!= 0x1D &&
861 resolve_wins(name
, name_type
, return_iplist
, return_count
)) {
864 } else if(strequal( tok
, "bcast")) {
865 if (name_resolve_bcast(name
, name_type
, return_iplist
, return_count
)) {
869 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok
));
873 SAFE_FREE(*return_iplist
);
877 /********************************************************
878 Internal interface to resolve a name into one IP address.
879 Use this function if the string is either an IP address, DNS
880 or host name or NetBIOS name. This uses the name switch in the
881 smb.conf to determine the order of name resolution.
882 *********************************************************/
884 BOOL
resolve_name(const char *name
, struct in_addr
*return_ip
, int name_type
)
886 struct in_addr
*ip_list
= NULL
;
889 if(internal_resolve_name(name
, name_type
, &ip_list
, &count
)) {
890 *return_ip
= ip_list
[0];
899 /********************************************************
900 resolve a name of format \\server_name or \\ipaddress
901 into a name. also, cut the \\ from the front for us.
902 *********************************************************/
904 BOOL
resolve_srv_name(const char* srv_name
, fstring dest_host
,
908 const char *sv_name
= srv_name
;
910 DEBUG(10,("resolve_srv_name: %s\n", srv_name
));
912 if (srv_name
== NULL
|| strequal("\\\\.", srv_name
))
914 extern pstring global_myname
;
915 fstrcpy(dest_host
, global_myname
);
916 ip
= interpret_addr2("127.0.0.1");
920 if (strnequal("\\\\", srv_name
, 2))
922 sv_name
= &srv_name
[2];
925 fstrcpy(dest_host
, sv_name
);
926 /* treat the '*' name specially - it is a magic name for the PDC */
927 if (strcmp(dest_host
,"*") == 0) {
928 extern pstring global_myname
;
929 ret
= resolve_name(lp_workgroup(), ip
, 0x1B);
930 lookup_dc_name(global_myname
, lp_workgroup(), ip
, dest_host
);
932 ret
= resolve_name(dest_host
, ip
, 0x20);
935 if (is_ipaddress(dest_host
))
937 fstrcpy(dest_host
, "*SMBSERVER");
944 /********************************************************
945 Find the IP address of the master browser or DMB for a workgroup.
946 *********************************************************/
948 BOOL
find_master_ip(char *group
, struct in_addr
*master_ip
)
950 struct in_addr
*ip_list
= NULL
;
953 if (internal_resolve_name(group
, 0x1D, &ip_list
, &count
)) {
954 *master_ip
= ip_list
[0];
958 if(internal_resolve_name(group
, 0x1B, &ip_list
, &count
)) {
959 *master_ip
= ip_list
[0];
968 /********************************************************
969 Lookup a DC name given a Domain name and IP address.
970 *********************************************************/
972 BOOL
lookup_dc_name(const char *srcname
, const char *domain
,
973 struct in_addr
*dc_ip
, char *ret_name
)
975 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
981 * Due to the fact win WinNT *sucks* we must do a node status
987 ret
= name_status_find(domain
, 0x1c, 0x20, *dc_ip
, dc_name
);
989 if(ret
&& *dc_name
) {
990 fstrcpy(ret_name
, dc_name
);
996 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
998 JRA
- This code is broken with BDC rollover
- we need to
do a full
999 NT GETDC call
, UNICODE
, NT domain SID
and uncle tom cobbley
and all
...
1002 int retry_time
= 2000;
1003 struct timeval tval
;
1004 struct packet_struct p
;
1005 struct dgram_packet
*dgram
= &p
.packet
.dgram
;
1009 struct sockaddr_in sock_name
;
1010 int sock_len
= sizeof(sock_name
);
1011 const char *mailslot
= NET_LOGON_MAILSLOT
;
1012 char *mailslot_name
;
1015 int dgm_id
= generate_trn_id();
1016 int sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
1021 /* Find out the transient UDP port we have been allocated. */
1022 if(getsockname(sock
, (struct sockaddr
*)&sock_name
, &sock_len
)<0) {
1023 DEBUG(0,("lookup_dc_name: Failed to get local UDP port. Error was %s\n",
1030 * Create the request data.
1033 memset(buffer
,'\0',sizeof(buffer
));
1035 SSVAL(bufp
,0,QUERYFORPDC
);
1037 fstrcpy(bufp
,srcname
);
1038 bufp
+= (strlen(bufp
) + 1);
1039 slprintf(bufp
, sizeof(fstring
)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id
);
1040 mailslot_name
= bufp
;
1041 bufp
+= (strlen(bufp
) + 1);
1042 bufp
= ALIGN2(bufp
, buffer
);
1043 bufp
+= dos_PutUniCode(bufp
, srcname
, sizeof(buffer
) - (bufp
- buffer
) - 1, True
);
1045 SSVAL(bufp
,4,0xFFFF);
1046 SSVAL(bufp
,6,0xFFFF);
1048 len
= PTR_DIFF(bufp
,buffer
);
1050 memset((char *)&p
,'\0',sizeof(p
));
1052 /* DIRECT GROUP or UNIQUE datagram. */
1053 dgram
->header
.msg_type
= 0x10;
1054 dgram
->header
.flags
.node_type
= M_NODE
;
1055 dgram
->header
.flags
.first
= True
;
1056 dgram
->header
.flags
.more
= False
;
1057 dgram
->header
.dgm_id
= dgm_id
;
1058 dgram
->header
.source_ip
= *iface_ip(*pdc_ip
);
1059 dgram
->header
.source_port
= ntohs(sock_name
.sin_port
);
1060 dgram
->header
.dgm_length
= 0; /* Let build_dgram() handle this. */
1061 dgram
->header
.packet_offset
= 0;
1063 make_nmb_name(&dgram
->source_name
,srcname
,0);
1064 make_nmb_name(&dgram
->dest_name
,domain
,0x1C);
1066 ptr
= &dgram
->data
[0];
1068 /* Setup the smb part. */
1069 ptr
-= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1071 set_message(ptr
,17,17 + len
,True
);
1074 CVAL(ptr
,smb_com
) = SMBtrans
;
1075 SSVAL(ptr
,smb_vwv1
,len
);
1076 SSVAL(ptr
,smb_vwv11
,len
);
1077 SSVAL(ptr
,smb_vwv12
,70 + strlen(mailslot
));
1078 SSVAL(ptr
,smb_vwv13
,3);
1079 SSVAL(ptr
,smb_vwv14
,1);
1080 SSVAL(ptr
,smb_vwv15
,1);
1081 SSVAL(ptr
,smb_vwv16
,2);
1083 pstrcpy(p2
,mailslot
);
1084 p2
= skip_string(p2
,1);
1086 memcpy(p2
,buffer
,len
);
1089 dgram
->datasize
= PTR_DIFF(p2
,ptr
+4); /* +4 for tcp length. */
1092 p
.port
= DGRAM_PORT
;
1094 p
.timestamp
= time(NULL
);
1095 p
.packet_type
= DGRAM_PACKET
;
1097 GetTimeOfDay(&tval
);
1099 if (!send_packet(&p
)) {
1100 DEBUG(0,("lookup_dc_name: send_packet failed.\n"));
1108 struct timeval tval2
;
1109 struct packet_struct
*p_ret
;
1111 GetTimeOfDay(&tval2
);
1112 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
1115 if (!send_packet(&p
)) {
1116 DEBUG(0,("lookup_dc_name: send_packet failed.\n"));
1120 GetTimeOfDay(&tval
);
1124 if ((p_ret
= receive_dgram_packet(sock
,90,mailslot_name
))) {
1125 struct dgram_packet
*dgram2
= &p_ret
->packet
.dgram
;
1129 buf
= &dgram2
->data
[0];
1132 if (CVAL(buf
,smb_com
) != SMBtrans
) {
1133 DEBUG(0,("lookup_dc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1134 CVAL(buf
,smb_com
), (unsigned int)SMBtrans
));
1139 len
= SVAL(buf
,smb_vwv11
);
1140 buf2
= smb_base(buf
) + SVAL(buf
,smb_vwv12
);
1143 DEBUG(0,("lookup_dc_name: datagram len < 0 (%d)\n", len
));
1148 DEBUG(4,("lookup_dc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1149 nmb_namestr(&dgram2
->source_name
),nmb_namestr(&dgram2
->dest_name
),
1150 inet_ntoa(p_ret
->ip
), smb_buf(buf
),SVAL(buf2
,0),len
));
1152 if(SVAL(buf2
,0) != QUERYFORPDC_R
) {
1153 DEBUG(0,("lookup_dc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1154 (unsigned int)SVAL(buf
,0), (unsigned int)QUERYFORPDC_R
));
1160 /* Note this is safe as it is a bounded strcpy. */
1161 fstrcpy(ret_name
, buf2
);
1162 ret_name
[sizeof(fstring
)-1] = '\0';
1171 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1175 /********************************************************
1176 Get the IP address list of the PDC/BDC's of a Domain.
1177 *********************************************************/
1179 BOOL
get_dc_list(BOOL pdc_only
, char *group
, struct in_addr
**ip_list
, int *count
)
1181 int name_type
= pdc_only
? 0x1B : 0x1C;
1184 * If it's our domain then
1185 * use the 'password server' parameter.
1188 if (strequal(group
, lp_workgroup())) {
1190 char *pserver
= lp_passwordserver();
1192 int num_adresses
= 0;
1193 struct in_addr
*return_iplist
= NULL
;
1196 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1199 while (next_token(&p
,name
,LIST_SEP
,sizeof(name
))) {
1200 if (strequal(name
, "*"))
1201 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1204 if (num_adresses
== 0)
1205 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1207 return_iplist
= (struct in_addr
*)malloc(num_adresses
* sizeof(struct in_addr
));
1208 if(return_iplist
== NULL
) {
1209 DEBUG(3,("get_dc_list: malloc fail !\n"));
1214 while (next_token(&p
,name
,LIST_SEP
,sizeof(name
))) {
1215 struct in_addr name_ip
;
1216 if (resolve_name( name
, &name_ip
, 0x20) == False
)
1218 return_iplist
[(*count
)++] = name_ip
;
1220 *ip_list
= return_iplist
;
1221 return (*count
!= 0);
1223 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1226 /********************************************************
1227 Get the IP address list of the Local Master Browsers
1228 ********************************************************/
1229 BOOL
get_lmb_list(struct in_addr
**ip_list
, int *count
)
1231 return internal_resolve_name( MSBROWSE
, 0x1, ip_list
, count
);