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: 77 218 35.3 %
Date: 2022-08-30 22:36:43 Functions: 5 9 55.6 %

          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             :                 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             : #ifndef UTEST
     163             : static
     164             : #endif
     165           6 : int status_server_parse_cmd(
     166             :         const char *buf,
     167             :         char **command,
     168             :         char **client,
     169             :         char **backup,
     170             :         char **logfile,
     171             :         char **browse
     172             : ) {
     173           6 :         int ret=-1;
     174           6 :         char *tok=NULL;
     175           6 :         char **current=NULL;
     176           6 :         char *copy=NULL;
     177             : 
     178           6 :         if(!buf)
     179             :                 return 0;
     180             : 
     181           6 :         if(!(copy=strdup_w(buf, __func__)))
     182             :                 goto end;
     183           6 :         if(!(tok=strtok(copy, ":")))
     184             :         {
     185             :                 ret=0;
     186             :                 goto end;
     187             :         }
     188             :         do {
     189          33 :                 if(current)
     190             :                 {
     191          15 :                         if(!(*current=strdup_w(tok, __func__)))
     192             :                                 goto end;
     193             :                         current=NULL;
     194             :                 }
     195             :                 else
     196             :                 {
     197          18 :                         if(!strcmp(tok, "j"))
     198             :                                 current=command;
     199          17 :                         else if(!strcmp(tok, "c"))
     200             :                                 current=client;
     201          12 :                         else if(!strcmp(tok, "b"))
     202             :                                 current=backup;
     203           7 :                         else if(!strcmp(tok, "l"))
     204             :                                 current=logfile;
     205           3 :                         else if(!strcmp(tok, "p"))
     206             :                         {
     207             :                                 // The path may have colons in it. So, make
     208             :                                 // this the last one.
     209           3 :                                 if(copy+strlen(buf) > tok+1)
     210             :                                 {
     211           2 :                                         if(!(*browse=strdup_w(tok+2, __func__)))
     212             :                                                 goto end;
     213             :                                 }
     214             :                                 break;
     215             :                         }
     216             :                         else
     217             :                                 current=NULL;
     218             :                 }
     219          30 :         } while((tok=strtok(NULL, ":")));
     220             : 
     221             :         ret=0;
     222             : end:
     223           6 :         free_w(&copy);
     224           6 :         return ret;
     225             : }
     226             : 
     227             : /*
     228             : void dump_cbno(struct cstat *clist, const char *msg)
     229             : {
     230             :         if(!clist) return;
     231             :         printf("dump %s: %s\n", msg, clist->name);
     232             :         struct bu *b;
     233             :         for(b=clist->bu; b; b=b->prev)
     234             :                 printf("   %d\n", b->bno);
     235             : }
     236             : */
     237             : 
     238             : static int response_marker_start(struct asfd *srfd, const char *buf)
     239             : {
     240           0 :         return json_send_msg(srfd, "response-start", buf);
     241             : }
     242             : 
     243             : static int response_marker_end(struct asfd *srfd, const char *buf)
     244             : {
     245           0 :         return json_send_msg(srfd, "response-end", buf);
     246             : }
     247             : 
     248           0 : static int parse_client_data(struct asfd *srfd,
     249             :         struct cstat *clist, int monitor_browse_cache, long *peer_version)
     250             : {
     251           0 :         int ret=0;
     252           0 :         char *command=NULL;
     253           0 :         char *client=NULL;
     254           0 :         char *backup=NULL;
     255           0 :         char *logfile=NULL;
     256           0 :         char *browse=NULL;
     257           0 :         struct cstat *cstat=NULL;
     258           0 :         struct bu *bu=NULL;
     259             :         static int response_markers=0;
     260           0 :         const char *cmd_result=NULL;
     261             : //logp("got client data: '%s'\n", srfd->rbuf->buf);
     262             : 
     263           0 :         if(status_server_parse_cmd(
     264           0 :                 srfd->rbuf->buf,
     265             :                 &command,
     266             :                 &client,
     267             :                 &backup,
     268             :                 &logfile,
     269             :                 &browse))
     270             :                         goto error;
     271             : 
     272           0 :         if(command)
     273             :         {
     274             :                 size_t l;
     275           0 :                 char peer_version_str[32]="peer_version=";
     276           0 :                 l=strlen(peer_version_str);
     277           0 :                 if(!strcmp(command, "pretty-print-on"))
     278             :                 {
     279           0 :                         json_set_pretty_print(1);
     280           0 :                         cmd_result="Pretty print on";
     281             :                 }
     282           0 :                 else if(!strcmp(command, "pretty-print-off"))
     283             :                 {
     284           0 :                         json_set_pretty_print(0);
     285           0 :                         cmd_result="Pretty print off";
     286             :                 }
     287           0 :                 else if(!strcmp(command, "response-markers-on"))
     288             :                 {
     289           0 :                         response_markers=1;
     290           0 :                         cmd_result="Response markers on";
     291             :                 }
     292           0 :                 else if(!strcmp(command, "response-markers-off"))
     293             :                 {
     294           0 :                         response_markers=0;
     295           0 :                         cmd_result="Response markers off";
     296             :                 }
     297           0 :                 else if(!strncmp(command, peer_version_str, l))
     298             :                 {
     299           0 :                         if(!(*peer_version=version_to_long(command+l)))
     300             :                                 goto error;
     301             :                         cmd_result="Peer version updated";
     302             :                 }
     303             :                 else
     304             :                 {
     305             :                         cmd_result="Unknown command";
     306             :                 }
     307             :         }
     308             : 
     309           0 :         if(response_markers
     310           0 :           && response_marker_start(srfd, srfd->rbuf->buf))
     311             :                 goto error;
     312             : 
     313           0 :         if(cmd_result)
     314             :         {
     315           0 :                 if(json_send_warn(srfd, cmd_result))
     316             :                         goto error;
     317             :                 goto end;
     318             :         }
     319             : 
     320           0 :         if(browse)
     321             :         {
     322           0 :                 free_w(&logfile);
     323           0 :                 if(!(logfile=strdup_w("manifest", __func__)))
     324             :                         goto error;
     325           0 :                 strip_trailing_slashes(&browse);
     326             :         }
     327             : 
     328             : //dump_cbno(clist, "pcd");
     329             : 
     330           0 :         if(client && *client)
     331             :         {
     332           0 :                 if(!(cstat=cstat_get_by_name(clist, client)))
     333             :                 {
     334           0 :                         char msg[256]="";
     335           0 :                         snprintf(msg, sizeof(msg),
     336             :                                 "Could not find client: %s", client);
     337           0 :                         if(json_send_warn(srfd, msg))
     338             :                                 goto error;
     339           0 :                         goto end;
     340             :                 }
     341             : 
     342           0 :                 if(cstat_set_backup_list(cstat))
     343             :                 {
     344           0 :                         if(json_send_warn(srfd, "Could not get backup list"))
     345             :                                 goto error;
     346             :                         goto end;
     347             :                         
     348             :                 }
     349             :         }
     350           0 :         if(cstat && backup)
     351             :         {
     352           0 :                 unsigned long bno=0;
     353           0 :                 if(!(bno=strtoul(backup, NULL, 10)))
     354             :                 {
     355           0 :                         if(json_send_warn(srfd, "Could not get backup number"))
     356             :                                 goto error;
     357             :                         goto end;
     358             :                 }
     359           0 :                 for(bu=cstat->bu; bu; bu=bu->prev)
     360           0 :                         if(bu->bno==bno) break;
     361             : 
     362           0 :                 if(!bu)
     363             :                 {
     364           0 :                         if(json_send_warn(srfd, "Backup not found"))
     365             :                                 goto error;
     366             :                         goto end;
     367             :                 }
     368             :         }
     369           0 :         if(logfile)
     370             :         {
     371           0 :                 if(strcmp(logfile, "manifest")
     372           0 :                   && strcmp(logfile, "backup")
     373           0 :                   && strcmp(logfile, "restore")
     374           0 :                   && strcmp(logfile, "verify")
     375           0 :                   && strcmp(logfile, "backup_stats")
     376           0 :                   && strcmp(logfile, "restore_stats")
     377           0 :                   && strcmp(logfile, "verify_stats"))
     378             :                 {
     379           0 :                         if(json_send_warn(srfd, "File not supported"))
     380             :                                 goto error;
     381             :                         goto end;
     382             :                 }
     383             :         }
     384             : /*
     385             :         printf("client: %s\n", client?:"");
     386             :         printf("backup: %s\n", backup?:"");
     387             :         printf("logfile: %s\n", logfile?:"");
     388             : */
     389           0 :         if(json_send(srfd, clist, cstat, bu, logfile, browse,
     390             :                 monitor_browse_cache, *peer_version))
     391             :                         goto error;
     392             : 
     393             :         goto end;
     394             : error:
     395             :         ret=-1;
     396             : end:
     397           0 :         if(response_markers
     398           0 :           && response_marker_end(srfd, srfd->rbuf->buf))
     399           0 :                 ret=-1;
     400             : 
     401           0 :         free_w(&client);
     402           0 :         free_w(&backup);
     403           0 :         free_w(&logfile);
     404           0 :         free_w(&browse);
     405           0 :         return ret;
     406             : }
     407             : 
     408           0 : static int parse_data(struct asfd *asfd, struct cstat *clist,
     409             :         struct asfd *cfd, int monitor_browse_cache, long *peer_version)
     410             : {
     411           0 :         if(asfd==cfd)
     412           0 :                 return parse_client_data(asfd,
     413             :                         clist, monitor_browse_cache, peer_version);
     414           0 :         return parse_parent_data(asfd->rbuf->buf, clist);
     415             : }
     416             : 
     417             : static int have_data_for_running_clients(struct cstat *clist)
     418             : {
     419             :         struct cstat *c;
     420           0 :         for(c=clist; c; c=c->next)
     421             :         {
     422           0 :                 if(c->run_status==RUN_STATUS_RUNNING)
     423             :                 {
     424           0 :                         if(!c->cntrs
     425           0 :                           || c->cntrs->cntr_status==CNTR_STATUS_UNSET)
     426             :                                 return 0;
     427             :                 }
     428             :         }
     429             :         return 1;
     430             : }
     431             : 
     432             : static int have_run_statuses(struct cstat *clist)
     433             : {
     434             :         struct cstat *c;
     435           0 :         for(c=clist; c; c=c->next)
     436           0 :                 if(c->permitted && c->run_status==RUN_STATUS_UNSET)
     437             :                         return 0;
     438             :         return 1;
     439             : }
     440             : 
     441           0 : static int get_initial_data(struct async *as,
     442             :         struct cstat **clist,
     443             :         struct conf **monitor_cconfs,
     444             :         struct conf **globalcs, struct conf **cconfs,
     445             :         int monitor_browse_cache, long *peer_version)
     446             : {
     447           0 :         int x=10;
     448           0 :         struct asfd *asfd=NULL;
     449             : 
     450           0 :         if(cstat_load_data_from_disk(clist, monitor_cconfs, globalcs, cconfs))
     451             :                 return -1;
     452             : 
     453             :         // Try to get the initial data.
     454           0 :         while(x)
     455             :         {
     456             :                 // Do not wait forever for running clients.
     457           0 :                 if(!have_data_for_running_clients(*clist))
     458           0 :                         x--;
     459           0 :                 else if(have_run_statuses(*clist))
     460             :                         return 0;
     461             : 
     462           0 :                 if(as->read_write(as))
     463             :                 {
     464           0 :                         logp("Exiting main status server loop\n");
     465           0 :                         return -1;
     466             :                 }
     467           0 :                 asfd=as->asfd->next;
     468           0 :                 if(asfd->rbuf->buf)
     469             :                 {
     470           0 :                         if(parse_data(asfd, *clist,
     471             :                                 NULL, monitor_browse_cache, peer_version))
     472             :                         {
     473           0 :                                 iobuf_free_content(asfd->rbuf);
     474           0 :                                 return -1;
     475             :                         }
     476           0 :                         iobuf_free_content(asfd->rbuf);
     477             :                 }
     478             :         }
     479             :         return 0;
     480             : }
     481             : 
     482           0 : int status_server(struct async *as, struct conf **monitor_cconfs)
     483             : {
     484           0 :         int ret=-1;
     485           0 :         int gotdata=0;
     486             :         struct asfd *asfd;
     487           0 :         struct cstat *clist=NULL;
     488           0 :         struct asfd *cfd=as->asfd; // Client.
     489           0 :         struct conf **cconfs=NULL;
     490           0 :         struct conf **globalcs=NULL;
     491           0 :         const char *conffile=get_string(monitor_cconfs[OPT_CONFFILE]);
     492           0 :         long peer_version=version_to_long(get_string(monitor_cconfs[OPT_PEER_VERSION]));
     493           0 :         int monitor_browse_cache=get_int(monitor_cconfs[OPT_MONITOR_BROWSE_CACHE]);
     494             : 
     495             :         // We need to load a fresh global conf so that the clients do not all
     496             :         // get settings from the monitor client. In particular, if protocol=0
     497             :         // in both burp-server.conf and the monitor burp.conf, the monitor
     498             :         // client gets protocol=1 from extra comms, and all the clients here
     499             :         // would end up getting protocol=1.
     500           0 :         if(!(globalcs=confs_alloc()))
     501             :                 goto end;
     502           0 :         if(confs_init(globalcs)) return -1;
     503           0 :         if(conf_load_global_only(conffile, globalcs))
     504             :                 return -1;
     505             : 
     506           0 :         if(!(cconfs=confs_alloc()))
     507             :                 goto end;
     508             : 
     509           0 :         if(get_initial_data(as, &clist, monitor_cconfs,
     510             :                 globalcs, cconfs, monitor_browse_cache, &peer_version))
     511             :                         goto end;
     512             : 
     513             :         while(1)
     514             :         {
     515             :                 // Take the opportunity to get data from the disk if nothing
     516             :                 // was read from the fds.
     517           0 :                 if(gotdata) gotdata=0;
     518           0 :                 else if(cstat_load_data_from_disk(&clist, monitor_cconfs,
     519             :                         globalcs, cconfs))
     520             :                                 goto end;
     521           0 :                 if(as->read_write(as))
     522             :                 {
     523           0 :                         logp("Exiting main status server loop\n");
     524             :                         break;
     525             :                 }
     526           0 :                 for(asfd=as->asfd; asfd; asfd=asfd->next)
     527           0 :                         while(asfd->rbuf->buf)
     528             :                 {
     529           0 :                         gotdata=1;
     530           0 :                         if(parse_data(asfd, clist,
     531             :                                 cfd, monitor_browse_cache, &peer_version)
     532           0 :                           || asfd->parse_readbuf(asfd))
     533             :                                 goto end;
     534           0 :                         iobuf_free_content(asfd->rbuf);
     535             :                 }
     536             :         }
     537           0 :         ret=0;
     538             : end:
     539             : // FIX THIS: should free clist;
     540           0 :         confs_free(&globalcs);
     541           0 :         return ret;
     542             : }

Generated by: LCOV version 1.13