LCOV - code coverage report
Current view: top level - src/server/monitor - cstat.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 124 125 99.2 %
Date: 2016-01-31 Functions: 9 9 100.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../bu.h"
       4             : #include "../../cstat.h"
       5             : #include "../../conffile.h"
       6             : #include "../../fsops.h"
       7             : #include "../../lock.h"
       8             : #include "../../log.h"
       9             : #include "../../strlist.h"
      10             : #include "../bu_get.h"
      11             : #include "../sdirs.h"
      12             : #include "cstat.h"
      13             : 
      14             : #ifndef UTEST
      15             : static 
      16             : #endif
      17          16 : int cstat_permitted(struct cstat *cstat,
      18             :         struct conf **parentconfs, struct conf **cconfs)
      19             : {
      20             :         struct strlist *rclient;
      21             :         const char *parentconf_cname;
      22             : 
      23          16 :         parentconf_cname=get_string(parentconfs[OPT_CNAME]);
      24          16 :         if(!parentconf_cname) return 0;
      25             : 
      26             :         // Allow clients to look at themselves.
      27           4 :         if(!strcmp(cstat->name, parentconf_cname)) return 1;
      28             : 
      29             :         // Do not allow clients using the restore_client option to see more
      30             :         // than the client that it is pretending to be.
      31           3 :         if(get_string(parentconfs[OPT_RESTORE_CLIENT])) return 0;
      32             : 
      33             :         // If we are listed in this restore_client list.
      34           4 :         for(rclient=get_strlist(cconfs[OPT_RESTORE_CLIENTS]);
      35             :           rclient; rclient=rclient->next)
      36           3 :                 if(!strcmp(get_string(parentconfs[OPT_CNAME]), rclient->path))
      37             :                         return 1;
      38             :         return 0;
      39             : }
      40             : 
      41          12 : static int set_cstat_from_conf(struct cstat *cstat,
      42             :         struct conf **parentconfs, struct conf **cconfs)
      43             : {
      44             :         // Make sure the permitted flag is set appropriately.
      45          12 :         cstat->permitted=cstat_permitted(cstat, parentconfs, cconfs);
      46             : 
      47          12 :         cstat->protocol=get_protocol(cconfs);
      48          12 :         sdirs_free((struct sdirs **)&cstat->sdirs);
      49          24 :         if(!(cstat->sdirs=sdirs_alloc())
      50          12 :           || sdirs_init_from_confs((struct sdirs *)cstat->sdirs, cconfs))
      51             :                 return -1;
      52          12 :         return 0;
      53             : }
      54             : 
      55             : #ifndef UTEST
      56             : static
      57             : #endif
      58          23 : int cstat_get_client_names(struct cstat **clist, const char *clientconfdir)
      59             : {
      60          23 :         int i=0;
      61          23 :         int n=0;
      62          23 :         int ret=-1;
      63             :         struct cstat *c;
      64             :         struct cstat *cnew;
      65          23 :         struct dirent **dir=NULL;
      66             : 
      67          23 :         if(entries_in_directory_no_sort(clientconfdir, &dir, &n, 1 /*atime*/))
      68             :         {
      69             :                 logp("scandir failed for %s in %s: %s\n",
      70           1 :                         clientconfdir, __func__, strerror(errno));
      71           1 :                 goto end;
      72             :         }
      73          72 :         for(i=0; i<n; i++)
      74             :         {
      75             :                 // looks_like...() also avoids '.' and '..'.
      76          72 :                 if(looks_like_tmp_or_hidden_file(dir[i]->d_name))
      77             :                         continue;
      78         167 :                 for(c=*clist; c; c=c->next)
      79             :                 {
      80         114 :                         if(!c->name) continue;
      81         114 :                         if(!strcmp(dir[i]->d_name, c->name))
      82             :                                 break;
      83             :                 }
      84          70 :                 if(c) continue;
      85             : 
      86             :                 // We do not have this client yet. Add it.
      87          53 :                 if(!(cnew=cstat_alloc())
      88          53 :                   || cstat_init_with_cntr(cnew, dir[i]->d_name, clientconfdir))
      89             :                         goto end;
      90          53 :                 cstat_add_to_list(clist, cnew);
      91             :         }
      92             : 
      93             :         ret=0;
      94             : end:
      95          23 :         if(dir)
      96             :         {
      97          72 :                 for(i=0; i<n; i++) free_v((void **)&dir[i]);
      98          22 :                 free_v((void **)&dir);
      99             :         }
     100          23 :         return ret;
     101             : }
     102             : 
     103             : static void cstat_free_w(struct cstat **cstat)
     104             : {
     105           8 :         sdirs_free((struct sdirs **)&(*cstat)->sdirs);
     106           8 :         cstat_free(cstat);
     107             : }
     108             : 
     109             : #ifndef UTEST
     110             : static
     111             : #endif
     112           8 : void cstat_remove(struct cstat **clist, struct cstat **cstat)
     113             : {
     114             :         struct cstat *c;
     115           8 :         if(!cstat || !*cstat) return;
     116           8 :         if(*clist==*cstat)
     117             :         {
     118           4 :                 *clist=(*clist)->next;
     119           4 :                 if(*clist) (*clist)->prev=NULL;
     120             :                 cstat_free_w(cstat);
     121           4 :                 *cstat=*clist;
     122           4 :                 return;
     123             :         }
     124           7 :         for(c=*clist; c; c=c->next)
     125             :         {
     126           7 :                 if(c->next!=*cstat)
     127             :                         continue;
     128           4 :                 c->next=(*cstat)->next;
     129           4 :                 if(c->next)
     130           3 :                         c->next->prev=(*cstat)->prev;
     131             :                 cstat_free_w(cstat);
     132           4 :                 *cstat=*clist;
     133           4 :                 return;
     134             :         }
     135             : }
     136             : 
     137             : // Returns -1 on error, otherwise the number of clients that were reloaded.
     138             : #ifndef UTEST
     139             : static
     140             : #endif
     141          11 : int cstat_reload_from_client_confs(struct cstat **clist,
     142             :         struct conf **globalcs, struct conf **cconfs)
     143             : {
     144             :         struct cstat *c;
     145             :         struct stat statp;
     146             :         static time_t global_mtime=0;
     147          11 :         time_t global_mtime_new=0;
     148             :         const char *globalconffile;
     149          11 :         int reloaded=0;
     150             : 
     151          11 :         globalconffile=get_string(globalcs[OPT_CONFFILE]);
     152             : 
     153          11 :         if(stat(globalconffile, &statp)
     154          11 :           || !S_ISREG(statp.st_mode))
     155             :         {
     156             :                 logp("Could not stat main conf file %s: %s\n",
     157           1 :                         globalconffile, strerror(errno));
     158           1 :                 return -1;
     159             :         }
     160          10 :         global_mtime_new=statp.st_mtime;
     161             : 
     162             :         // FIX THIS: If '. included' conf files have changed, this code will
     163             :         // not detect them. I guess that conf.c should make a list of them.
     164             :         while(1)
     165             :         {
     166          37 :                 for(c=*clist; c; c=c->next)
     167             :                 {
     168             :                         // Look at the client conf files to see if they have
     169             :                         // changed, and reload bits and pieces if they have.
     170             : 
     171          28 :                         if(!c->conffile) continue;
     172          56 :                         if(stat(c->conffile, &statp)
     173          28 :                           || !S_ISREG(statp.st_mode))
     174             :                         {
     175           3 :                                 cstat_remove(clist, &c);
     176           3 :                                 break; // Go to the beginning of the list.
     177             :                         }
     178          25 :                         if(statp.st_mtime==c->conf_mtime
     179          12 :                           && global_mtime_new==global_mtime)
     180             :                         {
     181             :                                 // The conf files have not changed - no need to
     182             :                                 // do anything.
     183             :                                 continue;
     184             :                         }
     185          13 :                         c->conf_mtime=statp.st_mtime;
     186             : 
     187          13 :                         confs_free_content(cconfs);
     188          13 :                         if(set_string(cconfs[OPT_CNAME], c->name))
     189             :                                 return -1;
     190          13 :                         if(conf_load_clientconfdir(globalcs, cconfs))
     191             :                         {
     192             :                                 // If the file has junk in it, we will keep
     193             :                                 // trying to reload it after removal.
     194             :                                 // So, just deny permission to view it.
     195           1 :                                 c->permitted=0;
     196           1 :                                 continue;
     197             :                         }
     198             : 
     199          12 :                         if(set_cstat_from_conf(c, globalcs, cconfs))
     200             :                                 return -1;
     201          12 :                         reloaded++;
     202             :                 }
     203             :                 // Only stop if the end of the list was not reached.
     204          12 :                 if(!c) break;
     205             :         }
     206          10 :         if(global_mtime!=global_mtime_new)
     207           2 :                 global_mtime=global_mtime_new;
     208          10 :         return reloaded;
     209             : }
     210             : 
     211          16 : void cstat_set_run_status(struct cstat *cstat)
     212             : {
     213             :         struct stat statp;
     214          16 :         struct sdirs *sdirs=(struct sdirs *)cstat->sdirs;
     215          16 :         if(!cstat->permitted) return;
     216             : 
     217          28 :         if(lstat(sdirs->lock->path, &statp))
     218             :         {
     219          16 :                 if(lstat(sdirs->working, &statp))
     220           6 :                         cstat->run_status=RUN_STATUS_IDLE;
     221             :                 else
     222           2 :                         cstat->run_status=RUN_STATUS_CLIENT_CRASHED;
     223             :         }
     224             :         else
     225             :         {
     226           6 :                 if(!lock_test(sdirs->lock->path)) // Could have got lock.
     227           4 :                         cstat->run_status=RUN_STATUS_SERVER_CRASHED;
     228             :                 else
     229           2 :                         cstat->run_status=RUN_STATUS_RUNNING;
     230             :         }
     231             : 
     232             :         return;
     233             : }
     234             : 
     235             : // Return -1 on error, or the number of reloaded clients.
     236             : #ifndef UTEST
     237             : static
     238             : #endif
     239           9 : int reload_from_clientdir(struct cstat **clist)
     240             : {
     241           9 :         int reloaded=0;
     242             :         struct cstat *c;
     243          29 :         for(c=*clist; c; c=c->next)
     244             :         {
     245          20 :                 time_t ltime=0;
     246             :                 struct stat statp;
     247             :                 struct stat lstatp;
     248             :                 struct sdirs *sdirs;
     249             : 
     250          36 :                 if(!c->permitted) continue;
     251             : 
     252           8 :                 sdirs=(struct sdirs *)c->sdirs;
     253           8 :                 if(!sdirs || !sdirs->client) continue;
     254          16 :                 if(stat(sdirs->client, &statp))
     255             :                 {
     256             :                         // No clientdir.
     257           2 :                         if(!c->run_status)
     258           2 :                                 cstat_set_run_status(c);
     259             :                         continue;
     260             :                 }
     261          12 :                 if(!lstat(sdirs->lock->path, &lstatp))
     262           2 :                         ltime=lstatp.st_mtime;
     263           6 :                 if(statp.st_mtime==c->clientdir_mtime
     264           4 :                   && ltime==c->lockfile_mtime
     265           2 :                   && c->run_status!=RUN_STATUS_SERVER_CRASHED)
     266             :                   //&& !c->cntr)
     267             :                 {
     268             :                         // clientdir has not changed - no need to do anything.
     269             :                         continue;
     270             :                 }
     271           4 :                 c->clientdir_mtime=statp.st_mtime;
     272           4 :                 c->lockfile_mtime=ltime;
     273           4 :                 cstat_set_run_status(c);
     274             : 
     275           4 :                 bu_list_free(&c->bu);
     276             : // FIX THIS: should probably not load everything each time.
     277             : //              if(bu_get_current(sdirs, &c->bu))
     278             : //                      goto error;
     279           4 :                 if(bu_get_list_with_working(sdirs, &c->bu, c))
     280             :                         goto error;
     281           4 :                 reloaded++;
     282             :         }
     283             :         return reloaded;
     284             : error:
     285           0 :         return -1;
     286             : }
     287             : 
     288           1 : int cstat_load_data_from_disk(struct cstat **clist, struct conf **globalcs,
     289             :         struct conf **cconfs)
     290             : {
     291           1 :         if(!globalcs) return -1;
     292             :         return cstat_get_client_names(clist,
     293           1 :                 get_string(globalcs[OPT_CLIENTCONFDIR]))
     294           1 :           || cstat_reload_from_client_confs(clist, globalcs, cconfs)<0
     295           2 :           || reload_from_clientdir(clist)<0;
     296             : }
     297             : 
     298          26 : int cstat_set_backup_list(struct cstat *cstat)
     299             : {
     300          26 :         struct bu *bu=NULL;
     301             : 
     302             :         // Free any previous list.
     303          26 :         bu_list_free(&cstat->bu);
     304             : 
     305          26 :         if(!cstat->permitted) return 0;
     306             : 
     307          24 :         if(bu_get_list_with_working((struct sdirs *)cstat->sdirs, &bu, cstat))
     308             :         {
     309             :                 //logp("error when looking up current backups\n");
     310             :                 return 0;
     311             :         }
     312             : 
     313             :         // Find the end of the list just loaded, so we can traverse
     314             :         // it backwards later.
     315          50 :         while(bu && bu->next) bu=bu->next;
     316             : 
     317          23 :         cstat->bu=bu;
     318          23 :         return 0;
     319             : }

Generated by: LCOV version 1.10