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