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 int updatecount = 0;
00027
00028
00029
00030
00031
00032 void remove_all_servers(struct work_record *work)
00033 {
00034 struct server_record *servrec;
00035 struct server_record *nexts;
00036
00037 for (servrec = work->serverlist; servrec; servrec = nexts) {
00038 DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name));
00039 nexts = servrec->next;
00040
00041 if (servrec->prev)
00042 servrec->prev->next = servrec->next;
00043 if (servrec->next)
00044 servrec->next->prev = servrec->prev;
00045
00046 if (work->serverlist == servrec)
00047 work->serverlist = servrec->next;
00048
00049 ZERO_STRUCTP(servrec);
00050 SAFE_FREE(servrec);
00051 }
00052
00053 work->subnet->work_changed = True;
00054 }
00055
00056
00057
00058
00059
00060 static void add_server_to_workgroup(struct work_record *work,
00061 struct server_record *servrec)
00062 {
00063 struct server_record *servrec2;
00064
00065 if (!work->serverlist) {
00066 work->serverlist = servrec;
00067 servrec->prev = NULL;
00068 servrec->next = NULL;
00069 return;
00070 }
00071
00072 for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next)
00073 ;
00074
00075 servrec2->next = servrec;
00076 servrec->next = NULL;
00077 servrec->prev = servrec2;
00078 work->subnet->work_changed = True;
00079 }
00080
00081
00082
00083
00084
00085 struct server_record *find_server_in_workgroup(struct work_record *work, const char *name)
00086 {
00087 struct server_record *ret;
00088
00089 for (ret = work->serverlist; ret; ret = ret->next) {
00090 if (strequal(ret->serv.name,name))
00091 return ret;
00092 }
00093 return NULL;
00094 }
00095
00096
00097
00098
00099
00100
00101 void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec)
00102 {
00103 if (servrec->prev)
00104 servrec->prev->next = servrec->next;
00105 if (servrec->next)
00106 servrec->next->prev = servrec->prev;
00107
00108 if (work->serverlist == servrec)
00109 work->serverlist = servrec->next;
00110
00111 ZERO_STRUCTP(servrec);
00112 SAFE_FREE(servrec);
00113 work->subnet->work_changed = True;
00114 }
00115
00116
00117
00118
00119
00120 struct server_record *create_server_on_workgroup(struct work_record *work,
00121 const char *name,int servertype,
00122 int ttl, const char *comment)
00123 {
00124 struct server_record *servrec;
00125
00126 if (name[0] == '*') {
00127 DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n",
00128 name));
00129 return (NULL);
00130 }
00131
00132 if((servrec = find_server_in_workgroup(work, name)) != NULL) {
00133 DEBUG(0,("create_server_on_workgroup: Server %s already exists on \
00134 workgroup %s. This is a bug.\n", name, work->work_group));
00135 return NULL;
00136 }
00137
00138 if((servrec = SMB_MALLOC_P(struct server_record)) == NULL) {
00139 DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n"));
00140 return NULL;
00141 }
00142
00143 memset((char *)servrec,'\0',sizeof(*servrec));
00144
00145 servrec->subnet = work->subnet;
00146
00147 fstrcpy(servrec->serv.name,name);
00148 fstrcpy(servrec->serv.comment,comment);
00149 strupper_m(servrec->serv.name);
00150 servrec->serv.type = servertype;
00151
00152 update_server_ttl(servrec, ttl);
00153
00154 add_server_to_workgroup(work, servrec);
00155
00156 DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \
00157 workgroup %s.\n", name,servertype,comment, work->work_group));
00158
00159 work->subnet->work_changed = True;
00160
00161 return(servrec);
00162 }
00163
00164
00165
00166
00167
00168 void update_server_ttl(struct server_record *servrec, int ttl)
00169 {
00170 if(ttl > lp_max_ttl())
00171 ttl = lp_max_ttl();
00172
00173 if(is_myname(servrec->serv.name))
00174 servrec->death_time = PERMANENT_TTL;
00175 else
00176 servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
00177
00178 servrec->subnet->work_changed = True;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 void expire_servers(struct work_record *work, time_t t)
00188 {
00189 struct server_record *servrec;
00190 struct server_record *nexts;
00191
00192 for (servrec = work->serverlist; servrec; servrec = nexts) {
00193 nexts = servrec->next;
00194
00195 if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) {
00196 DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name));
00197 remove_server_from_workgroup(work, servrec);
00198 work->subnet->work_changed = True;
00199 }
00200 }
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 static uint32 write_this_server_name( struct subnet_record *subrec,
00210 struct work_record *work,
00211 struct server_record *servrec)
00212 {
00213 struct subnet_record *ssub;
00214 struct work_record *iwork;
00215
00216
00217 for (ssub = FIRST_SUBNET; ssub && (ssub != subrec); ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) {
00218 for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) {
00219 if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) {
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 return 0;
00232 }
00233 }
00234 }
00235
00236 return servrec->serv.type;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 static uint32 write_this_workgroup_name( struct subnet_record *subrec,
00248 struct work_record *work)
00249 {
00250 struct subnet_record *ssub;
00251
00252 if(strequal(lp_workgroup(), work->work_group))
00253 return 0;
00254
00255
00256
00257
00258 if(subrec != unicast_subnet)
00259 return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
00260
00261 for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) {
00262
00263
00264
00265 if(find_workgroup_on_subnet( ssub, work->work_group) != NULL)
00266 return 0;
00267 }
00268
00269
00270
00271
00272 return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT);
00273 }
00274
00275
00276
00277
00278
00279 void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type,
00280 const char *local_master_browser_name, const char *description)
00281 {
00282 fstring tmp;
00283
00284 slprintf(tmp,sizeof(tmp)-1, "\"%s\"", name);
00285 x_fprintf(fp, "%-25s ", tmp);
00286 x_fprintf(fp, "%08x ", rec_type);
00287 slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", local_master_browser_name);
00288 x_fprintf(fp, "%-30s", tmp);
00289 x_fprintf(fp, "\"%s\"\n", description);
00290 }
00291
00292 void write_browse_list(time_t t, BOOL force_write)
00293 {
00294 struct subnet_record *subrec;
00295 struct work_record *work;
00296 struct server_record *servrec;
00297 pstring fname,fnamenew;
00298 uint32 stype;
00299 int i;
00300 XFILE *fp;
00301 BOOL list_changed = force_write;
00302 static time_t lasttime = 0;
00303
00304
00305 if(force_write == False) {
00306 if (!lasttime)
00307 lasttime = t;
00308 if (t - lasttime < 5)
00309 return;
00310 }
00311
00312 lasttime = t;
00313
00314 dump_workgroups(force_write);
00315
00316 for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
00317 if(subrec->work_changed) {
00318 list_changed = True;
00319 break;
00320 }
00321 }
00322
00323 if(!list_changed)
00324 return;
00325
00326 updatecount++;
00327
00328 pstrcpy(fname,lp_lockdir());
00329 trim_char(fname,'\0' ,'/');
00330 pstrcat(fname,"/");
00331 pstrcat(fname,SERVER_LIST);
00332 pstrcpy(fnamenew,fname);
00333 pstrcat(fnamenew,".");
00334
00335 fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644);
00336
00337 if (!fp) {
00338 DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n",
00339 fnamenew,strerror(errno)));
00340 return;
00341 }
00342
00343
00344
00345
00346
00347
00348 if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) {
00349 DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n",
00350 lp_workgroup()));
00351 x_fclose(fp);
00352 return;
00353 }
00354
00355 write_browse_list_entry(fp, work->work_group,
00356 SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY,
00357 work->local_master_browser_name, work->work_group);
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 for (i=0; my_netbios_names(i); i++) {
00368 stype = 0;
00369 for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
00370 if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL)
00371 continue;
00372 if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL)
00373 continue;
00374
00375 stype |= servrec->serv.type;
00376 }
00377
00378
00379 write_browse_list_entry(fp, my_netbios_names(i), stype,
00380 string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup());
00381 }
00382
00383 for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
00384 subrec->work_changed = False;
00385
00386 for (work = subrec->workgrouplist; work ; work = work->next) {
00387
00388 uint32 wg_type = write_this_workgroup_name( subrec, work);
00389
00390 if(wg_type) {
00391 write_browse_list_entry(fp, work->work_group, wg_type,
00392 work->local_master_browser_name,
00393 work->work_group);
00394 }
00395
00396
00397
00398 for (servrec = work->serverlist; servrec ; servrec = servrec->next) {
00399 uint32 serv_type;
00400
00401
00402 if(is_myname(servrec->serv.name))
00403 continue;
00404
00405 serv_type = write_this_server_name(subrec, work, servrec);
00406 if(serv_type) {
00407
00408 write_browse_list_entry(fp, servrec->serv.name, serv_type,
00409 servrec->serv.comment, work->work_group);
00410 }
00411 }
00412 }
00413 }
00414
00415 x_fclose(fp);
00416 unlink(fname);
00417 chmod(fnamenew,0644);
00418 rename(fnamenew,fname);
00419 DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname));
00420 }