LCOV - code coverage report
Current view: top level - src/server - extra_comms.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 217 225 96.4 %
Date: 2019-04-28 12:12:12 Functions: 9 9 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../cmd.h"
       6             : #include "../conf.h"
       7             : #include "../conffile.h"
       8             : #include "../fsops.h"
       9             : #include "../handy.h"
      10             : #include "../incexc_recv.h"
      11             : #include "../incexc_send.h"
      12             : #include "../iobuf.h"
      13             : #include "../log.h"
      14             : #include "../prepend.h"
      15             : #include "autoupgrade.h"
      16             : #include "extra_comms.h"
      17             : 
      18             : #include <librsync.h>
      19             : 
      20         314 : static int append_to_feat(char **feat, const char *str)
      21             : {
      22         314 :         char *tmp=NULL;
      23         314 :         if(!*feat)
      24             :         {
      25          35 :                 if(!(*feat=strdup_w(str, __func__)))
      26             :                         return -1;
      27          35 :                 return 0;
      28             :         }
      29         279 :         if(!(tmp=prepend(*feat, str)))
      30             :                 return -1;
      31         279 :         free_w(feat);
      32         279 :         *feat=tmp;
      33         279 :         return 0;
      34             : }
      35             : 
      36             : // It is unfortunate that we are having to figure out the server-initiated
      37             : // restore paths here instead of setting it in a struct sdirs.
      38             : // But doing the extra_comms needs to come before setting the sdirs, because
      39             : // extra_comms sets up a bunch of settings that sdirs need to know.
      40          35 : static char *get_restorepath_proto1(struct conf **cconfs)
      41             : {
      42          35 :         char *tmp=NULL;
      43          35 :         char *restorepath=NULL;
      44          35 :         if((tmp=prepend_s(get_string(cconfs[OPT_DIRECTORY]),
      45          35 :                 get_string(cconfs[OPT_CNAME]))))
      46          35 :                         restorepath=prepend_s(tmp, "restore");
      47          35 :         free_w(&tmp);
      48          35 :         return restorepath;
      49             : }
      50             : 
      51          35 : static char *get_restorepath_proto2(struct conf **cconfs)
      52             : {
      53          35 :         char *tmp1=NULL;
      54          35 :         char *tmp2=NULL;
      55          35 :         char *restorepath=NULL;
      56          35 :         if(!(tmp1=prepend_s(get_string(cconfs[OPT_DIRECTORY]),
      57          35 :                 get_string(cconfs[OPT_DEDUP_GROUP]))))
      58             :                         goto error;
      59          35 :         if(!(tmp2=prepend_s(tmp1, "clients")))
      60             :                 goto error;
      61          35 :         free_w(&tmp1);
      62          35 :         if(!(tmp1=prepend_s(tmp2, get_string(cconfs[OPT_CNAME]))))
      63             :                 goto error;
      64          35 :         if(!(restorepath=prepend_s(tmp1, "restore")))
      65             :                 goto error;
      66             :         goto end;
      67             : error:
      68           0 :         free_w(&restorepath);
      69             : end:
      70          35 :         free_w(&tmp1);
      71          35 :         free_w(&tmp2);
      72          35 :         return restorepath;
      73             : }
      74             : 
      75          35 : static int set_restore_path(struct conf **cconfs, char **feat)
      76             : {
      77          35 :         int ret=-1;
      78          35 :         char *restorepath1=NULL;
      79          35 :         char *restorepath2=NULL;
      80          35 :         if(!(restorepath1=get_restorepath_proto1(cconfs))
      81          35 :           || !(restorepath2=get_restorepath_proto2(cconfs)))
      82             :                 goto end;
      83          35 :         if(is_reg_lstat(restorepath1)==1
      84           4 :           && set_string(cconfs[OPT_RESTORE_PATH], restorepath1))
      85             :                 goto end;
      86          35 :         else if(is_reg_lstat(restorepath2)==1
      87           0 :           && set_string(cconfs[OPT_RESTORE_PATH], restorepath2))
      88             :                 goto end;
      89          35 :         if(get_string(cconfs[OPT_RESTORE_PATH])
      90           4 :           && append_to_feat(feat, "srestore:"))
      91             :                 goto end;
      92             :         ret=0;
      93             : end:
      94          35 :         free_w(&restorepath1);
      95          35 :         free_w(&restorepath2);
      96          35 :         return ret;
      97             : }
      98             : 
      99             : struct vers
     100             : {
     101             :         long min;
     102             :         long cli;
     103             :         long ser;
     104             :         long feat_list;
     105             :         long directory_tree;
     106             :         long burp2;
     107             :         long counters_json;
     108             : };
     109             : 
     110          35 : static int send_features(struct asfd *asfd, struct conf **cconfs,
     111             :         struct vers *vers)
     112             : {
     113          35 :         int ret=-1;
     114          35 :         char *feat=NULL;
     115          35 :         enum protocol protocol=get_protocol(cconfs);
     116          35 :         struct strlist *startdir=get_strlist(cconfs[OPT_STARTDIR]);
     117          35 :         struct strlist *incglob=get_strlist(cconfs[OPT_INCGLOB]);
     118             : 
     119          35 :         if(append_to_feat(&feat, "extra_comms_begin ok:")
     120             :                 /* clients can autoupgrade */
     121          35 :           || append_to_feat(&feat, "autoupgrade:")
     122             :                 /* clients can give server incexc conf so that the
     123             :                    server knows better what to do on resume */
     124          35 :           || append_to_feat(&feat, "incexc:")
     125             :                 /* clients can give the server an alternative client
     126             :                    to restore from */
     127          35 :           || append_to_feat(&feat, "orig_client:")
     128             :                 /* clients can tell the server what kind of system they are. */
     129          35 :           || append_to_feat(&feat, "uname:")
     130          35 :           || append_to_feat(&feat, "failover:"))
     131             :                 goto end;
     132             : 
     133             :         /* Clients can receive restore initiated from the server. */
     134          35 :         if(set_restore_path(cconfs, &feat))
     135             :                 goto end;
     136             : 
     137             :         /* Clients can receive incexc conf from the server.
     138             :            Only give it as an option if the server has some starting
     139             :            directory configured in the clientconfdir. */
     140          35 :         if((startdir || incglob)
     141           0 :           && append_to_feat(&feat, "sincexc:"))
     142             :                 goto end;
     143             : 
     144          35 :         if(vers->cli>=vers->counters_json)
     145             :         {
     146             :                 /* Clients can be sent cntrs on resume/verify/restore. */
     147          30 :                 if(append_to_feat(&feat, "counters_json:"))
     148             :                         goto end;
     149             :         }
     150             : 
     151             :         // We support CMD_MESSAGE.
     152          35 :         if(append_to_feat(&feat, "msg:"))
     153             :                 goto end;
     154             : 
     155          35 :         if(protocol==PROTO_AUTO)
     156             :         {
     157             :                 /* If the server is configured to use either protocol, let the
     158             :                    client know that it can choose. */
     159          25 :                 logp("Server is using protocol=0 (auto)\n");
     160          25 :                 if(append_to_feat(&feat, "csetproto:"))
     161             :                         goto end;
     162             :         }
     163             :         else
     164             :         {
     165          10 :                 char p[32]="";
     166             :                 /* Tell the client what we are going to use. */
     167          10 :                 logp("Server is using protocol=%d\n", (int)protocol);
     168          10 :                 snprintf(p, sizeof(p), "forceproto=%d:", (int)protocol);
     169          10 :                 if(append_to_feat(&feat, p))
     170             :                         goto end;
     171             :         }
     172             : 
     173             : #ifdef HAVE_BLAKE2
     174             :         if(append_to_feat(&feat, "rshash=blake2:"))
     175             :                 goto end;
     176             : #endif
     177             : 
     178             :         //printf("feat: %s\n", feat);
     179             : 
     180          35 :         if(asfd->write_str(asfd, CMD_GEN, feat))
     181             :         {
     182           1 :                 logp("problem in extra_comms\n");
     183             :                 goto end;
     184             :         }
     185             : 
     186             :         ret=0;
     187             : end:
     188          35 :         free_w(&feat);
     189          35 :         return ret;
     190             : }
     191             : 
     192           2 : static int do_autoupgrade(struct asfd *asfd, struct vers *vers,
     193             :         struct conf **globalcs)
     194             : {
     195           2 :         int ret=-1;
     196           2 :         char *os=NULL;
     197           2 :         struct iobuf *rbuf=asfd->rbuf;
     198           2 :         const char *autoupgrade_dir=get_string(globalcs[OPT_AUTOUPGRADE_DIR]);
     199             : 
     200           2 :         if(!(os=strdup_w(rbuf->buf+strlen("autoupgrade:"), __func__)))
     201             :                 goto end;
     202           2 :         iobuf_free_content(rbuf);
     203           2 :         ret=0;
     204           2 :         if(os && *os)
     205             :         {
     206             :                 // Sanitise path separators
     207           7 :                 for(char *i=os; *i; ++i)
     208           7 :                         if(*i == '/' || *i == '\\' || *i == ':')
     209           0 :                                 *i='-';
     210             : 
     211           1 :                 ret=autoupgrade_server(asfd, vers->ser,
     212             :                         vers->cli, os, get_cntr(globalcs),
     213             :                         autoupgrade_dir);
     214             :         }
     215             : end:
     216           2 :         free_w(&os);
     217           2 :         return ret;
     218             : }
     219             : 
     220          34 : static int extra_comms_read(struct async *as,
     221             :         struct vers *vers, int *srestore,
     222             :         char **incexc, struct conf **globalcs, struct conf **cconfs)
     223             : {
     224          34 :         int ret=-1;
     225             :         struct asfd *asfd;
     226             :         struct iobuf *rbuf;
     227          34 :         asfd=as->asfd;
     228          34 :         rbuf=asfd->rbuf;
     229             : 
     230             :         while(1)
     231             :         {
     232          54 :                 iobuf_free_content(rbuf);
     233          54 :                 if(asfd->read(asfd)) goto end;
     234             : 
     235          54 :                 if(rbuf->cmd!=CMD_GEN)
     236             :                 {
     237           1 :                         iobuf_log_unexpected(rbuf, __func__);
     238             :                         goto end;
     239             :                 }
     240             : 
     241          53 :                 if(!strcmp(rbuf->buf, "extra_comms_end"))
     242             :                 {
     243          24 :                         if(asfd->write_str(asfd, CMD_GEN, "extra_comms_end ok"))
     244             :                                 goto end;
     245             :                         break;
     246             :                 }
     247          29 :                 else if(!strncmp_w(rbuf->buf, "autoupgrade:"))
     248             :                 {
     249           2 :                         if(do_autoupgrade(asfd, vers, globalcs))
     250             :                                 goto end;
     251             :                 }
     252          27 :                 else if(!strcmp(rbuf->buf, "srestore ok"))
     253             :                 {
     254           4 :                         char *restore_path=get_string(cconfs[OPT_RESTORE_PATH]);
     255           4 :                         if(!restore_path)
     256             :                         {
     257           0 :                                 logp("got srestore ok without a restore_path");
     258             :                                 goto end;
     259             :                         }
     260             :                         
     261           4 :                         iobuf_free_content(rbuf);
     262             :                         // Client can accept the restore.
     263             :                         // Load the restore config, then send it.
     264           4 :                         *srestore=1;
     265             :                         // Need to wipe out OPT_INCEXDIR, as it is needed for
     266             :                         // srestore includes. If it is not wiped out, it can
     267             :                         // interfere if cconfs[OPT_RESTORE_PATH] contained no
     268             :                         // includes.
     269           4 :                         set_strlist(cconfs[OPT_INCEXCDIR], NULL);
     270           4 :                         if(conf_parse_incexcs_path(cconfs, restore_path)
     271           4 :                           || incexc_send_server_restore(asfd, cconfs))
     272             :                                 goto end;
     273             :                         // Do not unlink it here - wait until
     274             :                         // the client says that it wants to do the
     275             :                         // restore.
     276             :                         // Also need to leave it around if the
     277             :                         // restore is to an alternative client, so
     278             :                         // that the code below that reloads the config
     279             :                         // can read it again.
     280             :                         // NOTE: that appears to be in
     281             :                         // src/server/run_action.c::client_can_restore()
     282             :                         //unlink(get_string(cconfs[OPT_RESTORE_PATH]));
     283             :                 }
     284          23 :                 else if(!strcmp(rbuf->buf, "srestore not ok"))
     285             :                 {
     286           1 :                         const char *restore_path=get_string(
     287             :                                 cconfs[OPT_RESTORE_PATH]);
     288             :                         // Client will not accept the restore.
     289           1 :                         if (restore_path)
     290           1 :                                 unlink(restore_path);
     291           1 :                         if(set_string(cconfs[OPT_RESTORE_PATH], NULL))
     292             :                                 goto end;
     293           1 :                         logp("Client not accepting server initiated restore.\n");
     294             :                 }
     295          22 :                 else if(!strcmp(rbuf->buf, "sincexc ok"))
     296             :                 {
     297             :                         // Client can accept incexc conf from the
     298             :                         // server.
     299           1 :                         iobuf_free_content(rbuf);
     300           1 :                         if(incexc_send_server(asfd, cconfs))
     301             :                                 goto end;
     302             :                 }
     303          21 :                 else if(!strcmp(rbuf->buf, "incexc"))
     304             :                 {
     305             :                         // Client is telling server its incexc
     306             :                         // configuration so that it can better decide
     307             :                         // what to do on resume.
     308           1 :                         iobuf_free_content(rbuf);
     309           1 :                         if(incexc_recv_server(asfd, incexc, globalcs))
     310             :                                 goto end;
     311           1 :                         if(*incexc)
     312             :                         {
     313           1 :                                 char *tmp=NULL;
     314           1 :                                 char comp[32]="";
     315           1 :                                 snprintf(comp, sizeof(comp),
     316             :                                         "compression = %d\n",
     317             :                                         get_int(cconfs[OPT_COMPRESSION]));
     318           1 :                                 if(!(tmp=prepend(*incexc, comp)))
     319             :                                         goto end;
     320           1 :                                 free_w(incexc);
     321           1 :                                 *incexc=tmp;
     322             :                         }
     323             :                 }
     324          20 :                 else if(!strcmp(rbuf->buf, "counters_json ok"))
     325             :                 {
     326             :                         // Client can accept counters on
     327             :                         // resume/verify/restore.
     328           1 :                         logp("Client supports being sent json counters.\n");
     329           1 :                         set_int(cconfs[OPT_SEND_CLIENT_CNTR], 1);
     330             :                 }
     331          19 :                 else if(!strncmp_w(rbuf->buf, "uname=")
     332           2 :                   && strlen(rbuf->buf)>strlen("uname="))
     333             :                 {
     334           2 :                         char *uname=rbuf->buf+strlen("uname=");
     335           2 :                         if(!strncasecmp("Windows", uname, strlen("Windows")))
     336           1 :                                 set_int(cconfs[OPT_CLIENT_IS_WINDOWS], 1);
     337             :                 }
     338          17 :                 else if(!strncmp_w(rbuf->buf, "orig_client=")
     339           3 :                   && strlen(rbuf->buf)>strlen("orig_client="))
     340             :                 {
     341           3 :                         if(conf_switch_to_orig_client(globalcs, cconfs,
     342           3 :                                 rbuf->buf+strlen("orig_client=")))
     343             :                                         goto end;
     344             :                         // If this started out as a server-initiated
     345             :                         // restore, need to load the restore file
     346             :                         // again.
     347           2 :                         if(*srestore)
     348             :                         {
     349           1 :                                 if(conf_parse_incexcs_path(cconfs,
     350           1 :                                         get_string(cconfs[OPT_RESTORE_PATH])))
     351             :                                                 goto end;
     352             :                         }
     353           2 :                         if(asfd->write_str(asfd, CMD_GEN, "orig_client ok"))
     354             :                                 goto end;
     355             :                 }
     356          14 :                 else if(!strncmp_w(rbuf->buf, "restore_spool="))
     357             :                 {
     358             :                         // Removed.
     359             :                 }
     360          14 :                 else if(!strncmp_w(rbuf->buf, "protocol="))
     361             :                 {
     362          11 :                         char msg[128]="";
     363             :                         // Client wants to set protocol.
     364             :                         enum protocol protocol;
     365             :                         enum protocol cprotocol;
     366          11 :                         const char *cliproto=NULL;
     367          11 :                         protocol=get_protocol(cconfs);
     368          11 :                         cliproto=rbuf->buf+strlen("protocol=");
     369          11 :                         cprotocol=atoi(cliproto);
     370             : 
     371          11 :                         if(protocol!=PROTO_AUTO)
     372             :                         {
     373           6 :                                 if(protocol==cprotocol)
     374             :                                 {
     375           2 :                                         logp("Client is forcing protocol=%d\n", (int)protocol);
     376           2 :                                         continue;
     377             :                                 }
     378           4 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%d but server is set to protocol=%d\n", (int)cprotocol, (int)protocol);
     379           4 :                                 log_and_send(asfd, msg);
     380           5 :                                 goto end;
     381             :                         }
     382           5 :                         else if(cprotocol==PROTO_1)
     383             :                         {
     384           2 :                                 set_protocol(cconfs, cprotocol);
     385           2 :                                 set_protocol(globalcs, cprotocol);
     386             :                         }
     387           3 :                         else if(cprotocol==PROTO_2)
     388             :                         {
     389           2 :                                 set_protocol(cconfs, cprotocol);
     390           2 :                                 set_protocol(globalcs, cprotocol);
     391             :                         }
     392             :                         else
     393             :                         {
     394           1 :                                 snprintf(msg, sizeof(msg), "Client is trying to use protocol=%s, which is unknown\n", cliproto);
     395           1 :                                 log_and_send(asfd, msg);
     396             :                                 goto end;
     397             :                         }
     398           4 :                         logp("Client has set protocol=%d\n",
     399           4 :                                 (int)get_protocol(cconfs));
     400             :                 }
     401           3 :                 else if(!strncmp_w(rbuf->buf, "rshash=blake2"))
     402             :                 {
     403             : #ifdef HAVE_BLAKE2
     404             :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_BLAKE2);
     405             :                         set_e_rshash(globalcs[OPT_RSHASH], RSHASH_BLAKE2);
     406             : #else
     407           1 :                         logp("Client is trying to use librsync hash blake2, but server does not support it.\n");
     408             :                         goto end;
     409             : #endif
     410             :                 }
     411           2 :                 else if(!strncmp_w(rbuf->buf, "msg"))
     412             :                 {
     413           1 :                         set_int(cconfs[OPT_MESSAGE], 1);
     414           1 :                         set_int(globalcs[OPT_MESSAGE], 1);
     415             :                 }
     416           1 :                 else if(!strncmp_w(rbuf->buf, "backup_failovers_left="))
     417             :                 {
     418             :                         int l;
     419           0 :                         l=atoi(rbuf->buf+strlen("backup_failovers_left="));
     420           0 :                         set_int(cconfs[OPT_BACKUP_FAILOVERS_LEFT], l);
     421           0 :                         set_int(globalcs[OPT_BACKUP_FAILOVERS_LEFT], l);
     422             :                 }
     423             :                 else
     424             :                 {
     425           1 :                         iobuf_log_unexpected(rbuf, __func__);
     426             :                         goto end;
     427             :                 }
     428             :         }
     429             : 
     430          24 :         ret=0;
     431             : end:
     432          34 :         iobuf_free_content(rbuf);
     433          34 :         return ret;
     434             : }
     435             : 
     436          39 : static int vers_init(struct vers *vers, struct conf **cconfs)
     437             : {
     438          39 :         memset(vers, 0, sizeof(struct vers));
     439          39 :         return ((vers->min=version_to_long("1.2.7"))<0
     440          39 :           || (vers->cli=version_to_long(get_string(cconfs[OPT_PEER_VERSION])))<0
     441          39 :           || (vers->ser=version_to_long(PACKAGE_VERSION))<0
     442          39 :           || (vers->feat_list=version_to_long("1.3.0"))<0
     443          39 :           || (vers->directory_tree=version_to_long("1.3.6"))<0
     444          39 :           || (vers->burp2=version_to_long("2.0.0"))<0
     445          78 :           || (vers->counters_json=version_to_long("2.0.46"))<0);
     446             : }
     447             : 
     448          39 : int extra_comms(struct async *as,
     449             :         char **incexc, int *srestore, struct conf **confs, struct conf **cconfs)
     450             : {
     451             :         struct vers vers;
     452             :         struct asfd *asfd;
     453          39 :         asfd=as->asfd;
     454             :         //char *restorepath=NULL;
     455          39 :         const char *peer_version=NULL;
     456             : 
     457          39 :         if(vers_init(&vers, cconfs))
     458             :                 goto error;
     459             : 
     460          39 :         if(vers.cli<vers.directory_tree)
     461             :         {
     462           3 :                 set_int(confs[OPT_DIRECTORY_TREE], 0);
     463           3 :                 set_int(cconfs[OPT_DIRECTORY_TREE], 0);
     464             :         }
     465             : 
     466             :         // Clients before 1.2.7 did not know how to do extra comms, so skip
     467             :         // this section for them.
     468          39 :         if(vers.cli<vers.min)
     469             :                 return 0;
     470             : 
     471          37 :         if(asfd_read_expect(asfd, CMD_GEN, "extra_comms_begin"))
     472             :         {
     473           1 :                 logp("problem reading in extra_comms\n");
     474           1 :                 goto error;
     475             :         }
     476             :         // Want to tell the clients the extra comms features that are
     477             :         // supported, so that new clients are more likely to work with old
     478             :         // servers.
     479          36 :         if(vers.cli==vers.feat_list)
     480             :         {
     481             :                 // 1.3.0 did not support the feature list.
     482           1 :                 if(asfd->write_str(asfd, CMD_GEN, "extra_comms_begin ok"))
     483             :                 {
     484           1 :                         logp("problem writing in extra_comms\n");
     485           1 :                         goto error;
     486             :                 }
     487             :         }
     488             :         else
     489             :         {
     490          35 :                 if(send_features(asfd, cconfs, &vers))
     491             :                         goto error;
     492             :         }
     493             : 
     494          34 :         if(extra_comms_read(as, &vers, srestore, incexc, confs, cconfs))
     495             :                 goto error;
     496             : 
     497          24 :         peer_version=get_string(cconfs[OPT_PEER_VERSION]);
     498             : 
     499             :         // This needs to come after extra_comms_read, as the client might
     500             :         // have set PROTO_1 or PROTO_2.
     501          24 :         switch(get_protocol(cconfs))
     502             :         {
     503             :                 case PROTO_AUTO:
     504             :                         // The protocol has not been specified. Make a choice.
     505          14 :                         if(vers.cli<vers.burp2)
     506             :                         {
     507             :                                 // Client is burp-1.x.x, use protocol1.
     508           1 :                                 set_protocol(confs, PROTO_1);
     509           1 :                                 set_protocol(cconfs, PROTO_1);
     510           1 :                                 logp("Client is %s-%s - using protocol=%d\n",
     511             :                                         PACKAGE_TARNAME,
     512             :                                         peer_version, PROTO_1);
     513             :                         }
     514             :                         else
     515             :                         {
     516             :                                 // Client is burp-2.x.x, use protocol2.
     517             :                                 // This will probably never be reached because
     518             :                                 // the negotiation will take care of it.
     519             :                                 /*
     520             :                                 set_protocol(confs, PROTO_2);
     521             :                                 set_protocol(cconfs, PROTO_2);
     522             :                                 logp("Client is %s-%s - using protocol=%d\n",
     523             :                                         PACKAGE_TARNAME,
     524             :                                         peer_version, PROTO_2);
     525             :                                 */
     526             :                                 // PROTO_1 is safer for now.
     527          13 :                                 set_protocol(confs, PROTO_1);
     528          13 :                                 set_protocol(cconfs, PROTO_1);
     529          13 :                                 logp("Client is %s-%s - using protocol=%d\n",
     530             :                                         PACKAGE_TARNAME,
     531             :                                         peer_version, PROTO_1);
     532             :                         }
     533             :                         break;
     534             :                 case PROTO_1:
     535             :                         // It is OK for the client to be burp1 and for the
     536             :                         // server to be forced to protocol1.
     537             :                         break;
     538             :                 case PROTO_2:
     539           5 :                         if(vers.cli>=vers.burp2)
     540             :                                 break;
     541           2 :                         logp("protocol=%d is set server side, "
     542             :                           "but client is %s version %s\n",
     543             :                           PROTO_2, PACKAGE_TARNAME, peer_version);
     544           2 :                         goto error;
     545             :         }
     546             : 
     547          22 :         if(get_protocol(cconfs)==PROTO_1)
     548             :         {
     549          19 :                 if(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_UNSET)
     550             :                 {
     551          19 :                         set_e_rshash(confs[OPT_RSHASH], RSHASH_MD4);
     552          19 :                         set_e_rshash(cconfs[OPT_RSHASH], RSHASH_MD4);
     553             :                 }
     554             :         }
     555             : 
     556             :         return 0;
     557             : error:
     558             :         return -1;
     559             : }

Generated by: LCOV version 1.13