nmbd/nmbd_become_dmb.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 extern struct in_addr allones_ip;
00027 
00028 extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
00029 
00030 static void become_domain_master_browser_bcast(const char *);
00031 
00032 /****************************************************************************
00033   Fail to become a Domain Master Browser on a subnet.
00034   ****************************************************************************/
00035 
00036 static void become_domain_master_fail(struct subnet_record *subrec,
00037                                       struct response_record *rrec,
00038                                       struct nmb_name *fail_name)
00039 {
00040         unstring failname;
00041         struct work_record *work;
00042         struct server_record *servrec;
00043 
00044         pull_ascii_nstring(failname, sizeof(failname), fail_name->name);
00045         work = find_workgroup_on_subnet(subrec, failname);
00046         if(!work) {
00047                 DEBUG(0,("become_domain_master_fail: Error - cannot find \
00048 workgroup %s on subnet %s\n", failname, subrec->subnet_name));
00049                 return;
00050         }
00051 
00052         /* Set the state back to DOMAIN_NONE. */
00053         work->dom_state = DOMAIN_NONE;
00054 
00055         if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
00056                 DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
00057 in workgroup %s on subnet %s\n",
00058                         global_myname(), work->work_group, subrec->subnet_name));
00059                 return;
00060         }
00061 
00062         /* Update our server status. */
00063         servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
00064 
00065         /* Tell the namelist writer to write out a change. */
00066         subrec->work_changed = True;
00067 
00068         DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
00069 workgroup %s on subnet %s. Couldn't register name %s.\n",
00070                 work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
00071 }
00072 
00073 /****************************************************************************
00074   Become a Domain Master Browser on a subnet.
00075   ****************************************************************************/
00076 
00077 static void become_domain_master_stage2(struct subnet_record *subrec, 
00078                                         struct userdata_struct *userdata,
00079                                         struct nmb_name *registered_name,
00080                                         uint16 nb_flags,
00081                                         int ttl, struct in_addr registered_ip)
00082 {
00083         unstring regname;
00084         struct work_record *work;
00085         struct server_record *servrec;
00086 
00087         pull_ascii_nstring(regname, sizeof(regname), registered_name->name);
00088         work = find_workgroup_on_subnet( subrec, regname);
00089 
00090         if(!work) {
00091                 DEBUG(0,("become_domain_master_stage2: Error - cannot find \
00092 workgroup %s on subnet %s\n", regname, subrec->subnet_name));
00093                 return;
00094         }
00095 
00096         if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) {
00097                 DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
00098 in workgroup %s on subnet %s\n", 
00099                 global_myname(), regname, subrec->subnet_name));
00100                 work->dom_state = DOMAIN_NONE;
00101                 return;
00102         }
00103 
00104         /* Set the state in the workgroup structure. */
00105         work->dom_state = DOMAIN_MST; /* Become domain master. */
00106 
00107         /* Update our server status. */
00108         servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
00109 
00110         /* Tell the namelist writer to write out a change. */
00111         subrec->work_changed = True;
00112 
00113         if( DEBUGLVL( 0 ) ) {
00114                 dbgtext( "*****\n\nSamba server %s ", global_myname() );
00115                 dbgtext( "is now a domain master browser for " );
00116                 dbgtext( "workgroup %s ", work->work_group );
00117                 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
00118         }
00119 
00120         if( subrec == unicast_subnet ) {
00121                 struct nmb_name nmbname;
00122                 struct in_addr my_first_ip;
00123                 struct in_addr *nip;
00124 
00125                 /* Put our name and first IP address into the 
00126                    workgroup struct as domain master browser. This
00127                    will stop us syncing with ourself if we are also
00128                    a local master browser. */
00129 
00130                 make_nmb_name(&nmbname, global_myname(), 0x20);
00131 
00132                 work->dmb_name = nmbname;
00133                 /* Pick the first interface ip address as the domain master browser ip. */
00134                 nip = iface_n_ip(0);
00135 
00136                 if (!nip) {
00137                         DEBUG(0,("become_domain_master_stage2: Error. iface_n_ip returned NULL\n"));
00138                         return;
00139                 }
00140 
00141                 my_first_ip = *nip;
00142 
00143                 putip((char *)&work->dmb_addr, &my_first_ip);
00144 
00145                 /* We successfully registered by unicast with the
00146                    WINS server.  We now expect to become the domain
00147                    master on the local subnets. If this fails, it's
00148                    probably a 1.9.16p2 to 1.9.16p11 server's fault.
00149 
00150                    This is a configuration issue that should be addressed
00151                    by the network administrator - you shouldn't have
00152                    several machines configured as a domain master browser
00153                    for the same WINS scope (except if they are 1.9.17 or
00154                    greater, and you know what you're doing.
00155 
00156                    see docs/DOMAIN.txt.
00157 
00158                 */
00159                 become_domain_master_browser_bcast(work->work_group);
00160         } else {
00161                 /*
00162                  * Now we are a domain master on a broadcast subnet, we need to add
00163                  * the WORKGROUP<1b> name to the unicast subnet so that we can answer
00164                  * unicast requests sent to this name. This bug wasn't found for a while
00165                  * as it is strange to have a DMB without using WINS. JRA.
00166                  */
00167                 insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
00168         }
00169 }
00170 
00171 /****************************************************************************
00172   Start the name registration process when becoming a Domain Master Browser
00173   on a subnet.
00174 ****************************************************************************/
00175 
00176 static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name)
00177 { 
00178         struct work_record *work;
00179 
00180         DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
00181 workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
00182 
00183         /* First, find the workgroup on the subnet. */
00184         if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) {
00185                 DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
00186                         wg_name, subrec->subnet_name));
00187                 return;
00188         }
00189 
00190         DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
00191         work->dom_state = DOMAIN_WAIT;
00192 
00193         /* WORKGROUP<1b> is the domain master browser name. */
00194         register_name(subrec, work->work_group,0x1b,samba_nb_type,
00195                         become_domain_master_stage2,
00196                         become_domain_master_fail, NULL);
00197 }
00198 
00199 /****************************************************************************
00200   Function called when a query for a WORKGROUP<1b> name succeeds.
00201   This is normally a fail condition as it means there is already
00202   a domain master browser for a workgroup and we were trying to
00203   become one.
00204 ****************************************************************************/
00205 
00206 static void become_domain_master_query_success(struct subnet_record *subrec,
00207                         struct userdata_struct *userdata,
00208                         struct nmb_name *nmbname, struct in_addr ip, 
00209                         struct res_rec *rrec)
00210 {
00211         unstring name;
00212         pull_ascii_nstring(name, sizeof(name), nmbname->name);
00213 
00214         /* If the given ip is not ours, then we can't become a domain
00215                 controler as the name is already registered.
00216         */
00217 
00218         /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
00219                 address or zero ip for this query. Pretend this is ok. */
00220 
00221         if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) {
00222                 if( DEBUGLVL( 3 ) ) {
00223                         dbgtext( "become_domain_master_query_success():\n" );
00224                         dbgtext( "Our address (%s) ", inet_ntoa(ip) );
00225                         dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
00226                         dbgtext( "(domain master browser name) " );
00227                         dbgtext( "on subnet %s.\n", subrec->subnet_name );
00228                         dbgtext( "Continuing with domain master code.\n" );
00229                 }
00230 
00231                 become_domain_master_stage1(subrec, name);
00232         } else {
00233                 if( DEBUGLVL( 0 ) ) {
00234                         dbgtext( "become_domain_master_query_success:\n" );
00235                         dbgtext( "There is already a domain master browser at " );
00236                         dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), name );
00237                         dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
00238                 }
00239         }
00240 }
00241 
00242 /****************************************************************************
00243   Function called when a query for a WORKGROUP<1b> name fails.
00244   This is normally a success condition as it then allows us to register
00245   our own Domain Master Browser name.
00246   ****************************************************************************/
00247 
00248 static void become_domain_master_query_fail(struct subnet_record *subrec,
00249                                     struct response_record *rrec,
00250                                     struct nmb_name *question_name, int fail_code)
00251 {
00252         unstring name;
00253 
00254         /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
00255                 then this is a failure. Otherwise, not finding the name is what we want. */
00256 
00257         if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) {
00258                 DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
00259 querying WINS server for name %s.\n", 
00260                         fail_code, nmb_namestr(question_name)));
00261                 return;
00262         }
00263 
00264         /* Otherwise - not having the name allows us to register it. */
00265         pull_ascii_nstring(name, sizeof(name), question_name->name);
00266         become_domain_master_stage1(subrec, name);
00267 }
00268 
00269 /****************************************************************************
00270   Attempt to become a domain master browser on all broadcast subnets.
00271   ****************************************************************************/
00272 
00273 static void become_domain_master_browser_bcast(const char *workgroup_name)
00274 {
00275         struct subnet_record *subrec;
00276 
00277         for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { 
00278                 struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
00279 
00280                 if (work && (work->dom_state == DOMAIN_NONE)) {
00281                         struct nmb_name nmbname;
00282                         make_nmb_name(&nmbname,workgroup_name,0x1b);
00283 
00284                         /*
00285                          * Check for our name on the given broadcast subnet first, only initiate
00286                          * further processing if we cannot find it.
00287                          */
00288 
00289                         if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) {
00290                                 if( DEBUGLVL( 0 ) ) {
00291                                         dbgtext( "become_domain_master_browser_bcast:\n" );
00292                                         dbgtext( "Attempting to become domain master browser on " );
00293                                         dbgtext( "workgroup %s on subnet %s\n",
00294                                                 workgroup_name, subrec->subnet_name );
00295                                 }
00296 
00297                                 /* Send out a query to establish whether there's a 
00298                                    domain controller on the local subnet. If not,
00299                                    we can become a domain controller. 
00300                                 */
00301 
00302                                 DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
00303 for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
00304 
00305                                 query_name(subrec, workgroup_name, nmbname.name_type,
00306                                         become_domain_master_query_success, 
00307                                         become_domain_master_query_fail,
00308                                         NULL);
00309                         }
00310                 }
00311         }
00312 }
00313 
00314 /****************************************************************************
00315   Attempt to become a domain master browser by registering with WINS.
00316   ****************************************************************************/
00317 
00318 static void become_domain_master_browser_wins(const char *workgroup_name)
00319 {
00320         struct work_record *work;
00321 
00322         work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
00323 
00324         if (work && (work->dom_state == DOMAIN_NONE)) {
00325                 struct nmb_name nmbname;
00326 
00327                 make_nmb_name(&nmbname,workgroup_name,0x1b);
00328 
00329                 /*
00330                  * Check for our name on the unicast subnet first, only initiate
00331                  * further processing if we cannot find it.
00332                  */
00333 
00334                 if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) {
00335                         if( DEBUGLVL( 0 ) ) {
00336                                 dbgtext( "become_domain_master_browser_wins:\n" );
00337                                 dbgtext( "Attempting to become domain master browser " );
00338                                 dbgtext( "on workgroup %s, subnet %s.\n",
00339                                         workgroup_name, unicast_subnet->subnet_name );
00340                         }
00341 
00342                         /* Send out a query to establish whether there's a 
00343                            domain master broswer registered with WINS. If not,
00344                            we can become a domain master browser. 
00345                         */
00346 
00347                         DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
00348 for domain master browser name %s on workgroup %s\n",
00349                                 inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
00350 
00351                         query_name(unicast_subnet, workgroup_name, nmbname.name_type,
00352                                 become_domain_master_query_success,
00353                                 become_domain_master_query_fail,
00354                                 NULL);
00355                 }
00356         }
00357 }
00358 
00359 /****************************************************************************
00360   Add the domain logon server and domain master browser names
00361   if we are set up to do so.
00362   **************************************************************************/
00363 
00364 void add_domain_names(time_t t)
00365 {
00366         static time_t lastrun = 0;
00367 
00368         if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
00369                 return;
00370 
00371         lastrun = t;
00372 
00373         /* Do the "internet group" - <1c> names. */
00374         if (lp_domain_logons())
00375                 add_logon_names();
00376 
00377         /* Do the domain master names. */
00378         if(lp_domain_master()) {
00379                 if(we_are_a_wins_client()) {
00380                         /* We register the WORKGROUP<1b> name with the WINS
00381                                 server first, and call add_domain_master_bcast()
00382                                 only if this is successful.
00383 
00384                                 This results in domain logon services being gracefully provided,
00385                                 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
00386                                 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
00387                                 cannot provide domain master / domain logon services.
00388                         */
00389                         become_domain_master_browser_wins(lp_workgroup());
00390                 } else {
00391                         become_domain_master_browser_bcast(lp_workgroup());
00392                 }
00393         }
00394 }

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