00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029 extern int updatecount;
00030 extern BOOL found_lm_clients;
00031
00032
00033
00034
00035
00036 void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip)
00037 {
00038 char outbuf[PSTRING_LEN];
00039 char *p;
00040
00041 DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
00042 reset_type, to_name, to_type, inet_ntoa(to_ip) ));
00043
00044 memset(outbuf,'\0',sizeof(outbuf));
00045 p = outbuf;
00046 SCVAL(p,0,ANN_ResetBrowserState);
00047 p++;
00048 SCVAL(p,0,reset_type);
00049 p++;
00050
00051 send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
00052 global_myname(), 0x0, to_name, to_type, to_ip,
00053 FIRST_SUBNET->myip, DGRAM_PORT);
00054 }
00055
00056
00057
00058
00059
00060
00061 void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work)
00062 {
00063 char outbuf[PSTRING_LEN];
00064 char *p;
00065
00066 work->needannounce = True;
00067
00068 DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
00069 to subnet %s\n", work->work_group, subrec->subnet_name));
00070
00071 memset(outbuf,'\0',sizeof(outbuf));
00072 p = outbuf;
00073 SCVAL(p,0,ANN_AnnouncementRequest);
00074 p++;
00075
00076 SCVAL(p,0,work->token);
00077 p++;
00078 p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
00079
00080 send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
00081 global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip,
00082 subrec->myip, DGRAM_PORT);
00083 }
00084
00085
00086
00087
00088
00089 static void send_announcement(struct subnet_record *subrec, int announce_type,
00090 const char *from_name, const char *to_name, int to_type, struct in_addr to_ip,
00091 time_t announce_interval,
00092 const char *server_name, int server_type, const char *server_comment)
00093 {
00094 char outbuf[PSTRING_LEN];
00095 unstring upper_server_name;
00096 char *p;
00097
00098 memset(outbuf,'\0',sizeof(outbuf));
00099 p = outbuf+1;
00100
00101 SCVAL(outbuf,0,announce_type);
00102
00103
00104 SCVAL(p,0,updatecount);
00105 SIVAL(p,1,announce_interval*1000);
00106
00107 safe_strcpy(upper_server_name, server_name, sizeof(upper_server_name)-1);
00108 strupper_m(upper_server_name);
00109 push_string(NULL, p+5, upper_server_name, 16, STR_ASCII|STR_TERMINATE);
00110
00111 SCVAL(p,21,lp_major_announce_version());
00112 SCVAL(p,22,lp_minor_announce_version());
00113
00114 SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
00115
00116 SSVAL(p,27,BROWSER_ELECTION_VERSION);
00117 SSVAL(p,29,BROWSER_CONSTANT);
00118
00119 p += 31 + push_string(NULL, p+31, server_comment, sizeof(outbuf) - (p + 31 - outbuf), STR_ASCII|STR_TERMINATE);
00120
00121 send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
00122 from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
00123 DGRAM_PORT);
00124 }
00125
00126
00127
00128
00129
00130 static void send_lm_announcement(struct subnet_record *subrec, int announce_type,
00131 char *from_name, char *to_name, int to_type, struct in_addr to_ip,
00132 time_t announce_interval,
00133 char *server_name, int server_type, char *server_comment)
00134 {
00135 char outbuf[PSTRING_LEN];
00136 char *p=outbuf;
00137
00138 memset(outbuf,'\0',sizeof(outbuf));
00139
00140 SSVAL(p,0,announce_type);
00141 SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
00142 SCVAL(p,6,lp_major_announce_version());
00143 SCVAL(p,7,lp_minor_announce_version());
00144 SSVAL(p,8,announce_interval);
00145
00146 p += 10;
00147 p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
00148 p += push_string(NULL, p, server_comment, sizeof(outbuf)- (p - outbuf), STR_ASCII|STR_UPPER|STR_TERMINATE);
00149
00150 send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
00151 from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
00152 DGRAM_PORT);
00153 }
00154
00155
00156
00157
00158
00159 static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work,
00160 struct server_record *servrec)
00161 {
00162
00163 uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
00164
00165 DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
00166 type, global_myname(), subrec->subnet_name, work->work_group));
00167
00168 send_announcement(subrec, ANN_LocalMasterAnnouncement,
00169 global_myname(),
00170 work->work_group, 0x1e,
00171 subrec->bcast_ip,
00172 work->announce_interval,
00173 global_myname(),
00174 type,
00175 servrec->serv.comment);
00176 }
00177
00178
00179
00180
00181
00182 static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work)
00183 {
00184 DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n",
00185 subrec->subnet_name, work->work_group));
00186
00187 send_announcement(subrec, ANN_DomainAnnouncement,
00188 global_myname(),
00189 MSBROWSE, 0x1,
00190 subrec->bcast_ip,
00191 work->announce_interval,
00192 work->work_group,
00193 SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT,
00194 global_myname());
00195 }
00196
00197
00198
00199
00200
00201 static void send_host_announcement(struct subnet_record *subrec, struct work_record *work,
00202 struct server_record *servrec)
00203 {
00204
00205 uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
00206
00207 DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
00208 type, servrec->serv.name, subrec->subnet_name, work->work_group));
00209
00210 send_announcement(subrec, ANN_HostAnnouncement,
00211 servrec->serv.name,
00212 work->work_group, 0x1d,
00213 subrec->bcast_ip,
00214 work->announce_interval,
00215 servrec->serv.name,
00216 type,
00217 servrec->serv.comment);
00218 }
00219
00220
00221
00222
00223
00224 static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work,
00225 struct server_record *servrec, int lm_interval)
00226 {
00227
00228 uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
00229
00230 DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
00231 type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval));
00232
00233 send_lm_announcement(subrec, ANN_HostAnnouncement,
00234 servrec->serv.name,
00235 work->work_group, 0x00,
00236 subrec->bcast_ip,
00237 lm_interval,
00238 servrec->serv.name,
00239 type,
00240 servrec->serv.comment);
00241 }
00242
00243
00244
00245
00246
00247 static void announce_server(struct subnet_record *subrec, struct work_record *work,
00248 struct server_record *servrec)
00249 {
00250
00251
00252
00253 if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) {
00254 send_local_master_announcement(subrec, work, servrec);
00255 send_workgroup_announcement(subrec, work);
00256 } else {
00257 send_host_announcement(subrec, work, servrec);
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266 void announce_my_server_names(time_t t)
00267 {
00268 struct subnet_record *subrec;
00269
00270 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00271 struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
00272
00273 if(work) {
00274 struct server_record *servrec;
00275
00276 if (work->needannounce) {
00277
00278
00279
00280 work->announce_interval = MIN(work->announce_interval,
00281 CHECK_TIME_MIN_HOST_ANNCE*60);
00282 work->lastannounce_time = t - (work->announce_interval+1);
00283 work->needannounce = False;
00284 }
00285
00286
00287 if ((t - work->lastannounce_time) < work->announce_interval)
00288 continue;
00289
00290 if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
00291 work->announce_interval += 60;
00292
00293 work->lastannounce_time = t;
00294
00295 for (servrec = work->serverlist; servrec; servrec = servrec->next) {
00296 if (is_myname(servrec->serv.name))
00297 announce_server(subrec, work, servrec);
00298 }
00299 }
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308 void announce_my_lm_server_names(time_t t)
00309 {
00310 struct subnet_record *subrec;
00311 static time_t last_lm_announce_time=0;
00312 int announce_interval = lp_lm_interval();
00313 int lm_announce = lp_lm_announce();
00314
00315 if ((announce_interval <= 0) || (lm_announce <= 0)) {
00316
00317 return;
00318 }
00319
00320 if ((lm_announce >= 2) && (!found_lm_clients)) {
00321
00322 return;
00323 }
00324
00325
00326
00327
00328 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00329 struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
00330
00331 if(work) {
00332 struct server_record *servrec;
00333
00334 if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
00335 continue;
00336
00337 last_lm_announce_time = t;
00338
00339 for (servrec = work->serverlist; servrec; servrec = servrec->next) {
00340 if (is_myname(servrec->serv.name))
00341
00342 send_lm_host_announcement(subrec, work, servrec, announce_interval);
00343 }
00344 }
00345 }
00346 }
00347
00348
00349
00350 static time_t announce_timer_last=0;
00351
00352
00353
00354
00355
00356
00357 void reset_announce_timer(void)
00358 {
00359 announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
00360 }
00361
00362
00363
00364
00365
00366 void announce_myself_to_domain_master_browser(time_t t)
00367 {
00368 struct subnet_record *subrec;
00369 struct work_record *work;
00370
00371 if(!we_are_a_wins_client()) {
00372 DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
00373 return;
00374 }
00375
00376 if (!announce_timer_last)
00377 announce_timer_last = t;
00378
00379 if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) {
00380 DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
00381 (int)t, (int)announce_timer_last,
00382 CHECK_TIME_MST_ANNOUNCE * 60 ));
00383 return;
00384 }
00385
00386 announce_timer_last = t;
00387
00388
00389
00390
00391 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00392 for (work = subrec->workgrouplist; work; work = work->next) {
00393 if (AM_LOCAL_MASTER_BROWSER(work)) {
00394 DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
00395 workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
00396
00397
00398 announce_and_sync_with_domain_master_browser(subrec, work);
00399 }
00400 }
00401 }
00402 }
00403
00404
00405
00406
00407
00408
00409 void announce_my_servers_removed(void)
00410 {
00411 int announce_interval = lp_lm_interval();
00412 int lm_announce = lp_lm_announce();
00413 struct subnet_record *subrec;
00414
00415 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
00416 struct work_record *work;
00417 for (work = subrec->workgrouplist; work; work = work->next) {
00418 struct server_record *servrec;
00419
00420 work->announce_interval = 0;
00421 for (servrec = work->serverlist; servrec; servrec = servrec->next) {
00422 if (!is_myname(servrec->serv.name))
00423 continue;
00424 servrec->serv.type = 0;
00425 if(AM_LOCAL_MASTER_BROWSER(work))
00426 send_local_master_announcement(subrec, work, servrec);
00427 send_host_announcement(subrec, work, servrec);
00428
00429 if ((announce_interval <= 0) || (lm_announce <= 0)) {
00430
00431 continue;
00432 }
00433
00434 if ((lm_announce >= 2) && (!found_lm_clients)) {
00435
00436 continue;
00437 }
00438
00439
00440
00441
00442
00443
00444 send_lm_host_announcement(subrec, work, servrec, 0);
00445 }
00446 }
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 void announce_remote(time_t t)
00457 {
00458 char *s;
00459 const char *ptr;
00460 static time_t last_time = 0;
00461 pstring s2;
00462 struct in_addr addr;
00463 char *comment;
00464 int stype = lp_default_server_announce();
00465
00466 if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
00467 return;
00468
00469 last_time = t;
00470
00471 s = lp_remote_announce();
00472 if (!*s)
00473 return;
00474
00475 comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH);
00476
00477 for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) {
00478
00479
00480 const char *wgroup;
00481 char *pwgroup;
00482 int i;
00483
00484 pwgroup = strchr_m(s2,'/');
00485 if (pwgroup)
00486 *pwgroup++ = 0;
00487 if (!pwgroup || !*pwgroup)
00488 wgroup = lp_workgroup();
00489 else
00490 wgroup = pwgroup;
00491
00492 addr = *interpret_addr2(s2);
00493
00494
00495
00496
00497
00498 for(i=0; my_netbios_names(i); i++) {
00499 const char *name = my_netbios_names(i);
00500
00501 DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n",
00502 name, inet_ntoa(addr) ));
00503
00504 send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
00505 name,
00506 wgroup, 0x1d,
00507 addr,
00508 REMOTE_ANNOUNCE_INTERVAL,
00509 name,
00510 stype,
00511 comment);
00512 }
00513 }
00514 }
00515
00516
00517
00518
00519
00520
00521 void browse_sync_remote(time_t t)
00522 {
00523 char *s;
00524 const char *ptr;
00525 static time_t last_time = 0;
00526 pstring s2;
00527 struct in_addr addr;
00528 struct work_record *work;
00529 pstring outbuf;
00530 char *p;
00531 unstring myname;
00532
00533 if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
00534 return;
00535
00536 last_time = t;
00537
00538 s = lp_remote_browse_sync();
00539 if (!*s)
00540 return;
00541
00542
00543
00544
00545
00546
00547 if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {
00548 DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
00549 lp_workgroup(), FIRST_SUBNET->subnet_name ));
00550 return;
00551 }
00552
00553 if(!AM_LOCAL_MASTER_BROWSER(work)) {
00554 DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
00555 for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name ));
00556 return;
00557 }
00558
00559 memset(outbuf,'\0',sizeof(outbuf));
00560 p = outbuf;
00561 SCVAL(p,0,ANN_MasterAnnouncement);
00562 p++;
00563
00564 unstrcpy(myname, global_myname());
00565 strupper_m(myname);
00566 myname[15]='\0';
00567 push_pstring_base(p, myname, outbuf);
00568
00569 p = skip_string(outbuf,sizeof(outbuf),p);
00570
00571 for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) {
00572
00573 addr = *interpret_addr2(s2);
00574
00575 DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
00576 global_myname(), inet_ntoa(addr) ));
00577
00578 send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
00579 global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT);
00580 }
00581 }