updated the 3.0 branch from the head branch - ready for alpha18
[nivanova/samba-autobuild/.git] / source3 / libsmb / namequery.c
1 /* 
2    Unix SMB/CIFS implementation.
3    name query routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    
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.
10    
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.
15    
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.
19    
20 */
21
22 #include "includes.h"
23
24 /* nmbd.c sets this to True. */
25 BOOL global_in_nmbd = False;
26
27 /****************************************************************************
28 generate a random trn_id
29 ****************************************************************************/
30 static int generate_trn_id(void)
31 {
32         static int trn_id;
33
34         if (trn_id == 0) {
35                 sys_srandom(sys_getpid());
36         }
37
38         trn_id = sys_random();
39
40         return trn_id % (unsigned)0x7FFF;
41 }
42
43
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)
48 {
49         struct node_status *ret;
50         int i;
51
52         *num_names = CVAL(p,0);
53
54         if (*num_names == 0) return NULL;
55
56         ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
57         if (!ret) return NULL;
58
59         p++;
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);
64                 ret[i].flags = p[16];
65                 p += 18;
66                 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name, 
67                            ret[i].type, ret[i].flags));
68         }
69         return ret;
70 }
71
72
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)
79 {
80         BOOL found=False;
81         int retries = 2;
82         int retry_time = 2000;
83         struct timeval tval;
84         struct packet_struct p;
85         struct packet_struct *p2;
86         struct nmb_packet *nmb = &p.packet.nmb;
87         struct node_status *ret;
88
89         ZERO_STRUCT(p);
90
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;
107
108         p.ip = to_ip;
109         p.port = NMB_PORT;
110         p.fd = fd;
111         p.timestamp = time(NULL);
112         p.packet_type = NMB_PACKET;
113         
114         GetTimeOfDay(&tval);
115   
116         if (!send_packet(&p)) 
117                 return NULL;
118
119         retries--;
120
121         while (1) {
122                 struct timeval tval2;
123                 GetTimeOfDay(&tval2);
124                 if (TvalDiff(&tval,&tval2) > retry_time) {
125                         if (!retries)
126                                 break;
127                         if (!found && !send_packet(&p))
128                                 return NULL;
129                         GetTimeOfDay(&tval);
130                         retries--;
131                 }
132
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);
136                         
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
144                                    moment */
145                                 free_packet(p2);
146                                 continue;
147                         }
148
149                         ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
150                         free_packet(p2);
151                         return ret;
152                 }
153         }
154         
155         return NULL;
156 }
157
158
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 **************************************************************************/
164
165 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
166 {
167         struct node_status *status = NULL;
168         struct nmb_name nname;
169         int count, i;
170         int sock;
171         BOOL result = False;
172
173         DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, 
174                    q_type, inet_ntoa(to_ip)));
175
176         sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
177         if (sock == -1)
178                 goto done;
179
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);
183         close(sock);
184         if (!status)
185                 goto done;
186
187         for (i=0;i<count;i++) {
188                 if (status[i].type == type)
189                         break;
190         }
191         if (i == count)
192                 goto done;
193
194         pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
195         result = True;
196
197  done:
198         SAFE_FREE(status);
199
200         DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
201
202         if (result)
203                 DEBUGADD(10, (", ip address is %s", inet_ntoa(to_ip)));
204
205         DEBUG(10, ("\n"));      
206
207         return result;
208 }
209
210
211 /*
212   comparison function used by sort_ip_list
213 */
214 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
215 {
216         int max_bits1=0, max_bits2=0;
217         int num_interfaces = iface_count();
218         int i;
219
220         for (i=0;i<num_interfaces;i++) {
221                 struct in_addr ip;
222                 int bits1, bits2;
223                 ip = *iface_n_bcast(i);
224                 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
225                 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
226                 max_bits1 = MAX(bits1, max_bits1);
227                 max_bits2 = MAX(bits2, max_bits2);
228         }       
229         
230         /* bias towards directly reachable IPs */
231         if (iface_local(*ip1)) {
232                 max_bits1 += 32;
233         }
234         if (iface_local(*ip2)) {
235                 max_bits2 += 32;
236         }
237
238         return max_bits2 - max_bits1;
239 }
240
241 /*
242   sort an IP list so that names that are close to one of our interfaces 
243   are at the top. This prevents the problem where a WINS server returns an IP that
244   is not reachable from our subnet as the first match
245 */
246 static void sort_ip_list(struct in_addr *iplist, int count)
247 {
248         if (count <= 1) {
249                 return;
250         }
251
252         qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);    
253 }
254
255
256 /****************************************************************************
257  Do a netbios name query to find someones IP.
258  Returns an array of IP addresses or NULL if none.
259  *count will be set to the number of addresses returned.
260  *timed_out is set if we failed by timing out
261 ****************************************************************************/
262 struct in_addr *name_query(int fd,const char *name,int name_type, 
263                            BOOL bcast,BOOL recurse,
264                            struct in_addr to_ip, int *count, int *flags,
265                            BOOL *timed_out)
266 {
267         BOOL found=False;
268         int i, retries = 3;
269         int retry_time = bcast?250:2000;
270         struct timeval tval;
271         struct packet_struct p;
272         struct packet_struct *p2;
273         struct nmb_packet *nmb = &p.packet.nmb;
274         struct in_addr *ip_list = NULL;
275
276         if (timed_out) {
277                 *timed_out = False;
278         }
279         
280         memset((char *)&p,'\0',sizeof(p));
281         (*count) = 0;
282         (*flags) = 0;
283         
284         nmb->header.name_trn_id = generate_trn_id();
285         nmb->header.opcode = 0;
286         nmb->header.response = False;
287         nmb->header.nm_flags.bcast = bcast;
288         nmb->header.nm_flags.recursion_available = False;
289         nmb->header.nm_flags.recursion_desired = recurse;
290         nmb->header.nm_flags.trunc = False;
291         nmb->header.nm_flags.authoritative = False;
292         nmb->header.rcode = 0;
293         nmb->header.qdcount = 1;
294         nmb->header.ancount = 0;
295         nmb->header.nscount = 0;
296         nmb->header.arcount = 0;
297         
298         make_nmb_name(&nmb->question.question_name,name,name_type);
299         
300         nmb->question.question_type = 0x20;
301         nmb->question.question_class = 0x1;
302         
303         p.ip = to_ip;
304         p.port = NMB_PORT;
305         p.fd = fd;
306         p.timestamp = time(NULL);
307         p.packet_type = NMB_PACKET;
308         
309         GetTimeOfDay(&tval);
310         
311         if (!send_packet(&p)) 
312                 return NULL;
313         
314         retries--;
315         
316         while (1) {
317                 struct timeval tval2;
318                 struct in_addr *tmp_ip_list;
319                 
320                 GetTimeOfDay(&tval2);
321                 if (TvalDiff(&tval,&tval2) > retry_time) {
322                         if (!retries)
323                                 break;
324                         if (!found && !send_packet(&p))
325                                 return NULL;
326                         GetTimeOfDay(&tval);
327                         retries--;
328                 }
329                 
330                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
331                         struct nmb_packet *nmb2 = &p2->packet.nmb;
332                         debug_nmb_packet(p2);
333                         
334                         /* If we get a Negative Name Query Response from a WINS
335                          * server, we should report it and give up.
336                          */
337                         if( 0 == nmb2->header.opcode            /* A query response   */
338                             && !(bcast)                 /* from a WINS server */
339                             && nmb2->header.rcode               /* Error returned     */
340                                 ) {
341                                 
342                                 if( DEBUGLVL( 3 ) ) {
343                                         /* Only executed if DEBUGLEVEL >= 3 */
344                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
345                                         switch( nmb2->header.rcode ) {
346                                         case 0x01:
347                                                 dbgtext( "Request was invalidly formatted.\n" );
348                                                 break;
349                                         case 0x02:
350                                                 dbgtext( "Problem with NBNS, cannot process name.\n");
351                                                 break;
352                                         case 0x03:
353                                                 dbgtext( "The name requested does not exist.\n" );
354                                                 break;
355                                         case 0x04:
356                                                 dbgtext( "Unsupported request error.\n" );
357                                                 break;
358                                         case 0x05:
359                                                 dbgtext( "Query refused error.\n" );
360                                                 break;
361                                         default:
362                                                 dbgtext( "Unrecognized error code.\n" );
363                                                 break;
364                                         }
365                                 }
366                                 free_packet(p2);
367                                 return( NULL );
368                         }
369                         
370                         if (nmb2->header.opcode != 0 ||
371                             nmb2->header.nm_flags.bcast ||
372                             nmb2->header.rcode ||
373                             !nmb2->header.ancount) {
374                                 /* 
375                                  * XXXX what do we do with this? Could be a
376                                  * redirect, but we'll discard it for the
377                                  * moment.
378                                  */
379                                 free_packet(p2);
380                                 continue;
381                         }
382                         
383                         tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
384                                                                  * ( (*count) + nmb2->answers->rdlength/6 ) );
385                         
386                         if (!tmp_ip_list) {
387                                 DEBUG(0,("name_query: Realloc failed.\n"));
388                                 SAFE_FREE(ip_list);
389                         }
390                         
391                         ip_list = tmp_ip_list;
392                         
393                         if (ip_list) {
394                                 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
395                                 for (i=0;i<nmb2->answers->rdlength/6;i++) {
396                                         putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
397                                         DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
398                                         (*count)++;
399                                 }
400                                 DEBUGADD(2,(")\n"));
401                         }
402                         
403                         found=True;
404                         retries=0;
405                         /* We add the flags back ... */
406                         if (nmb2->header.response)
407                                 (*flags) |= NM_FLAGS_RS;
408                         if (nmb2->header.nm_flags.authoritative)
409                                 (*flags) |= NM_FLAGS_AA;
410                         if (nmb2->header.nm_flags.trunc)
411                                 (*flags) |= NM_FLAGS_TC;
412                         if (nmb2->header.nm_flags.recursion_desired)
413                                 (*flags) |= NM_FLAGS_RD;
414                         if (nmb2->header.nm_flags.recursion_available)
415                                 (*flags) |= NM_FLAGS_RA;
416                         if (nmb2->header.nm_flags.bcast)
417                                 (*flags) |= NM_FLAGS_B;
418                         free_packet(p2);
419                         /*
420                          * If we're doing a unicast lookup we only
421                          * expect one reply. Don't wait the full 2
422                          * seconds if we got one. JRA.
423                          */
424                         if(!bcast && found)
425                                 break;
426                 }
427         }
428
429         if (timed_out) {
430                 *timed_out = True;
431         }
432
433         /* sort the ip list so we choose close servers first if possible */
434         sort_ip_list(ip_list, *count);
435
436         return ip_list;
437 }
438
439 /********************************************************
440  Start parsing the lmhosts file.
441 *********************************************************/
442
443 XFILE *startlmhosts(char *fname)
444 {
445         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
446         if (!fp) {
447                 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
448                          fname, strerror(errno)));
449                 return NULL;
450         }
451         return fp;
452 }
453
454 /********************************************************
455  Parse the next line in the lmhosts file.
456 *********************************************************/
457
458 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
459 {
460   pstring line;
461
462   while(!x_feof(fp) && !x_ferror(fp)) {
463     pstring ip,flags,extra;
464     char *ptr;
465     int count = 0;
466
467     *name_type = -1;
468
469     if (!fgets_slash(line,sizeof(pstring),fp))
470       continue;
471
472     if (*line == '#')
473       continue;
474
475     pstrcpy(ip,"");
476     pstrcpy(name,"");
477     pstrcpy(flags,"");
478
479     ptr = line;
480
481     if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
482       ++count;
483     if (next_token(&ptr,name ,NULL, sizeof(pstring)))
484       ++count;
485     if (next_token(&ptr,flags,NULL, sizeof(flags)))
486       ++count;
487     if (next_token(&ptr,extra,NULL, sizeof(extra)))
488       ++count;
489
490     if (count <= 0)
491       continue;
492
493     if (count > 0 && count < 2)
494     {
495       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
496       continue;
497     }
498
499     if (count >= 4)
500     {
501       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
502       continue;
503     }
504
505     DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
506
507     if (strchr_m(flags,'G') || strchr_m(flags,'S'))
508     {
509       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
510       continue;
511     }
512
513     *ipaddr = *interpret_addr2(ip);
514
515     /* Extra feature. If the name ends in '#XX', where XX is a hex number,
516        then only add that name type. */
517     if((ptr = strchr_m(name, '#')) != NULL)
518     {
519       char *endptr;
520
521       ptr++;
522       *name_type = (int)strtol(ptr, &endptr, 16);
523
524       if(!*ptr || (endptr == ptr))
525       {
526         DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
527         continue;
528       }
529
530       *(--ptr) = '\0'; /* Truncate at the '#' */
531     }
532
533     return True;
534   }
535
536   return False;
537 }
538
539 /********************************************************
540  Finish parsing the lmhosts file.
541 *********************************************************/
542
543 void endlmhosts(XFILE *fp)
544 {
545         x_fclose(fp);
546 }
547
548
549 /********************************************************
550  Resolve via "bcast" method.
551 *********************************************************/
552
553 BOOL name_resolve_bcast(const char *name, int name_type,
554                         struct in_addr **return_ip_list, int *return_count)
555 {
556         int sock, i;
557         int num_interfaces = iface_count();
558
559         *return_ip_list = NULL;
560         *return_count = 0;
561         
562         /*
563          * "bcast" means do a broadcast lookup on all the local interfaces.
564          */
565
566         DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
567
568         sock = open_socket_in( SOCK_DGRAM, 0, 3,
569                                interpret_addr(lp_socket_address()), True );
570
571         if (sock == -1) return False;
572
573         set_socket_options(sock,"SO_BROADCAST");
574         /*
575          * Lookup the name on all the interfaces, return on
576          * the first successful match.
577          */
578         for( i = num_interfaces-1; i >= 0; i--) {
579                 struct in_addr sendto_ip;
580                 int flags;
581                 /* Done this way to fix compiler error on IRIX 5.x */
582                 sendto_ip = *iface_n_bcast(i);
583                 *return_ip_list = name_query(sock, name, name_type, True, 
584                                     True, sendto_ip, return_count, &flags, NULL);
585                 if(*return_ip_list != NULL) {
586                         close(sock);
587                         return True;
588                 }
589         }
590
591         close(sock);
592         return False;
593 }
594
595 /********************************************************
596  Resolve via "wins" method.
597 *********************************************************/
598 BOOL resolve_wins(const char *name, int name_type,
599                   struct in_addr **return_iplist, int *return_count)
600 {
601         int sock, t, i;
602         char **wins_tags;
603         struct in_addr src_ip;
604
605         *return_iplist = NULL;
606         *return_count = 0;
607         
608         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
609
610         if (wins_srv_count() < 1) {
611                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
612                 return False;
613         }
614
615         /* we try a lookup on each of the WINS tags in turn */
616         wins_tags = wins_srv_tags();
617
618         if (!wins_tags) {
619                 /* huh? no tags?? give up in disgust */
620                 return False;
621         }
622
623         /* the address we will be sending from */
624         src_ip = *interpret_addr2(lp_socket_address());
625
626         /* in the worst case we will try every wins server with every
627            tag! */
628         for (t=0; wins_tags && wins_tags[t]; t++) {
629                 int srv_count = wins_srv_count_tag(wins_tags[t]);
630                 for (i=0; i<srv_count; i++) {
631                         struct in_addr wins_ip;
632                         int flags;
633                         BOOL timed_out;
634
635                         wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
636
637                         if (global_in_nmbd && ismyip(wins_ip)) {
638                                 /* yikes! we'll loop forever */
639                                 continue;
640                         }
641
642                         /* skip any that have been unresponsive lately */
643                         if (wins_srv_is_dead(wins_ip, src_ip)) {
644                                 continue;
645                         }
646
647                         DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
648
649                         sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
650                         if (sock == -1) {
651                                 continue;
652                         }
653
654                         *return_iplist = name_query(sock,name,name_type, False, 
655                                                     True, wins_ip, return_count, &flags, 
656                                                     &timed_out);
657                         if (*return_iplist != NULL) {
658                                 goto success;
659                         }
660                         close(sock);
661
662                         if (timed_out) {
663                                 /* Timed out wating for WINS server to respond.  Mark it dead. */
664                                 wins_srv_died(wins_ip, src_ip);
665                         } else {
666                                 /* The name definately isn't in this
667                                    group of WINS servers. goto the next group  */
668                                 break;
669                         }
670                 }
671         }
672
673         wins_srv_tags_free(wins_tags);
674         return False;
675
676 success:
677         wins_srv_tags_free(wins_tags);
678         close(sock);
679         return True;
680 }
681
682 /********************************************************
683  Resolve via "lmhosts" method.
684 *********************************************************/
685
686 static BOOL resolve_lmhosts(const char *name, int name_type,
687                          struct in_addr **return_iplist, int *return_count)
688 {
689         /*
690          * "lmhosts" means parse the local lmhosts file.
691          */
692         
693         XFILE *fp;
694         pstring lmhost_name;
695         int name_type2;
696         struct in_addr return_ip;
697
698         *return_iplist = NULL;
699         *return_count = 0;
700
701         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
702
703         fp = startlmhosts(dyn_LMHOSTSFILE);
704         if(fp) {
705                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
706                         if (strequal(name, lmhost_name) && 
707                 ((name_type2 == -1) || (name_type == name_type2))
708                ) {
709                                 endlmhosts(fp);
710                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
711                                 if(*return_iplist == NULL) {
712                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
713                                         return False;
714                                 }
715                                 **return_iplist = return_ip;
716                                 *return_count = 1;
717                                 return True; 
718                         }
719                 }
720                 endlmhosts(fp);
721         }
722         return False;
723 }
724
725
726 /********************************************************
727  Resolve via "hosts" method.
728 *********************************************************/
729
730 static BOOL resolve_hosts(const char *name,
731                          struct in_addr **return_iplist, int *return_count)
732 {
733         /*
734          * "host" means do a localhost, or dns lookup.
735          */
736         struct hostent *hp;
737
738         *return_iplist = NULL;
739         *return_count = 0;
740
741         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
742         
743         if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
744                 struct in_addr return_ip;
745                 putip((char *)&return_ip,(char *)hp->h_addr);
746                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
747                 if(*return_iplist == NULL) {
748                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
749                         return False;
750                 }
751                 **return_iplist = return_ip;
752                 *return_count = 1;
753                 return True;
754         }
755         return False;
756 }
757
758 /********************************************************
759  Internal interface to resolve a name into an IP address.
760  Use this function if the string is either an IP address, DNS
761  or host name or NetBIOS name. This uses the name switch in the
762  smb.conf to determine the order of name resolution.
763 *********************************************************/
764
765 static BOOL internal_resolve_name(const char *name, int name_type,
766                                         struct in_addr **return_iplist, int *return_count)
767 {
768   pstring name_resolve_list;
769   fstring tok;
770   char *ptr;
771   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
772   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
773   BOOL is_address = is_ipaddress(name);
774   BOOL result = False;
775   struct in_addr *nodupes_iplist;
776   int i;
777
778   *return_iplist = NULL;
779   *return_count = 0;
780
781   DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
782
783   if (allzeros || allones || is_address) {
784         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
785         if(*return_iplist == NULL) {
786                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
787                 return False;
788         }
789         if(is_address) { 
790                 /* if it's in the form of an IP address then get the lib to interpret it */
791                 (*return_iplist)->s_addr = inet_addr(name);
792     } else {
793                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
794                 *return_count = 1;
795         }
796     return True;
797   }
798   
799   pstrcpy(name_resolve_list, lp_name_resolve_order());
800   ptr = name_resolve_list;
801   if (!ptr || !*ptr)
802     ptr = "host";
803
804   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
805           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
806                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
807                     result = True;
808                     goto done;
809                   }
810           } else if(strequal( tok, "lmhosts")) {
811                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
812                     result = True;
813                     goto done;
814                   }
815           } else if(strequal( tok, "wins")) {
816                   /* don't resolve 1D via WINS */
817                   if (name_type != 0x1D &&
818                       resolve_wins(name, name_type, return_iplist, return_count)) {
819                     result = True;
820                     goto done;
821                   }
822           } else if(strequal( tok, "bcast")) {
823                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
824                     result = True;
825                     goto done;
826                   }
827           } else {
828                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
829           }
830   }
831
832   /* All of the resolve_* functions above have returned false. */
833
834   SAFE_FREE(*return_iplist);
835   *return_count = 0;
836
837   return False;
838
839  done:
840
841   /* Remove duplicate entries.  Some queries, notably #1c (domain
842      controllers) return the PDC in iplist[0] and then all domain
843      controllers including the PDC in iplist[1..n].  Iterating over
844      the iplist when the PDC is down will cause two sets of timeouts. */
845
846   if (*return_count && (nodupes_iplist = (struct in_addr *)
847        malloc(sizeof(struct in_addr) * (*return_count)))) {
848           int nodupes_count = 0;
849
850           /* Iterate over return_iplist looking for duplicates */
851
852           for (i = 0; i < *return_count; i++) {
853                   BOOL is_dupe = False;
854                   int j;
855
856                   for (j = i + 1; j < *return_count; j++) {
857                           if (ip_equal((*return_iplist)[i], 
858                                        (*return_iplist)[j])) {
859                                   is_dupe = True;
860                                   break;
861                           }
862                   }
863
864                   if (!is_dupe) {
865
866                           /* This one not a duplicate */
867
868                           nodupes_iplist[nodupes_count] = (*return_iplist)[i];
869                           nodupes_count++;
870                   }
871           }
872           
873           /* Switcheroo with original list */
874           
875           free(*return_iplist);
876
877           *return_iplist = nodupes_iplist;
878           *return_count = nodupes_count;
879   }
880
881   /* Display some debugging info */
882
883   DEBUG(10, ("internal_resolve_name: returning %d addresses: ", 
884              *return_count));
885
886   for (i = 0; i < *return_count; i++)
887           DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
888
889   DEBUG(10, ("\n"));
890
891   return result;
892 }
893
894 /********************************************************
895  Internal interface to resolve a name into one IP address.
896  Use this function if the string is either an IP address, DNS
897  or host name or NetBIOS name. This uses the name switch in the
898  smb.conf to determine the order of name resolution.
899 *********************************************************/
900
901 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
902 {
903         struct in_addr *ip_list = NULL;
904         int count = 0;
905
906         if (is_ipaddress(name)) {
907                 *return_ip = *interpret_addr2(name);
908                 return True;
909         }
910
911         if (internal_resolve_name(name, name_type, &ip_list, &count)) {
912                 int i;
913                 /* only return valid addresses for TCP connections */
914                 for (i=0; i<count; i++) {
915                         char *ip_str = inet_ntoa(ip_list[i]);
916                         if (ip_str &&
917                             strcmp(ip_str, "255.255.255.255") != 0 &&
918                             strcmp(ip_str, "0.0.0.0") != 0) {
919                                 *return_ip = ip_list[i];
920                                 SAFE_FREE(ip_list);
921                                 return True;
922                         }
923                 }
924         }
925         SAFE_FREE(ip_list);
926         return False;
927 }
928
929 /********************************************************
930  Find the IP address of the master browser or DMB for a workgroup.
931 *********************************************************/
932
933 BOOL find_master_ip(char *group, struct in_addr *master_ip)
934 {
935         struct in_addr *ip_list = NULL;
936         int count = 0;
937
938         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
939                 *master_ip = ip_list[0];
940                 SAFE_FREE(ip_list);
941                 return True;
942         }
943         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
944                 *master_ip = ip_list[0];
945                 SAFE_FREE(ip_list);
946                 return True;
947         }
948
949         SAFE_FREE(ip_list);
950         return False;
951 }
952
953 /********************************************************
954  Lookup a DC name given a Domain name and IP address.
955 *********************************************************/
956
957 BOOL lookup_dc_name(const char *srcname, const char *domain, 
958                     struct in_addr *dc_ip, char *ret_name)
959 {
960 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
961         
962         fstring dc_name;
963         BOOL ret;
964         
965         /*
966          * Due to the fact win WinNT *sucks* we must do a node status
967          * query here... JRA.
968          */
969         
970         *dc_name = '\0';
971         
972         ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
973
974         if(ret && *dc_name) {
975                 fstrcpy(ret_name, dc_name);
976                 return True;
977         }
978         
979         return False;
980
981 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
982
983 JRA - This code is broken with BDC rollover - we need to do a full
984 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
985
986         int retries = 3;
987         int retry_time = 2000;
988         struct timeval tval;
989         struct packet_struct p;
990         struct dgram_packet *dgram = &p.packet.dgram;
991         char *ptr,*p2;
992         char tmp[4];
993         int len;
994         struct sockaddr_in sock_name;
995         int sock_len = sizeof(sock_name);
996         const char *mailslot = NET_LOGON_MAILSLOT;
997         char *mailslot_name;
998         char buffer[1024];
999         char *bufp;
1000         int dgm_id = generate_trn_id();
1001         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1002         
1003         if(sock == -1)
1004                 return False;
1005         
1006         /* Find out the transient UDP port we have been allocated. */
1007         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1008                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1009                          strerror(errno)));
1010                 close(sock);
1011                 return False;
1012         }
1013
1014         /*
1015          * Create the request data.
1016          */
1017
1018         memset(buffer,'\0',sizeof(buffer));
1019         bufp = buffer;
1020         SSVAL(bufp,0,QUERYFORPDC);
1021         bufp += 2;
1022         fstrcpy(bufp,srcname);
1023         bufp += (strlen(bufp) + 1);
1024         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1025         mailslot_name = bufp;
1026         bufp += (strlen(bufp) + 1);
1027         bufp = ALIGN2(bufp, buffer);
1028         bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);        
1029         
1030         SIVAL(bufp,0,1);
1031         SSVAL(bufp,4,0xFFFF); 
1032         SSVAL(bufp,6,0xFFFF); 
1033         bufp += 8;
1034         len = PTR_DIFF(bufp,buffer);
1035
1036         memset((char *)&p,'\0',sizeof(p));
1037
1038         /* DIRECT GROUP or UNIQUE datagram. */
1039         dgram->header.msg_type = 0x10;
1040         dgram->header.flags.node_type = M_NODE;
1041         dgram->header.flags.first = True;
1042         dgram->header.flags.more = False;
1043         dgram->header.dgm_id = dgm_id;
1044         dgram->header.source_ip = *iface_ip(*pdc_ip);
1045         dgram->header.source_port = ntohs(sock_name.sin_port);
1046         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1047         dgram->header.packet_offset = 0;
1048         
1049         make_nmb_name(&dgram->source_name,srcname,0);
1050         make_nmb_name(&dgram->dest_name,domain,0x1C);
1051         
1052         ptr = &dgram->data[0];
1053         
1054         /* Setup the smb part. */
1055         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1056         memcpy(tmp,ptr,4);
1057         set_message(ptr,17,17 + len,True);
1058         memcpy(ptr,tmp,4);
1059
1060         CVAL(ptr,smb_com) = SMBtrans;
1061         SSVAL(ptr,smb_vwv1,len);
1062         SSVAL(ptr,smb_vwv11,len);
1063         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1064         SSVAL(ptr,smb_vwv13,3);
1065         SSVAL(ptr,smb_vwv14,1);
1066         SSVAL(ptr,smb_vwv15,1);
1067         SSVAL(ptr,smb_vwv16,2);
1068         p2 = smb_buf(ptr);
1069         pstrcpy(p2,mailslot);
1070         p2 = skip_string(p2,1);
1071         
1072         memcpy(p2,buffer,len);
1073         p2 += len;
1074         
1075         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1076         
1077         p.ip = *pdc_ip;
1078         p.port = DGRAM_PORT;
1079         p.fd = sock;
1080         p.timestamp = time(NULL);
1081         p.packet_type = DGRAM_PACKET;
1082         
1083         GetTimeOfDay(&tval);
1084         
1085         if (!send_packet(&p)) {
1086                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1087                 close(sock);
1088                 return False;
1089         }
1090         
1091         retries--;
1092         
1093         while (1) {
1094                 struct timeval tval2;
1095                 struct packet_struct *p_ret;
1096                 
1097                 GetTimeOfDay(&tval2);
1098                 if (TvalDiff(&tval,&tval2) > retry_time) {
1099                         if (!retries)
1100                                 break;
1101                         if (!send_packet(&p)) {
1102                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1103                                 close(sock);
1104                                 return False;
1105                         }
1106                         GetTimeOfDay(&tval);
1107                         retries--;
1108                 }
1109
1110                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1111                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1112                         char *buf;
1113                         char *buf2;
1114
1115                         buf = &dgram2->data[0];
1116                         buf -= 4;
1117
1118                         if (CVAL(buf,smb_com) != SMBtrans) {
1119                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1120                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1121                                 free_packet(p_ret);
1122                                 continue;
1123                         }
1124                         
1125                         len = SVAL(buf,smb_vwv11);
1126                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1127                         
1128                         if (len <= 0) {
1129                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1130                                 free_packet(p_ret);
1131                                 continue;
1132                         }
1133
1134                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1135                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1136                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1137
1138                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1139                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1140                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1141                                 free_packet(p_ret);
1142                                 continue;
1143                         }
1144
1145                         buf2 += 2;
1146                         /* Note this is safe as it is a bounded strcpy. */
1147                         fstrcpy(ret_name, buf2);
1148                         ret_name[sizeof(fstring)-1] = '\0';
1149                         close(sock);
1150                         free_packet(p_ret);
1151                         return True;
1152                 }
1153         }
1154         
1155         close(sock);
1156         return False;
1157 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1158 }
1159
1160
1161 /********************************************************
1162  Get the IP address list of the PDC/BDC's of a Domain.
1163 *********************************************************/
1164
1165 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1166 {
1167         int name_type = pdc_only ? 0x1B : 0x1C;
1168
1169         /*
1170          * If it's our domain then
1171          * use the 'password server' parameter.
1172          */
1173
1174         if (strequal(group, lp_workgroup())) {
1175                 char *p;
1176                 char *pserver = lp_passwordserver();
1177                 fstring name;
1178                 int num_adresses = 0;
1179                 struct in_addr *return_iplist = NULL;
1180
1181                 if (! *pserver)
1182                         return internal_resolve_name(group, name_type, ip_list, count);
1183
1184                 p = pserver;
1185                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1186                         if (strequal(name, "*"))
1187                                 return internal_resolve_name(group, name_type, ip_list, count);
1188                         num_adresses++;
1189                 }
1190                 if (num_adresses == 0)
1191                         return internal_resolve_name(group, name_type, ip_list, count);
1192
1193                 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1194                 if(return_iplist == NULL) {
1195                         DEBUG(3,("get_dc_list: malloc fail !\n"));
1196                         return False;
1197                 }
1198                 p = pserver;
1199                 *count = 0;
1200                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1201                         struct in_addr name_ip;
1202                         if (resolve_name( name, &name_ip, 0x20) == False)
1203                                 continue;
1204                         return_iplist[(*count)++] = name_ip;
1205                 }
1206                 *ip_list = return_iplist;
1207                 return (*count != 0);
1208         } else
1209                 return internal_resolve_name(group, name_type, ip_list, count);
1210 }