nmbd/nmbd_browsesync.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    NBT netbios routines and daemon - version 2
00004    Copyright (C) Andrew Tridgell 1994-1998
00005    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
00006    Copyright (C) Jeremy Allison 1994-2003
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021    
00022 */
00023 
00024 #include "includes.h"
00025 
00026 /* This is our local master browser list database. */
00027 extern struct browse_cache_record *lmb_browserlist;
00028 
00029 /****************************************************************************
00030 As a domain master browser, do a sync with a local master browser.
00031 **************************************************************************/
00032 
00033 static void sync_with_lmb(struct browse_cache_record *browc)
00034 {                     
00035         struct work_record *work;
00036 
00037         if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) {
00038                 if( DEBUGLVL( 0 ) ) {
00039                         dbgtext( "sync_with_lmb:\n" );
00040                         dbgtext( "Failed to get a workgroup for a local master browser " );
00041                         dbgtext( "cache entry workgroup " );
00042                         dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
00043                 }
00044                 return;
00045         }
00046 
00047         /* We should only be doing this if we are a domain master browser for
00048                 the given workgroup. Ensure this is so. */
00049 
00050         if(!AM_DOMAIN_MASTER_BROWSER(work)) {
00051                 if( DEBUGLVL( 0 ) ) {
00052                         dbgtext( "sync_with_lmb:\n" );
00053                         dbgtext( "We are trying to sync with a local master browser " );
00054                         dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
00055                         dbgtext( "and we are not a domain master browser on this workgroup.\n" );
00056                         dbgtext( "Error!\n" );
00057                 }
00058                 return;
00059         }
00060 
00061         if( DEBUGLVL( 2 ) ) {
00062                 dbgtext( "sync_with_lmb:\n" );
00063                 dbgtext( "Initiating sync with local master browser " );
00064                 dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
00065                 dbgtext( "for workgroup %s\n", browc->work_group );
00066         }
00067 
00068         sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
00069 
00070         browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
00071 }
00072 
00073 /****************************************************************************
00074 Sync or expire any local master browsers.
00075 **************************************************************************/
00076 
00077 void dmb_expire_and_sync_browser_lists(time_t t)
00078 {
00079         static time_t last_run = 0;
00080         struct browse_cache_record *browc;
00081 
00082         /* Only do this every 20 seconds. */  
00083         if (t - last_run < 20) 
00084                 return;
00085 
00086         last_run = t;
00087 
00088         expire_lmb_browsers(t);
00089 
00090         for( browc = lmb_browserlist; browc; browc = browc->next ) {
00091                 if (browc->sync_time < t)
00092                         sync_with_lmb(browc);
00093         }
00094 }
00095 
00096 /****************************************************************************
00097 As a local master browser, send an announce packet to the domain master browser.
00098 **************************************************************************/
00099 
00100 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
00101 {
00102         pstring outbuf;
00103         unstring myname;
00104         unstring dmb_name;
00105         char *p;
00106 
00107         if(ismyip(work->dmb_addr)) {
00108                 if( DEBUGLVL( 2 ) ) {
00109                         dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
00110                         dbgtext( "We are both a domain and a local master browser for " );
00111                         dbgtext( "workgroup %s.  ", work->work_group );
00112                         dbgtext( "Do not announce to ourselves.\n" );
00113                 }
00114                 return;
00115         }
00116 
00117         memset(outbuf,'\0',sizeof(outbuf));
00118         p = outbuf;
00119         SCVAL(p,0,ANN_MasterAnnouncement);
00120         p++;
00121 
00122         unstrcpy(myname, global_myname());
00123         strupper_m(myname);
00124         myname[15]='\0';
00125         /* The call below does CH_UNIX -> CH_DOS conversion. JRA */
00126         push_pstring_base(p, myname, outbuf);
00127 
00128         p = skip_string(outbuf,sizeof(outbuf),p);
00129 
00130         if( DEBUGLVL( 4 ) ) {
00131                 dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
00132                 dbgtext( "Sending local master announce to " );
00133                 dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
00134                                         work->work_group );
00135         }
00136 
00137         /* Target name for send_mailslot must be in UNIX charset. */
00138         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
00139         send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
00140                 global_myname(), 0x0, dmb_name, 0x0, 
00141                 work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
00142 }
00143 
00144 /****************************************************************************
00145 As a local master browser, do a sync with a domain master browser.
00146 **************************************************************************/
00147 
00148 static void sync_with_dmb(struct work_record *work)
00149 {
00150         unstring dmb_name;
00151 
00152         if( DEBUGLVL( 2 ) ) {
00153                 dbgtext( "sync_with_dmb:\n" );
00154                 dbgtext( "Initiating sync with domain master browser " );
00155                 dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
00156                 dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
00157                 dbgtext( "for workgroup %s\n", work->work_group );
00158         }
00159 
00160         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
00161         sync_browse_lists(work, dmb_name, work->dmb_name.name_type, 
00162                 work->dmb_addr, False, True);
00163 }
00164 
00165 /****************************************************************************
00166   Function called when a node status query to a domain master browser IP succeeds.
00167 ****************************************************************************/
00168 
00169 static void domain_master_node_status_success(struct subnet_record *subrec,
00170                                               struct userdata_struct *userdata,
00171                                               struct res_rec *answers,
00172                                               struct in_addr from_ip)
00173 {
00174         struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
00175 
00176         if( work == NULL ) {
00177                 if( DEBUGLVL( 0 ) ) {
00178                         dbgtext( "domain_master_node_status_success:\n" );
00179                         dbgtext( "Unable to find workgroup " );
00180                         dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
00181                 }
00182                 return;
00183         }
00184 
00185         if( DEBUGLVL( 3 ) ) {
00186                 dbgtext( "domain_master_node_status_success:\n" );
00187                 dbgtext( "Success in node status for workgroup " );
00188                 dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
00189         }
00190 
00191   /* Go through the list of names found at answers->rdata and look for
00192      the first SERVER<0x20> name. */
00193 
00194         if(answers->rdata != NULL) {
00195                 char *p = answers->rdata;
00196                 int numnames = CVAL(p, 0);
00197 
00198                 p += 1;
00199 
00200                 while (numnames--) {
00201                         unstring qname;
00202                         uint16 nb_flags;
00203                         int name_type;
00204 
00205                         pull_ascii_nstring(qname, sizeof(qname), p);
00206                         name_type = CVAL(p,15);
00207                         nb_flags = get_nb_flags(&p[16]);
00208                         trim_char(qname,'\0',' ');
00209 
00210                         p += 18;
00211 
00212                         if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) {
00213                                 struct nmb_name nmbname;
00214 
00215                                 make_nmb_name(&nmbname, qname, name_type);
00216 
00217                                 /* Copy the dmb name and IP address
00218                                         into the workgroup struct. */
00219 
00220                                 work->dmb_name = nmbname;
00221                                 putip((char *)&work->dmb_addr, &from_ip);
00222 
00223                                 /* Do the local master browser announcement to the domain
00224                                         master browser name and IP. */
00225                                 announce_local_master_browser_to_domain_master_browser( work );
00226 
00227                                 /* Now synchronise lists with the domain master browser. */
00228                                 sync_with_dmb(work);
00229                                 break;
00230                         }
00231                 }
00232         } else if( DEBUGLVL( 0 ) ) {
00233                 dbgtext( "domain_master_node_status_success:\n" );
00234                 dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
00235                 dbgtext( "%s.\n", inet_ntoa(from_ip) );
00236         }
00237 }
00238 
00239 /****************************************************************************
00240   Function called when a node status query to a domain master browser IP fails.
00241 ****************************************************************************/
00242 
00243 static void domain_master_node_status_fail(struct subnet_record *subrec,
00244                        struct response_record *rrec)
00245 {
00246         struct userdata_struct *userdata = rrec->userdata;
00247 
00248         if( DEBUGLVL( 0 ) ) {
00249                 dbgtext( "domain_master_node_status_fail:\n" );
00250                 dbgtext( "Doing a node status request to the domain master browser\n" );
00251                 dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" );
00252                 dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
00253                 dbgtext( "Cannot sync browser lists.\n" );
00254         }
00255 }
00256 
00257 /****************************************************************************
00258   Function called when a query for a WORKGROUP<1b> name succeeds.
00259 ****************************************************************************/
00260 
00261 static void find_domain_master_name_query_success(struct subnet_record *subrec,
00262                         struct userdata_struct *userdata_in,
00263                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
00264 {
00265         /* 
00266          * Unfortunately, finding the IP address of the Domain Master Browser,
00267          * as we have here, is not enough. We need to now do a sync to the
00268          * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
00269          * respond to the SMBSERVER name. To get this name from IP
00270          * address we do a Node status request, and look for the first
00271          * NAME<0x20> in the response, and take that as the server name.
00272          * We also keep a cache of the Domain Master Browser name for this
00273          * workgroup in the Workgroup struct, so that if the same IP addess
00274          * is returned every time, we don't need to do the node status
00275          * request.
00276          */
00277 
00278         struct work_record *work;
00279         struct nmb_name nmbname;
00280         struct userdata_struct *userdata;
00281         size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
00282         unstring qname;
00283 
00284         pull_ascii_nstring(qname, sizeof(qname), q_name->name);
00285         if( !(work = find_workgroup_on_subnet(subrec, qname)) ) {
00286                 if( DEBUGLVL( 0 ) ) {
00287                         dbgtext( "find_domain_master_name_query_success:\n" );
00288                         dbgtext( "Failed to find workgroup %s\n", qname);
00289                 }
00290         return;
00291   }
00292 
00293   /* First check if we already have a dmb for this workgroup. */
00294 
00295         if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) {
00296                 /* Do the local master browser announcement to the domain
00297                         master browser name and IP. */
00298                 announce_local_master_browser_to_domain_master_browser( work );
00299 
00300                 /* Now synchronise lists with the domain master browser. */
00301                 sync_with_dmb(work);
00302                 return;
00303         } else {
00304                 zero_ip(&work->dmb_addr);
00305         }
00306 
00307         /* Now initiate the node status request. */
00308 
00309         /* We used to use the name "*",0x0 here, but some Windows
00310          * servers don't answer that name. However we *know* they
00311          * have the name workgroup#1b (as we just looked it up).
00312          * So do the node status request on this name instead.
00313          * Found at LBL labs. JRA.
00314          */
00315 
00316         make_nmb_name(&nmbname,work->work_group,0x1b);
00317 
00318         /* Put the workgroup name into the userdata so we know
00319          what workgroup we're talking to when the reply comes
00320          back. */
00321 
00322         /* Setup the userdata_struct - this is copied so we can use
00323         a stack variable for this. */
00324 
00325         if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) {
00326                 DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
00327                 return;
00328         }
00329 
00330         userdata->copy_fn = NULL;
00331         userdata->free_fn = NULL;
00332         userdata->userdata_len = strlen(work->work_group)+1;
00333         overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1);
00334 
00335         node_status( subrec, &nmbname, answer_ip, 
00336                 domain_master_node_status_success,
00337                 domain_master_node_status_fail,
00338                 userdata);
00339 
00340         zero_free(userdata, size);
00341 }
00342 
00343 /****************************************************************************
00344   Function called when a query for a WORKGROUP<1b> name fails.
00345   ****************************************************************************/
00346 
00347 static void find_domain_master_name_query_fail(struct subnet_record *subrec,
00348                                     struct response_record *rrec,
00349                                     struct nmb_name *question_name, int fail_code)
00350 {
00351         if( DEBUGLVL( 0 ) ) {
00352                 dbgtext( "find_domain_master_name_query_fail:\n" );
00353                 dbgtext( "Unable to find the Domain Master Browser name " );
00354                 dbgtext( "%s for the workgroup %s.\n",
00355                         nmb_namestr(question_name), question_name->name );
00356                 dbgtext( "Unable to sync browse lists in this workgroup.\n" );
00357         }
00358 }
00359 
00360 /****************************************************************************
00361 As a local master browser for a workgroup find the domain master browser
00362 name, announce ourselves as local master browser to it and then pull the
00363 full domain browse lists from it onto the given subnet.
00364 **************************************************************************/
00365 
00366 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
00367                                                    struct work_record *work)
00368 {
00369         /* Only do this if we are using a WINS server. */
00370         if(we_are_a_wins_client() == False) {
00371                 if( DEBUGLVL( 10 ) ) {
00372                         dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
00373                         dbgtext( "Ignoring, as we are not a WINS client.\n" );
00374                 }
00375                 return;
00376         }
00377 
00378         /* First, query for the WORKGROUP<1b> name from the WINS server. */
00379         query_name(unicast_subnet, work->work_group, 0x1b,
00380              find_domain_master_name_query_success,
00381              find_domain_master_name_query_fail,
00382              NULL);
00383 }
00384 
00385 /****************************************************************************
00386   Function called when a node status query to a domain master browser IP succeeds.
00387   This function is only called on query to a Samba 1.9.18 or above WINS server.
00388 
00389   Note that adding the workgroup name is enough for this workgroup to be
00390   browsable by clients, as clients query the WINS server or broadcast 
00391   nets for the WORKGROUP<1b> name when they want to browse a workgroup
00392   they are not in. We do not need to do a sync with this Domain Master
00393   Browser in order for our browse clients to see machines in this workgroup.
00394   JRA.
00395 ****************************************************************************/
00396 
00397 static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
00398                                               struct userdata_struct *userdata,
00399                                               struct res_rec *answers,
00400                                               struct in_addr from_ip)
00401 {
00402         struct work_record *work;
00403         unstring server_name;
00404 
00405         server_name[0] = 0;
00406 
00407         if( DEBUGLVL( 3 ) ) {
00408                 dbgtext( "get_domain_master_name_node_status_success:\n" );
00409                 dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
00410         }
00411 
00412         /* 
00413          * Go through the list of names found at answers->rdata and look for
00414          * the first WORKGROUP<0x1b> name.
00415          */
00416 
00417         if(answers->rdata != NULL) {
00418                 char *p = answers->rdata;
00419                 int numnames = CVAL(p, 0);
00420 
00421                 p += 1;
00422 
00423                 while (numnames--) {
00424                         unstring qname;
00425                         uint16 nb_flags;
00426                         int name_type;
00427 
00428                         pull_ascii_nstring(qname, sizeof(qname), p);
00429                         name_type = CVAL(p,15);
00430                         nb_flags = get_nb_flags(&p[16]);
00431                         trim_char(qname,'\0',' ');
00432 
00433                         p += 18;
00434 
00435                         if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
00436                                         server_name[0] == 0) {
00437                                 /* this is almost certainly the server netbios name */
00438                                 unstrcpy(server_name, qname);
00439                                 continue;
00440                         }
00441 
00442                         if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) {
00443                                 if( DEBUGLVL( 5 ) ) {
00444                                         dbgtext( "get_domain_master_name_node_status_success:\n" );
00445                                         dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
00446                                         dbgtext( "is a domain master browser for workgroup " );
00447                                         dbgtext( "%s. Adding this name.\n", qname );
00448                                 }
00449 
00450                                 /* 
00451                                  * If we don't already know about this workgroup, add it
00452                                  * to the workgroup list on the unicast_subnet.
00453                                  */
00454 
00455                                 if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) {
00456                                         struct nmb_name nmbname;
00457                                         /* 
00458                                          * Add it - with an hour in the cache.
00459                                          */
00460                                         if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
00461                                                 return;
00462 
00463                                         /* remember who the master is */
00464                                         unstrcpy(work->local_master_browser_name, server_name);
00465                                         make_nmb_name(&nmbname, server_name, 0x20);
00466                                         work->dmb_name = nmbname;
00467                                         work->dmb_addr = from_ip;
00468                                 }
00469                                 break;
00470                         }
00471                 }
00472         } else if( DEBUGLVL( 0 ) ) {
00473                 dbgtext( "get_domain_master_name_node_status_success:\n" );
00474                 dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
00475                 dbgtext( "%s.\n", inet_ntoa(from_ip) );
00476         }
00477 }
00478 
00479 /****************************************************************************
00480   Function called when a node status query to a domain master browser IP fails.
00481 ****************************************************************************/
00482 
00483 static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
00484                        struct response_record *rrec)
00485 {
00486         if( DEBUGLVL( 0 ) ) {
00487                 dbgtext( "get_domain_master_name_node_status_fail:\n" );
00488                 dbgtext( "Doing a node status request to the domain master browser " );
00489                 dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
00490                 dbgtext( "Cannot get workgroup name.\n" );
00491         }
00492 }
00493 
00494 /****************************************************************************
00495   Function called when a query for *<1b> name succeeds.
00496 ****************************************************************************/
00497 
00498 static void find_all_domain_master_names_query_success(struct subnet_record *subrec,
00499                         struct userdata_struct *userdata_in,
00500                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
00501 {
00502         /* 
00503          * We now have a list of all the domain master browsers for all workgroups
00504          * that have registered with the WINS server. Now do a node status request
00505          * to each one and look for the first 1b name in the reply. This will be
00506          * the workgroup name that we will add to the unicast subnet as a 'non-local'
00507          * workgroup.
00508          */
00509 
00510         struct nmb_name nmbname;
00511         struct in_addr send_ip;
00512         int i;
00513 
00514         if( DEBUGLVL( 5 ) ) {
00515                 dbgtext( "find_all_domain_master_names_query_succes:\n" );
00516                 dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
00517                 dbgtext( "IP addresses for Domain Master Browsers.\n" );
00518         }
00519 
00520         for(i = 0; i < rrec->rdlength / 6; i++) {
00521                 /* Initiate the node status requests. */
00522                 make_nmb_name(&nmbname, "*", 0);
00523 
00524                 putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
00525 
00526                 /* 
00527                  * Don't send node status requests to ourself.
00528                  */
00529 
00530                 if(ismyip( send_ip )) {
00531                         if( DEBUGLVL( 5 ) ) {
00532                                 dbgtext( "find_all_domain_master_names_query_succes:\n" );
00533                                 dbgtext( "Not sending node status to our own IP " );
00534                                 dbgtext( "%s.\n", inet_ntoa(send_ip) );
00535                         }
00536                         continue;
00537                 }
00538 
00539                 if( DEBUGLVL( 5 ) ) {
00540                         dbgtext( "find_all_domain_master_names_query_success:\n" );
00541                         dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
00542                 }
00543 
00544                 node_status( subrec, &nmbname, send_ip, 
00545                                 get_domain_master_name_node_status_success,
00546                                 get_domain_master_name_node_status_fail,
00547                                 NULL);
00548         }
00549 }
00550 
00551 /****************************************************************************
00552   Function called when a query for *<1b> name fails.
00553   ****************************************************************************/
00554 static void find_all_domain_master_names_query_fail(struct subnet_record *subrec,
00555                                     struct response_record *rrec,
00556                                     struct nmb_name *question_name, int fail_code)
00557 {
00558         if( DEBUGLVL( 10 ) ) {
00559                 dbgtext( "find_domain_master_name_query_fail:\n" );
00560                 dbgtext( "WINS server did not reply to a query for name " );
00561                 dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
00562                 dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
00563         }
00564 }
00565 
00566 /****************************************************************************
00567  If we are a domain master browser on the unicast subnet, do a query to the
00568  WINS server for the *<1b> name. This will only work to a Samba WINS server,
00569  so ignore it if we fail. If we succeed, contact each of the IP addresses in
00570  turn and do a node status request to them. If this succeeds then look for a
00571  <1b> name in the reply - this is the workgroup name. Add this to the unicast
00572  subnet. This is expensive, so we only do this every 15 minutes.
00573 **************************************************************************/
00574 
00575 void collect_all_workgroup_names_from_wins_server(time_t t)
00576 {
00577         static time_t lastrun = 0;
00578         struct work_record *work;
00579 
00580         /* Only do this if we are using a WINS server. */
00581         if(we_are_a_wins_client() == False)
00582                 return;
00583 
00584         /* Check to see if we are a domain master browser on the unicast subnet. */
00585         if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
00586                 if( DEBUGLVL( 0 ) ) {
00587                         dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
00588                         dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
00589                         dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
00590                 }
00591                 return;
00592         }
00593 
00594         if(!AM_DOMAIN_MASTER_BROWSER(work))
00595                 return;
00596 
00597         if ((lastrun != 0) && (t < lastrun + (15 * 60)))
00598                 return;
00599      
00600         lastrun = t;
00601 
00602         /* First, query for the *<1b> name from the WINS server. */
00603         query_name(unicast_subnet, "*", 0x1b,
00604                 find_all_domain_master_names_query_success,
00605                 find_all_domain_master_names_query_fail,
00606                 NULL);
00607 } 
00608 
00609 
00610 /****************************************************************************
00611  If we are a domain master browser on the unicast subnet, do a regular sync
00612  with all other DMBs that we know of on that subnet.
00613 
00614 To prevent exponential network traffic with large numbers of workgroups
00615 we use a randomised system where sync probability is inversely proportional
00616 to the number of known workgroups
00617 **************************************************************************/
00618 
00619 void sync_all_dmbs(time_t t)
00620 {
00621         static time_t lastrun = 0;
00622         struct work_record *work;
00623         int count=0;
00624 
00625         /* Only do this if we are using a WINS server. */
00626         if(we_are_a_wins_client() == False)
00627                 return;
00628 
00629         /* Check to see if we are a domain master browser on the
00630            unicast subnet. */
00631         work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
00632         if (!work)
00633                 return;
00634 
00635         if (!AM_DOMAIN_MASTER_BROWSER(work))
00636                 return;
00637 
00638         if ((lastrun != 0) && (t < lastrun + (5 * 60)))
00639                 return;
00640      
00641         /* count how many syncs we might need to do */
00642         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
00643                 if (strcmp(lp_workgroup(), work->work_group)) {
00644                         count++;
00645                 }
00646         }
00647 
00648         /* sync with a probability of 1/count */
00649         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
00650                 if (strcmp(lp_workgroup(), work->work_group)) {
00651                         unstring dmb_name;
00652 
00653                         if (((unsigned)sys_random()) % count != 0)
00654                                 continue;
00655 
00656                         lastrun = t;
00657 
00658                         if (!work->dmb_name.name[0]) {
00659                                 /* we don't know the DMB - assume it is
00660                                    the same as the unicast local master */
00661                                 make_nmb_name(&work->dmb_name, 
00662                                               work->local_master_browser_name,
00663                                               0x20);
00664                         }
00665 
00666                         pull_ascii_nstring(dmb_name, sizeof(dmb_name), work->dmb_name.name);
00667 
00668                         DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
00669                                  dmb_name, inet_ntoa(work->dmb_addr)));
00670 
00671                         sync_browse_lists(work, 
00672                                           dmb_name,
00673                                           work->dmb_name.name_type, 
00674                                           work->dmb_addr, False, False);
00675                 }
00676         }
00677 }

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