2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* nmbd.c sets this to True. */
25 BOOL global_in_nmbd = False;
27 /****************************************************************************
28 generate a random trn_id
29 ****************************************************************************/
30 static int generate_trn_id(void)
35 sys_srandom(sys_getpid());
38 trn_id = sys_random();
40 return trn_id % (unsigned)0x7FFF;
44 /****************************************************************************
45 parse a node status response into an array of structures
46 ****************************************************************************/
47 static struct node_status *parse_node_status(char *p, int *num_names)
49 struct node_status *ret;
52 *num_names = CVAL(p,0);
54 if (*num_names == 0) return NULL;
56 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
57 if (!ret) return NULL;
60 for (i=0;i< *num_names;i++) {
61 StrnCpy(ret[i].name,p,15);
62 trim_string(ret[i].name,NULL," ");
63 ret[i].type = CVAL(p,15);
66 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
67 ret[i].type, ret[i].flags));
73 /****************************************************************************
74 do a NBT node status query on an open socket and return an array of
75 structures holding the returned names or NULL if the query failed
76 **************************************************************************/
77 struct node_status *node_status_query(int fd,struct nmb_name *name,
78 struct in_addr to_ip, int *num_names)
82 int retry_time = 2000;
84 struct packet_struct p;
85 struct packet_struct *p2;
86 struct nmb_packet *nmb = &p.packet.nmb;
87 struct node_status *ret;
91 nmb->header.name_trn_id = generate_trn_id();
92 nmb->header.opcode = 0;
93 nmb->header.response = False;
94 nmb->header.nm_flags.bcast = False;
95 nmb->header.nm_flags.recursion_available = False;
96 nmb->header.nm_flags.recursion_desired = False;
97 nmb->header.nm_flags.trunc = False;
98 nmb->header.nm_flags.authoritative = False;
99 nmb->header.rcode = 0;
100 nmb->header.qdcount = 1;
101 nmb->header.ancount = 0;
102 nmb->header.nscount = 0;
103 nmb->header.arcount = 0;
104 nmb->question.question_name = *name;
105 nmb->question.question_type = 0x21;
106 nmb->question.question_class = 0x1;
111 p.timestamp = time(NULL);
112 p.packet_type = NMB_PACKET;
116 if (!send_packet(&p))
122 struct timeval tval2;
123 GetTimeOfDay(&tval2);
124 if (TvalDiff(&tval,&tval2) > retry_time) {
127 if (!found && !send_packet(&p))
133 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
134 struct nmb_packet *nmb2 = &p2->packet.nmb;
135 debug_nmb_packet(p2);
137 if (nmb2->header.opcode != 0 ||
138 nmb2->header.nm_flags.bcast ||
139 nmb2->header.rcode ||
140 !nmb2->header.ancount ||
141 nmb2->answers->rr_type != 0x21) {
142 /* XXXX what do we do with this? could be a
143 redirect, but we'll discard it for the
149 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
159 /****************************************************************************
160 find the first type XX name in a node status reply - used for finding
161 a servers name given its IP
162 return the matched name in *name
163 **************************************************************************/
165 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
167 struct node_status *status = NULL;
168 struct nmb_name nname;
173 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
174 q_type, inet_ntoa(to_ip)));
176 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
180 /* W2K PDC's seem not to respond to '*'#0. JRA */
181 make_nmb_name(&nname, q_name, q_type);
182 status = node_status_query(sock, &nname, to_ip, &count);
187 for (i=0;i<count;i++) {
188 if (status[i].type == type)
194 pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
200 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
203 DEBUGADD(10, (", ip address is %s", inet_ntoa(to_ip)));
210 /****************************************************************************
211 Do a NetBIOS name registation to try to claim a name ...
212 ***************************************************************************/
213 BOOL name_register(int fd, const char *name, int name_type,
214 struct in_addr name_ip, int opcode,
216 struct in_addr to_ip, int *count)
220 struct packet_struct p;
221 struct packet_struct *p2;
222 struct nmb_packet *nmb = &p.packet.nmb;
223 struct in_addr register_ip;
225 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
227 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
229 memset((char *)&p, '\0', sizeof(p));
233 nmb->header.name_trn_id = generate_trn_id();
234 nmb->header.opcode = opcode;
235 nmb->header.response = False;
236 nmb->header.nm_flags.bcast = False;
237 nmb->header.nm_flags.recursion_available = False;
238 nmb->header.nm_flags.recursion_desired = True; /* ? */
239 nmb->header.nm_flags.trunc = False;
240 nmb->header.nm_flags.authoritative = True;
242 nmb->header.qdcount = 1;
243 nmb->header.ancount = 0;
244 nmb->header.nscount = 0;
245 nmb->header.arcount = 1;
247 make_nmb_name(&nmb->question.question_name, name, name_type);
249 nmb->question.question_type = 0x20;
250 nmb->question.question_class = 0x1;
252 /* Now, create the additional stuff for a registration request */
254 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
256 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
261 memset((char *)nmb->additional, '\0', sizeof(struct res_rec));
263 nmb->additional->rr_name = nmb->question.question_name;
264 nmb->additional->rr_type = RR_TYPE_NB;
265 nmb->additional->rr_class = RR_CLASS_IN;
267 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
268 if (nmb->header.nm_flags.bcast)
269 nmb->additional->ttl = PERMANENT_TTL;
271 nmb->additional->ttl = lp_max_ttl();
273 nmb->additional->rdlength = 6;
275 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
277 /* Set the address for the name we are registering. */
278 putip(&nmb->additional->rdata[2], ®ister_ip);
283 p.timestamp = time(NULL);
284 p.packet_type = NMB_PACKET;
288 if (!send_packet(&p))
293 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
294 debug_nmb_packet(p2);
295 SAFE_FREE(p2); /* No memory leaks ... */
301 /****************************************************************************
302 Do a netbios name query to find someones IP.
303 Returns an array of IP addresses or NULL if none.
304 *count will be set to the number of addresses returned.
305 ****************************************************************************/
306 struct in_addr *name_query(int fd,const char *name,int name_type,
307 BOOL bcast,BOOL recurse,
308 struct in_addr to_ip, int *count, int *flags)
312 int retry_time = bcast?250:2000;
314 struct packet_struct p;
315 struct packet_struct *p2;
316 struct nmb_packet *nmb = &p.packet.nmb;
317 struct in_addr *ip_list = NULL;
319 memset((char *)&p,'\0',sizeof(p));
323 nmb->header.name_trn_id = generate_trn_id();
324 nmb->header.opcode = 0;
325 nmb->header.response = False;
326 nmb->header.nm_flags.bcast = bcast;
327 nmb->header.nm_flags.recursion_available = False;
328 nmb->header.nm_flags.recursion_desired = recurse;
329 nmb->header.nm_flags.trunc = False;
330 nmb->header.nm_flags.authoritative = False;
331 nmb->header.rcode = 0;
332 nmb->header.qdcount = 1;
333 nmb->header.ancount = 0;
334 nmb->header.nscount = 0;
335 nmb->header.arcount = 0;
337 make_nmb_name(&nmb->question.question_name,name,name_type);
339 nmb->question.question_type = 0x20;
340 nmb->question.question_class = 0x1;
345 p.timestamp = time(NULL);
346 p.packet_type = NMB_PACKET;
350 if (!send_packet(&p))
356 struct timeval tval2;
357 struct in_addr *tmp_ip_list;
359 GetTimeOfDay(&tval2);
360 if (TvalDiff(&tval,&tval2) > retry_time) {
363 if (!found && !send_packet(&p))
369 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
370 struct nmb_packet *nmb2 = &p2->packet.nmb;
371 debug_nmb_packet(p2);
373 /* If we get a Negative Name Query Response from a WINS
374 * server, we should report it and give up.
376 if( 0 == nmb2->header.opcode /* A query response */
377 && !(bcast) /* from a WINS server */
378 && nmb2->header.rcode /* Error returned */
381 if( DEBUGLVL( 3 ) ) {
382 /* Only executed if DEBUGLEVEL >= 3 */
383 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
384 switch( nmb2->header.rcode ) {
386 dbgtext( "Request was invalidly formatted.\n" );
389 dbgtext( "Problem with NBNS, cannot process name.\n");
392 dbgtext( "The name requested does not exist.\n" );
395 dbgtext( "Unsupported request error.\n" );
398 dbgtext( "Query refused error.\n" );
401 dbgtext( "Unrecognized error code.\n" );
409 if (nmb2->header.opcode != 0 ||
410 nmb2->header.nm_flags.bcast ||
411 nmb2->header.rcode ||
412 !nmb2->header.ancount) {
414 * XXXX what do we do with this? Could be a
415 * redirect, but we'll discard it for the
422 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
423 * ( (*count) + nmb2->answers->rdlength/6 ) );
426 DEBUG(0,("name_query: Realloc failed.\n"));
430 ip_list = tmp_ip_list;
433 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
434 for (i=0;i<nmb2->answers->rdlength/6;i++) {
435 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
436 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
444 /* We add the flags back ... */
445 if (nmb2->header.response)
446 (*flags) |= NM_FLAGS_RS;
447 if (nmb2->header.nm_flags.authoritative)
448 (*flags) |= NM_FLAGS_AA;
449 if (nmb2->header.nm_flags.trunc)
450 (*flags) |= NM_FLAGS_TC;
451 if (nmb2->header.nm_flags.recursion_desired)
452 (*flags) |= NM_FLAGS_RD;
453 if (nmb2->header.nm_flags.recursion_available)
454 (*flags) |= NM_FLAGS_RA;
455 if (nmb2->header.nm_flags.bcast)
456 (*flags) |= NM_FLAGS_B;
459 * If we're doing a unicast lookup we only
460 * expect one reply. Don't wait the full 2
461 * seconds if we got one. JRA.
468 /* Reach here if we've timed out waiting for replies.. */
469 if( !bcast && !found ) {
470 /* Timed out wating for WINS server to respond. Mark it dead. */
471 wins_srv_died( to_ip );
477 /********************************************************
478 Start parsing the lmhosts file.
479 *********************************************************/
481 XFILE *startlmhosts(char *fname)
483 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
485 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
486 fname, strerror(errno)));
492 /********************************************************
493 Parse the next line in the lmhosts file.
494 *********************************************************/
496 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
500 while(!x_feof(fp) && !x_ferror(fp)) {
501 pstring ip,flags,extra;
507 if (!fgets_slash(line,sizeof(pstring),fp))
519 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
521 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
523 if (next_token(&ptr,flags,NULL, sizeof(flags)))
525 if (next_token(&ptr,extra,NULL, sizeof(extra)))
531 if (count > 0 && count < 2)
533 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
539 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
543 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
545 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
547 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
551 *ipaddr = *interpret_addr2(ip);
553 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
554 then only add that name type. */
555 if((ptr = strchr_m(name, '#')) != NULL)
560 *name_type = (int)strtol(ptr, &endptr, 16);
562 if(!*ptr || (endptr == ptr))
564 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
568 *(--ptr) = '\0'; /* Truncate at the '#' */
577 /********************************************************
578 Finish parsing the lmhosts file.
579 *********************************************************/
581 void endlmhosts(XFILE *fp)
586 BOOL name_register_wins(const char *name, int name_type)
588 int sock, i, return_count;
589 int num_interfaces = iface_count();
590 struct in_addr sendto_ip;
593 * Check if we have any interfaces, prevents a segfault later
596 if (num_interfaces <= 0)
597 return False; /* Should return some indication of the problem */
600 * Do a broadcast register ...
603 if (0 == wins_srv_count())
606 sendto_ip = wins_srv_ip();
610 dbgtext( "name_register_wins: Registering my name %s ", name );
611 dbgtext( "with WINS server %s.\n", inet_ntoa(sendto_ip));
614 sock = open_socket_in( SOCK_DGRAM, 0, 3,
615 interpret_addr("0.0.0.0"), True );
617 if (sock == -1) return False;
619 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
621 if (num_interfaces > 1) {
623 for (i = 0; i < num_interfaces; i++) {
625 if (!name_register(sock, name, name_type, *iface_n_ip(i),
626 NMB_NAME_MULTIHOMED_REG_OPCODE,
627 True, sendto_ip, &return_count)) {
639 if (!name_register(sock, name, name_type, *iface_n_ip(0),
641 True, sendto_ip, &return_count)) {
656 /********************************************************
657 Resolve via "bcast" method.
658 *********************************************************/
660 BOOL name_resolve_bcast(const char *name, int name_type,
661 struct in_addr **return_ip_list, int *return_count)
664 int num_interfaces = iface_count();
666 *return_ip_list = NULL;
670 * "bcast" means do a broadcast lookup on all the local interfaces.
673 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
675 sock = open_socket_in( SOCK_DGRAM, 0, 3,
676 interpret_addr(lp_socket_address()), True );
678 if (sock == -1) return False;
680 set_socket_options(sock,"SO_BROADCAST");
682 * Lookup the name on all the interfaces, return on
683 * the first successful match.
685 for( i = num_interfaces-1; i >= 0; i--) {
686 struct in_addr sendto_ip;
688 /* Done this way to fix compiler error on IRIX 5.x */
689 sendto_ip = *iface_n_bcast(i);
690 *return_ip_list = name_query(sock, name, name_type, True,
691 True, sendto_ip, return_count, &flags);
692 if(*return_ip_list != NULL) {
702 /********************************************************
703 Resolve via "wins" method.
704 *********************************************************/
706 static BOOL resolve_wins(const char *name, int name_type,
707 struct in_addr **return_iplist, int *return_count)
710 struct in_addr wins_ip;
713 *return_iplist = NULL;
717 * "wins" means do a unicast lookup to the WINS server.
718 * Ignore if there is no WINS server specified or if the
719 * WINS server is one of our interfaces (if we're being
720 * called from within nmbd - we can't do this call as we
724 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
726 if (lp_wins_support()) {
728 * We're providing WINS support. Call ourselves so
729 * long as we're not nmbd.
731 extern struct in_addr loopback_ip;
732 wins_ip = loopback_ip;
734 } else if( wins_srv_count() < 1 ) {
735 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
738 wins_ip = wins_srv_ip();
739 wins_ismyip = ismyip(wins_ip);
742 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
743 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
745 sock = open_socket_in( SOCK_DGRAM, 0, 3,
746 interpret_addr(lp_socket_address()),
749 *return_iplist = name_query( sock, name,
752 return_count, &flags);
753 if(*return_iplist != NULL) {
764 /********************************************************
765 Resolve via "lmhosts" method.
766 *********************************************************/
768 static BOOL resolve_lmhosts(const char *name, int name_type,
769 struct in_addr **return_iplist, int *return_count)
772 * "lmhosts" means parse the local lmhosts file.
778 struct in_addr return_ip;
780 *return_iplist = NULL;
783 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
785 fp = startlmhosts(dyn_LMHOSTSFILE);
787 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
788 if (strequal(name, lmhost_name) &&
789 ((name_type2 == -1) || (name_type == name_type2))
792 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
793 if(*return_iplist == NULL) {
794 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
797 **return_iplist = return_ip;
808 /********************************************************
809 Resolve via "hosts" method.
810 *********************************************************/
812 static BOOL resolve_hosts(const char *name,
813 struct in_addr **return_iplist, int *return_count)
816 * "host" means do a localhost, or dns lookup.
820 *return_iplist = NULL;
823 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
825 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
826 struct in_addr return_ip;
827 putip((char *)&return_ip,(char *)hp->h_addr);
828 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
829 if(*return_iplist == NULL) {
830 DEBUG(3,("resolve_hosts: malloc fail !\n"));
833 **return_iplist = return_ip;
840 /********************************************************
841 Internal interface to resolve a name into an IP address.
842 Use this function if the string is either an IP address, DNS
843 or host name or NetBIOS name. This uses the name switch in the
844 smb.conf to determine the order of name resolution.
845 *********************************************************/
847 static BOOL internal_resolve_name(const char *name, int name_type,
848 struct in_addr **return_iplist, int *return_count)
850 pstring name_resolve_list;
853 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
854 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
855 BOOL is_address = is_ipaddress(name);
857 struct in_addr *nodupes_iplist;
860 *return_iplist = NULL;
863 DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
865 if (allzeros || allones || is_address) {
866 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
867 if(*return_iplist == NULL) {
868 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
872 /* if it's in the form of an IP address then get the lib to interpret it */
873 (*return_iplist)->s_addr = inet_addr(name);
875 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
881 pstrcpy(name_resolve_list, lp_name_resolve_order());
882 ptr = name_resolve_list;
886 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
887 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
888 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
892 } else if(strequal( tok, "lmhosts")) {
893 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
897 } else if(strequal( tok, "wins")) {
898 /* don't resolve 1D via WINS */
899 if (name_type != 0x1D &&
900 resolve_wins(name, name_type, return_iplist, return_count)) {
904 } else if(strequal( tok, "bcast")) {
905 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
910 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
914 /* All of the resolve_* functions above have returned false. */
916 SAFE_FREE(*return_iplist);
923 /* Remove duplicate entries. Some queries, notably #1c (domain
924 controllers) return the PDC in iplist[0] and then all domain
925 controllers including the PDC in iplist[1..n]. Iterating over
926 the iplist when the PDC is down will cause two sets of timeouts. */
928 if (*return_count && (nodupes_iplist = (struct in_addr *)
929 malloc(sizeof(struct in_addr) * (*return_count)))) {
930 int nodupes_count = 0;
932 /* Iterate over return_iplist looking for duplicates */
934 for (i = 0; i < *return_count; i++) {
935 BOOL is_dupe = False;
938 for (j = i + 1; j < *return_count; j++) {
939 if (ip_equal((*return_iplist)[i],
940 (*return_iplist)[j])) {
948 /* This one not a duplicate */
950 nodupes_iplist[nodupes_count] = (*return_iplist)[i];
955 /* Switcheroo with original list */
957 free(*return_iplist);
959 *return_iplist = nodupes_iplist;
960 *return_count = nodupes_count;
963 /* Display some debugging info */
965 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
968 for (i = 0; i < *return_count; i++)
969 DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
976 /********************************************************
977 Internal interface to resolve a name into one IP address.
978 Use this function if the string is either an IP address, DNS
979 or host name or NetBIOS name. This uses the name switch in the
980 smb.conf to determine the order of name resolution.
981 *********************************************************/
983 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
985 struct in_addr *ip_list = NULL;
988 if (is_ipaddress(name)) {
989 *return_ip = *interpret_addr2(name);
993 if (internal_resolve_name(name, name_type, &ip_list, &count)) {
995 /* only return valid addresses for TCP connections */
996 for (i=0; i<count; i++) {
997 char *ip_str = inet_ntoa(ip_list[i]);
999 strcmp(ip_str, "255.255.255.255") != 0 &&
1000 strcmp(ip_str, "0.0.0.0") != 0) {
1001 *return_ip = ip_list[i];
1011 /********************************************************
1012 Find the IP address of the master browser or DMB for a workgroup.
1013 *********************************************************/
1015 BOOL find_master_ip(char *group, struct in_addr *master_ip)
1017 struct in_addr *ip_list = NULL;
1020 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
1021 *master_ip = ip_list[0];
1025 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
1026 *master_ip = ip_list[0];
1035 /********************************************************
1036 Lookup a DC name given a Domain name and IP address.
1037 *********************************************************/
1039 BOOL lookup_dc_name(const char *srcname, const char *domain,
1040 struct in_addr *dc_ip, char *ret_name)
1042 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1048 * Due to the fact win WinNT *sucks* we must do a node status
1049 * query here... JRA.
1054 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1056 if(ret && *dc_name) {
1057 fstrcpy(ret_name, dc_name);
1063 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1065 JRA - This code is broken with BDC rollover - we need to do a full
1066 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1069 int retry_time = 2000;
1070 struct timeval tval;
1071 struct packet_struct p;
1072 struct dgram_packet *dgram = &p.packet.dgram;
1076 struct sockaddr_in sock_name;
1077 int sock_len = sizeof(sock_name);
1078 const char *mailslot = NET_LOGON_MAILSLOT;
1079 char *mailslot_name;
1082 int dgm_id = generate_trn_id();
1083 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1088 /* Find out the transient UDP port we have been allocated. */
1089 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1090 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1097 * Create the request data.
1100 memset(buffer,'\0',sizeof(buffer));
1102 SSVAL(bufp,0,QUERYFORPDC);
1104 fstrcpy(bufp,srcname);
1105 bufp += (strlen(bufp) + 1);
1106 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1107 mailslot_name = bufp;
1108 bufp += (strlen(bufp) + 1);
1109 bufp = ALIGN2(bufp, buffer);
1110 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1113 SSVAL(bufp,4,0xFFFF);
1114 SSVAL(bufp,6,0xFFFF);
1116 len = PTR_DIFF(bufp,buffer);
1118 memset((char *)&p,'\0',sizeof(p));
1120 /* DIRECT GROUP or UNIQUE datagram. */
1121 dgram->header.msg_type = 0x10;
1122 dgram->header.flags.node_type = M_NODE;
1123 dgram->header.flags.first = True;
1124 dgram->header.flags.more = False;
1125 dgram->header.dgm_id = dgm_id;
1126 dgram->header.source_ip = *iface_ip(*pdc_ip);
1127 dgram->header.source_port = ntohs(sock_name.sin_port);
1128 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1129 dgram->header.packet_offset = 0;
1131 make_nmb_name(&dgram->source_name,srcname,0);
1132 make_nmb_name(&dgram->dest_name,domain,0x1C);
1134 ptr = &dgram->data[0];
1136 /* Setup the smb part. */
1137 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1139 set_message(ptr,17,17 + len,True);
1142 CVAL(ptr,smb_com) = SMBtrans;
1143 SSVAL(ptr,smb_vwv1,len);
1144 SSVAL(ptr,smb_vwv11,len);
1145 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1146 SSVAL(ptr,smb_vwv13,3);
1147 SSVAL(ptr,smb_vwv14,1);
1148 SSVAL(ptr,smb_vwv15,1);
1149 SSVAL(ptr,smb_vwv16,2);
1151 pstrcpy(p2,mailslot);
1152 p2 = skip_string(p2,1);
1154 memcpy(p2,buffer,len);
1157 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1160 p.port = DGRAM_PORT;
1162 p.timestamp = time(NULL);
1163 p.packet_type = DGRAM_PACKET;
1165 GetTimeOfDay(&tval);
1167 if (!send_packet(&p)) {
1168 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1176 struct timeval tval2;
1177 struct packet_struct *p_ret;
1179 GetTimeOfDay(&tval2);
1180 if (TvalDiff(&tval,&tval2) > retry_time) {
1183 if (!send_packet(&p)) {
1184 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1188 GetTimeOfDay(&tval);
1192 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1193 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1197 buf = &dgram2->data[0];
1200 if (CVAL(buf,smb_com) != SMBtrans) {
1201 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1202 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1207 len = SVAL(buf,smb_vwv11);
1208 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1211 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1216 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1217 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1218 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1220 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1221 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1222 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1228 /* Note this is safe as it is a bounded strcpy. */
1229 fstrcpy(ret_name, buf2);
1230 ret_name[sizeof(fstring)-1] = '\0';
1239 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1242 /********************************************************
1243 Get the IP address list of the Local Master Browsers
1244 ********************************************************/
1246 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1248 return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1251 /********************************************************
1252 Get the IP address list of the PDC/BDC's of a Domain.
1253 *********************************************************/
1255 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1257 int name_type = pdc_only ? 0x1B : 0x1C;
1260 * If it's our domain then
1261 * use the 'password server' parameter.
1264 if (strequal(group, lp_workgroup())) {
1266 char *pserver = lp_passwordserver();
1268 int num_adresses = 0;
1269 struct in_addr *return_iplist = NULL;
1272 return internal_resolve_name(group, name_type, ip_list, count);
1275 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1276 if (strequal(name, "*"))
1277 return internal_resolve_name(group, name_type, ip_list, count);
1280 if (num_adresses == 0)
1281 return internal_resolve_name(group, name_type, ip_list, count);
1283 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1284 if(return_iplist == NULL) {
1285 DEBUG(3,("get_dc_list: malloc fail !\n"));
1290 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1291 struct in_addr name_ip;
1292 if (resolve_name( name, &name_ip, 0x20) == False)
1294 return_iplist[(*count)++] = name_ip;
1296 *ip_list = return_iplist;
1297 return (*count != 0);
1299 return internal_resolve_name(group, name_type, ip_list, count);