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 ****************************************************************************/
32 static int generate_trn_id(void)
37 sys_srandom(sys_getpid());
39 trn_id
= sys_random();
41 return trn_id
% (unsigned)0x7FFF;
44 /****************************************************************************
45 Parse a node status response into an array of structures.
46 ****************************************************************************/
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);
71 /****************************************************************************
72 Do a NBT node status query on an open socket and return an array of
73 structures holding the returned names or NULL if the query failed.
74 **************************************************************************/
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);
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
, int *flags
)
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
));
310 nmb
->header
.name_trn_id
= generate_trn_id();
311 nmb
->header
.opcode
= 0;
312 nmb
->header
.response
= False
;
313 nmb
->header
.nm_flags
.bcast
= bcast
;
314 nmb
->header
.nm_flags
.recursion_available
= False
;
315 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
316 nmb
->header
.nm_flags
.trunc
= False
;
317 nmb
->header
.nm_flags
.authoritative
= False
;
318 nmb
->header
.rcode
= 0;
319 nmb
->header
.qdcount
= 1;
320 nmb
->header
.ancount
= 0;
321 nmb
->header
.nscount
= 0;
322 nmb
->header
.arcount
= 0;
324 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
);
326 nmb
->question
.question_type
= 0x20;
327 nmb
->question
.question_class
= 0x1;
332 p
.timestamp
= time(NULL
);
333 p
.packet_type
= NMB_PACKET
;
337 if (!send_packet(&p
))
343 struct timeval tval2
;
344 struct in_addr
*tmp_ip_list
;
346 GetTimeOfDay(&tval2
);
347 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
350 if (!found
&& !send_packet(&p
))
356 if ((p2
=receive_nmb_packet(fd
,90,nmb
->header
.name_trn_id
))) {
357 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
358 debug_nmb_packet(p2
);
360 /* If we get a Negative Name Query Response from a WINS
361 * server, we should report it and give up.
363 if( 0 == nmb2
->header
.opcode
/* A query response */
364 && !(bcast
) /* from a WINS server */
365 && nmb2
->header
.rcode
/* Error returned */
368 if( DEBUGLVL( 3 ) ) {
369 /* Only executed if DEBUGLEVEL >= 3 */
370 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2
->header
.rcode
);
371 switch( nmb2
->header
.rcode
) {
373 dbgtext( "Request was invalidly formatted.\n" );
376 dbgtext( "Problem with NBNS, cannot process name.\n");
379 dbgtext( "The name requested does not exist.\n" );
382 dbgtext( "Unsupported request error.\n" );
385 dbgtext( "Query refused error.\n" );
388 dbgtext( "Unrecognized error code.\n" );
397 if (nmb2
->header
.opcode
!= 0 ||
398 nmb2
->header
.nm_flags
.bcast
||
399 nmb2
->header
.rcode
||
400 !nmb2
->header
.ancount
) {
402 * XXXX what do we do with this? Could be a
403 * redirect, but we'll discard it for the
410 tmp_ip_list
= (struct in_addr
*)Realloc( ip_list
, sizeof( ip_list
[0] )
411 * ( (*count
) + nmb2
->answers
->rdlength
/6 ) );
414 DEBUG(0,("name_query: Realloc failed.\n"));
418 ip_list
= tmp_ip_list
;
421 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2
->ip
)));
422 for (i
=0;i
<nmb2
->answers
->rdlength
/6;i
++) {
423 putip((char *)&ip_list
[(*count
)],&nmb2
->answers
->rdata
[2+i
*6]);
424 DEBUGADD(2,("%s ",inet_ntoa(ip_list
[(*count
)])));
432 /* We add the flags back ... */
433 if (nmb2
->header
.response
)
434 (*flags
) |= NM_FLAGS_RS
;
435 if (nmb2
->header
.nm_flags
.authoritative
)
436 (*flags
) |= NM_FLAGS_AA
;
437 if (nmb2
->header
.nm_flags
.trunc
)
438 (*flags
) |= NM_FLAGS_TC
;
439 if (nmb2
->header
.nm_flags
.recursion_desired
)
440 (*flags
) |= NM_FLAGS_RD
;
441 if (nmb2
->header
.nm_flags
.recursion_available
)
442 (*flags
) |= NM_FLAGS_RA
;
443 if (nmb2
->header
.nm_flags
.bcast
)
444 (*flags
) |= NM_FLAGS_B
;
448 * If we're doing a unicast lookup we only
449 * expect one reply. Don't wait the full 2
450 * seconds if we got one. JRA.
457 /* Reach here if we've timed out waiting for replies.. */
458 if( !bcast
&& !found
) {
459 /* Timed out wating for WINS server to respond. Mark it dead. */
460 wins_srv_died( to_ip
);
466 /********************************************************
467 Start parsing the lmhosts file.
468 *********************************************************/
470 FILE *startlmhosts(char *fname
)
472 FILE *fp
= sys_fopen(fname
,"r");
474 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
475 fname
, strerror(errno
)));
481 /********************************************************
482 Parse the next line in the lmhosts file.
483 *********************************************************/
485 BOOL
getlmhostsent( FILE *fp
, pstring name
, int *name_type
, struct in_addr
*ipaddr
)
489 while(!feof(fp
) && !ferror(fp
)) {
490 pstring ip
,flags
,extra
;
496 if (!fgets_slash(line
,sizeof(pstring
),fp
))
508 if (next_token(&ptr
,ip
,NULL
,sizeof(ip
)))
510 if (next_token(&ptr
,name
,NULL
, sizeof(pstring
)))
512 if (next_token(&ptr
,flags
,NULL
, sizeof(flags
)))
514 if (next_token(&ptr
,extra
,NULL
, sizeof(extra
)))
520 if (count
> 0 && count
< 2)
522 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line
));
528 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
532 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip
, name
, flags
));
534 if (strchr(flags
,'G') || strchr(flags
,'S'))
536 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
540 *ipaddr
= *interpret_addr2(ip
);
542 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
543 then only add that name type. */
544 if((ptr
= strchr(name
, '#')) != NULL
)
549 *name_type
= (int)strtol(ptr
, &endptr
, 16);
551 if(!*ptr
|| (endptr
== ptr
))
553 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name
));
557 *(--ptr
) = '\0'; /* Truncate at the '#' */
566 /********************************************************
567 Finish parsing the lmhosts file.
568 *********************************************************/
570 void endlmhosts(FILE *fp
)
575 BOOL
name_register_wins(const char *name
, int name_type
)
577 int sock
, i
, return_count
;
578 int num_interfaces
= iface_count();
579 struct in_addr sendto_ip
;
582 * Check if we have any interfaces, prevents a segfault later
585 if (num_interfaces
<= 0)
586 return False
; /* Should return some indication of the problem */
589 * Do a broadcast register ...
592 if (!lp_wins_server())
595 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name
, lp_wins_server()));
597 sock
= open_socket_in(SOCK_DGRAM
, 0, 3,
598 interpret_addr("0.0.0.0"), True
);
600 if (sock
== -1) return False
;
602 set_socket_options(sock
, "SO_BROADCAST");
604 sendto_ip
.s_addr
= inet_addr(lp_wins_server());
606 if (num_interfaces
> 1) {
608 for (i
= 0; i
< num_interfaces
; i
++) {
610 if (!name_register(sock
, name
, name_type
, *iface_n_ip(i
),
611 NMB_NAME_MULTIHOMED_REG_OPCODE
,
612 True
, sendto_ip
, &return_count
)) {
624 if (!name_register(sock
, name
, name_type
, *iface_n_ip(0),
626 True
, sendto_ip
, &return_count
)) {
641 /********************************************************
642 Resolve via "bcast" method.
643 *********************************************************/
645 BOOL
name_resolve_bcast(const char *name
, int name_type
,
646 struct in_addr
**return_ip_list
, int *return_count
)
649 int num_interfaces
= iface_count();
651 *return_ip_list
= NULL
;
655 * "bcast" means do a broadcast lookup on all the local interfaces.
658 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name
, name_type
));
660 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
661 interpret_addr(lp_socket_address()), True
);
663 if (sock
== -1) return False
;
665 set_socket_options(sock
,"SO_BROADCAST");
667 * Lookup the name on all the interfaces, return on
668 * the first successful match.
670 for( i
= num_interfaces
-1; i
>= 0; i
--) {
671 struct in_addr sendto_ip
;
673 /* Done this way to fix compiler error on IRIX 5.x */
674 sendto_ip
= *iface_bcast(*iface_n_ip(i
));
675 *return_ip_list
= name_query(sock
, name
, name_type
, True
,
676 True
, sendto_ip
, return_count
, &flags
);
677 if(*return_ip_list
!= NULL
) {
687 /********************************************************
688 Resolve via "wins" method.
689 *********************************************************/
691 static BOOL
resolve_wins(const char *name
, int name_type
,
692 struct in_addr
**return_iplist
, int *return_count
)
695 struct in_addr wins_ip
;
698 *return_iplist
= NULL
;
702 * "wins" means do a unicast lookup to the WINS server.
703 * Ignore if there is no WINS server specified or if the
704 * WINS server is one of our interfaces (if we're being
705 * called from within nmbd - we can't do this call as we
709 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name
, name_type
));
711 if (lp_wins_support()) {
713 * We're providing WINS support. Call ourselves so
714 * long as we're not nmbd.
716 extern struct in_addr loopback_ip
;
717 wins_ip
= loopback_ip
;
719 } else if( wins_srv_count() < 1 ) {
720 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
723 wins_ip
= wins_srv_ip();
724 wins_ismyip
= ismyip(wins_ip
);
727 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip
)) );
728 if((wins_ismyip
&& !global_in_nmbd
) || !wins_ismyip
) {
729 sock
= open_socket_in( SOCK_DGRAM
, 0, 3,
730 interpret_addr(lp_socket_address()),
734 *return_iplist
= name_query( sock
, name
,
737 return_count
, &flags
);
738 if(*return_iplist
!= NULL
) {
749 /********************************************************
750 Resolve via "lmhosts" method.
751 *********************************************************/
753 static BOOL
resolve_lmhosts(const char *name
, int name_type
,
754 struct in_addr
**return_iplist
, int *return_count
)
757 * "lmhosts" means parse the local lmhosts file.
763 struct in_addr return_ip
;
765 *return_iplist
= NULL
;
768 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name
, name_type
));
770 fp
= startlmhosts( LMHOSTSFILE
);
772 while (getlmhostsent(fp
, lmhost_name
, &name_type2
, &return_ip
)) {
773 if (strequal(name
, lmhost_name
) &&
774 ((name_type2
== -1) || (name_type
== name_type2
))
777 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
778 if(*return_iplist
== NULL
) {
779 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
782 **return_iplist
= return_ip
;
793 /********************************************************
794 Resolve via "hosts" method.
795 *********************************************************/
797 static BOOL
resolve_hosts(const char *name
,
798 struct in_addr
**return_iplist
, int *return_count
)
801 * "host" means do a localhost, or dns lookup.
805 *return_iplist
= NULL
;
808 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name
));
810 if (((hp
= sys_gethostbyname(name
)) != NULL
) && (hp
->h_addr
!= NULL
)) {
812 while (hp
->h_addr_list
[i
]) i
++;
813 DEBUG(10, ("%d addresses returned\n", i
));
814 *return_iplist
= (struct in_addr
*)malloc(i
*sizeof(struct in_addr
));
815 if(*return_iplist
== NULL
) {
816 DEBUG(3,("resolve_hosts: malloc fail !\n"));
819 for (j
= 0; j
< i
; j
++)
820 putip(&(*return_iplist
)[j
], (char *)hp
->h_addr_list
[j
]);
827 /********************************************************
828 Internal interface to resolve a name into an IP address.
829 Use this function if the string is either an IP address, DNS
830 or host name or NetBIOS name. This uses the name switch in the
831 smb.conf to determine the order of name resolution.
832 *********************************************************/
834 static BOOL
internal_resolve_name(const char *name
, int name_type
,
835 struct in_addr
**return_iplist
, int *return_count
)
837 pstring name_resolve_list
;
840 BOOL allones
= (strcmp(name
,"255.255.255.255") == 0);
841 BOOL allzeros
= (strcmp(name
,"0.0.0.0") == 0);
842 BOOL is_address
= is_ipaddress(name
);
844 struct in_addr
*nodupes_iplist
;
847 *return_iplist
= NULL
;
850 if (allzeros
|| allones
|| is_address
) {
851 *return_iplist
= (struct in_addr
*)malloc(sizeof(struct in_addr
));
852 if(*return_iplist
== NULL
) {
853 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
857 /* if it's in the form of an IP address then get the lib to interpret it */
858 (*return_iplist
)->s_addr
= inet_addr(name
);
860 (*return_iplist
)->s_addr
= allones
? 0xFFFFFFFF : 0;
866 pstrcpy(name_resolve_list
, lp_name_resolve_order());
867 ptr
= name_resolve_list
;
871 while (next_token(&ptr
, tok
, LIST_SEP
, sizeof(tok
))) {
872 if((strequal(tok
, "host") || strequal(tok
, "hosts"))) {
873 if (name_type
== 0x20 && resolve_hosts(name
, return_iplist
, return_count
)) {
877 } else if(strequal( tok
, "lmhosts")) {
878 if (resolve_lmhosts(name
, name_type
, return_iplist
, return_count
)) {
882 } else if(strequal( tok
, "wins")) {
883 /* don't resolve 1D via WINS */
884 if (name_type
!= 0x1D &&
885 resolve_wins(name
, name_type
, return_iplist
, return_count
)) {
889 } else if(strequal( tok
, "bcast")) {
890 if (name_resolve_bcast(name
, name_type
, return_iplist
, return_count
)) {
895 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok
));
899 /* All of the resolve_* functions above have returned false. */
901 SAFE_FREE(*return_iplist
);
906 /* Remove duplicate entries. Some queries, notably #1c (domain
907 controllers) return the PDC in iplist[0] and then all domain
908 controllers including the PDC in iplist[1..n]. Iterating over
909 the iplist when the PDC is down will cause two sets of timeouts. */
911 if (*return_count
&& (nodupes_iplist
=
912 (struct in_addr
*)malloc(sizeof(struct in_addr
) * (*return_count
)))) {
913 int nodupes_count
= 0;
915 /* Iterate over return_iplist looking for duplicates */
917 for (i
= 0; i
< *return_count
; i
++) {
918 BOOL is_dupe
= False
;
921 for (j
= i
+ 1; j
< *return_count
; j
++) {
922 if (ip_equal((*return_iplist
)[i
],
923 (*return_iplist
)[j
])) {
931 /* This one not a duplicate */
933 nodupes_iplist
[nodupes_count
] = (*return_iplist
)[i
];
938 /* Switcheroo with original list */
940 free(*return_iplist
);
942 *return_iplist
= nodupes_iplist
;
943 *return_count
= nodupes_count
;
946 /* Display some debugging info */
948 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
951 for (i
= 0; i
< *return_count
; i
++)
952 DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist
)[i
])));
959 /********************************************************
960 Internal interface to resolve a name into one IP address.
961 Use this function if the string is either an IP address, DNS
962 or host name or NetBIOS name. This uses the name switch in the
963 smb.conf to determine the order of name resolution.
964 *********************************************************/
966 BOOL
resolve_name(const char *name
, struct in_addr
*return_ip
, int name_type
)
968 struct in_addr
*ip_list
= NULL
;
971 if (is_ipaddress(name
)) {
972 *return_ip
= *interpret_addr2(name
);
976 if(internal_resolve_name(name
, name_type
, &ip_list
, &count
)) {
978 /* only return valid addresses for TCP connections */
979 for (i
=0; i
<count
; i
++) {
980 char *ip_str
= inet_ntoa(ip_list
[i
]);
982 strcmp(ip_str
, "255.255.255.255") != 0 &&
983 strcmp(ip_str
, "0.0.0.0") != 0) {
984 *return_ip
= ip_list
[i
];
994 /**************************************************************************
995 Resolve a name to a list of addresses
996 **************************************************************************/
997 BOOL
resolve_name_2(const char *name
, struct in_addr
**return_ip
, int *count
, int name_type
)
1000 return internal_resolve_name(name
, name_type
, return_ip
, count
);
1004 /********************************************************
1005 resolve a name of format \\server_name or \\ipaddress
1006 into a name. also, cut the \\ from the front for us.
1007 *********************************************************/
1009 BOOL
resolve_srv_name(const char* srv_name
, fstring dest_host
,
1013 const char *sv_name
= srv_name
;
1015 DEBUG(10,("resolve_srv_name: %s\n", srv_name
));
1017 if (srv_name
== NULL
|| strequal("\\\\.", srv_name
))
1019 extern pstring global_myname
;
1020 fstrcpy(dest_host
, global_myname
);
1021 ip
= interpret_addr2("127.0.0.1");
1025 if (strnequal("\\\\", srv_name
, 2))
1027 sv_name
= &srv_name
[2];
1030 fstrcpy(dest_host
, sv_name
);
1031 /* treat the '*' name specially - it is a magic name for the PDC */
1032 if (strcmp(dest_host
,"*") == 0) {
1033 extern pstring global_myname
;
1034 ret
= resolve_name(lp_workgroup(), ip
, 0x1B);
1035 lookup_dc_name(global_myname
, lp_workgroup(), ip
, dest_host
);
1037 ret
= resolve_name(dest_host
, ip
, 0x20);
1040 if (is_ipaddress(dest_host
))
1042 fstrcpy(dest_host
, "*SMBSERVER");
1049 /********************************************************
1050 Find the IP address of the master browser or DMB for a workgroup.
1051 *********************************************************/
1053 BOOL
find_master_ip(char *group
, struct in_addr
*master_ip
)
1055 struct in_addr
*ip_list
= NULL
;
1058 if (internal_resolve_name(group
, 0x1D, &ip_list
, &count
)) {
1059 *master_ip
= ip_list
[0];
1063 if(internal_resolve_name(group
, 0x1B, &ip_list
, &count
)) {
1064 *master_ip
= ip_list
[0];
1073 /********************************************************
1074 Lookup a DC name given a Domain name and IP address.
1075 *********************************************************/
1077 BOOL
lookup_dc_name(const char *srcname
, const char *domain
,
1078 struct in_addr
*dc_ip
, char *ret_name
)
1080 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1086 * Due to the fact win WinNT *sucks* we must do a node status
1087 * query here... JRA.
1092 ret
= name_status_find(domain
, 0x1c, 0x20, *dc_ip
, dc_name
);
1094 if(ret
&& *dc_name
) {
1095 fstrcpy(ret_name
, dc_name
);
1101 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1103 JRA
- This code is broken with BDC rollover
- we need to
do a full
1104 NT GETDC call
, UNICODE
, NT domain SID
and uncle tom cobbley
and all
...
1107 int retry_time
= 2000;
1108 struct timeval tval
;
1109 struct packet_struct p
;
1110 struct dgram_packet
*dgram
= &p
.packet
.dgram
;
1114 struct sockaddr_in sock_name
;
1115 int sock_len
= sizeof(sock_name
);
1116 const char *mailslot
= NET_LOGON_MAILSLOT
;
1117 char *mailslot_name
;
1120 int dgm_id
= generate_trn_id();
1121 int sock
= open_socket_in(SOCK_DGRAM
, 0, 3, interpret_addr(lp_socket_address()), True
);
1126 /* Find out the transient UDP port we have been allocated. */
1127 if(getsockname(sock
, (struct sockaddr
*)&sock_name
, &sock_len
)<0) {
1128 DEBUG(0,("lookup_dc_name: Failed to get local UDP port. Error was %s\n",
1135 * Create the request data.
1138 memset(buffer
,'\0',sizeof(buffer
));
1140 SSVAL(bufp
,0,QUERYFORPDC
);
1142 fstrcpy(bufp
,srcname
);
1143 bufp
+= (strlen(bufp
) + 1);
1144 slprintf(bufp
, sizeof(fstring
)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id
);
1145 mailslot_name
= bufp
;
1146 bufp
+= (strlen(bufp
) + 1);
1147 bufp
= ALIGN2(bufp
, buffer
);
1148 bufp
+= dos_PutUniCode(bufp
, srcname
, sizeof(buffer
) - (bufp
- buffer
) - 1, True
);
1150 SSVAL(bufp
,4,0xFFFF);
1151 SSVAL(bufp
,6,0xFFFF);
1153 len
= PTR_DIFF(bufp
,buffer
);
1155 memset((char *)&p
,'\0',sizeof(p
));
1157 /* DIRECT GROUP or UNIQUE datagram. */
1158 dgram
->header
.msg_type
= 0x10;
1159 dgram
->header
.flags
.node_type
= M_NODE
;
1160 dgram
->header
.flags
.first
= True
;
1161 dgram
->header
.flags
.more
= False
;
1162 dgram
->header
.dgm_id
= dgm_id
;
1163 dgram
->header
.source_ip
= *iface_ip(*pdc_ip
);
1164 dgram
->header
.source_port
= ntohs(sock_name
.sin_port
);
1165 dgram
->header
.dgm_length
= 0; /* Let build_dgram() handle this. */
1166 dgram
->header
.packet_offset
= 0;
1168 make_nmb_name(&dgram
->source_name
,srcname
,0);
1169 make_nmb_name(&dgram
->dest_name
,domain
,0x1C);
1171 ptr
= &dgram
->data
[0];
1173 /* Setup the smb part. */
1174 ptr
-= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1176 set_message(ptr
,17,17 + len
,True
);
1179 CVAL(ptr
,smb_com
) = SMBtrans
;
1180 SSVAL(ptr
,smb_vwv1
,len
);
1181 SSVAL(ptr
,smb_vwv11
,len
);
1182 SSVAL(ptr
,smb_vwv12
,70 + strlen(mailslot
));
1183 SSVAL(ptr
,smb_vwv13
,3);
1184 SSVAL(ptr
,smb_vwv14
,1);
1185 SSVAL(ptr
,smb_vwv15
,1);
1186 SSVAL(ptr
,smb_vwv16
,2);
1188 pstrcpy(p2
,mailslot
);
1189 p2
= skip_string(p2
,1);
1191 memcpy(p2
,buffer
,len
);
1194 dgram
->datasize
= PTR_DIFF(p2
,ptr
+4); /* +4 for tcp length. */
1197 p
.port
= DGRAM_PORT
;
1199 p
.timestamp
= time(NULL
);
1200 p
.packet_type
= DGRAM_PACKET
;
1202 GetTimeOfDay(&tval
);
1204 if (!send_packet(&p
)) {
1205 DEBUG(0,("lookup_dc_name: send_packet failed.\n"));
1213 struct timeval tval2
;
1214 struct packet_struct
*p_ret
;
1216 GetTimeOfDay(&tval2
);
1217 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
1220 if (!send_packet(&p
)) {
1221 DEBUG(0,("lookup_dc_name: send_packet failed.\n"));
1225 GetTimeOfDay(&tval
);
1229 if ((p_ret
= receive_dgram_packet(sock
,90,mailslot_name
))) {
1230 struct dgram_packet
*dgram2
= &p_ret
->packet
.dgram
;
1234 buf
= &dgram2
->data
[0];
1237 if (CVAL(buf
,smb_com
) != SMBtrans
) {
1238 DEBUG(0,("lookup_dc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1239 CVAL(buf
,smb_com
), (unsigned int)SMBtrans
));
1244 len
= SVAL(buf
,smb_vwv11
);
1245 buf2
= smb_base(buf
) + SVAL(buf
,smb_vwv12
);
1248 DEBUG(0,("lookup_dc_name: datagram len < 0 (%d)\n", len
));
1253 DEBUG(4,("lookup_dc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1254 nmb_namestr(&dgram2
->source_name
),nmb_namestr(&dgram2
->dest_name
),
1255 inet_ntoa(p_ret
->ip
), smb_buf(buf
),SVAL(buf2
,0),len
));
1257 if(SVAL(buf2
,0) != QUERYFORPDC_R
) {
1258 DEBUG(0,("lookup_dc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1259 (unsigned int)SVAL(buf
,0), (unsigned int)QUERYFORPDC_R
));
1265 /* Note this is safe as it is a bounded strcpy. */
1266 fstrcpy(ret_name
, buf2
);
1267 ret_name
[sizeof(fstring
)-1] = '\0';
1276 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1280 /********************************************************
1281 Get the IP address list of the PDC/BDC's of a Domain.
1282 *********************************************************/
1284 BOOL
get_dc_list(BOOL pdc_only
, const char *group
, struct in_addr
**ip_list
, int *count
)
1286 int name_type
= pdc_only
? 0x1B : 0x1C;
1289 * If it's our domain then
1290 * use the 'password server' parameter.
1293 if (strequal(group
, lp_workgroup())) {
1295 char *pserver
= lp_passwordserver();
1297 int num_addresses
= 0;
1298 struct in_addr
*return_iplist
= NULL
;
1301 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1304 while (next_token(&p
,name
,LIST_SEP
,sizeof(name
))) {
1305 if (strequal(name
, "*")) {
1307 * Use 1C followed by 1B. This shouldn't work but with
1308 * broken WINS servers it might. JRA.
1310 if (!pdc_only
&& internal_resolve_name(group
, 0x1C, ip_list
, count
))
1312 return internal_resolve_name(group
, 0x1B, ip_list
, count
);
1316 if (num_addresses
== 0)
1317 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1319 return_iplist
= (struct in_addr
*)malloc(num_addresses
* sizeof(struct in_addr
));
1320 if(return_iplist
== NULL
) {
1321 DEBUG(3,("get_dc_list: malloc fail !\n"));
1326 while (next_token(&p
,name
,LIST_SEP
,sizeof(name
))) {
1327 struct in_addr
*more_ip
, *tmp
;
1329 if (resolve_name_2( name
, &more_ip
, &count_more
, 0x20) == False
)
1331 tmp
= (struct in_addr
*)realloc(return_iplist
,(num_addresses
+ count_more
) * sizeof(struct in_addr
));
1332 if (return_iplist
== NULL
) {
1333 DEBUG(3, ("realloc failed with %d addresses\n", num_addresses
+ count_more
));
1334 SAFE_FREE(return_iplist
);
1338 return_iplist
= tmp
;
1339 memmove(&return_iplist
[(*count
)], more_ip
, count_more
* sizeof(struct in_addr
));
1340 SAFE_FREE(more_ip
); /* Done with this ... */
1341 *count
+= count_more
;
1342 num_addresses
+= count_more
- 1;
1344 *ip_list
= return_iplist
;
1345 return (*count
!= 0);
1347 return internal_resolve_name(group
, name_type
, ip_list
, count
);
1350 /********************************************************
1351 Get the IP address list of the Local Master Browsers
1352 ********************************************************/
1354 BOOL
get_lmb_list(struct in_addr
**ip_list
, int *count
)
1356 return internal_resolve_name( MSBROWSE
, 0x1, ip_list
, count
);