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())
608 dbgtext( "name_register_wins: Registering my name %s ", name );
609 dbgtext( "with WINS server %s.\n", wins_srv_name() );
612 sock = open_socket_in( SOCK_DGRAM, 0, 3,
613 interpret_addr("0.0.0.0"), True );
615 if (sock == -1) return False;
617 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
619 sendto_ip = wins_srv_ip();
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];
1012 /********************************************************
1013 resolve a name of format \\server_name or \\ipaddress
1014 into a name. also, cut the \\ from the front for us.
1015 *********************************************************/
1017 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
1021 const char *sv_name = srv_name;
1023 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
1025 if (srv_name == NULL || strequal("\\\\.", srv_name))
1027 extern pstring global_myname;
1028 fstrcpy(dest_host, global_myname);
1029 ip = interpret_addr2("127.0.0.1");
1033 if (strnequal("\\\\", srv_name, 2))
1035 sv_name = &srv_name[2];
1038 fstrcpy(dest_host, sv_name);
1039 /* treat the '*' name specially - it is a magic name for the PDC */
1040 if (strcmp(dest_host,"*") == 0) {
1041 extern pstring global_myname;
1042 ret = resolve_name(lp_workgroup(), ip, 0x1B);
1043 lookup_dc_name(global_myname, lp_workgroup(), ip, dest_host);
1045 ret = resolve_name(dest_host, ip, 0x20);
1048 if (is_ipaddress(dest_host))
1050 fstrcpy(dest_host, "*SMBSERVER");
1057 /********************************************************
1058 Find the IP address of the master browser or DMB for a workgroup.
1059 *********************************************************/
1061 BOOL find_master_ip(char *group, struct in_addr *master_ip)
1063 struct in_addr *ip_list = NULL;
1066 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
1067 *master_ip = ip_list[0];
1071 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
1072 *master_ip = ip_list[0];
1081 /********************************************************
1082 Lookup a DC name given a Domain name and IP address.
1083 *********************************************************/
1085 BOOL lookup_dc_name(const char *srcname, const char *domain,
1086 struct in_addr *dc_ip, char *ret_name)
1088 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1094 * Due to the fact win WinNT *sucks* we must do a node status
1095 * query here... JRA.
1100 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1102 if(ret && *dc_name) {
1103 fstrcpy(ret_name, dc_name);
1109 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1111 JRA - This code is broken with BDC rollover - we need to do a full
1112 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1115 int retry_time = 2000;
1116 struct timeval tval;
1117 struct packet_struct p;
1118 struct dgram_packet *dgram = &p.packet.dgram;
1122 struct sockaddr_in sock_name;
1123 int sock_len = sizeof(sock_name);
1124 const char *mailslot = NET_LOGON_MAILSLOT;
1125 char *mailslot_name;
1128 int dgm_id = generate_trn_id();
1129 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1134 /* Find out the transient UDP port we have been allocated. */
1135 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1136 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1143 * Create the request data.
1146 memset(buffer,'\0',sizeof(buffer));
1148 SSVAL(bufp,0,QUERYFORPDC);
1150 fstrcpy(bufp,srcname);
1151 bufp += (strlen(bufp) + 1);
1152 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1153 mailslot_name = bufp;
1154 bufp += (strlen(bufp) + 1);
1155 bufp = ALIGN2(bufp, buffer);
1156 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1159 SSVAL(bufp,4,0xFFFF);
1160 SSVAL(bufp,6,0xFFFF);
1162 len = PTR_DIFF(bufp,buffer);
1164 memset((char *)&p,'\0',sizeof(p));
1166 /* DIRECT GROUP or UNIQUE datagram. */
1167 dgram->header.msg_type = 0x10;
1168 dgram->header.flags.node_type = M_NODE;
1169 dgram->header.flags.first = True;
1170 dgram->header.flags.more = False;
1171 dgram->header.dgm_id = dgm_id;
1172 dgram->header.source_ip = *iface_ip(*pdc_ip);
1173 dgram->header.source_port = ntohs(sock_name.sin_port);
1174 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1175 dgram->header.packet_offset = 0;
1177 make_nmb_name(&dgram->source_name,srcname,0);
1178 make_nmb_name(&dgram->dest_name,domain,0x1C);
1180 ptr = &dgram->data[0];
1182 /* Setup the smb part. */
1183 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1185 set_message(ptr,17,17 + len,True);
1188 CVAL(ptr,smb_com) = SMBtrans;
1189 SSVAL(ptr,smb_vwv1,len);
1190 SSVAL(ptr,smb_vwv11,len);
1191 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1192 SSVAL(ptr,smb_vwv13,3);
1193 SSVAL(ptr,smb_vwv14,1);
1194 SSVAL(ptr,smb_vwv15,1);
1195 SSVAL(ptr,smb_vwv16,2);
1197 pstrcpy(p2,mailslot);
1198 p2 = skip_string(p2,1);
1200 memcpy(p2,buffer,len);
1203 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1206 p.port = DGRAM_PORT;
1208 p.timestamp = time(NULL);
1209 p.packet_type = DGRAM_PACKET;
1211 GetTimeOfDay(&tval);
1213 if (!send_packet(&p)) {
1214 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1222 struct timeval tval2;
1223 struct packet_struct *p_ret;
1225 GetTimeOfDay(&tval2);
1226 if (TvalDiff(&tval,&tval2) > retry_time) {
1229 if (!send_packet(&p)) {
1230 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1234 GetTimeOfDay(&tval);
1238 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1239 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1243 buf = &dgram2->data[0];
1246 if (CVAL(buf,smb_com) != SMBtrans) {
1247 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1248 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1253 len = SVAL(buf,smb_vwv11);
1254 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1257 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1262 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1263 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1264 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1266 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1267 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1268 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1274 /* Note this is safe as it is a bounded strcpy. */
1275 fstrcpy(ret_name, buf2);
1276 ret_name[sizeof(fstring)-1] = '\0';
1285 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1288 /********************************************************
1289 Get the IP address list of the Local Master Browsers
1290 ********************************************************/
1292 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1294 return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1297 /********************************************************
1298 Get the IP address list of the PDC/BDC's of a Domain.
1299 *********************************************************/
1301 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1303 int name_type = pdc_only ? 0x1B : 0x1C;
1306 * If it's our domain then
1307 * use the 'password server' parameter.
1310 if (strequal(group, lp_workgroup())) {
1312 char *pserver = lp_passwordserver();
1314 int num_adresses = 0;
1315 struct in_addr *return_iplist = NULL;
1318 return internal_resolve_name(group, name_type, ip_list, count);
1321 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1322 if (strequal(name, "*"))
1323 return internal_resolve_name(group, name_type, ip_list, count);
1326 if (num_adresses == 0)
1327 return internal_resolve_name(group, name_type, ip_list, count);
1329 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1330 if(return_iplist == NULL) {
1331 DEBUG(3,("get_dc_list: malloc fail !\n"));
1336 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1337 struct in_addr name_ip;
1338 if (resolve_name( name, &name_ip, 0x20) == False)
1340 return_iplist[(*count)++] = name_ip;
1342 *ip_list = return_iplist;
1343 return (*count != 0);
1345 return internal_resolve_name(group, name_type, ip_list, count);