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 parse a node status response into an array of structures
49 ****************************************************************************/
50 static struct node_status
*parse_node_status(char *p
, int *num_names
)
52 struct node_status
*ret
;
55 *num_names
= CVAL(p
,0);
57 if (*num_names
== 0) return NULL
;
59 ret
= (struct node_status
*)malloc(sizeof(struct node_status
)* (*num_names
));
60 if (!ret
) return NULL
;
63 for (i
=0;i
< *num_names
;i
++) {
64 StrnCpy(ret
[i
].name
,p
,15);
65 trim_string(ret
[i
].name
,NULL
," ");
66 ret
[i
].type
= CVAL(p
,15);
74 /****************************************************************************
75 do a NBT node status query on an open socket and return an array of
76 structures holding the returned names or NULL if the query failed
77 **************************************************************************/
78 struct node_status
*name_status_query(int fd
,struct nmb_name
*name
,
79 struct in_addr to_ip
, int *num_names
)
83 int retry_time
= 2000;
85 struct packet_struct p
;
86 struct packet_struct
*p2
;
87 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
88 struct node_status
*ret
;
92 nmb
->header
.name_trn_id
= generate_trn_id();
93 nmb
->header
.opcode
= 0;
94 nmb
->header
.response
= False
;
95 nmb
->header
.nm_flags
.bcast
= False
;
96 nmb
->header
.nm_flags
.recursion_available
= False
;
97 nmb
->header
.nm_flags
.recursion_desired
= False
;
98 nmb
->header
.nm_flags
.trunc
= False
;
99 nmb
->header
.nm_flags
.authoritative
= False
;
100 nmb
->header
.rcode
= 0;
101 nmb
->header
.qdcount
= 1;
102 nmb
->header
.ancount
= 0;
103 nmb
->header
.nscount
= 0;
104 nmb
->header
.arcount
= 0;
105 nmb
->question
.question_name
= *name
;
106 nmb
->question
.question_type
= 0x21;
107 nmb
->question
.question_class
= 0x1;
112 p
.timestamp
= time(NULL
);
113 p
.packet_type
= NMB_PACKET
;
117 if (!send_packet(&p
))
123 struct timeval tval2
;
124 GetTimeOfDay(&tval2
);
125 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
128 if (!found
&& !send_packet(&p
))
134 if ((p2
=receive_nmb_packet(fd
,90,nmb
->header
.name_trn_id
))) {
135 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
136 debug_nmb_packet(p2
);
138 if (nmb2
->header
.opcode
!= 0 ||
139 nmb2
->header
.nm_flags
.bcast
||
140 nmb2
->header
.rcode
||
141 !nmb2
->header
.ancount
||
142 nmb2
->answers
->rr_type
!= 0x21) {
143 /* XXXX what do we do with this? could be a
144 redirect, but we'll discard it for the
150 ret
= parse_node_status(&nmb2
->answers
->rdata
[0], num_names
);
160 /****************************************************************************
161 find the first type XX name in a node status reply - used for finding
162 a servers name given its IP
163 return the matched name in *name
164 **************************************************************************/
165 BOOL
name_status_find(int type
, struct in_addr to_ip
, char *name
)
167 struct node_status
*status
;
168 struct nmb_name nname
;
172 sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
173 if (sock
== -1) return False
;
175 make_nmb_name(&nname
, "*", 0);
176 status
= name_status_query(sock
, &nname
, to_ip
, &count
);
178 if (!status
) return False
;
180 for (i
=0;i
<count
;i
++) {
181 if (status
[i
].type
== type
) break;
183 if (i
== count
) return False
;
185 StrnCpy(name
, status
[i
].name
, 15);
187 dos_to_unix(name
, True
);
193 /****************************************************************************
194 Do a NetBIOS name registation to try to claim a name ...
195 ***************************************************************************/
196 BOOL
name_register(int fd
, const char *name
, int name_type
,
197 struct in_addr name_ip
, int opcode
,
199 struct in_addr to_ip
, int *count
)
203 struct packet_struct p
;
204 struct packet_struct
*p2
;
205 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
206 struct in_addr register_ip
;
208 DEBUG(4, ("name_register: %s as %s on %s\n", name
, inet_ntoa(name_ip
), inet_ntoa(to_ip
)));
210 register_ip
.s_addr
= name_ip
.s_addr
; /* Fix this ... */
212 bzero((char *)&p
, sizeof(p
));
216 nmb
->header
.name_trn_id
= generate_trn_id();
217 nmb
->header
.opcode
= opcode
;
218 nmb
->header
.response
= False
;
219 nmb
->header
.nm_flags
.bcast
= False
;
220 nmb
->header
.nm_flags
.recursion_available
= False
;
221 nmb
->header
.nm_flags
.recursion_desired
= True
; /* ? */
222 nmb
->header
.nm_flags
.trunc
= False
;
223 nmb
->header
.nm_flags
.authoritative
= True
;
225 nmb
->header
.qdcount
= 1;
226 nmb
->header
.ancount
= 0;
227 nmb
->header
.nscount
= 0;
228 nmb
->header
.arcount
= 1;
230 make_nmb_name(&nmb
->question
.question_name
, name
, name_type
);
232 nmb
->question
.question_type
= 0x20;
233 nmb
->question
.question_class
= 0x1;
235 /* Now, create the additional stuff for a registration request */
237 if ((nmb
->additional
= (struct res_rec
*)malloc(sizeof(struct res_rec
))) == NULL
) {
239 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
244 bzero((char *)nmb
->additional
, sizeof(struct res_rec
));
246 nmb
->additional
->rr_name
= nmb
->question
.question_name
;
247 nmb
->additional
->rr_type
= RR_TYPE_NB
;
248 nmb
->additional
->rr_class
= RR_CLASS_IN
;
250 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
251 if (nmb
->header
.nm_flags
.bcast
)
252 nmb
->additional
->ttl
= PERMANENT_TTL
;
254 nmb
->additional
->ttl
= lp_max_ttl();
256 nmb
->additional
->rdlength
= 6;
258 nmb
->additional
->rdata
[0] = NB_MFLAG
& 0xFF;
260 /* Set the address for the name we are registering. */
261 putip(&nmb
->additional
->rdata
[2], ®ister_ip
);
266 p
.timestamp
= time(NULL
);
267 p
.packet_type
= NMB_PACKET
;
271 if (!send_packet(&p
))
276 if ((p2
= receive_nmb_packet(fd
, 10, nmb
->header
.name_trn_id
))) {
277 debug_nmb_packet(p2
);
278 free(p2
); /* No memory leaks ... */
284 /****************************************************************************
285 Do a netbios name query to find someones IP.
286 Returns an array of IP addresses or NULL if none.
287 *count will be set to the number of addresses returned.
288 ****************************************************************************/
289 struct in_addr
*name_query(int fd
,const char *name
,int name_type
,
290 BOOL bcast
,BOOL recurse
,
291 struct in_addr to_ip
, int *count
)
295 int retry_time
= bcast
?250:2000;
297 struct packet_struct p
;
298 struct packet_struct
*p2
;
299 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
300 struct in_addr
*ip_list
= NULL
;
302 memset((char *)&p
,'\0',sizeof(p
));
305 nmb
->header
.name_trn_id
= generate_trn_id();
306 nmb
->header
.opcode
= 0;
307 nmb
->header
.response
= False
;
308 nmb
->header
.nm_flags
.bcast
= bcast
;
309 nmb
->header
.nm_flags
.recursion_available
= False
;
310 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
311 nmb
->header
.nm_flags
.trunc
= False
;
312 nmb
->header
.nm_flags
.authoritative
= False
;
313 nmb
->header
.rcode
= 0;
314 nmb
->header
.qdcount
= 1;
315 nmb
->header
.ancount
= 0;
316 nmb
->header
.nscount
= 0;
317 nmb
->header
.arcount
= 0;
319 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
);
321 nmb
->question
.question_type
= 0x20;
322 nmb
->question
.question_class
= 0x1;
327 p
.timestamp
= time(NULL
);
328 p
.packet_type
= NMB_PACKET
;
332 if (!send_packet(&p
))
339 struct timeval tval2
;
340 GetTimeOfDay(&tval2
);
341 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
344 if (!found
&& !send_packet(&p
))
350 if ((p2
=receive_nmb_packet(fd
,90,nmb
->header
.name_trn_id
))) {
351 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
352 debug_nmb_packet(p2
);
354 /* If we get a Negative Name Query Response from a WINS
355 * server, we should report it and give up.
357 if( 0 == nmb2
->header
.opcode
/* A query response */
358 && !(bcast
) /* from a WINS server */
359 && nmb2
->header
.rcode
/* Error returned */
362 if( DEBUGLVL( 3 ) ) {
363 /* Only executed if DEBUGLEVEL >= 3 */
364 dbgtext( "Negative name query response, rcode 0x%02x: ",
365 nmb2
->header
.rcode
);
366 switch( nmb2
->header
.rcode
) {
368 dbgtext( "Request was invalidly formatted.\n" );
371 dbgtext( "Problem with NBNS, cannot process name.\n");
374 dbgtext( "The name requested does not exist.\n" );
377 dbgtext( "Unsupported request error.\n" );
380 dbgtext( "Query refused error.\n" );
383 dbgtext( "Unrecognized error code.\n" );
391 if (nmb2
->header
.opcode
!= 0 ||
392 nmb2
->header
.nm_flags
.bcast
||
393 nmb2
->header
.rcode
||
394 !nmb2
->header
.ancount
) {
396 * XXXX what do we do with this? Could be a
397 * redirect, but we'll discard it for the
403 ip_list
= (struct in_addr
*)Realloc( ip_list
,
405 * ( (*count
) + nmb2
->answers
->rdlength
/6 ) );
407 DEBUG(2,("Got a positive name query response from %s ( ",
409 for (i
=0;i
<nmb2
->answers
->rdlength
/6;i
++) {
410 putip((char *)&ip_list
[(*count
)],&nmb2
->answers
->rdata
[2+i
*6]);
411 DEBUGADD(2,("%s ",inet_ntoa(ip_list
[(*count
)])));
421 * If we're doing a unicast lookup we only
422 * expect one reply. Don't wait the full 2
423 * seconds if we got one. JRA.
430 /* Reach here if we've timed out waiting for replies.. */
431 if( !bcast
&& !found
)
433 /* Timed out wating for WINS server to respond. Mark it dead. */
434 wins_srv_died( to_ip
);
440 /********************************************************
441 Start parsing the lmhosts file.
442 *********************************************************/
444 FILE *startlmhosts(char *fname
)
446 FILE *fp
= sys_fopen(fname
,"r");
448 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
449 fname
, strerror(errno
)));
455 /********************************************************
456 Parse the next line in the lmhosts file.
457 *********************************************************/
459 BOOL
getlmhostsent( FILE *fp
, pstring name
, int *name_type
, struct in_addr
*ipaddr
)
463 while(!feof(fp
) && !ferror(fp
)) {
464 pstring ip
,flags
,extra
;
470 if (!fgets_slash(line
,sizeof(pstring
),fp
))
482 if (next_token(&ptr
,ip
,NULL
,sizeof(ip
)))
484 if (next_token(&ptr
,name
,NULL
, sizeof(pstring
)))
486 if (next_token(&ptr
,flags
,NULL
, sizeof(flags
)))
488 if (next_token(&ptr
,extra
,NULL
, sizeof(extra
)))
494 if (count
> 0 && count
< 2)
496 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line
));
502 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
506 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip
, name
, flags
));
508 if (strchr(flags
,'G') || strchr(flags
,'S'))
510 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
514 *ipaddr
= *interpret_addr2(ip
);
516 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
517 then only add that name type. */
518 if((ptr
= strchr(name
, '#')) != NULL
)
523 *name_type
= (int)strtol(ptr
, &endptr
, 16);
525 if(!*ptr
|| (endptr
== ptr
))
527 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name
));
531 *(--ptr
) = '\0'; /* Truncate at the '#' */
540 /********************************************************
541 Finish parsing the lmhosts file.
542 *********************************************************/
544 void endlmhosts(FILE *fp
)
549 BOOL
name_register_wins(const char *name
, int name_type
)
551 int sock
, i
, return_count
;
552 int num_interfaces
= iface_count();
553 struct in_addr sendto_ip
;
556 * Do a broadcast register ...
559 if (!lp_wins_server())
562 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name
, lp_wins_server()));
564 sock
= open_socket_in(SOCK_DGRAM
, 0, 3,
565 interpret_addr("0.0.0.0"), True
);
567 if (sock
== -1) return False
;
569 set_socket_options(sock
, "SO_BROADCAST");
571 sendto_ip
.s_addr
= inet_addr(lp_wins_server());
573 if (num_interfaces
> 1) {
575 for (i
= 0; i
< num_interfaces
; i
++) {
577 if (!name_register(sock
, name
, name_type
, *iface_n_ip(i
),
578 NMB_NAME_MULTIHOMED_REG_OPCODE
,
579 True
, sendto_ip
, &return_count
)) {
591 if (!name_register(sock
, name
, name_type
, *iface_n_ip(0),
593 True
, sendto_ip
, &return_count
)) {
608 /********************************************************
609 Resolve via "bcast" method.
610 *********************************************************/
612 BOOL
name_resolve_bcast(const char *name
, int name_type
,
613 struct in_addr
**return_ip_list
, int *return_count
)
616 int num_interfaces
= iface_count();
618 *return_ip_list
= NULL
;
622 * "bcast" means do a broadcast lookup on all the local interfaces.
625 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name
, name_type
));
627 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
628 interpret_addr(lp_socket_address()), True
);
630 if (sock
== -1) return False
;
632 set_socket_options(sock
,"SO_BROADCAST");
634 * Lookup the name on all the interfaces, return on
635 * the first successful match.
637 for( i
= num_interfaces
-1; i
>= 0; i
--) {
638 struct in_addr sendto_ip
;
639 /* Done this way to fix compiler error on IRIX 5.x */
640 sendto_ip
= *iface_bcast(*iface_n_ip(i
));
641 *return_ip_list
= name_query(sock
, name
, name_type
, True
,
642 True
, sendto_ip
, return_count
);
643 if(*return_ip_list
!= NULL
) {
653 /********************************************************
654 Resolve via "wins" method.
655 *********************************************************/
657 static BOOL
resolve_wins(const char *name
, int name_type
,
658 struct in_addr
**return_iplist
, int *return_count
)
661 struct in_addr wins_ip
;
664 *return_iplist
= NULL
;
668 * "wins" means do a unicast lookup to the WINS server.
669 * Ignore if there is no WINS server specified or if the
670 * WINS server is one of our interfaces (if we're being
671 * called from within nmbd - we can't do this call as we
675 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name
, name_type
));
677 if (lp_wins_support()) {
679 * We're providing WINS support. Call ourselves so
680 * long as we're not nmbd.
682 extern struct in_addr loopback_ip
;
683 wins_ip
= loopback_ip
;
685 } else if( wins_srv_count() < 1 ) {
686 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
689 wins_ip
= wins_srv_ip();
690 wins_ismyip
= ismyip(wins_ip
);
693 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip
)) );
694 if((wins_ismyip
&& !global_in_nmbd
) || !wins_ismyip
) {
695 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
696 interpret_addr(lp_socket_address()),
699 *return_iplist
= name_query( sock
, name
,
703 if(*return_iplist
!= NULL
) {
714 /********************************************************
715 Resolve via "lmhosts" method.
716 *********************************************************/
718 static BOOL
resolve_lmhosts(const char *name
, int name_type
,
719 struct in_addr
**return_iplist
, int *return_count
)
722 * "lmhosts" means parse the local lmhosts file.
728 struct in_addr return_ip
;
730 *return_iplist
= NULL
;
733 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name
, name_type
));
735 fp
= startlmhosts( LMHOSTSFILE
);
737 while (getlmhostsent(fp
, lmhost_name
, &name_type2
, &return_ip
)) {
738 if (strequal(name
, lmhost_name
) &&
739 ((name_type2
== -1) || (name_type
== name_type2
))
742 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
743 if(*return_iplist
== NULL
) {
744 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
747 **return_iplist
= return_ip
;
758 /********************************************************
759 Resolve via "hosts" method.
760 *********************************************************/
762 static BOOL
resolve_hosts(const char *name
,
763 struct in_addr
**return_iplist
, int *return_count
)
766 * "host" means do a localhost, or dns lookup.
770 *return_iplist
= NULL
;
773 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name
));
775 if (((hp
= Get_Hostbyname(name
)) != NULL
) && (hp
->h_addr
!= NULL
)) {
776 struct in_addr return_ip
;
777 putip((char *)&return_ip
,(char *)hp
->h_addr
);
778 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
779 if(*return_iplist
== NULL
) {
780 DEBUG(3,("resolve_hosts: malloc fail !\n"));
783 **return_iplist
= return_ip
;
790 /********************************************************
791 Internal interface to resolve a name into an IP address.
792 Use this function if the string is either an IP address, DNS
793 or host name or NetBIOS name. This uses the name switch in the
794 smb.conf to determine the order of name resolution.
795 *********************************************************/
797 static BOOL
internal_resolve_name(const char *name
, int name_type
,
798 struct in_addr
**return_iplist
, int *return_count
)
800 pstring name_resolve_list
;
803 BOOL allones
= (strcmp(name
,"255.255.255.255") == 0);
804 BOOL allzeros
= (strcmp(name
,"0.0.0.0") == 0);
805 BOOL is_address
= is_ipaddress(name
);
806 *return_iplist
= NULL
;
809 if (allzeros
|| allones
|| is_address
) {
810 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
811 if(*return_iplist
== NULL
) {
812 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
816 /* if it's in the form of an IP address then get the lib to interpret it */
817 (*return_iplist
)->s_addr
= inet_addr(name
);
819 (*return_iplist
)->s_addr
= allones
? 0xFFFFFFFF : 0;
825 pstrcpy(name_resolve_list
, lp_name_resolve_order());
826 ptr
= name_resolve_list
;
830 while (next_token(&ptr
, tok
, LIST_SEP
, sizeof(tok
))) {
831 if((strequal(tok
, "host") || strequal(tok
, "hosts"))) {
832 if (name_type
== 0x20 && resolve_hosts(name
, return_iplist
, return_count
)) {
835 } else if(strequal( tok
, "lmhosts")) {
836 if (resolve_lmhosts(name
, name_type
, return_iplist
, return_count
)) {
839 } else if(strequal( tok
, "wins")) {
840 /* don't resolve 1D via WINS */
841 if (name_type
!= 0x1D &&
842 resolve_wins(name
, name_type
, return_iplist
, return_count
)) {
845 } else if(strequal( tok
, "bcast")) {
846 if (name_resolve_bcast(name
, name_type
, return_iplist
, return_count
)) {
850 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok
));
854 if((*return_iplist
) != NULL
) {
855 free((char *)(*return_iplist
));
856 *return_iplist
= NULL
;
861 /********************************************************
862 Internal interface to resolve a name into one IP address.
863 Use this function if the string is either an IP address, DNS
864 or host name or NetBIOS name. This uses the name switch in the
865 smb.conf to determine the order of name resolution.
866 *********************************************************/
868 BOOL
resolve_name(const char *name
, struct in_addr
*return_ip
, int name_type
)
870 struct in_addr
*ip_list
= NULL
;
873 if(internal_resolve_name(name
, name_type
, &ip_list
, &count
)) {
874 *return_ip
= ip_list
[0];
875 free((char *)ip_list
);
879 free((char *)ip_list
);
884 /********************************************************
885 resolve a name of format \\server_name or \\ipaddress
886 into a name. also, cut the \\ from the front for us.
887 *********************************************************/
889 BOOL
resolve_srv_name(const char* srv_name
, fstring dest_host
,
893 const char *sv_name
= srv_name
;
895 DEBUG(10,("resolve_srv_name: %s\n", srv_name
));
897 if (srv_name
== NULL
|| strequal("\\\\.", srv_name
))
899 extern pstring global_myname
;
900 fstrcpy(dest_host
, global_myname
);
901 ip
= interpret_addr2("127.0.0.1");
905 if (strnequal("\\\\", srv_name
, 2))
907 sv_name
= &srv_name
[2];
910 fstrcpy(dest_host
, sv_name
);
911 /* treat the '*' name specially - it is a magic name for the PDC */
912 if (strcmp(dest_host
,"*") == 0) {
913 extern pstring global_myname
;
914 ret
= resolve_name(lp_workgroup(), ip
, 0x1B);
915 lookup_pdc_name(global_myname
, lp_workgroup(), ip
, dest_host
);
917 ret
= resolve_name(dest_host
, ip
, 0x20);
920 if (is_ipaddress(dest_host
))
922 fstrcpy(dest_host
, "*SMBSERVER");
929 /********************************************************
930 Find the IP address of the master browser or DMB for a workgroup.
931 *********************************************************/
933 BOOL
find_master_ip(char *group
, struct in_addr
*master_ip
)
935 struct in_addr
*ip_list
= NULL
;
938 if (internal_resolve_name(group
, 0x1D, &ip_list
, &count
)) {
939 *master_ip
= ip_list
[0];
940 free((char *)ip_list
);
943 if(internal_resolve_name(group
, 0x1B, &ip_list
, &count
)) {
944 *master_ip
= ip_list
[0];
945 free((char *)ip_list
);
950 free((char *)ip_list
);
954 /********************************************************
955 Lookup a PDC name given a Domain name and IP address.
956 *********************************************************/
958 BOOL
lookup_pdc_name(const char *srcname
, const char *domain
, struct in_addr
*pdc_ip
, char *ret_name
)
960 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
966 * Due to the fact win WinNT *sucks* we must do a node status
972 ret
= name_status_find(0x20,*pdc_ip
,pdc_name
);
974 if(ret
&& *pdc_name
) {
975 fstrcpy(ret_name
, pdc_name
);
981 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
983 JRA
- This code is broken with BDC rollover
- we need to
do a full
984 NT GETDC call
, UNICODE
, NT domain SID
and uncle tom cobbley
and all
...
987 int retry_time
= 2000;
989 struct packet_struct p
;
990 struct dgram_packet
*dgram
= &p
.packet
.dgram
;
994 struct sockaddr_in sock_name
;
995 int sock_len
= sizeof(sock_name
);
996 const char *mailslot
= NET_LOGON_MAILSLOT
;
1000 int dgm_id
= generate_trn_id();
1001 int sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
1006 /* Find out the transient UDP port we have been allocated. */
1007 if(getsockname(sock
, (struct sockaddr
*)&sock_name
, &sock_len
)<0) {
1008 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1015 * Create the request data.
1018 memset(buffer
,'\0',sizeof(buffer
));
1020 SSVAL(bufp
,0,QUERYFORPDC
);
1022 fstrcpy(bufp
,srcname
);
1023 bufp
+= (strlen(bufp
) + 1);
1024 slprintf(bufp
, sizeof(fstring
)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id
);
1025 mailslot_name
= bufp
;
1026 bufp
+= (strlen(bufp
) + 1);
1027 bufp
= ALIGN2(bufp
, buffer
);
1028 bufp
+= dos_PutUniCode(bufp
, srcname
, sizeof(buffer
) - (bufp
- buffer
) - 1, True
);
1030 SSVAL(bufp
,4,0xFFFF);
1031 SSVAL(bufp
,6,0xFFFF);
1033 len
= PTR_DIFF(bufp
,buffer
);
1035 memset((char *)&p
,'\0',sizeof(p
));
1037 /* DIRECT GROUP or UNIQUE datagram. */
1038 dgram
->header
.msg_type
= 0x10;
1039 dgram
->header
.flags
.node_type
= M_NODE
;
1040 dgram
->header
.flags
.first
= True
;
1041 dgram
->header
.flags
.more
= False
;
1042 dgram
->header
.dgm_id
= dgm_id
;
1043 dgram
->header
.source_ip
= *iface_ip(*pdc_ip
);
1044 dgram
->header
.source_port
= ntohs(sock_name
.sin_port
);
1045 dgram
->header
.dgm_length
= 0; /* Let build_dgram() handle this. */
1046 dgram
->header
.packet_offset
= 0;
1048 make_nmb_name(&dgram
->source_name
,srcname
,0);
1049 make_nmb_name(&dgram
->dest_name
,domain
,0x1C);
1051 ptr
= &dgram
->data
[0];
1053 /* Setup the smb part. */
1054 ptr
-= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1056 set_message(ptr
,17,17 + len
,True
);
1059 CVAL(ptr
,smb_com
) = SMBtrans
;
1060 SSVAL(ptr
,smb_vwv1
,len
);
1061 SSVAL(ptr
,smb_vwv11
,len
);
1062 SSVAL(ptr
,smb_vwv12
,70 + strlen(mailslot
));
1063 SSVAL(ptr
,smb_vwv13
,3);
1064 SSVAL(ptr
,smb_vwv14
,1);
1065 SSVAL(ptr
,smb_vwv15
,1);
1066 SSVAL(ptr
,smb_vwv16
,2);
1068 pstrcpy(p2
,mailslot
);
1069 p2
= skip_string(p2
,1);
1071 memcpy(p2
,buffer
,len
);
1074 dgram
->datasize
= PTR_DIFF(p2
,ptr
+4); /* +4 for tcp length. */
1077 p
.port
= DGRAM_PORT
;
1079 p
.timestamp
= time(NULL
);
1080 p
.packet_type
= DGRAM_PACKET
;
1082 GetTimeOfDay(&tval
);
1084 if (!send_packet(&p
)) {
1085 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1093 struct timeval tval2
;
1094 struct packet_struct
*p_ret
;
1096 GetTimeOfDay(&tval2
);
1097 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
1100 if (!send_packet(&p
)) {
1101 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1105 GetTimeOfDay(&tval
);
1109 if ((p_ret
= receive_dgram_packet(sock
,90,mailslot_name
))) {
1110 struct dgram_packet
*dgram2
= &p_ret
->packet
.dgram
;
1114 buf
= &dgram2
->data
[0];
1117 if (CVAL(buf
,smb_com
) != SMBtrans
) {
1118 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1119 CVAL(buf
,smb_com
), (unsigned int)SMBtrans
));
1124 len
= SVAL(buf
,smb_vwv11
);
1125 buf2
= smb_base(buf
) + SVAL(buf
,smb_vwv12
);
1128 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len
));
1133 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1134 nmb_namestr(&dgram2
->source_name
),nmb_namestr(&dgram2
->dest_name
),
1135 inet_ntoa(p_ret
->ip
), smb_buf(buf
),SVAL(buf2
,0),len
));
1137 if(SVAL(buf2
,0) != QUERYFORPDC_R
) {
1138 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1139 (unsigned int)SVAL(buf
,0), (unsigned int)QUERYFORPDC_R
));
1145 /* Note this is safe as it is a bounded strcpy. */
1146 fstrcpy(ret_name
, buf2
);
1147 ret_name
[sizeof(fstring
)-1] = '\0';
1156 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1160 /********************************************************
1161 Get the IP address list of the PDC/BDC's of a Domain.
1162 *********************************************************/
1163 BOOL
get_dc_list(BOOL pdc_only
, char *group
, struct in_addr
**ip_list
, int *count
)
1165 return internal_resolve_name(group
, pdc_only
? 0x1B : 0x1C, ip_list
, count
);