00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026
00027 extern time_t StartupTime;
00028
00029
00030
00031
00032
00033 static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
00034 uint32 criterion, int timeup,const char *server_name)
00035 {
00036 pstring outbuf;
00037 unstring srv_name;
00038 char *p;
00039
00040 DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
00041 workgroup_name, subrec->subnet_name ));
00042
00043 memset(outbuf,'\0',sizeof(outbuf));
00044 p = outbuf;
00045 SCVAL(p,0,ANN_Election);
00046 p++;
00047
00048 SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
00049 SIVAL(p,1,criterion);
00050 SIVAL(p,5,timeup*1000);
00051 p += 13;
00052 unstrcpy(srv_name, server_name);
00053 strupper_m(srv_name);
00054
00055 pstrcpy_base(p, srv_name, outbuf);
00056 p = skip_string(outbuf,sizeof(outbuf),p);
00057
00058 send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
00059 global_myname(), 0,
00060 workgroup_name, 0x1e,
00061 subrec->bcast_ip, subrec->myip, DGRAM_PORT);
00062 }
00063
00064
00065
00066
00067
00068 static void check_for_master_browser_success(struct subnet_record *subrec,
00069 struct userdata_struct *userdata,
00070 struct nmb_name *answer_name,
00071 struct in_addr answer_ip, struct res_rec *rrec)
00072 {
00073 unstring aname;
00074 pull_ascii_nstring(aname, sizeof(aname), answer_name->name);
00075 DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
00076 IP %s (just checking).\n", aname, inet_ntoa(answer_ip) ));
00077 }
00078
00079
00080
00081
00082
00083 static void check_for_master_browser_fail( struct subnet_record *subrec,
00084 struct response_record *rrec,
00085 struct nmb_name *question_name,
00086 int fail_code)
00087 {
00088 unstring workgroup_name;
00089 struct work_record *work;
00090
00091 pull_ascii_nstring(workgroup_name,sizeof(workgroup_name),question_name->name);
00092
00093 work = find_workgroup_on_subnet(subrec, workgroup_name);
00094 if(work == NULL) {
00095 DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
00096 workgroup_name, subrec->subnet_name ));
00097 return;
00098 }
00099
00100 if (strequal(work->work_group, lp_workgroup())) {
00101
00102 if (lp_local_master()) {
00103
00104
00105
00106
00107 DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
00108 work->work_group, subrec->subnet_name ));
00109
00110
00111
00112 work->needelection = True;
00113 } else {
00114
00115
00116
00117
00118 send_election_dgram(subrec, work->work_group, 0, 0, "");
00119 }
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128 void check_master_browser_exists(time_t t)
00129 {
00130 static time_t lastrun=0;
00131 struct subnet_record *subrec;
00132 const char *workgroup_name = lp_workgroup();
00133
00134 if (!lastrun)
00135 lastrun = t;
00136
00137 if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
00138 return;
00139
00140 lastrun = t;
00141
00142 dump_workgroups(False);
00143
00144 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00145 struct work_record *work;
00146
00147 for (work = subrec->workgrouplist; work; work = work->next) {
00148 if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
00149
00150 query_name( subrec, work->work_group, 0x1d,
00151 check_for_master_browser_success,
00152 check_for_master_browser_fail,
00153 NULL);
00154 }
00155 }
00156 }
00157 }
00158
00159
00160
00161
00162
00163 void run_elections(time_t t)
00164 {
00165 static time_t lastime = 0;
00166
00167 struct subnet_record *subrec;
00168
00169 START_PROFILE(run_elections);
00170
00171
00172 if (lastime && (t - lastime < 2)) {
00173 END_PROFILE(run_elections);
00174 return;
00175 }
00176
00177 lastime = t;
00178
00179 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00180 struct work_record *work;
00181
00182 for (work = subrec->workgrouplist; work; work = work->next) {
00183 if (work->RunningElection) {
00184
00185
00186
00187
00188
00189 struct nmb_name nmbname;
00190
00191 make_nmb_name(&nmbname, work->work_group, 0x1e);
00192 if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
00193 DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
00194 yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
00195 continue;
00196 }
00197
00198 send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
00199 t - StartupTime, global_myname());
00200
00201 if (work->ElectionCount++ >= 4) {
00202
00203 DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
00204 work->work_group, subrec->subnet_name ));
00205
00206 work->RunningElection = False;
00207
00208 become_local_master_browser(subrec, work);
00209 }
00210 }
00211 }
00212 }
00213 END_PROFILE(run_elections);
00214 }
00215
00216
00217
00218
00219
00220 static BOOL win_election(struct work_record *work, int version,
00221 uint32 criterion, int timeup, const char *server_name)
00222 {
00223 int mytimeup = time(NULL) - StartupTime;
00224 uint32 mycriterion = work->ElectionCriterion;
00225
00226
00227 if(!lp_local_master()) {
00228 DEBUG(3,("win_election: Losing election as local master == False\n"));
00229 return False;
00230 }
00231
00232 DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
00233 version, ELECTION_VERSION,
00234 criterion, mycriterion,
00235 timeup, mytimeup,
00236 server_name, global_myname()));
00237
00238 if (version > ELECTION_VERSION)
00239 return(False);
00240 if (version < ELECTION_VERSION)
00241 return(True);
00242
00243 if (criterion > mycriterion)
00244 return(False);
00245 if (criterion < mycriterion)
00246 return(True);
00247
00248 if (timeup > mytimeup)
00249 return(False);
00250 if (timeup < mytimeup)
00251 return(True);
00252
00253 if (StrCaseCmp(global_myname(), server_name) > 0)
00254 return(False);
00255
00256 return(True);
00257 }
00258
00259
00260
00261
00262
00263 void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
00264 {
00265 struct dgram_packet *dgram = &p->packet.dgram;
00266 int version = CVAL(buf,0);
00267 uint32 criterion = IVAL(buf,1);
00268 int timeup = IVAL(buf,5)/1000;
00269 unstring server_name;
00270 struct work_record *work;
00271 unstring workgroup_name;
00272
00273 START_PROFILE(election);
00274
00275 pull_ascii_nstring(server_name, sizeof(server_name), buf+13);
00276 pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);
00277
00278 server_name[15] = 0;
00279
00280 DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
00281 server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
00282
00283 DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
00284
00285 if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) {
00286 DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
00287 workgroup_name, subrec->subnet_name ));
00288 goto done;
00289 }
00290
00291 if (!strequal(work->work_group, lp_workgroup())) {
00292 DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
00293 is not my workgroup.\n", work->work_group, subrec->subnet_name ));
00294 goto done;
00295 }
00296
00297 if (win_election(work, version,criterion,timeup,server_name)) {
00298
00299 if (!work->RunningElection) {
00300
00301
00302 work->needelection = True;
00303 work->ElectionCount=0;
00304 }
00305
00306
00307
00308 } else {
00309
00310 work->needelection = False;
00311
00312 if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) {
00313 work->RunningElection = False;
00314 DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
00315 work->work_group, subrec->subnet_name ));
00316 if (AM_LOCAL_MASTER_BROWSER(work))
00317 unbecome_local_master_browser(subrec, work, False);
00318 }
00319 }
00320 done:
00321
00322 END_PROFILE(election);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 BOOL check_elections(void)
00333 {
00334 struct subnet_record *subrec;
00335 BOOL run_any_election = False;
00336
00337 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00338 struct work_record *work;
00339 for (work = subrec->workgrouplist; work; work = work->next) {
00340 run_any_election |= work->RunningElection;
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 if (work->needelection && !work->RunningElection && lp_local_master()) {
00351
00352
00353
00354
00355
00356 struct nmb_name nmbname;
00357
00358 make_nmb_name(&nmbname, work->work_group, 0x1e);
00359 if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
00360 DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
00361 yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
00362 continue;
00363 }
00364
00365 DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
00366 work->work_group, subrec->subnet_name ));
00367
00368 work->ElectionCount = 0;
00369 work->RunningElection = True;
00370 work->needelection = False;
00371 }
00372 }
00373 }
00374 return run_any_election;
00375 }
00376
00377
00378
00379
00380
00381 void nmbd_message_election(int msg_type, struct process_id src,
00382 void *buf, size_t len, void *private_data)
00383 {
00384 struct subnet_record *subrec;
00385
00386 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00387 struct work_record *work;
00388 for (work = subrec->workgrouplist; work; work = work->next) {
00389 if (strequal(work->work_group, lp_workgroup())) {
00390 work->needelection = True;
00391 work->ElectionCount=0;
00392 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
00393 }
00394 }
00395 }
00396 }