LCOV - code coverage report
Current view: top level - src/server/monitor - status_server.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 58 204 28.4 %
Date: 2018-01-01 Functions: 4 9 44.4 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../asfd.h"
       4             : #include "../../async.h"
       5             : #include "../../bu.h"
       6             : #include "../../cstat.h"
       7             : #include "../../conffile.h"
       8             : #include "../../handy.h"
       9             : #include "../../iobuf.h"
      10             : #include "../../log.h"
      11             : #include "cstat.h"
      12             : #include "json_output.h"
      13             : #include "status_server.h"
      14             : 
      15           6 : static int parse_cntr_data(const char *buf, struct cstat *clist)
      16             : {
      17           6 :         int bno=0;
      18           6 :         int ret=-1;
      19           6 :         char *cname=NULL;
      20           6 :         struct cstat *c=NULL;
      21           6 :         char *path=NULL;
      22           6 :         char *dp=NULL;
      23           6 :         pid_t pid=-1;
      24             : 
      25             :         // Skip the type.
      26           6 :         if(!(dp=strchr(buf, '\t')))
      27             :                 return 0;
      28           5 :         dp++;
      29             : 
      30           5 :         if(extract_client_pid_bno(dp, &cname, &pid, &bno))
      31             :                 return -1;
      32           5 :         if(!cname)
      33             :                 return 0;
      34             : 
      35             :         // Find the array entry for this client,
      36             :         // and add the detail from the parent to it.
      37           3 :         for(c=clist; c; c=c->next)
      38             :         {
      39           3 :                 struct cntr *cntr=NULL;
      40           3 :                 if(strcmp(c->name, cname))
      41           2 :                         continue;
      42           1 :                 cstat_set_run_status(c, RUN_STATUS_RUNNING);
      43             : 
      44             :                 // Find the cntr entry for this client/pid.
      45           1 :                 for(cntr=c->cntrs; cntr; cntr=cntr->next)
      46           0 :                         if(cntr->pid==pid)
      47             :                                 break;
      48           1 :                 if(!cntr)
      49             :                 {
      50             :                         // Need to allocate a new cntr.
      51           1 :                         if(!(cntr=cntr_alloc())
      52           1 :                           || cntr_init(cntr, cname, pid))
      53             :                                 goto end;
      54           1 :                         cstat_add_cntr_to_list(c, cntr);
      55             :                 }
      56           1 :                 if(str_to_cntr(buf, cntr, &path))
      57             :                         goto end;
      58             :         }
      59             : 
      60             : // FIX THIS: Do something with path.
      61             : 
      62             :         ret=0;
      63             : end:
      64           5 :         free_w(&cname);
      65           5 :         free_w(&path);
      66           5 :         return ret;
      67             : }
      68             : 
      69           4 : static void clean_up_cntrs(struct cstat *clist)
      70             : {
      71             :         struct cstat *c;
      72          16 :         for(c=clist; c; c=c->next)
      73             :         {
      74          12 :                 struct cntr *cntr=NULL;
      75          24 :                 for(cntr=c->cntrs; cntr; )
      76             :                 {
      77           0 :                         if(cntr->found)
      78             :                         {
      79           0 :                                 cntr=cntr->next;
      80           0 :                                 continue;
      81             :                         }
      82           0 :                         cstat_remove_cntr_from_list(c, cntr);
      83           0 :                         cntr_free(&cntr);
      84           0 :                         if(c->cntrs)
      85           0 :                                 cntr=c->cntrs;
      86             :                 }
      87             :         }
      88           4 : }
      89             : 
      90           9 : static int parse_clients_list(char *buf, struct cstat *clist)
      91             : {
      92           9 :         char *tok=NULL;
      93             :         struct cstat *c;
      94             : 
      95           9 :         if(!clist)
      96             :                 return 0;
      97             : 
      98             :         // Do not need the first token.
      99           4 :         if(!(tok=strtok(buf, "\t\n")))
     100             :                 return 0;
     101          12 :         for(c=clist; c; c=c->next)
     102             :         {
     103             :                 struct cntr *cntr;
     104          12 :                 for(cntr=c->cntrs; cntr; cntr=cntr->next)
     105           0 :                         cntr->found=0;
     106          12 :                 cstat_set_run_status(c, RUN_STATUS_IDLE);
     107             :         }
     108             : 
     109           7 :         while((tok=strtok(NULL, "\t\n")))
     110             :         {
     111           3 :                 int bno=0;
     112           3 :                 pid_t pid=-1;
     113           3 :                 char *cname=NULL;
     114           3 :                 if(extract_client_pid_bno(tok, &cname, &pid, &bno))
     115           0 :                         return -1;
     116          11 :                 for(c=clist; c; c=c->next)
     117             :                 {
     118             :                         struct cntr *cntr;
     119           7 :                         if(strcmp(c->name, cname))
     120           4 :                                 continue;
     121           3 :                         cstat_set_run_status(c, RUN_STATUS_RUNNING);
     122           3 :                         for(cntr=c->cntrs; cntr; cntr=cntr->next)
     123           0 :                                 if(cntr->pid==pid)
     124             :                                         break;
     125           3 :                         if(cntr)
     126             :                         {
     127           0 :                                 cntr->found=1;
     128           0 :                                 cntr->bno=bno;
     129             :                         }
     130             :                         break;
     131             :                 }
     132           3 :                 free_w(&cname);
     133             :         }
     134             : 
     135           4 :         clean_up_cntrs(clist);
     136             : 
     137           4 :         return 0;
     138             : }
     139             : 
     140             : #ifndef UTEST
     141             : static
     142             : #endif
     143          18 : int parse_parent_data(char *buf, struct cstat *clist)
     144             : {
     145          18 :         if(!buf || !*buf)
     146             :                 return 0;
     147             : 
     148          17 :         if(!strncmp(buf, "cntr", strlen("cntr")))
     149             :         {
     150           6 :                 if(parse_cntr_data(buf, clist))
     151             :                         return -1;
     152             :         }
     153          11 :         else if(!strncmp(buf, "clients", strlen("clients")))
     154             :         {
     155           9 :                 if(parse_clients_list(buf, clist))
     156             :                         return -1;
     157             :         }
     158             : 
     159             :         return 0;
     160             : }
     161             : 
     162           0 : static char *get_str(const char **buf, const char *pre, int last)
     163             : {
     164           0 :         size_t len=0;
     165           0 :         char *cp=NULL;
     166           0 :         char *copy=NULL;
     167           0 :         char *ret=NULL;
     168           0 :         if(!buf || !*buf) goto end;
     169           0 :         len=strlen(pre);
     170           0 :         if(strncmp(*buf, pre, len)
     171           0 :           || !(copy=strdup_w((*buf)+len, __func__)))
     172             :                 goto end;
     173           0 :         if(!last && (cp=strchr(copy, ':'))) *cp='\0';
     174           0 :         *buf+=len+strlen(copy)+1;
     175           0 :         ret=strdup_w(copy, __func__);
     176             : end:
     177           0 :         free_w(&copy);
     178           0 :         return ret;
     179             : }
     180             : 
     181             : /*
     182             : void dump_cbno(struct cstat *clist, const char *msg)
     183             : {
     184             :         if(!clist) return;
     185             :         printf("dump %s: %s\n", msg, clist->name);
     186             :         struct bu *b;
     187             :         for(b=clist->bu; b; b=b->prev)
     188             :                 printf("   %d\n", b->bno);
     189             : }
     190             : */
     191             : 
     192           0 : static int parse_client_data(struct asfd *srfd,
     193             :         struct cstat *clist, int monitor_browse_cache, long *peer_version)
     194             : {
     195           0 :         int ret=0;
     196           0 :         char *command=NULL;
     197           0 :         char *client=NULL;
     198           0 :         char *backup=NULL;
     199           0 :         char *logfile=NULL;
     200           0 :         char *browse=NULL;
     201           0 :         const char *cp=NULL;
     202           0 :         struct cstat *cstat=NULL;
     203           0 :         struct bu *bu=NULL;
     204             : //logp("got client data: '%s'\n", srfd->rbuf->buf);
     205             : 
     206           0 :         cp=srfd->rbuf->buf;
     207             : 
     208           0 :         command=get_str(&cp, "j:", 0);
     209           0 :         client=get_str(&cp, "c:", 0);
     210           0 :         backup=get_str(&cp, "b:", 0);
     211           0 :         logfile=get_str(&cp, "l:", 0);
     212           0 :         browse=get_str(&cp, "p:", 1);
     213             : 
     214           0 :         if(command)
     215             :         {
     216             :                 size_t l;
     217           0 :                 char peer_version_str[32]="peer_version=";
     218           0 :                 l=strlen(peer_version_str);
     219           0 :                 if(!strcmp(command, "pretty-print-on"))
     220             :                 {
     221           0 :                         json_set_pretty_print(1);
     222           0 :                         if(json_send_warn(srfd, "Pretty print on"))
     223             :                                 goto error;
     224             :                 }
     225           0 :                 else if(!strcmp(command, "pretty-print-off"))
     226             :                 {
     227           0 :                         json_set_pretty_print(0);
     228           0 :                         if(json_send_warn(srfd, "Pretty print off"))
     229             :                                 goto error;
     230             :                 }
     231           0 :                 else if(!strncmp(command, peer_version_str, l))
     232             :                 {
     233           0 :                         if(!(*peer_version=version_to_long(command+l)))
     234             :                                 goto error;
     235             :                 }
     236             :                 else
     237             :                 {
     238           0 :                         if(json_send_warn(srfd, "Unknown command"))
     239             :                                 goto error;
     240             :                 }
     241           0 :                 goto end;
     242             :         }
     243             : 
     244           0 :         if(browse)
     245             :         {
     246           0 :                 free_w(&logfile);
     247           0 :                 if(!(logfile=strdup_w("manifest", __func__)))
     248             :                         goto error;
     249           0 :                 strip_trailing_slashes(&browse);
     250             :         }
     251             : 
     252             : //dump_cbno(clist, "pcd");
     253             : 
     254           0 :         if(client && *client)
     255             :         {
     256           0 :                 if(!(cstat=cstat_get_by_name(clist, client)))
     257             :                 {
     258           0 :                         char msg[256]="";
     259           0 :                         snprintf(msg, sizeof(msg),
     260             :                                 "Could not find client: %s", client);
     261           0 :                         if(json_send_warn(srfd, msg))
     262             :                                 goto error;
     263           0 :                         goto end;
     264             :                 }
     265             : 
     266           0 :                 if(cstat_set_backup_list(cstat))
     267             :                 {
     268           0 :                         if(json_send_warn(srfd, "Could not get backup list"))
     269             :                                 goto error;
     270             :                         goto end;
     271             :                         
     272             :                 }
     273             :         }
     274           0 :         if(cstat && backup)
     275             :         {
     276           0 :                 unsigned long bno=0;
     277           0 :                 if(!(bno=strtoul(backup, NULL, 10)))
     278             :                 {
     279           0 :                         if(json_send_warn(srfd, "Could not get backup number"))
     280             :                                 goto error;
     281             :                         goto end;
     282             :                 }
     283           0 :                 for(bu=cstat->bu; bu; bu=bu->prev)
     284           0 :                         if(bu->bno==bno) break;
     285             : 
     286           0 :                 if(!bu)
     287             :                 {
     288           0 :                         if(json_send_warn(srfd, "Backup not found"))
     289             :                                 goto error;
     290             :                         goto end;
     291             :                 }
     292             :         }
     293           0 :         if(logfile)
     294             :         {
     295           0 :                 if(strcmp(logfile, "manifest")
     296           0 :                   && strcmp(logfile, "backup")
     297           0 :                   && strcmp(logfile, "restore")
     298           0 :                   && strcmp(logfile, "verify")
     299           0 :                   && strcmp(logfile, "backup_stats")
     300           0 :                   && strcmp(logfile, "restore_stats")
     301           0 :                   && strcmp(logfile, "verify_stats"))
     302             :                 {
     303           0 :                         if(json_send_warn(srfd, "File not supported"))
     304             :                                 goto error;
     305             :                         goto end;
     306             :                 }
     307             :         }
     308             : /*
     309             :         printf("client: %s\n", client?:"");
     310             :         printf("backup: %s\n", backup?:"");
     311             :         printf("logfile: %s\n", logfile?:"");
     312             : */
     313           0 :         if(json_send(srfd, clist, cstat, bu, logfile, browse,
     314             :                 monitor_browse_cache, *peer_version))
     315             :                         goto error;
     316             : 
     317             :         goto end;
     318             : error:
     319             :         ret=-1;
     320             : end:
     321           0 :         free_w(&client);
     322           0 :         free_w(&backup);
     323           0 :         free_w(&logfile);
     324           0 :         free_w(&browse);
     325           0 :         return ret;
     326             : }
     327             : 
     328           0 : static int parse_data(struct asfd *asfd, struct cstat *clist,
     329             :         struct asfd *cfd, int monitor_browse_cache, long *peer_version)
     330             : {
     331           0 :         if(asfd==cfd)
     332           0 :                 return parse_client_data(asfd,
     333             :                         clist, monitor_browse_cache, peer_version);
     334           0 :         return parse_parent_data(asfd->rbuf->buf, clist);
     335             : }
     336             : 
     337             : static int have_data_for_running_clients(struct cstat *clist)
     338             : {
     339             :         struct cstat *c;
     340           0 :         for(c=clist; c; c=c->next)
     341             :         {
     342           0 :                 if(c->run_status==RUN_STATUS_RUNNING)
     343             :                 {
     344           0 :                         if(!c->cntrs
     345           0 :                           || c->cntrs->cntr_status==CNTR_STATUS_UNSET)
     346             :                                 return 0;
     347             :                 }
     348             :         }
     349             :         return 1;
     350             : }
     351             : 
     352             : static int have_run_statuses(struct cstat *clist)
     353             : {
     354             :         struct cstat *c;
     355           0 :         for(c=clist; c; c=c->next)
     356           0 :                 if(c->permitted && c->run_status==RUN_STATUS_UNSET)
     357             :                         return 0;
     358             :         return 1;
     359             : }
     360             : 
     361           0 : static int get_initial_data(struct async *as,
     362             :         struct cstat **clist,
     363             :         struct conf **monitor_cconfs,
     364             :         struct conf **globalcs, struct conf **cconfs,
     365             :         int monitor_browse_cache, long *peer_version)
     366             : {
     367           0 :         int x=10;
     368           0 :         struct asfd *asfd=NULL;
     369             : 
     370           0 :         if(cstat_load_data_from_disk(clist, monitor_cconfs, globalcs, cconfs))
     371             :                 return -1;
     372             : 
     373             :         // Try to get the initial data.
     374           0 :         while(x)
     375             :         {
     376             :                 // Do not wait forever for running clients.
     377           0 :                 if(!have_data_for_running_clients(*clist))
     378           0 :                         x--;
     379           0 :                 else if(have_run_statuses(*clist))
     380             :                         return 0;
     381             : 
     382           0 :                 if(as->read_write(as))
     383             :                 {
     384           0 :                         logp("Exiting main status server loop\n");
     385           0 :                         return -1;
     386             :                 }
     387           0 :                 asfd=as->asfd->next;
     388           0 :                 if(asfd->rbuf->buf)
     389             :                 {
     390           0 :                         if(parse_data(asfd, *clist,
     391             :                                 NULL, monitor_browse_cache, peer_version))
     392             :                         {
     393           0 :                                 iobuf_free_content(asfd->rbuf);
     394           0 :                                 return -1;
     395             :                         }
     396           0 :                         iobuf_free_content(asfd->rbuf);
     397             :                 }
     398             :         }
     399             :         return 0;
     400             : }
     401             : 
     402           0 : int status_server(struct async *as, struct conf **monitor_cconfs)
     403             : {
     404           0 :         int ret=-1;
     405           0 :         int gotdata=0;
     406             :         struct asfd *asfd;
     407           0 :         struct cstat *clist=NULL;
     408           0 :         struct asfd *cfd=as->asfd; // Client.
     409           0 :         struct conf **cconfs=NULL;
     410           0 :         struct conf **globalcs=NULL;
     411           0 :         const char *conffile=get_string(monitor_cconfs[OPT_CONFFILE]);
     412           0 :         long peer_version=version_to_long(get_string(monitor_cconfs[OPT_PEER_VERSION]));
     413           0 :         int monitor_browse_cache=get_int(monitor_cconfs[OPT_MONITOR_BROWSE_CACHE]);
     414             : 
     415             :         // We need to load a fresh global conf so that the clients do not all
     416             :         // get settings from the monitor client. In particular, if protocol=0
     417             :         // in both burp-server.conf and the monitor burp.conf, the monitor
     418             :         // client gets protocol=1 from extra comms, and all the clients here
     419             :         // would end up getting protocol=1.
     420           0 :         if(!(globalcs=confs_alloc()))
     421             :                 goto end;
     422           0 :         if(confs_init(globalcs)) return -1;
     423           0 :         if(conf_load_global_only(conffile, globalcs))
     424             :                 return -1;
     425             : 
     426           0 :         if(!(cconfs=confs_alloc()))
     427             :                 goto end;
     428             : 
     429           0 :         if(get_initial_data(as, &clist, monitor_cconfs,
     430             :                 globalcs, cconfs, monitor_browse_cache, &peer_version))
     431             :                         goto end;
     432             : 
     433             :         while(1)
     434             :         {
     435             :                 // Take the opportunity to get data from the disk if nothing
     436             :                 // was read from the fds.
     437           0 :                 if(gotdata) gotdata=0;
     438           0 :                 else if(cstat_load_data_from_disk(&clist, monitor_cconfs,
     439             :                         globalcs, cconfs))
     440             :                                 goto end;
     441           0 :                 if(as->read_write(as))
     442             :                 {
     443           0 :                         logp("Exiting main status server loop\n");
     444             :                         break;
     445             :                 }
     446           0 :                 for(asfd=as->asfd; asfd; asfd=asfd->next)
     447           0 :                         while(asfd->rbuf->buf)
     448             :                 {
     449           0 :                         gotdata=1;
     450           0 :                         if(parse_data(asfd, clist,
     451             :                                 cfd, monitor_browse_cache, &peer_version)
     452           0 :                           || asfd->parse_readbuf(asfd))
     453             :                                 goto end;
     454           0 :                         iobuf_free_content(asfd->rbuf);
     455             :                 }
     456             :         }
     457           0 :         ret=0;
     458             : end:
     459             : // FIX THIS: should free clist;
     460           0 :         confs_free(&globalcs);
     461           0 :         return ret;
     462             : }

Generated by: LCOV version 1.10