libsmb/namequery.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    name query routines
00004    Copyright (C) Andrew Tridgell 1994-1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   
00019 */
00020 
00021 #include "includes.h"
00022 
00023 /* nmbd.c sets this to True. */
00024 BOOL global_in_nmbd = False;
00025 
00026 /****************************
00027  * SERVER AFFINITY ROUTINES *
00028  ****************************/
00029  
00030  /* Server affinity is the concept of preferring the last domain 
00031     controller with whom you had a successful conversation */
00032  
00033 /****************************************************************************
00034 ****************************************************************************/
00035 #define SAFKEY_FMT      "SAF/DOMAIN/%s"
00036 #define SAF_TTL         900
00037 
00038 static char *saf_key(const char *domain)
00039 {
00040         char *keystr;
00041         
00042         asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
00043 
00044         return keystr;
00045 }
00046 
00047 /****************************************************************************
00048 ****************************************************************************/
00049 
00050 BOOL saf_store( const char *domain, const char *servername )
00051 {
00052         char *key;
00053         time_t expire;
00054         BOOL ret = False;
00055         
00056         if ( !domain || !servername ) {
00057                 DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
00058                 return False;
00059         }
00060 
00061         if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
00062                 DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
00063                 return False;
00064         }
00065         
00066         if ( !gencache_init() ) 
00067                 return False;
00068         
00069         key = saf_key( domain );
00070         expire = time( NULL ) + SAF_TTL;
00071         
00072         
00073         DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
00074                 domain, servername, (unsigned int)expire ));
00075                 
00076         ret = gencache_set( key, servername, expire );
00077         
00078         SAFE_FREE( key );
00079         
00080         return ret;
00081 }
00082 
00083 BOOL saf_delete( const char *domain )
00084 {
00085         char *key;
00086         BOOL ret = False;
00087         
00088         if ( !domain ) {
00089                 DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));             
00090                 return False;
00091         }
00092         
00093         if ( !gencache_init() ) 
00094                 return False;
00095         
00096         key = saf_key(domain);
00097         ret = gencache_del(key);
00098         
00099         if (ret) {
00100                 DEBUG(10,("saf_delete: domain = [%s]\n", domain ));             
00101         }
00102 
00103         SAFE_FREE( key );
00104 
00105         return ret;
00106 }
00107 
00108 /****************************************************************************
00109 ****************************************************************************/
00110 
00111 char *saf_fetch( const char *domain )
00112 {
00113         char *server = NULL;
00114         time_t timeout;
00115         BOOL ret = False;
00116         char *key = NULL;
00117 
00118         if ( !domain || strlen(domain) == 0) {
00119                 DEBUG(2,("saf_fetch: Empty domain name!\n"));
00120                 return NULL;
00121         }
00122         
00123         if ( !gencache_init() ) 
00124                 return False;
00125         
00126         key = saf_key( domain );
00127         
00128         ret = gencache_get( key, &server, &timeout );
00129         
00130         SAFE_FREE( key );
00131         
00132         if ( !ret ) {
00133                 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain ));
00134         } else {
00135                 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n", 
00136                         server, domain ));
00137         }
00138                 
00139         return server;
00140 }
00141 
00142 /****************************************************************************
00143  Generate a random trn_id.
00144 ****************************************************************************/
00145 
00146 static int generate_trn_id(void)
00147 {
00148         static int trn_id;
00149 
00150         if (trn_id == 0) {
00151                 sys_srandom(sys_getpid());
00152         }
00153 
00154         trn_id = sys_random();
00155 
00156         return trn_id % (unsigned)0x7FFF;
00157 }
00158 
00159 /****************************************************************************
00160  Parse a node status response into an array of structures.
00161 ****************************************************************************/
00162 
00163 static NODE_STATUS_STRUCT *parse_node_status(char *p, int *num_names, struct node_status_extra *extra)
00164 {
00165         NODE_STATUS_STRUCT *ret;
00166         int i;
00167 
00168         *num_names = CVAL(p,0);
00169 
00170         if (*num_names == 0)
00171                 return NULL;
00172 
00173         ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
00174         if (!ret)
00175                 return NULL;
00176 
00177         p++;
00178         for (i=0;i< *num_names;i++) {
00179                 StrnCpy(ret[i].name,p,15);
00180                 trim_char(ret[i].name,'\0',' ');
00181                 ret[i].type = CVAL(p,15);
00182                 ret[i].flags = p[16];
00183                 p += 18;
00184                 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name, 
00185                            ret[i].type, ret[i].flags));
00186         }
00187         /*
00188          * Also, pick up the MAC address ...
00189          */
00190         if (extra) {
00191                 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
00192         }
00193         return ret;
00194 }
00195 
00196 
00197 /****************************************************************************
00198  Do a NBT node status query on an open socket and return an array of
00199  structures holding the returned names or NULL if the query failed.
00200 **************************************************************************/
00201 
00202 NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,
00203                                       struct in_addr to_ip, int *num_names,
00204                                       struct node_status_extra *extra)
00205 {
00206         BOOL found=False;
00207         int retries = 2;
00208         int retry_time = 2000;
00209         struct timeval tval;
00210         struct packet_struct p;
00211         struct packet_struct *p2;
00212         struct nmb_packet *nmb = &p.packet.nmb;
00213         NODE_STATUS_STRUCT *ret;
00214 
00215         ZERO_STRUCT(p);
00216 
00217         nmb->header.name_trn_id = generate_trn_id();
00218         nmb->header.opcode = 0;
00219         nmb->header.response = False;
00220         nmb->header.nm_flags.bcast = False;
00221         nmb->header.nm_flags.recursion_available = False;
00222         nmb->header.nm_flags.recursion_desired = False;
00223         nmb->header.nm_flags.trunc = False;
00224         nmb->header.nm_flags.authoritative = False;
00225         nmb->header.rcode = 0;
00226         nmb->header.qdcount = 1;
00227         nmb->header.ancount = 0;
00228         nmb->header.nscount = 0;
00229         nmb->header.arcount = 0;
00230         nmb->question.question_name = *name;
00231         nmb->question.question_type = 0x21;
00232         nmb->question.question_class = 0x1;
00233 
00234         p.ip = to_ip;
00235         p.port = NMB_PORT;
00236         p.fd = fd;
00237         p.timestamp = time(NULL);
00238         p.packet_type = NMB_PACKET;
00239         
00240         GetTimeOfDay(&tval);
00241   
00242         if (!send_packet(&p)) 
00243                 return NULL;
00244 
00245         retries--;
00246 
00247         while (1) {
00248                 struct timeval tval2;
00249                 GetTimeOfDay(&tval2);
00250                 if (TvalDiff(&tval,&tval2) > retry_time) {
00251                         if (!retries)
00252                                 break;
00253                         if (!found && !send_packet(&p))
00254                                 return NULL;
00255                         GetTimeOfDay(&tval);
00256                         retries--;
00257                 }
00258 
00259                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
00260                         struct nmb_packet *nmb2 = &p2->packet.nmb;
00261                         debug_nmb_packet(p2);
00262                         
00263                         if (nmb2->header.opcode != 0 ||
00264                             nmb2->header.nm_flags.bcast ||
00265                             nmb2->header.rcode ||
00266                             !nmb2->header.ancount ||
00267                             nmb2->answers->rr_type != 0x21) {
00268                                 /* XXXX what do we do with this? could be a
00269                                    redirect, but we'll discard it for the
00270                                    moment */
00271                                 free_packet(p2);
00272                                 continue;
00273                         }
00274 
00275                         ret = parse_node_status(&nmb2->answers->rdata[0], num_names, extra);
00276                         free_packet(p2);
00277                         return ret;
00278                 }
00279         }
00280         
00281         return NULL;
00282 }
00283 
00284 /****************************************************************************
00285  Find the first type XX name in a node status reply - used for finding
00286  a servers name given its IP. Return the matched name in *name.
00287 **************************************************************************/
00288 
00289 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, fstring name)
00290 {
00291         NODE_STATUS_STRUCT *status = NULL;
00292         struct nmb_name nname;
00293         int count, i;
00294         int sock;
00295         BOOL result = False;
00296 
00297         if (lp_disable_netbios()) {
00298                 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
00299                 return False;
00300         }
00301 
00302         DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, 
00303                    q_type, inet_ntoa(to_ip)));
00304 
00305         /* Check the cache first. */
00306 
00307         if (namecache_status_fetch(q_name, q_type, type, to_ip, name))
00308                 return True;
00309 
00310         sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
00311         if (sock == -1)
00312                 goto done;
00313 
00314         /* W2K PDC's seem not to respond to '*'#0. JRA */
00315         make_nmb_name(&nname, q_name, q_type);
00316         status = node_status_query(sock, &nname, to_ip, &count, NULL);
00317         close(sock);
00318         if (!status)
00319                 goto done;
00320 
00321         for (i=0;i<count;i++) {
00322                 if (status[i].type == type)
00323                         break;
00324         }
00325         if (i == count)
00326                 goto done;
00327 
00328         pull_ascii_nstring(name, sizeof(fstring), status[i].name);
00329 
00330         /* Store the result in the cache. */
00331         /* but don't store an entry for 0x1c names here.  Here we have 
00332            a single host and DOMAIN<0x1c> names should be a list of hosts */
00333            
00334         if ( q_type != 0x1c )
00335                 namecache_status_store(q_name, q_type, type, to_ip, name);
00336 
00337         result = True;
00338 
00339  done:
00340         SAFE_FREE(status);
00341 
00342         DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
00343 
00344         if (result)
00345                 DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip)));
00346 
00347         DEBUG(10, ("\n"));      
00348 
00349         return result;
00350 }
00351 
00352 /*
00353   comparison function used by sort_ip_list
00354 */
00355 
00356 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
00357 {
00358         int max_bits1=0, max_bits2=0;
00359         int num_interfaces = iface_count();
00360         int i;
00361 
00362         for (i=0;i<num_interfaces;i++) {
00363                 struct in_addr ip;
00364                 int bits1, bits2;
00365                 ip = *iface_n_bcast(i);
00366                 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
00367                 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
00368                 max_bits1 = MAX(bits1, max_bits1);
00369                 max_bits2 = MAX(bits2, max_bits2);
00370         }       
00371         
00372         /* bias towards directly reachable IPs */
00373         if (iface_local(*ip1)) {
00374                 max_bits1 += 32;
00375         }
00376         if (iface_local(*ip2)) {
00377                 max_bits2 += 32;
00378         }
00379 
00380         return max_bits2 - max_bits1;
00381 }
00382 
00383 /*******************************************************************
00384  compare 2 ldap IPs by nearness to our interfaces - used in qsort
00385 *******************************************************************/
00386 
00387 int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
00388 {
00389         int result;
00390         
00391         if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 )
00392                 return result;
00393                 
00394         if ( ip1->port > ip2->port )
00395                 return 1;
00396         
00397         if ( ip1->port < ip2->port )
00398                 return -1;
00399                 
00400         return 0;
00401 }
00402 
00403 /*
00404   sort an IP list so that names that are close to one of our interfaces 
00405   are at the top. This prevents the problem where a WINS server returns an IP that
00406   is not reachable from our subnet as the first match
00407 */
00408 
00409 static void sort_ip_list(struct in_addr *iplist, int count)
00410 {
00411         if (count <= 1) {
00412                 return;
00413         }
00414 
00415         qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);    
00416 }
00417 
00418 static void sort_ip_list2(struct ip_service *iplist, int count)
00419 {
00420         if (count <= 1) {
00421                 return;
00422         }
00423 
00424         qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare); 
00425 }
00426 
00427 /**********************************************************************
00428  Remove any duplicate address/port pairs in the list 
00429  *********************************************************************/
00430 
00431 static int remove_duplicate_addrs2( struct ip_service *iplist, int count )
00432 {
00433         int i, j;
00434         
00435         DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n"));
00436         
00437         /* one loop to remove duplicates */
00438         for ( i=0; i<count; i++ ) {
00439                 if ( is_zero_ip(iplist[i].ip) )
00440                         continue;
00441                                         
00442                 for ( j=i+1; j<count; j++ ) {
00443                         if ( ip_service_equal(iplist[i], iplist[j]) )
00444                                 zero_ip(&iplist[j].ip);
00445                 }
00446         }
00447                         
00448         /* one loop to clean up any holes we left */
00449         /* first ip should never be a zero_ip() */
00450         for (i = 0; i<count; ) {
00451                 if ( is_zero_ip(iplist[i].ip) ) {
00452                         if (i != count-1 )
00453                                 memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i]));
00454                         count--;
00455                         continue;
00456                 }
00457                 i++;
00458         }
00459 
00460         return count;
00461 }
00462 
00463 /****************************************************************************
00464  Do a netbios name query to find someones IP.
00465  Returns an array of IP addresses or NULL if none.
00466  *count will be set to the number of addresses returned.
00467  *timed_out is set if we failed by timing out
00468 ****************************************************************************/
00469 
00470 struct in_addr *name_query(int fd,const char *name,int name_type, 
00471                            BOOL bcast,BOOL recurse,
00472                            struct in_addr to_ip, int *count, int *flags,
00473                            BOOL *timed_out)
00474 {
00475         BOOL found=False;
00476         int i, retries = 3;
00477         int retry_time = bcast?250:2000;
00478         struct timeval tval;
00479         struct packet_struct p;
00480         struct packet_struct *p2;
00481         struct nmb_packet *nmb = &p.packet.nmb;
00482         struct in_addr *ip_list = NULL;
00483 
00484         if (lp_disable_netbios()) {
00485                 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
00486                 return NULL;
00487         }
00488 
00489         if (timed_out) {
00490                 *timed_out = False;
00491         }
00492         
00493         memset((char *)&p,'\0',sizeof(p));
00494         (*count) = 0;
00495         (*flags) = 0;
00496         
00497         nmb->header.name_trn_id = generate_trn_id();
00498         nmb->header.opcode = 0;
00499         nmb->header.response = False;
00500         nmb->header.nm_flags.bcast = bcast;
00501         nmb->header.nm_flags.recursion_available = False;
00502         nmb->header.nm_flags.recursion_desired = recurse;
00503         nmb->header.nm_flags.trunc = False;
00504         nmb->header.nm_flags.authoritative = False;
00505         nmb->header.rcode = 0;
00506         nmb->header.qdcount = 1;
00507         nmb->header.ancount = 0;
00508         nmb->header.nscount = 0;
00509         nmb->header.arcount = 0;
00510         
00511         make_nmb_name(&nmb->question.question_name,name,name_type);
00512         
00513         nmb->question.question_type = 0x20;
00514         nmb->question.question_class = 0x1;
00515         
00516         p.ip = to_ip;
00517         p.port = NMB_PORT;
00518         p.fd = fd;
00519         p.timestamp = time(NULL);
00520         p.packet_type = NMB_PACKET;
00521         
00522         GetTimeOfDay(&tval);
00523         
00524         if (!send_packet(&p)) 
00525                 return NULL;
00526         
00527         retries--;
00528         
00529         while (1) {
00530                 struct timeval tval2;
00531                 
00532                 GetTimeOfDay(&tval2);
00533                 if (TvalDiff(&tval,&tval2) > retry_time) {
00534                         if (!retries)
00535                                 break;
00536                         if (!found && !send_packet(&p))
00537                                 return NULL;
00538                         GetTimeOfDay(&tval);
00539                         retries--;
00540                 }
00541                 
00542                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
00543                         struct nmb_packet *nmb2 = &p2->packet.nmb;
00544                         debug_nmb_packet(p2);
00545                         
00546                         /* If we get a Negative Name Query Response from a WINS
00547                          * server, we should report it and give up.
00548                          */
00549                         if( 0 == nmb2->header.opcode            /* A query response   */
00550                             && !(bcast)                 /* from a WINS server */
00551                             && nmb2->header.rcode               /* Error returned     */
00552                                 ) {
00553                                 
00554                                 if( DEBUGLVL( 3 ) ) {
00555                                         /* Only executed if DEBUGLEVEL >= 3 */
00556                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
00557                                         switch( nmb2->header.rcode ) {
00558                                         case 0x01:
00559                                                 dbgtext( "Request was invalidly formatted.\n" );
00560                                                 break;
00561                                         case 0x02:
00562                                                 dbgtext( "Problem with NBNS, cannot process name.\n");
00563                                                 break;
00564                                         case 0x03:
00565                                                 dbgtext( "The name requested does not exist.\n" );
00566                                                 break;
00567                                         case 0x04:
00568                                                 dbgtext( "Unsupported request error.\n" );
00569                                                 break;
00570                                         case 0x05:
00571                                                 dbgtext( "Query refused error.\n" );
00572                                                 break;
00573                                         default:
00574                                                 dbgtext( "Unrecognized error code.\n" );
00575                                                 break;
00576                                         }
00577                                 }
00578                                 free_packet(p2);
00579                                 return( NULL );
00580                         }
00581                         
00582                         if (nmb2->header.opcode != 0 ||
00583                             nmb2->header.nm_flags.bcast ||
00584                             nmb2->header.rcode ||
00585                             !nmb2->header.ancount) {
00586                                 /* 
00587                                  * XXXX what do we do with this? Could be a
00588                                  * redirect, but we'll discard it for the
00589                                  * moment.
00590                                  */
00591                                 free_packet(p2);
00592                                 continue;
00593                         }
00594                         
00595                         ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
00596                                                 (*count) + nmb2->answers->rdlength/6 );
00597                         
00598                         if (!ip_list) {
00599                                 DEBUG(0,("name_query: Realloc failed.\n"));
00600                                 free_packet(p2);
00601                                 return( NULL );
00602                         }
00603                         
00604                         DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
00605                         for (i=0;i<nmb2->answers->rdlength/6;i++) {
00606                                 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
00607                                 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
00608                                 (*count)++;
00609                         }
00610                         DEBUGADD(2,(")\n"));
00611                         
00612                         found=True;
00613                         retries=0;
00614                         /* We add the flags back ... */
00615                         if (nmb2->header.response)
00616                                 (*flags) |= NM_FLAGS_RS;
00617                         if (nmb2->header.nm_flags.authoritative)
00618                                 (*flags) |= NM_FLAGS_AA;
00619                         if (nmb2->header.nm_flags.trunc)
00620                                 (*flags) |= NM_FLAGS_TC;
00621                         if (nmb2->header.nm_flags.recursion_desired)
00622                                 (*flags) |= NM_FLAGS_RD;
00623                         if (nmb2->header.nm_flags.recursion_available)
00624                                 (*flags) |= NM_FLAGS_RA;
00625                         if (nmb2->header.nm_flags.bcast)
00626                                 (*flags) |= NM_FLAGS_B;
00627                         free_packet(p2);
00628                         /*
00629                          * If we're doing a unicast lookup we only
00630                          * expect one reply. Don't wait the full 2
00631                          * seconds if we got one. JRA.
00632                          */
00633                         if(!bcast && found)
00634                                 break;
00635                 }
00636         }
00637 
00638         /* only set timed_out if we didn't fund what we where looking for*/
00639         
00640         if ( !found && timed_out ) {
00641                 *timed_out = True;
00642         }
00643 
00644         /* sort the ip list so we choose close servers first if possible */
00645         sort_ip_list(ip_list, *count);
00646 
00647         return ip_list;
00648 }
00649 
00650 /********************************************************
00651  Start parsing the lmhosts file.
00652 *********************************************************/
00653 
00654 XFILE *startlmhosts(char *fname)
00655 {
00656         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
00657         if (!fp) {
00658                 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
00659                          fname, strerror(errno)));
00660                 return NULL;
00661         }
00662         return fp;
00663 }
00664 
00665 /********************************************************
00666  Parse the next line in the lmhosts file.
00667 *********************************************************/
00668 
00669 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
00670 {
00671         pstring line;
00672 
00673         while(!x_feof(fp) && !x_ferror(fp)) {
00674                 pstring ip,flags,extra;
00675                 const char *ptr;
00676                 char *ptr1;
00677                 int count = 0;
00678 
00679                 *name_type = -1;
00680 
00681                 if (!fgets_slash(line,sizeof(pstring),fp)) {
00682                         continue;
00683                 }
00684 
00685                 if (*line == '#') {
00686                         continue;
00687                 }
00688 
00689                 pstrcpy(ip,"");
00690                 pstrcpy(name,"");
00691                 pstrcpy(flags,"");
00692 
00693                 ptr = line;
00694 
00695                 if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
00696                         ++count;
00697                 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
00698                         ++count;
00699                 if (next_token(&ptr,flags,NULL, sizeof(flags)))
00700                         ++count;
00701                 if (next_token(&ptr,extra,NULL, sizeof(extra)))
00702                         ++count;
00703 
00704                 if (count <= 0)
00705                         continue;
00706 
00707                 if (count > 0 && count < 2) {
00708                         DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
00709                         continue;
00710                 }
00711 
00712                 if (count >= 4) {
00713                         DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
00714                         continue;
00715                 }
00716 
00717                 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
00718 
00719                 if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
00720                         DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
00721                         continue;
00722                 }
00723 
00724                 *ipaddr = *interpret_addr2(ip);
00725 
00726                 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
00727                         then only add that name type. */
00728                 if((ptr1 = strchr_m(name, '#')) != NULL) {
00729                         char *endptr;
00730                         ptr1++;
00731 
00732                         *name_type = (int)strtol(ptr1, &endptr, 16);
00733                         if(!*ptr1 || (endptr == ptr1)) {
00734                                 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
00735                                 continue;
00736                         }
00737 
00738                         *(--ptr1) = '\0'; /* Truncate at the '#' */
00739                 }
00740 
00741                 return True;
00742         }
00743 
00744         return False;
00745 }
00746 
00747 /********************************************************
00748  Finish parsing the lmhosts file.
00749 *********************************************************/
00750 
00751 void endlmhosts(XFILE *fp)
00752 {
00753         x_fclose(fp);
00754 }
00755 
00756 /********************************************************
00757  convert an array if struct in_addrs to struct ip_service
00758  return False on failure.  Port is set to PORT_NONE;
00759 *********************************************************/
00760 
00761 static BOOL convert_ip2service( struct ip_service **return_iplist, struct in_addr *ip_list, int count )
00762 {
00763         int i;
00764 
00765         if ( count==0 || !ip_list )
00766                 return False;
00767                 
00768         /* copy the ip address; port will be PORT_NONE */
00769         if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
00770                 DEBUG(0,("convert_ip2service: malloc failed for %d enetries!\n", count ));
00771                 return False;
00772         }
00773         
00774         for ( i=0; i<count; i++ ) {
00775                 (*return_iplist)[i].ip   = ip_list[i];
00776                 (*return_iplist)[i].port = PORT_NONE;
00777         }
00778 
00779         return True;
00780 }       
00781 /********************************************************
00782  Resolve via "bcast" method.
00783 *********************************************************/
00784 
00785 BOOL name_resolve_bcast(const char *name, int name_type,
00786                         struct ip_service **return_iplist, int *return_count)
00787 {
00788         int sock, i;
00789         int num_interfaces = iface_count();
00790         struct in_addr *ip_list;
00791         BOOL ret;
00792 
00793         if (lp_disable_netbios()) {
00794                 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
00795                 return False;
00796         }
00797 
00798         *return_iplist = NULL;
00799         *return_count = 0;
00800         
00801         /*
00802          * "bcast" means do a broadcast lookup on all the local interfaces.
00803          */
00804 
00805         DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
00806 
00807         sock = open_socket_in( SOCK_DGRAM, 0, 3,
00808                                interpret_addr(lp_socket_address()), True );
00809 
00810         if (sock == -1) return False;
00811 
00812         set_socket_options(sock,"SO_BROADCAST");
00813         /*
00814          * Lookup the name on all the interfaces, return on
00815          * the first successful match.
00816          */
00817         for( i = num_interfaces-1; i >= 0; i--) {
00818                 struct in_addr sendto_ip;
00819                 int flags;
00820                 /* Done this way to fix compiler error on IRIX 5.x */
00821                 sendto_ip = *iface_n_bcast(i);
00822                 ip_list = name_query(sock, name, name_type, True, 
00823                                     True, sendto_ip, return_count, &flags, NULL);
00824                 if( ip_list ) 
00825                         goto success;
00826         }
00827         
00828         /* failed - no response */
00829         
00830         close(sock);
00831         return False;
00832         
00833 success:
00834         ret = True;
00835         if ( !convert_ip2service(return_iplist, ip_list, *return_count) )
00836                 ret = False;
00837         
00838         SAFE_FREE( ip_list );
00839         close(sock);
00840         return ret;
00841 }
00842 
00843 /********************************************************
00844  Resolve via "wins" method.
00845 *********************************************************/
00846 
00847 BOOL resolve_wins(const char *name, int name_type,
00848                   struct ip_service **return_iplist, int *return_count)
00849 {
00850         int sock, t, i;
00851         char **wins_tags;
00852         struct in_addr src_ip, *ip_list = NULL;
00853         BOOL ret;
00854 
00855         if (lp_disable_netbios()) {
00856                 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
00857                 return False;
00858         }
00859 
00860         *return_iplist = NULL;
00861         *return_count = 0;
00862         
00863         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
00864 
00865         if (wins_srv_count() < 1) {
00866                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
00867                 return False;
00868         }
00869 
00870         /* we try a lookup on each of the WINS tags in turn */
00871         wins_tags = wins_srv_tags();
00872 
00873         if (!wins_tags) {
00874                 /* huh? no tags?? give up in disgust */
00875                 return False;
00876         }
00877 
00878         /* the address we will be sending from */
00879         src_ip = *interpret_addr2(lp_socket_address());
00880 
00881         /* in the worst case we will try every wins server with every
00882            tag! */
00883         for (t=0; wins_tags && wins_tags[t]; t++) {
00884                 int srv_count = wins_srv_count_tag(wins_tags[t]);
00885                 for (i=0; i<srv_count; i++) {
00886                         struct in_addr wins_ip;
00887                         int flags;
00888                         BOOL timed_out;
00889 
00890                         wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
00891 
00892                         if (global_in_nmbd && ismyip(wins_ip)) {
00893                                 /* yikes! we'll loop forever */
00894                                 continue;
00895                         }
00896 
00897                         /* skip any that have been unresponsive lately */
00898                         if (wins_srv_is_dead(wins_ip, src_ip)) {
00899                                 continue;
00900                         }
00901 
00902                         DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
00903 
00904                         sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
00905                         if (sock == -1) {
00906                                 continue;
00907                         }
00908 
00909                         ip_list = name_query(sock,name,name_type, False, 
00910                                                     True, wins_ip, return_count, &flags, 
00911                                                     &timed_out);
00912                                                     
00913                         /* exit loop if we got a list of addresses */
00914                         
00915                         if ( ip_list ) 
00916                                 goto success;
00917                                 
00918                         close(sock);
00919 
00920                         if (timed_out) {
00921                                 /* Timed out wating for WINS server to respond.  Mark it dead. */
00922                                 wins_srv_died(wins_ip, src_ip);
00923                         } else {
00924                                 /* The name definately isn't in this
00925                                    group of WINS servers. goto the next group  */
00926                                 break;
00927                         }
00928                 }
00929         }
00930 
00931         wins_srv_tags_free(wins_tags);
00932         return False;
00933 
00934 success:
00935         ret = True;
00936         if ( !convert_ip2service( return_iplist, ip_list, *return_count ) )
00937                 ret = False;
00938         
00939         SAFE_FREE( ip_list );
00940         wins_srv_tags_free(wins_tags);
00941         close(sock);
00942         
00943         return ret;
00944 }
00945 
00946 /********************************************************
00947  Resolve via "lmhosts" method.
00948 *********************************************************/
00949 
00950 static BOOL resolve_lmhosts(const char *name, int name_type,
00951                          struct ip_service **return_iplist, int *return_count)
00952 {
00953         /*
00954          * "lmhosts" means parse the local lmhosts file.
00955          */
00956         
00957         XFILE *fp;
00958         pstring lmhost_name;
00959         int name_type2;
00960         struct in_addr return_ip;
00961         BOOL result = False;
00962 
00963         *return_iplist = NULL;
00964         *return_count = 0;
00965 
00966         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
00967 
00968         fp = startlmhosts(dyn_LMHOSTSFILE);
00969 
00970         if ( fp == NULL )
00971                 return False;
00972 
00973         while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) 
00974         {
00975 
00976                 if (!strequal(name, lmhost_name))
00977                         continue;
00978 
00979                 if ((name_type2 != -1) && (name_type != name_type2))
00980                         continue;
00981 
00982                 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist), struct ip_service,
00983                                         (*return_count)+1);
00984 
00985                 if ((*return_iplist) == NULL) {
00986                         endlmhosts(fp);
00987                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
00988                         return False;
00989                 }
00990 
00991                 (*return_iplist)[*return_count].ip   = return_ip;
00992                 (*return_iplist)[*return_count].port = PORT_NONE;
00993                 *return_count += 1;
00994 
00995                 /* we found something */
00996                 result = True;
00997 
00998                 /* Multiple names only for DC lookup */
00999                 if (name_type != 0x1c)
01000                         break;
01001         }
01002 
01003         endlmhosts(fp);
01004 
01005         return result;
01006 }
01007 
01008 
01009 /********************************************************
01010  Resolve via "hosts" method.
01011 *********************************************************/
01012 
01013 static BOOL resolve_hosts(const char *name, int name_type,
01014                          struct ip_service **return_iplist, int *return_count)
01015 {
01016         /*
01017          * "host" means do a localhost, or dns lookup.
01018          */
01019         struct hostent *hp;
01020         
01021         if ( name_type != 0x20 && name_type != 0x0) {
01022                 DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
01023                 return False;
01024         }
01025 
01026         *return_iplist = NULL;
01027         *return_count = 0;
01028 
01029         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
01030         
01031         if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
01032                 struct in_addr return_ip;
01033                 putip((char *)&return_ip,(char *)hp->h_addr);
01034                 *return_iplist = SMB_MALLOC_P(struct ip_service);
01035                 if(*return_iplist == NULL) {
01036                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
01037                         return False;
01038                 }
01039                 (*return_iplist)->ip   = return_ip;
01040                 (*return_iplist)->port = PORT_NONE;
01041                 *return_count = 1;
01042                 return True;
01043         }
01044         return False;
01045 }
01046 
01047 /********************************************************
01048  Resolve via "ADS" method.
01049 *********************************************************/
01050 
01051 static BOOL resolve_ads(const char *name, int name_type,
01052                         const char *sitename,
01053                          struct ip_service **return_iplist, int *return_count)
01054 {
01055         int                     i, j;
01056         NTSTATUS                status;
01057         TALLOC_CTX              *ctx;
01058         struct dns_rr_srv       *dcs = NULL;
01059         int                     numdcs = 0;
01060         int                     numaddrs = 0;
01061 
01062         if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
01063                 return False;
01064                 
01065         DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
01066                 name));
01067                         
01068         if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
01069                 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
01070                 return False;
01071         }
01072 
01073         if (name_type == KDC_NAME_TYPE) {
01074                 status = ads_dns_query_kdcs(ctx, name, sitename, &dcs, &numdcs);
01075         } else {
01076                 status = ads_dns_query_dcs(ctx, name, sitename, &dcs, &numdcs);
01077         }
01078         if ( !NT_STATUS_IS_OK( status ) ) {
01079                 talloc_destroy(ctx);
01080                 return False;
01081         }
01082 
01083         for (i=0;i<numdcs;i++) {
01084                 numaddrs += MAX(dcs[i].num_ips,1);
01085         }
01086                 
01087         if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
01088                 DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
01089                 talloc_destroy(ctx);
01090                 return False;
01091         }
01092         
01093         /* now unroll the list of IP addresses */
01094 
01095         *return_count = 0;
01096         i = 0;
01097         j = 0;
01098         while ( i < numdcs && (*return_count<numaddrs) ) {
01099                 struct ip_service *r = &(*return_iplist)[*return_count];
01100 
01101                 r->port = dcs[i].port;
01102                 
01103                 /* If we don't have an IP list for a name, lookup it up */
01104                 
01105                 if ( !dcs[i].ips ) {
01106                         r->ip = *interpret_addr2(dcs[i].hostname);
01107                         i++;
01108                         j = 0;
01109                 } else {
01110                         /* use the IP addresses from the SRV sresponse */
01111                         
01112                         if ( j >= dcs[i].num_ips ) {
01113                                 i++;
01114                                 j = 0;
01115                                 continue;
01116                         }
01117                         
01118                         r->ip = dcs[i].ips[j];
01119                         j++;
01120                 }
01121                         
01122                 /* make sure it is a valid IP.  I considered checking the negative
01123                    connection cache, but this is the wrong place for it.  Maybe only
01124                    as a hac.  After think about it, if all of the IP addresses retuend
01125                    from DNS are dead, what hope does a netbios name lookup have?
01126                    The standard reason for falling back to netbios lookups is that 
01127                    our DNS server doesn't know anything about the DC's   -- jerry */    
01128                            
01129                 if ( ! is_zero_ip(r->ip) )
01130                         (*return_count)++;
01131         }
01132                 
01133         talloc_destroy(ctx);
01134         return True;
01135 }
01136 
01137 /*******************************************************************
01138  Internal interface to resolve a name into an IP address.
01139  Use this function if the string is either an IP address, DNS
01140  or host name or NetBIOS name. This uses the name switch in the
01141  smb.conf to determine the order of name resolution.
01142  
01143  Added support for ip addr/port to support ADS ldap servers.
01144  the only place we currently care about the port is in the 
01145  resolve_hosts() when looking up DC's via SRV RR entries in DNS
01146 **********************************************************************/
01147 
01148 BOOL internal_resolve_name(const char *name, int name_type,
01149                            const char *sitename,
01150                            struct ip_service **return_iplist, 
01151                            int *return_count, const char *resolve_order)
01152 {
01153         pstring name_resolve_list;
01154         fstring tok;
01155         const char *ptr;
01156         BOOL allones = (strcmp(name,"255.255.255.255") == 0);
01157         BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
01158         BOOL is_address = is_ipaddress(name);
01159         BOOL result = False;
01160         int i;
01161 
01162         *return_iplist = NULL;
01163         *return_count = 0;
01164 
01165         DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
01166                         name, name_type, sitename ? sitename : NULL));
01167 
01168         if (allzeros || allones || is_address) {
01169   
01170                 if ( (*return_iplist = SMB_MALLOC_P(struct ip_service)) == NULL ) {
01171                         DEBUG(0,("internal_resolve_name: malloc fail !\n"));
01172                         return False;
01173                 }
01174         
01175                 if(is_address) { 
01176                         /* ignore the port here */
01177                         (*return_iplist)->port = PORT_NONE;
01178                 
01179                         /* if it's in the form of an IP address then get the lib to interpret it */
01180                         if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
01181                                 DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
01182                                 SAFE_FREE(*return_iplist);
01183                                 return False;
01184                         }
01185                 } else {
01186                         (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
01187                 }
01188                 *return_count = 1;
01189                 return True;
01190         }
01191   
01192         /* Check name cache */
01193 
01194         if (namecache_fetch(name, name_type, return_iplist, return_count)) {
01195                 /* This could be a negative response */
01196                 return (*return_count > 0);
01197         }
01198 
01199         /* set the name resolution order */
01200 
01201         if ( strcmp( resolve_order, "NULL") == 0 ) {
01202                 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
01203                 return False;
01204         }
01205   
01206         if ( !resolve_order ) {
01207                 pstrcpy(name_resolve_list, lp_name_resolve_order());
01208         } else {
01209                 pstrcpy(name_resolve_list, resolve_order);
01210         }
01211 
01212         if ( !name_resolve_list[0] ) {
01213                 ptr = "host";
01214         } else {
01215                 ptr = name_resolve_list;
01216         }
01217 
01218         /* iterate through the name resolution backends */
01219   
01220         while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
01221                 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
01222                         if (resolve_hosts(name, name_type, return_iplist, return_count)) {
01223                                 result = True;
01224                                 goto done;
01225                         }
01226                 } else if(strequal( tok, "kdc")) {
01227                         /* deal with KDC_NAME_TYPE names here.  This will result in a
01228                                 SRV record lookup */
01229                         if (resolve_ads(name, KDC_NAME_TYPE, sitename, return_iplist, return_count)) {
01230                                 result = True;
01231                                 /* Ensure we don't namecache this with the KDC port. */
01232                                 name_type = KDC_NAME_TYPE;
01233                                 goto done;
01234                         }
01235                 } else if(strequal( tok, "ads")) {
01236                         /* deal with 0x1c names here.  This will result in a
01237                                 SRV record lookup */
01238                         if (resolve_ads(name, name_type, sitename, return_iplist, return_count)) {
01239                                 result = True;
01240                                 goto done;
01241                         }
01242                 } else if(strequal( tok, "lmhosts")) {
01243                         if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
01244                                 result = True;
01245                                 goto done;
01246                         }
01247                 } else if(strequal( tok, "wins")) {
01248                         /* don't resolve 1D via WINS */
01249                         if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) {
01250                                 result = True;
01251                                 goto done;
01252                         }
01253                 } else if(strequal( tok, "bcast")) {
01254                         if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
01255                                 result = True;
01256                                 goto done;
01257                         }
01258                 } else {
01259                         DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
01260                 }
01261         }
01262 
01263         /* All of the resolve_* functions above have returned false. */
01264 
01265         SAFE_FREE(*return_iplist);
01266         *return_count = 0;
01267 
01268         return False;
01269 
01270   done:
01271 
01272         /* Remove duplicate entries.  Some queries, notably #1c (domain
01273         controllers) return the PDC in iplist[0] and then all domain
01274         controllers including the PDC in iplist[1..n].  Iterating over
01275         the iplist when the PDC is down will cause two sets of timeouts. */
01276 
01277         if ( *return_count ) {
01278                 *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
01279         }
01280  
01281         /* Save in name cache */
01282         if ( DEBUGLEVEL >= 100 ) {
01283                 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
01284                         DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
01285                                 name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
01286         }
01287    
01288         namecache_store(name, name_type, *return_count, *return_iplist);
01289 
01290         /* Display some debugging info */
01291 
01292         if ( DEBUGLEVEL >= 10 ) {
01293                 DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count));
01294 
01295                 for (i = 0; i < *return_count; i++) {
01296                         DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
01297                 }
01298                 DEBUG(10, ("\n"));
01299         }
01300   
01301         return result;
01302 }
01303 
01304 /********************************************************
01305  Internal interface to resolve a name into one IP address.
01306  Use this function if the string is either an IP address, DNS
01307  or host name or NetBIOS name. This uses the name switch in the
01308  smb.conf to determine the order of name resolution.
01309 *********************************************************/
01310 
01311 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
01312 {
01313         struct ip_service *ip_list = NULL;
01314         char *sitename = sitename_fetch(lp_realm()); /* wild guess */
01315         int count = 0;
01316 
01317         if (is_ipaddress(name)) {
01318                 *return_ip = *interpret_addr2(name);
01319                 SAFE_FREE(sitename);
01320                 return True;
01321         }
01322 
01323         if (internal_resolve_name(name, name_type, sitename, &ip_list, &count, lp_name_resolve_order())) {
01324                 int i;
01325                 
01326                 /* only return valid addresses for TCP connections */
01327                 for (i=0; i<count; i++) {
01328                         char *ip_str = inet_ntoa(ip_list[i].ip);
01329                         if (ip_str &&
01330                             strcmp(ip_str, "255.255.255.255") != 0 &&
01331                             strcmp(ip_str, "0.0.0.0") != 0) 
01332                         {
01333                                 *return_ip = ip_list[i].ip;
01334                                 SAFE_FREE(ip_list);
01335                                 SAFE_FREE(sitename);
01336                                 return True;
01337                         }
01338                 }
01339         }
01340         
01341         SAFE_FREE(ip_list);
01342         SAFE_FREE(sitename);
01343         return False;
01344 }
01345 
01346 /********************************************************
01347  Find the IP address of the master browser or DMB for a workgroup.
01348 *********************************************************/
01349 
01350 BOOL find_master_ip(const char *group, struct in_addr *master_ip)
01351 {
01352         struct ip_service *ip_list = NULL;
01353         int count = 0;
01354 
01355         if (lp_disable_netbios()) {
01356                 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
01357                 return False;
01358         }
01359 
01360         if (internal_resolve_name(group, 0x1D, NULL, &ip_list, &count, lp_name_resolve_order())) {
01361                 *master_ip = ip_list[0].ip;
01362                 SAFE_FREE(ip_list);
01363                 return True;
01364         }
01365         if(internal_resolve_name(group, 0x1B, NULL, &ip_list, &count, lp_name_resolve_order())) {
01366                 *master_ip = ip_list[0].ip;
01367                 SAFE_FREE(ip_list);
01368                 return True;
01369         }
01370 
01371         SAFE_FREE(ip_list);
01372         return False;
01373 }
01374 
01375 /********************************************************
01376  Get the IP address list of the primary domain controller
01377  for a domain.
01378 *********************************************************/
01379 
01380 BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
01381 {
01382         struct ip_service *ip_list = NULL;
01383         int count = 0;
01384 
01385         /* Look up #1B name */
01386 
01387         if (!internal_resolve_name(domain, 0x1b, NULL, &ip_list, &count, lp_name_resolve_order())) {
01388                 return False;
01389         }
01390 
01391         /* if we get more than 1 IP back we have to assume it is a
01392            multi-homed PDC and not a mess up */
01393 
01394         if ( count > 1 ) {
01395                 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));             
01396                 sort_ip_list2( ip_list, count );
01397         }
01398 
01399         *ip = ip_list[0].ip;
01400         
01401         SAFE_FREE(ip_list);
01402 
01403         return True;
01404 }
01405 
01406 /* Private enum type for lookups. */
01407 
01408 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
01409 
01410 /********************************************************
01411  Get the IP address list of the domain controllers for
01412  a domain.
01413 *********************************************************/
01414 
01415 static NTSTATUS get_dc_list(const char *domain, const char *sitename, struct ip_service **ip_list, 
01416                             int *count, enum dc_lookup_type lookup_type, int *ordered)
01417 {
01418         fstring resolve_order;
01419         char *saf_servername;
01420         pstring pserver;
01421         const char *p;
01422         char *port_str;
01423         int port;
01424         fstring name;
01425         int num_addresses = 0;
01426         int  local_count, i, j;
01427         struct ip_service *return_iplist = NULL;
01428         struct ip_service *auto_ip_list = NULL;
01429         BOOL done_auto_lookup = False;
01430         int auto_count = 0;
01431         NTSTATUS status;
01432 
01433         *ip_list = NULL;
01434         *count = 0;
01435 
01436         *ordered = False;
01437 
01438         /* if we are restricted to solely using DNS for looking
01439            up a domain controller, make sure that host lookups
01440            are enabled for the 'name resolve order'.  If host lookups
01441            are disabled and ads_only is True, then set the string to
01442            NULL. */
01443 
01444         fstrcpy( resolve_order, lp_name_resolve_order() );
01445         strlower_m( resolve_order );
01446         if ( lookup_type == DC_ADS_ONLY)  {
01447                 if ( strstr( resolve_order, "host" ) ) {
01448                         fstrcpy( resolve_order, "ads" );
01449 
01450                         /* DNS SRV lookups used by the ads resolver
01451                            are already sorted by priority and weight */
01452                         *ordered = True;
01453                 } else {
01454                         fstrcpy( resolve_order, "NULL" );
01455                 }
01456         } else if (lookup_type == DC_KDC_ONLY) {
01457                 /* DNS SRV lookups used by the ads/kdc resolver
01458                    are already sorted by priority and weight */
01459                 *ordered = True;
01460                 fstrcpy( resolve_order, "kdc" );
01461         }
01462 
01463         /* fetch the server we have affinity for.  Add the 
01464            'password server' list to a search for our domain controllers */
01465         
01466         saf_servername = saf_fetch( domain);
01467         
01468         if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
01469                 pstr_sprintf( pserver, "%s, %s", 
01470                         saf_servername ? saf_servername : "",
01471                         lp_passwordserver() );
01472         } else {
01473                 pstr_sprintf( pserver, "%s, *", 
01474                         saf_servername ? saf_servername : "" );
01475         }
01476 
01477         SAFE_FREE( saf_servername );
01478 
01479         /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
01480 
01481         if ( !*pserver ) {
01482                 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
01483                 /* TODO: change return type of internal_resolve_name to
01484                  * NTSTATUS */
01485                 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
01486                                           resolve_order)) {
01487                         status = NT_STATUS_OK;
01488                         goto out;
01489                 } else {
01490                         status = NT_STATUS_NO_LOGON_SERVERS;
01491                         goto out;
01492                 }
01493         }
01494 
01495         DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
01496         
01497         /*
01498          * if '*' appears in the "password server" list then add
01499          * an auto lookup to the list of manually configured
01500          * DC's.  If any DC is listed by name, then the list should be 
01501          * considered to be ordered 
01502          */
01503 
01504         p = pserver;
01505         while (next_token(&p,name,LIST_SEP,sizeof(name))) {
01506                 if (!done_auto_lookup && strequal(name, "*")) {
01507                         if (internal_resolve_name(domain, 0x1C, sitename, &auto_ip_list,
01508                                                   &auto_count, resolve_order))
01509                                 num_addresses += auto_count;
01510                         done_auto_lookup = True;
01511                         DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
01512                 } else  {
01513                         num_addresses++;
01514                 }
01515         }
01516 
01517         /* if we have no addresses and haven't done the auto lookup, then
01518            just return the list of DC's.  Or maybe we just failed. */
01519                    
01520         if ( (num_addresses == 0) ) {
01521                 if ( done_auto_lookup ) {
01522                         DEBUG(4,("get_dc_list: no servers found\n")); 
01523                         status = NT_STATUS_NO_LOGON_SERVERS;
01524                         goto out;
01525                 }
01526                 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
01527                                           resolve_order)) {
01528                         status = NT_STATUS_OK;
01529                         goto out;
01530                 } else {
01531                         status = NT_STATUS_NO_LOGON_SERVERS;
01532                         goto out;
01533                 }
01534         }
01535 
01536         if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
01537                 DEBUG(3,("get_dc_list: malloc fail !\n"));
01538                 status = NT_STATUS_NO_MEMORY;
01539                 goto out;
01540         }
01541 
01542         p = pserver;
01543         local_count = 0;
01544 
01545         /* fill in the return list now with real IP's */
01546                                 
01547         while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
01548                 struct in_addr name_ip;
01549                         
01550                 /* copy any addersses from the auto lookup */
01551                         
01552                 if ( strequal(name, "*") ) {
01553                         for ( j=0; j<auto_count; j++ ) {
01554                                 /* Check for and don't copy any known bad DC IP's. */
01555                                 if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain, 
01556                                                 inet_ntoa(auto_ip_list[j].ip)))) {
01557                                         DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
01558                                                 inet_ntoa(auto_ip_list[j].ip) ));
01559                                         continue;
01560                                 }
01561                                 return_iplist[local_count].ip   = auto_ip_list[j].ip;
01562                                 return_iplist[local_count].port = auto_ip_list[j].port;
01563                                 local_count++;
01564                         }
01565                         continue;
01566                 }
01567                         
01568                         
01569                 /* added support for address:port syntax for ads (not that I think 
01570                    anyone will ever run the LDAP server in an AD domain on something 
01571                    other than port 389 */
01572                         
01573                 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
01574                 if ( (port_str=strchr(name, ':')) != NULL ) {
01575                         *port_str = '\0';
01576                         port_str++;
01577                         port = atoi( port_str );
01578                 }
01579 
01580                 /* explicit lookup; resolve_name() will handle names & IP addresses */
01581                 if ( resolve_name( name, &name_ip, 0x20 ) ) {
01582 
01583                         /* Check for and don't copy any known bad DC IP's. */
01584                         if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
01585                                 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
01586                                 continue;
01587                         }
01588 
01589                         return_iplist[local_count].ip   = name_ip;
01590                         return_iplist[local_count].port = port;
01591                         local_count++;
01592                         *ordered = True;
01593                 }
01594         }
01595                                 
01596         /* need to remove duplicates in the list if we have any 
01597            explicit password servers */
01598            
01599         if ( local_count ) {
01600                 local_count = remove_duplicate_addrs2( return_iplist, local_count );
01601         }
01602                 
01603         if ( DEBUGLEVEL >= 4 ) {
01604                 DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, 
01605                         *ordered ? "":"un"));
01606                 DEBUG(4,("get_dc_list: "));
01607                 for ( i=0; i<local_count; i++ )
01608                         DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
01609                 DEBUGADD(4,("\n"));
01610         }
01611                         
01612         *ip_list = return_iplist;
01613         *count = local_count;
01614 
01615         status = ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
01616 
01617   out:
01618 
01619         if (!NT_STATUS_IS_OK(status)) {
01620                 SAFE_FREE(return_iplist);
01621                 *ip_list = NULL;
01622                 *count = 0;
01623         }
01624 
01625         SAFE_FREE(auto_ip_list);
01626 
01627         return status;
01628 }
01629 
01630 /*********************************************************************
01631  Small wrapper function to get the DC list and sort it if neccessary.
01632 *********************************************************************/
01633 
01634 NTSTATUS get_sorted_dc_list( const char *domain, const char *sitename, struct ip_service **ip_list, int *count, BOOL ads_only )
01635 {
01636         BOOL ordered;
01637         NTSTATUS status;
01638         enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
01639 
01640         DEBUG(8,("get_sorted_dc_list: attempting lookup for name %s (sitename %s) "
01641                 "using [%s]\n",
01642                 domain,
01643                 sitename ? sitename : "NULL",
01644                 (ads_only ? "ads" : lp_name_resolve_order())));
01645         
01646         if (ads_only) {
01647                 lookup_type = DC_ADS_ONLY;
01648         }
01649 
01650         status = get_dc_list(domain, sitename, ip_list, count, lookup_type, &ordered);
01651         if (!NT_STATUS_IS_OK(status)) {
01652                 return status; 
01653         }
01654                 
01655         /* only sort if we don't already have an ordered list */
01656         if ( !ordered ) {
01657                 sort_ip_list2( *ip_list, *count );
01658         }
01659                 
01660         return NT_STATUS_OK;
01661 }
01662 
01663 /*********************************************************************
01664  Get the KDC list - re-use all the logic in get_dc_list.
01665 *********************************************************************/
01666 
01667 NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_service **ip_list, int *count)
01668 {
01669         BOOL ordered;
01670         NTSTATUS status;
01671 
01672         *count = 0;
01673         *ip_list = NULL;
01674 
01675         status = get_dc_list(realm, sitename, ip_list, count, DC_KDC_ONLY, &ordered);
01676 
01677         if (!NT_STATUS_IS_OK(status)) {
01678                 return status; 
01679         }
01680 
01681         /* only sort if we don't already have an ordered list */
01682         if ( !ordered ) {
01683                 sort_ip_list2( *ip_list, *count );
01684         }
01685 
01686         return NT_STATUS_OK;
01687 }

Sambaに対してSat Aug 29 21:23:05 2009に生成されました。  doxygen 1.4.7