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 *timed_out is set if we failed by timing out
306 ****************************************************************************/
307 struct in_addr *name_query(int fd,const char *name,int name_type,
308 BOOL bcast,BOOL recurse,
309 struct in_addr to_ip, int *count, int *flags,
314 int retry_time = bcast?250:2000;
316 struct packet_struct p;
317 struct packet_struct *p2;
318 struct nmb_packet *nmb = &p.packet.nmb;
319 struct in_addr *ip_list = NULL;
325 memset((char *)&p,'\0',sizeof(p));
329 nmb->header.name_trn_id = generate_trn_id();
330 nmb->header.opcode = 0;
331 nmb->header.response = False;
332 nmb->header.nm_flags.bcast = bcast;
333 nmb->header.nm_flags.recursion_available = False;
334 nmb->header.nm_flags.recursion_desired = recurse;
335 nmb->header.nm_flags.trunc = False;
336 nmb->header.nm_flags.authoritative = False;
337 nmb->header.rcode = 0;
338 nmb->header.qdcount = 1;
339 nmb->header.ancount = 0;
340 nmb->header.nscount = 0;
341 nmb->header.arcount = 0;
343 make_nmb_name(&nmb->question.question_name,name,name_type);
345 nmb->question.question_type = 0x20;
346 nmb->question.question_class = 0x1;
351 p.timestamp = time(NULL);
352 p.packet_type = NMB_PACKET;
356 if (!send_packet(&p))
362 struct timeval tval2;
363 struct in_addr *tmp_ip_list;
365 GetTimeOfDay(&tval2);
366 if (TvalDiff(&tval,&tval2) > retry_time) {
369 if (!found && !send_packet(&p))
375 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
376 struct nmb_packet *nmb2 = &p2->packet.nmb;
377 debug_nmb_packet(p2);
379 /* If we get a Negative Name Query Response from a WINS
380 * server, we should report it and give up.
382 if( 0 == nmb2->header.opcode /* A query response */
383 && !(bcast) /* from a WINS server */
384 && nmb2->header.rcode /* Error returned */
387 if( DEBUGLVL( 3 ) ) {
388 /* Only executed if DEBUGLEVEL >= 3 */
389 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
390 switch( nmb2->header.rcode ) {
392 dbgtext( "Request was invalidly formatted.\n" );
395 dbgtext( "Problem with NBNS, cannot process name.\n");
398 dbgtext( "The name requested does not exist.\n" );
401 dbgtext( "Unsupported request error.\n" );
404 dbgtext( "Query refused error.\n" );
407 dbgtext( "Unrecognized error code.\n" );
415 if (nmb2->header.opcode != 0 ||
416 nmb2->header.nm_flags.bcast ||
417 nmb2->header.rcode ||
418 !nmb2->header.ancount) {
420 * XXXX what do we do with this? Could be a
421 * redirect, but we'll discard it for the
428 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
429 * ( (*count) + nmb2->answers->rdlength/6 ) );
432 DEBUG(0,("name_query: Realloc failed.\n"));
436 ip_list = tmp_ip_list;
439 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
440 for (i=0;i<nmb2->answers->rdlength/6;i++) {
441 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
442 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
450 /* We add the flags back ... */
451 if (nmb2->header.response)
452 (*flags) |= NM_FLAGS_RS;
453 if (nmb2->header.nm_flags.authoritative)
454 (*flags) |= NM_FLAGS_AA;
455 if (nmb2->header.nm_flags.trunc)
456 (*flags) |= NM_FLAGS_TC;
457 if (nmb2->header.nm_flags.recursion_desired)
458 (*flags) |= NM_FLAGS_RD;
459 if (nmb2->header.nm_flags.recursion_available)
460 (*flags) |= NM_FLAGS_RA;
461 if (nmb2->header.nm_flags.bcast)
462 (*flags) |= NM_FLAGS_B;
465 * If we're doing a unicast lookup we only
466 * expect one reply. Don't wait the full 2
467 * seconds if we got one. JRA.
481 /********************************************************
482 Start parsing the lmhosts file.
483 *********************************************************/
485 XFILE *startlmhosts(char *fname)
487 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
489 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
490 fname, strerror(errno)));
496 /********************************************************
497 Parse the next line in the lmhosts file.
498 *********************************************************/
500 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
504 while(!x_feof(fp) && !x_ferror(fp)) {
505 pstring ip,flags,extra;
511 if (!fgets_slash(line,sizeof(pstring),fp))
523 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
525 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
527 if (next_token(&ptr,flags,NULL, sizeof(flags)))
529 if (next_token(&ptr,extra,NULL, sizeof(extra)))
535 if (count > 0 && count < 2)
537 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
543 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
547 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
549 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
551 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
555 *ipaddr = *interpret_addr2(ip);
557 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
558 then only add that name type. */
559 if((ptr = strchr_m(name, '#')) != NULL)
564 *name_type = (int)strtol(ptr, &endptr, 16);
566 if(!*ptr || (endptr == ptr))
568 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
572 *(--ptr) = '\0'; /* Truncate at the '#' */
581 /********************************************************
582 Finish parsing the lmhosts file.
583 *********************************************************/
585 void endlmhosts(XFILE *fp)
591 /********************************************************
592 Resolve via "bcast" method.
593 *********************************************************/
595 BOOL name_resolve_bcast(const char *name, int name_type,
596 struct in_addr **return_ip_list, int *return_count)
599 int num_interfaces = iface_count();
601 *return_ip_list = NULL;
605 * "bcast" means do a broadcast lookup on all the local interfaces.
608 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
610 sock = open_socket_in( SOCK_DGRAM, 0, 3,
611 interpret_addr(lp_socket_address()), True );
613 if (sock == -1) return False;
615 set_socket_options(sock,"SO_BROADCAST");
617 * Lookup the name on all the interfaces, return on
618 * the first successful match.
620 for( i = num_interfaces-1; i >= 0; i--) {
621 struct in_addr sendto_ip;
623 /* Done this way to fix compiler error on IRIX 5.x */
624 sendto_ip = *iface_n_bcast(i);
625 *return_ip_list = name_query(sock, name, name_type, True,
626 True, sendto_ip, return_count, &flags, NULL);
627 if(*return_ip_list != NULL) {
637 /********************************************************
638 Resolve via "wins" method.
639 *********************************************************/
640 BOOL resolve_wins(const char *name, int name_type,
641 struct in_addr **return_iplist, int *return_count)
645 struct in_addr src_ip;
647 *return_iplist = NULL;
650 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
652 if (wins_srv_count() < 1) {
653 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
657 /* we try a lookup on each of the WINS tags in turn */
658 wins_tags = wins_srv_tags();
661 /* huh? no tags?? give up in disgust */
665 /* the address we will be sending from */
666 src_ip = *interpret_addr2(lp_socket_address());
668 /* in the worst case we will try every wins server with every
670 for (t=0; wins_tags && wins_tags[t]; t++) {
671 int srv_count = wins_srv_count_tag(wins_tags[t]);
672 for (i=0; i<srv_count; i++) {
673 struct in_addr wins_ip;
677 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
679 if (global_in_nmbd && ismyip(wins_ip)) {
680 /* yikes! we'll loop forever */
684 /* skip any that have been unresponsive lately */
685 if (wins_srv_is_dead(wins_ip, src_ip)) {
689 DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
691 sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
696 *return_iplist = name_query(sock,name,name_type, False,
697 True, wins_ip, return_count, &flags,
699 if (*return_iplist != NULL) {
705 /* Timed out wating for WINS server to respond. Mark it dead. */
706 wins_srv_died(wins_ip, src_ip);
708 /* The name definately isn't in this
709 group of WINS servers. goto the next group */
715 wins_srv_tags_free(wins_tags);
719 wins_srv_tags_free(wins_tags);
724 /********************************************************
725 Resolve via "lmhosts" method.
726 *********************************************************/
728 static BOOL resolve_lmhosts(const char *name, int name_type,
729 struct in_addr **return_iplist, int *return_count)
732 * "lmhosts" means parse the local lmhosts file.
738 struct in_addr return_ip;
740 *return_iplist = NULL;
743 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
745 fp = startlmhosts(dyn_LMHOSTSFILE);
747 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
748 if (strequal(name, lmhost_name) &&
749 ((name_type2 == -1) || (name_type == name_type2))
752 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
753 if(*return_iplist == NULL) {
754 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
757 **return_iplist = return_ip;
768 /********************************************************
769 Resolve via "hosts" method.
770 *********************************************************/
772 static BOOL resolve_hosts(const char *name,
773 struct in_addr **return_iplist, int *return_count)
776 * "host" means do a localhost, or dns lookup.
780 *return_iplist = NULL;
783 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
785 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
786 struct in_addr return_ip;
787 putip((char *)&return_ip,(char *)hp->h_addr);
788 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
789 if(*return_iplist == NULL) {
790 DEBUG(3,("resolve_hosts: malloc fail !\n"));
793 **return_iplist = return_ip;
800 /********************************************************
801 Internal interface to resolve a name into an IP address.
802 Use this function if the string is either an IP address, DNS
803 or host name or NetBIOS name. This uses the name switch in the
804 smb.conf to determine the order of name resolution.
805 *********************************************************/
807 static BOOL internal_resolve_name(const char *name, int name_type,
808 struct in_addr **return_iplist, int *return_count)
810 pstring name_resolve_list;
813 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
814 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
815 BOOL is_address = is_ipaddress(name);
817 struct in_addr *nodupes_iplist;
820 *return_iplist = NULL;
823 DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
825 if (allzeros || allones || is_address) {
826 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
827 if(*return_iplist == NULL) {
828 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
832 /* if it's in the form of an IP address then get the lib to interpret it */
833 (*return_iplist)->s_addr = inet_addr(name);
835 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
841 pstrcpy(name_resolve_list, lp_name_resolve_order());
842 ptr = name_resolve_list;
846 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
847 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
848 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
852 } else if(strequal( tok, "lmhosts")) {
853 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
857 } else if(strequal( tok, "wins")) {
858 /* don't resolve 1D via WINS */
859 if (name_type != 0x1D &&
860 resolve_wins(name, name_type, return_iplist, return_count)) {
864 } else if(strequal( tok, "bcast")) {
865 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
870 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
874 /* All of the resolve_* functions above have returned false. */
876 SAFE_FREE(*return_iplist);
883 /* Remove duplicate entries. Some queries, notably #1c (domain
884 controllers) return the PDC in iplist[0] and then all domain
885 controllers including the PDC in iplist[1..n]. Iterating over
886 the iplist when the PDC is down will cause two sets of timeouts. */
888 if (*return_count && (nodupes_iplist = (struct in_addr *)
889 malloc(sizeof(struct in_addr) * (*return_count)))) {
890 int nodupes_count = 0;
892 /* Iterate over return_iplist looking for duplicates */
894 for (i = 0; i < *return_count; i++) {
895 BOOL is_dupe = False;
898 for (j = i + 1; j < *return_count; j++) {
899 if (ip_equal((*return_iplist)[i],
900 (*return_iplist)[j])) {
908 /* This one not a duplicate */
910 nodupes_iplist[nodupes_count] = (*return_iplist)[i];
915 /* Switcheroo with original list */
917 free(*return_iplist);
919 *return_iplist = nodupes_iplist;
920 *return_count = nodupes_count;
923 /* Display some debugging info */
925 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
928 for (i = 0; i < *return_count; i++)
929 DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
936 /********************************************************
937 Internal interface to resolve a name into one IP address.
938 Use this function if the string is either an IP address, DNS
939 or host name or NetBIOS name. This uses the name switch in the
940 smb.conf to determine the order of name resolution.
941 *********************************************************/
943 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
945 struct in_addr *ip_list = NULL;
948 if (is_ipaddress(name)) {
949 *return_ip = *interpret_addr2(name);
953 if (internal_resolve_name(name, name_type, &ip_list, &count)) {
955 /* only return valid addresses for TCP connections */
956 for (i=0; i<count; i++) {
957 char *ip_str = inet_ntoa(ip_list[i]);
959 strcmp(ip_str, "255.255.255.255") != 0 &&
960 strcmp(ip_str, "0.0.0.0") != 0) {
961 *return_ip = ip_list[i];
971 /********************************************************
972 Find the IP address of the master browser or DMB for a workgroup.
973 *********************************************************/
975 BOOL find_master_ip(char *group, struct in_addr *master_ip)
977 struct in_addr *ip_list = NULL;
980 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
981 *master_ip = ip_list[0];
985 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
986 *master_ip = ip_list[0];
995 /********************************************************
996 Lookup a DC name given a Domain name and IP address.
997 *********************************************************/
999 BOOL lookup_dc_name(const char *srcname, const char *domain,
1000 struct in_addr *dc_ip, char *ret_name)
1002 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1008 * Due to the fact win WinNT *sucks* we must do a node status
1009 * query here... JRA.
1014 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1016 if(ret && *dc_name) {
1017 fstrcpy(ret_name, dc_name);
1023 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1025 JRA - This code is broken with BDC rollover - we need to do a full
1026 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1029 int retry_time = 2000;
1030 struct timeval tval;
1031 struct packet_struct p;
1032 struct dgram_packet *dgram = &p.packet.dgram;
1036 struct sockaddr_in sock_name;
1037 int sock_len = sizeof(sock_name);
1038 const char *mailslot = NET_LOGON_MAILSLOT;
1039 char *mailslot_name;
1042 int dgm_id = generate_trn_id();
1043 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1048 /* Find out the transient UDP port we have been allocated. */
1049 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1050 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1057 * Create the request data.
1060 memset(buffer,'\0',sizeof(buffer));
1062 SSVAL(bufp,0,QUERYFORPDC);
1064 fstrcpy(bufp,srcname);
1065 bufp += (strlen(bufp) + 1);
1066 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1067 mailslot_name = bufp;
1068 bufp += (strlen(bufp) + 1);
1069 bufp = ALIGN2(bufp, buffer);
1070 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1073 SSVAL(bufp,4,0xFFFF);
1074 SSVAL(bufp,6,0xFFFF);
1076 len = PTR_DIFF(bufp,buffer);
1078 memset((char *)&p,'\0',sizeof(p));
1080 /* DIRECT GROUP or UNIQUE datagram. */
1081 dgram->header.msg_type = 0x10;
1082 dgram->header.flags.node_type = M_NODE;
1083 dgram->header.flags.first = True;
1084 dgram->header.flags.more = False;
1085 dgram->header.dgm_id = dgm_id;
1086 dgram->header.source_ip = *iface_ip(*pdc_ip);
1087 dgram->header.source_port = ntohs(sock_name.sin_port);
1088 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1089 dgram->header.packet_offset = 0;
1091 make_nmb_name(&dgram->source_name,srcname,0);
1092 make_nmb_name(&dgram->dest_name,domain,0x1C);
1094 ptr = &dgram->data[0];
1096 /* Setup the smb part. */
1097 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1099 set_message(ptr,17,17 + len,True);
1102 CVAL(ptr,smb_com) = SMBtrans;
1103 SSVAL(ptr,smb_vwv1,len);
1104 SSVAL(ptr,smb_vwv11,len);
1105 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1106 SSVAL(ptr,smb_vwv13,3);
1107 SSVAL(ptr,smb_vwv14,1);
1108 SSVAL(ptr,smb_vwv15,1);
1109 SSVAL(ptr,smb_vwv16,2);
1111 pstrcpy(p2,mailslot);
1112 p2 = skip_string(p2,1);
1114 memcpy(p2,buffer,len);
1117 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1120 p.port = DGRAM_PORT;
1122 p.timestamp = time(NULL);
1123 p.packet_type = DGRAM_PACKET;
1125 GetTimeOfDay(&tval);
1127 if (!send_packet(&p)) {
1128 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1136 struct timeval tval2;
1137 struct packet_struct *p_ret;
1139 GetTimeOfDay(&tval2);
1140 if (TvalDiff(&tval,&tval2) > retry_time) {
1143 if (!send_packet(&p)) {
1144 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1148 GetTimeOfDay(&tval);
1152 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1153 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1157 buf = &dgram2->data[0];
1160 if (CVAL(buf,smb_com) != SMBtrans) {
1161 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1162 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1167 len = SVAL(buf,smb_vwv11);
1168 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1171 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1176 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1177 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1178 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1180 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1181 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1182 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1188 /* Note this is safe as it is a bounded strcpy. */
1189 fstrcpy(ret_name, buf2);
1190 ret_name[sizeof(fstring)-1] = '\0';
1199 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1202 /********************************************************
1203 Get the IP address list of the Local Master Browsers
1204 ********************************************************/
1206 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1208 return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1211 /********************************************************
1212 Get the IP address list of the PDC/BDC's of a Domain.
1213 *********************************************************/
1215 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1217 int name_type = pdc_only ? 0x1B : 0x1C;
1220 * If it's our domain then
1221 * use the 'password server' parameter.
1224 if (strequal(group, lp_workgroup())) {
1226 char *pserver = lp_passwordserver();
1228 int num_adresses = 0;
1229 struct in_addr *return_iplist = NULL;
1232 return internal_resolve_name(group, name_type, ip_list, count);
1235 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1236 if (strequal(name, "*"))
1237 return internal_resolve_name(group, name_type, ip_list, count);
1240 if (num_adresses == 0)
1241 return internal_resolve_name(group, name_type, ip_list, count);
1243 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1244 if(return_iplist == NULL) {
1245 DEBUG(3,("get_dc_list: malloc fail !\n"));
1250 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1251 struct in_addr name_ip;
1252 if (resolve_name( name, &name_ip, 0x20) == False)
1254 return_iplist[(*count)++] = name_ip;
1256 *ip_list = return_iplist;
1257 return (*count != 0);
1259 return internal_resolve_name(group, name_type, ip_list, count);