1 #include "../test.h"
2 #include "../../src/alloc.h"
3 #include "../../src/asfd.h"
4 #include "../../src/async.h"
5 #include "../../src/conf.h"
6 #include "../../src/fsops.h"
7 #include "../../src/iobuf.h"
8 #include "../../src/sbuf.h"
9 #include "../../src/server/extra_comms.h"
10 #include "../../src/strlist.h"
11 #include "../builders/build.h"
12 #include "../builders/build_file.h"
13 #include "../builders/build_asfd_mock.h"
14 
15 #define BASE			"utest_server_extra_comms"
16 #define TESTCLIENT		"testclient"
17 #define SPOOL			BASE "/spool"
18 #define SRESTORE_FILE		SPOOL "/testclient/restore"
19 #define SRESTORE_FILE_CLI2	SPOOL "/cli2/restore"
20 
21 static struct ioevent_list reads;
22 static struct ioevent_list writes;
23 
setup_conf(void)24 static struct conf **setup_conf(void)
25 {
26 	struct conf **confs=NULL;
27 	fail_unless((confs=confs_alloc())!=NULL);
28 	fail_unless(!confs_init(confs));
29 	return confs;
30 }
31 
setup_async(void)32 static struct async *setup_async(void)
33 {
34 	struct async *as;
35 	fail_unless((as=async_alloc())!=NULL);
36 	as->init(as, 0 /* estimate */);
37 	return as;
38 }
39 
clean(void)40 static void clean(void)
41 {
42 	fail_unless(!recursive_delete(BASE));
43 	fail_unless(!recursive_delete(CLIENTCONFDIR));
44 }
45 
setup(struct async ** as,struct conf *** confs,struct conf *** cconfs)46 static void setup(struct async **as,
47 	struct conf ***confs, struct conf ***cconfs)
48 {
49 	clean();
50 	if(as) *as=setup_async();
51 	if(confs) *confs=setup_conf();
52 	if(cconfs) *cconfs=setup_conf();
53 }
54 
tear_down(struct async ** as,struct asfd ** asfd,struct conf *** confs,struct conf *** cconfs)55 static void tear_down(struct async **as, struct asfd **asfd,
56 	struct conf ***confs, struct conf ***cconfs)
57 {
58 	async_free(as);
59 	asfd_free(asfd);
60 	asfd_mock_teardown(&reads, &writes);
61 	confs_free(confs);
62 	confs_free(cconfs);
63 	clean();
64 	alloc_check();
65 }
66 
async_rw_simple(struct async * as)67 static int async_rw_simple(struct async *as)
68 {
69 	return as->asfd->read(as->asfd);
70 }
71 
run_test(int expected_ret,void setup_callback (struct asfd * asfd,struct conf ** confs,struct conf ** cconfs),void checks_callback (struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore))72 static void run_test(int expected_ret,
73 	void setup_callback(struct asfd *asfd,
74 		struct conf **confs, struct conf **cconfs),
75 	void checks_callback(struct conf **confs, struct conf **cconfs,
76 		const char *incexc, int srestore))
77 {
78         struct async *as;
79         struct asfd *asfd;
80         struct conf **confs;
81         struct conf **cconfs;
82 	char *incexc=NULL;
83 	int srestore=0;
84 
85         setup(&as, &confs, &cconfs);
86         asfd=asfd_mock_setup(&reads, &writes);
87 	as->asfd_add(as, asfd);
88 	as->read_write=async_rw_simple;
89 	asfd->as=as;
90 
91 	setup_callback(asfd, confs, cconfs);
92 
93 	fail_unless(extra_comms(
94 		as,
95 		&incexc,
96 		&srestore,
97 		confs,
98 		cconfs
99 	)==expected_ret);
100 
101 	if(checks_callback)
102 		checks_callback(confs, cconfs, incexc, srestore);
103 
104 	free_w(&incexc);
105 	tear_down(&as, &asfd, &confs, &cconfs);
106 }
107 
setup_no_version(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)108 static void setup_no_version(struct asfd *asfd,
109 	struct conf **confs, struct conf **cconfs)
110 {
111 }
112 
setup_old_version(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)113 static void setup_old_version(struct asfd *asfd,
114 	struct conf **confs, struct conf **cconfs)
115 {
116 	set_string(cconfs[OPT_PEER_VERSION], "1.2.0");
117 }
118 
setup_unexpected_first_string(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)119 static void setup_unexpected_first_string(struct asfd *asfd,
120 	struct conf **confs, struct conf **cconfs)
121 {
122 	int r=0;
123 	set_string(cconfs[OPT_PEER_VERSION], "1.4.40");
124 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "blah");
125 }
126 
setup_1_3_0_write_problem(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)127 static void setup_1_3_0_write_problem(struct asfd *asfd,
128 	struct conf **confs, struct conf **cconfs)
129 {
130 	int r=0; int w=0;
131 	set_string(cconfs[OPT_PEER_VERSION], "1.3.0");
132 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "extra_comms_begin");
133 	asfd_assert_write(asfd, &w, -1, CMD_GEN, "extra_comms_begin ok");
134 }
135 
common_confs(struct conf ** cconfs,const char * version,enum protocol protocol)136 static void common_confs(struct conf **cconfs, const char *version,
137 	enum protocol protocol)
138 {
139 	set_string(cconfs[OPT_PEER_VERSION], version);
140 	set_string(cconfs[OPT_DIRECTORY], BASE "/spool");
141 	set_string(cconfs[OPT_CNAME], TESTCLIENT);
142 	set_string(cconfs[OPT_DEDUP_GROUP], "global");
143 	set_protocol(cconfs, protocol);
144 }
145 
get_features(enum protocol protocol,int srestore,const char * version)146 static const char *get_features(enum protocol protocol, int srestore,
147 	const char *version)
148 {
149 	char proto[32]="";
150 	char rshash[32]="";
151 	int old_version=0;
152 	static char features[256]="";
153 
154 #ifdef HAVE_BLAKE2
155 	snprintf(rshash, sizeof(rshash), "rshash=blake2:");
156 #endif
157 	if(protocol==PROTO_AUTO)
158 		snprintf(proto, sizeof(proto), "csetproto:");
159 	else
160 		snprintf(proto, sizeof(proto), "forceproto=%d:",
161 			(int)protocol);
162 
163 	if(version && !strcmp(version, "1.4.40"))
164 		old_version=1;
165 
166 	snprintf(features, sizeof(features), "extra_comms_begin ok:autoupgrade:incexc:orig_client:uname:failover:vss_restore:regex_icase:%s%smsg:%s%sseed:", srestore?"srestore:":"", old_version?"":"counters_json:", proto, rshash);
167 	return features;
168 }
169 
setup_feature_write_problem(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)170 static void setup_feature_write_problem(struct asfd *asfd,
171 	struct conf **confs, struct conf **cconfs)
172 {
173 	int r=0; int w=0;
174 	const char *features;
175 	enum protocol protocol=PROTO_AUTO;
176 	common_confs(cconfs, PACKAGE_VERSION, protocol);
177 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "extra_comms_begin");
178 	features=get_features(protocol, /*srestore*/0, NULL/*version*/);
179 	asfd_assert_write(asfd, &w, -1, CMD_GEN, features);
180 }
181 
setup_send_features_proto_begin(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,enum protocol protocol,int * r,int * w,const char * version,int srestore)182 static void setup_send_features_proto_begin(struct asfd *asfd,
183 	struct conf **confs, struct conf **cconfs, enum protocol protocol,
184 	int *r, int *w, const char *version, int srestore)
185 {
186 	const char *features=NULL;
187 	common_confs(cconfs, version, protocol);
188 	asfd_mock_read(asfd, r, 0, CMD_GEN, "extra_comms_begin");
189 	features=get_features(protocol, srestore, version);
190 	asfd_assert_write(asfd, w, 0, CMD_GEN, features);
191 }
192 
setup_send_features_proto_end(struct asfd * asfd,int * r,int * w)193 static void setup_send_features_proto_end(struct asfd *asfd, int *r, int *w)
194 {
195 	asfd_mock_read(asfd, r, 0, CMD_GEN, "extra_comms_end");
196 	asfd_assert_write(asfd, w, 0, CMD_GEN, "extra_comms_end ok");
197 }
198 
setup_send_features_proto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,enum protocol protocol,const char * version)199 static void setup_send_features_proto(struct asfd *asfd,
200 	struct conf **confs, struct conf **cconfs, enum protocol protocol,
201 	const char *version)
202 {
203 	int r=0; int w=0;
204 	setup_send_features_proto_begin(asfd, confs, cconfs, protocol, &r, &w,
205 		version, /*srestore*/0);
206 	setup_send_features_proto_end(asfd, &r, &w);
207 }
208 
setup_send_features_proto_auto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)209 static void setup_send_features_proto_auto(struct asfd *asfd,
210 	struct conf **confs, struct conf **cconfs)
211 {
212 	setup_send_features_proto(asfd, confs, cconfs, PROTO_AUTO, PACKAGE_VERSION);
213 }
214 
setup_send_features_proto_auto_old_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)215 static void setup_send_features_proto_auto_old_client(struct asfd *asfd,
216 	struct conf **confs, struct conf **cconfs)
217 {
218 	setup_send_features_proto(asfd, confs, cconfs, PROTO_AUTO, "1.4.40");
219 }
220 
setup_send_features_proto1(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)221 static void setup_send_features_proto1(struct asfd *asfd,
222 	struct conf **confs, struct conf **cconfs)
223 {
224 	setup_send_features_proto(asfd, confs, cconfs, PROTO_1, PACKAGE_VERSION);
225 }
226 
setup_send_features_proto1_old_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)227 static void setup_send_features_proto1_old_client(struct asfd *asfd,
228 	struct conf **confs, struct conf **cconfs)
229 {
230 	setup_send_features_proto(asfd, confs, cconfs, PROTO_1, "1.4.40");
231 }
232 
setup_send_features_proto2(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)233 static void setup_send_features_proto2(struct asfd *asfd,
234 	struct conf **confs, struct conf **cconfs)
235 {
236 	setup_send_features_proto(asfd, confs, cconfs, PROTO_2, PACKAGE_VERSION);
237 }
238 
setup_send_features_proto2_old_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)239 static void setup_send_features_proto2_old_client(struct asfd *asfd,
240 	struct conf **confs, struct conf **cconfs)
241 {
242 	setup_send_features_proto(asfd, confs, cconfs, PROTO_2, "1.4.40");
243 }
244 
setup_send_features_proto_auto_auto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)245 static void setup_send_features_proto_auto_auto(struct asfd *asfd,
246 	struct conf **confs, struct conf **cconfs)
247 {
248 	int r=0; int w=0;
249 	setup_send_features_proto_begin(asfd, confs, cconfs,
250 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
251 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "protocol=0");
252 	asfd_assert_write(asfd, &w, 0, CMD_ERROR,
253 		"Client is trying to use protocol=0, which is unknown\n");
254 }
255 
setup_send_features_proto_proto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,const char * version,enum protocol protocol_server,enum protocol protocol_client)256 static void setup_send_features_proto_proto(struct asfd *asfd,
257 	struct conf **confs, struct conf **cconfs, const char *version,
258 	enum protocol protocol_server, enum protocol protocol_client)
259 {
260 	int r=0; int w=0;
261 	char cprotocol[16]="";
262 	snprintf(cprotocol, sizeof(cprotocol),
263 		"protocol=%d", (int)protocol_client);
264 	setup_send_features_proto_begin(asfd, confs, cconfs,
265 		protocol_server, &r, &w, version, /*srestore*/0);
266 	asfd_mock_read(asfd, &r, 0, CMD_GEN, cprotocol);
267 	setup_send_features_proto_end(asfd, &r, &w);
268 }
269 
setup_send_features_proto_auto_1(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)270 static void setup_send_features_proto_auto_1(struct asfd *asfd,
271 	struct conf **confs, struct conf **cconfs)
272 {
273 	setup_send_features_proto_proto(asfd, confs, cconfs, PACKAGE_VERSION,
274 		PROTO_AUTO, PROTO_1);
275 }
276 
setup_send_features_proto_auto_1_old_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)277 static void setup_send_features_proto_auto_1_old_client(struct asfd *asfd,
278 	struct conf **confs, struct conf **cconfs)
279 {
280 	setup_send_features_proto_proto(asfd, confs, cconfs, "1.4.40",
281 		PROTO_AUTO, PROTO_1);
282 }
283 
setup_send_features_proto_auto_2(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)284 static void setup_send_features_proto_auto_2(struct asfd *asfd,
285 	struct conf **confs, struct conf **cconfs)
286 {
287 	setup_send_features_proto_proto(asfd, confs, cconfs, PACKAGE_VERSION,
288 		PROTO_AUTO, PROTO_2);
289 }
290 
setup_send_features_proto_auto_2_old_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)291 static void setup_send_features_proto_auto_2_old_client(struct asfd *asfd,
292 	struct conf **confs, struct conf **cconfs)
293 {
294 	setup_send_features_proto_proto(asfd, confs, cconfs, "1.4.40",
295 		PROTO_AUTO, PROTO_2);
296 }
297 
setup_send_features_proto_x_y(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,enum protocol s_protocol,enum protocol c_protocol)298 static void setup_send_features_proto_x_y(struct asfd *asfd,
299 	struct conf **confs, struct conf **cconfs,
300 	enum protocol s_protocol, enum protocol c_protocol)
301 {
302 	int r=0; int w=0;
303 	char msg[256]="";
304 	char cliproto[16]="";
305 	snprintf(cliproto, sizeof(cliproto), "protocol=%d", (int)c_protocol);
306 	setup_send_features_proto_begin(asfd, confs, cconfs,
307 		s_protocol, &r, &w, PACKAGE_VERSION, /*srestore*/0);
308 	asfd_mock_read(asfd, &r, 0, CMD_GEN, cliproto);
309 	snprintf(msg, sizeof(msg), "Client is trying to use protocol=%d but server is set to protocol=%d\n", (int)c_protocol, (int)s_protocol);
310 	asfd_assert_write(asfd, &w, 0, CMD_ERROR, msg);
311 }
312 
setup_send_features_proto_1_auto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)313 static void setup_send_features_proto_1_auto(struct asfd *asfd,
314 	struct conf **confs, struct conf **cconfs)
315 {
316 	setup_send_features_proto_x_y(asfd, confs, cconfs,
317 		PROTO_1, PROTO_AUTO);
318 }
319 
setup_send_features_proto_2_auto(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)320 static void setup_send_features_proto_2_auto(struct asfd *asfd,
321 	struct conf **confs, struct conf **cconfs)
322 {
323 	setup_send_features_proto_x_y(asfd, confs, cconfs,
324 		PROTO_2, PROTO_AUTO);
325 }
326 
setup_send_features_proto_1_2(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)327 static void setup_send_features_proto_1_2(struct asfd *asfd,
328 	struct conf **confs, struct conf **cconfs)
329 {
330 	setup_send_features_proto_x_y(asfd, confs, cconfs,
331 		PROTO_1, PROTO_2);
332 }
333 
setup_send_features_proto_2_1(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)334 static void setup_send_features_proto_2_1(struct asfd *asfd,
335 	struct conf **confs, struct conf **cconfs)
336 {
337 	setup_send_features_proto_x_y(asfd, confs, cconfs,
338 		PROTO_2, PROTO_1);
339 }
340 
setup_send_features_proto_1_1(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)341 static void setup_send_features_proto_1_1(struct asfd *asfd,
342 	struct conf **confs, struct conf **cconfs)
343 {
344 	setup_send_features_proto_proto(asfd, confs, cconfs, PACKAGE_VERSION,
345 		PROTO_1, PROTO_1);
346 }
347 
setup_send_features_proto_2_2(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)348 static void setup_send_features_proto_2_2(struct asfd *asfd,
349 	struct conf **confs, struct conf **cconfs)
350 {
351 	setup_send_features_proto_proto(asfd, confs, cconfs, PACKAGE_VERSION,
352 		PROTO_2, PROTO_2);
353 }
354 
checks_proto_auto_no_features_from_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)355 static void checks_proto_auto_no_features_from_client(
356 	struct conf **confs, struct conf **cconfs, const char *incexc,
357 	int srestore)
358 {
359 	// Server is PROTO_AUTO, client said nothing.
360 	fail_unless(get_protocol(confs)==PROTO_1);
361 }
362 
checks_proto_auto_no_features_from_client_old_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)363 static void checks_proto_auto_no_features_from_client_old_client(
364 	struct conf **confs, struct conf **cconfs, const char *incexc,
365 	int srestore)
366 {
367 	// Server is PROTO_AUTO, client said nothing. Client is old version,
368 	// so should be forced to PROTO_1.
369 	fail_unless(get_protocol(cconfs)==PROTO_1);
370 	fail_unless(get_protocol(confs)==PROTO_1);
371 }
372 
checks_proto1_no_features_from_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)373 static void checks_proto1_no_features_from_client(
374 	struct conf **confs, struct conf **cconfs, const char *incexc,
375 	int srestore)
376 {
377 	// Server is PROTO_1, client said nothing.
378 	fail_unless(get_protocol(confs)==PROTO_AUTO);
379 }
380 
checks_proto1_no_features_from_client_old_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)381 static void checks_proto1_no_features_from_client_old_client(
382 	struct conf **confs, struct conf **cconfs, const char *incexc,
383 	int srestore)
384 {
385 	// Server is PROTO_1, client said nothing. Client is old version.
386 	fail_unless(get_protocol(confs)==PROTO_AUTO);
387 }
388 
checks_proto2_no_features_from_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)389 static void checks_proto2_no_features_from_client(
390 	struct conf **confs, struct conf **cconfs, const char *incexc,
391 	int srestore)
392 {
393 	// Server is PROTO_2, client said nothing.
394 	fail_unless(get_protocol(confs)==PROTO_AUTO);
395 }
396 
checks_proto_auto_1(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)397 static void checks_proto_auto_1(
398 	struct conf **confs, struct conf **cconfs, const char *incexc,
399 	int srestore)
400 {
401 	// Server is PROTO_AUTO, client said PROTO_1
402 	fail_unless(get_protocol(confs)==PROTO_1);
403 	// We did not set OPT_RSHASH. It should be set to RSHASH_MD4 for us.
404 	fail_unless(get_e_rshash(confs[OPT_RSHASH])==RSHASH_MD4);
405 	fail_unless(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_MD4);
406 }
407 
checks_proto_auto_2(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)408 static void checks_proto_auto_2(
409 	struct conf **confs, struct conf **cconfs, const char *incexc,
410 	int srestore)
411 {
412 	// Server is PROTO_AUTO, client said PROTO_2
413 	fail_unless(get_protocol(confs)==PROTO_2);
414 }
415 
setup_unexpected_cmd_feature(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)416 static void setup_unexpected_cmd_feature(struct asfd *asfd,
417 	struct conf **confs, struct conf **cconfs)
418 {
419 	int r=0; int w=0;
420 	setup_send_features_proto_begin(asfd, confs, cconfs,
421 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
422 	asfd_mock_read(asfd, &r, 0, CMD_FILE, "blah");
423 }
424 
setup_simple(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,const char * feature,int srestore)425 static void setup_simple(struct asfd *asfd,
426 	struct conf **confs, struct conf **cconfs, const char *feature,
427 	int srestore)
428 {
429 	int r=0; int w=0;
430 	setup_send_features_proto_begin(asfd, confs, cconfs,
431 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, srestore);
432 	asfd_mock_read(asfd, &r, 0, CMD_GEN, feature);
433 	setup_send_features_proto_end(asfd, &r, &w);
434 }
435 
setup_autoupgrade_no_os(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)436 static void setup_autoupgrade_no_os(struct asfd *asfd,
437 	struct conf **confs, struct conf **cconfs)
438 {
439 	setup_simple(asfd, confs, cconfs, "autoupgrade:", /*srestore*/0);
440 }
441 
setup_autoupgrade(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)442 static void setup_autoupgrade(struct asfd *asfd,
443 	struct conf **confs, struct conf **cconfs)
444 {
445 	int r=0; int w=0;
446 	setup_send_features_proto_begin(asfd, confs, cconfs,
447 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
448 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "autoupgrade:some_os");
449 	// Server does not have an autoupgrade_dir set.
450 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "do not autoupgrade");
451 	setup_send_features_proto_end(asfd, &r, &w);
452 }
453 
setup_rshash_blake2(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)454 static void setup_rshash_blake2(struct asfd *asfd,
455 	struct conf **confs, struct conf **cconfs)
456 {
457 #ifdef HAVE_BLAKE2
458 	setup_simple(asfd, confs, cconfs, "rshash=blake2", /*srestore*/0);
459 #else
460 	int r=0; int w=0;
461 	setup_send_features_proto_begin(asfd, confs, cconfs,
462 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
463 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "rshash=blake2");
464 #endif
465 }
466 
checks_rshash_blake2(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)467 static void checks_rshash_blake2(struct conf **confs, struct conf **cconfs,
468 	const char *incexc, int srestore)
469 {
470 #ifdef HAVE_BLAKE2
471 	fail_unless(get_e_rshash(confs[OPT_RSHASH])==RSHASH_BLAKE2);
472 	fail_unless(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_BLAKE2);
473 #else
474 	fail_unless(get_e_rshash(confs[OPT_RSHASH])==RSHASH_UNSET);
475 	fail_unless(get_e_rshash(cconfs[OPT_RSHASH])==RSHASH_UNSET);
476 #endif
477 }
478 
setup_msg(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)479 static void setup_msg(struct asfd *asfd,
480 	struct conf **confs, struct conf **cconfs)
481 {
482 	setup_simple(asfd, confs, cconfs, "msg", /*srestore*/0);
483 }
484 
checks_msg(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)485 static void checks_msg(struct conf **confs, struct conf **cconfs,
486 	const char *incexc, int srestore)
487 {
488 	fail_unless(get_int(confs[OPT_MESSAGE])==1);
489 	fail_unless(get_int(cconfs[OPT_MESSAGE])==1);
490 }
491 
setup_counters_ok(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)492 static void setup_counters_ok(struct asfd *asfd,
493 	struct conf **confs, struct conf **cconfs)
494 {
495 	setup_simple(asfd, confs, cconfs, "counters_json ok", /*srestore*/0);
496 }
497 
checks_counters_ok(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)498 static void checks_counters_ok(struct conf **confs, struct conf **cconfs,
499 	const char *incexc, int srestore)
500 {
501 	fail_unless(get_int(cconfs[OPT_SEND_CLIENT_CNTR])==1);
502 }
503 
setup_uname(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)504 static void setup_uname(struct asfd *asfd,
505 	struct conf **confs, struct conf **cconfs)
506 {
507 	setup_simple(asfd, confs, cconfs, "uname=some_os", /*srestore*/0);
508 }
509 
checks_uname(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)510 static void checks_uname(struct conf **confs, struct conf **cconfs,
511 	const char *incexc, int srestore)
512 {
513 	fail_unless(get_int(cconfs[OPT_CLIENT_IS_WINDOWS])==0);
514 }
515 
setup_uname_is_windows(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)516 static void setup_uname_is_windows(struct asfd *asfd,
517 	struct conf **confs, struct conf **cconfs)
518 {
519 	setup_simple(asfd, confs, cconfs, "uname=Windows", /*srestore*/0);
520 }
521 
checks_uname_is_windows(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)522 static void checks_uname_is_windows(struct conf **confs, struct conf **cconfs,
523 	const char *incexc, int srestore)
524 {
525 	fail_unless(get_int(cconfs[OPT_CLIENT_IS_WINDOWS])==1);
526 }
527 
setup_unexpected_feature(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)528 static void setup_unexpected_feature(struct asfd *asfd,
529 	struct conf **confs, struct conf **cconfs)
530 {
531 	int r=0; int w=0;
532 	setup_send_features_proto_begin(asfd, confs, cconfs,
533 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
534 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "somenonsense");
535 }
536 
setup_srestore_not_ok(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)537 static void setup_srestore_not_ok(struct asfd *asfd,
538 	struct conf **confs, struct conf **cconfs)
539 {
540 	build_file(SRESTORE_FILE, "");
541 	setup_simple(asfd, confs, cconfs, "srestore not ok", /*srestore*/1);
542 }
543 
checks_srestore_not_ok(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)544 static void checks_srestore_not_ok(struct conf **confs, struct conf **cconfs,
545 	const char *incexc, int srestore)
546 {
547 	struct stat statp;
548 	// Should have deleted the restore file.
549 	fail_unless(lstat(SRESTORE_FILE, &statp));
550 	fail_unless(get_string(cconfs[OPT_RESTORE_PATH])==NULL);
551 }
552 
setup_srestore(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs,int * r,int * w)553 static void setup_srestore(struct asfd *asfd,
554 	struct conf **confs, struct conf **cconfs, int *r, int *w)
555 {
556 	struct strlist *strlist=NULL;
557 	build_file(SRESTORE_FILE, "");
558 	setup_send_features_proto_begin(asfd, confs, cconfs, PROTO_AUTO,
559 		r, w, PACKAGE_VERSION, /*srestore*/1);
560 
561 	strlist_add(&strlist, "/some/path", 1);
562 	// This needs to get unset.
563 	set_strlist(cconfs[OPT_INCEXCDIR], strlist);
564 
565 	asfd_mock_read(asfd, r, 0, CMD_GEN, "srestore ok");
566 	asfd_assert_write(asfd, w, 0, CMD_GEN, "overwrite = 0");
567 	asfd_assert_write(asfd, w, 0, CMD_GEN, "strip = 0");
568 	asfd_assert_write(asfd, w, 0, CMD_GEN, "regex_case_insensitive = 0");
569 	asfd_assert_write(asfd, w, 0, CMD_GEN, "srestore end");
570 }
571 
setup_srestore_ok(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)572 static void setup_srestore_ok(struct asfd *asfd,
573 	struct conf **confs, struct conf **cconfs)
574 {
575 	int r=0; int w=0;
576 	setup_srestore(asfd, confs, cconfs, &r, &w);
577 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "srestore end ok");
578 	setup_send_features_proto_end(asfd, &r, &w);
579 }
580 
checks_srestore_ok(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)581 static void checks_srestore_ok(struct conf **confs, struct conf **cconfs,
582 	const char *incexc, int srestore)
583 {
584 	struct stat statp;
585 	// Should not have deleted the restore file.
586 	fail_unless(!lstat(SRESTORE_FILE, &statp));
587 	fail_unless(!strcmp(get_string(cconfs[OPT_RESTORE_PATH]),
588 		SRESTORE_FILE));
589 	fail_unless(srestore==1);
590 	fail_unless(get_strlist(cconfs[OPT_INCEXCDIR])==NULL);
591 }
592 
setup_srestore_ok_error(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)593 static void setup_srestore_ok_error(struct asfd *asfd,
594 	struct conf **confs, struct conf **cconfs)
595 {
596 	int r=0; int w=0;
597 	setup_srestore(asfd, confs, cconfs, &r, &w);
598 	asfd_mock_read(asfd, &r, -1, CMD_GEN, "srestore end ok");
599 }
600 
setup_sincexc_ok(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)601 static void setup_sincexc_ok(struct asfd *asfd,
602 	struct conf **confs, struct conf **cconfs)
603 {
604 	int r=0; int w=0;
605 	setup_send_features_proto_begin(asfd, confs, cconfs, PROTO_AUTO,
606 		&r, &w, PACKAGE_VERSION, /*srestore*/0);
607 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "sincexc ok");
608 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "cross_all_filesystems = 0");
609 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "read_all_fifos = 0");
610 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "read_all_blockdevs = 0");
611 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "min_file_size = 0");
612 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "max_file_size = 0");
613 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "split_vss = 0");
614 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "strip_vss = 0");
615 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "acl = 1");
616 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "xattr = 1");
617 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "atime = 0");
618 	asfd_assert_write(asfd, &w, 0,
619 		CMD_GEN, "scan_problem_raises_error = 0");
620 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "overwrite = 0");
621 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "strip = 0");
622 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "regex_case_insensitive = 0");
623 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "sincexc end");
624 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "sincexc end ok");
625 	setup_send_features_proto_end(asfd, &r, &w);
626 }
627 
setup_incexc(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)628 static void setup_incexc(struct asfd *asfd,
629 	struct conf **confs, struct conf **cconfs)
630 {
631 	int r=0; int w=0;
632 	setup_send_features_proto_begin(asfd, confs, cconfs, PROTO_AUTO,
633 		&r, &w, PACKAGE_VERSION, /*srestore*/0);
634 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "incexc");
635 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "incexc ok");
636 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "include = /some/path");
637 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "incexc end");
638 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "incexc end ok");
639 	setup_send_features_proto_end(asfd, &r, &w);
640 }
641 
checks_incexc(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)642 static void checks_incexc(struct conf **confs, struct conf **cconfs,
643 	const char *incexc, int srestore)
644 {
645 	fail_unless(!strcmp(incexc,
646 		"include = /some/path\n\ncompression = 9\n"));
647 }
648 
setup_orig_client_not_existing(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)649 static void setup_orig_client_not_existing(struct asfd *asfd,
650 	struct conf **confs, struct conf **cconfs)
651 {
652 	int r=0; int w=0;
653 
654 	setup_send_features_proto_begin(asfd, confs, cconfs,
655 		PROTO_AUTO, &r, &w, PACKAGE_VERSION, /*srestore*/0);
656 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "orig_client=cli2");
657 }
658 
setup_orig_client(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)659 static void setup_orig_client(struct asfd *asfd,
660 	struct conf **confs, struct conf **cconfs)
661 {
662 	int r=0; int w=0;
663 	enum protocol protocol=PROTO_AUTO;
664 
665 	common_confs(cconfs, PACKAGE_VERSION, protocol);
666 	set_string(confs[OPT_CLIENTCONFDIR], CLIENTCONFDIR);
667 	build_file(CLIENTCONFDIR "/cli2", "restore_client=" TESTCLIENT);
668 	setup_send_features_proto_begin(asfd, confs, cconfs,
669 		protocol, &r, &w, PACKAGE_VERSION, /*srestore*/0);
670 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "orig_client=cli2");
671 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "orig_client ok");
672 	setup_send_features_proto_end(asfd, &r, &w);
673 }
674 
checks_orig_client(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)675 static void checks_orig_client(struct conf **confs, struct conf **cconfs,
676 	const char *incexc, int srestore)
677 {
678 	const char *orig_client;
679 	const char *restore_client;
680 	fail_unless(!strcmp(get_string(cconfs[OPT_CNAME]), "cli2"));
681 	restore_client=get_string(cconfs[OPT_SUPER_CLIENT]);
682 	orig_client=get_string(cconfs[OPT_ORIG_CLIENT]);
683 	fail_unless(!strcmp(orig_client, restore_client));
684 }
685 
setup_orig_client_srestore(struct asfd * asfd,struct conf ** confs,struct conf ** cconfs)686 static void setup_orig_client_srestore(struct asfd *asfd,
687 	struct conf **confs, struct conf **cconfs)
688 {
689 	int r=0; int w=0;
690 	enum protocol protocol=PROTO_AUTO;
691 	build_file(SRESTORE_FILE, "overwrite=1");
692 	build_file(SRESTORE_FILE_CLI2, "strip=1");
693 
694 	common_confs(cconfs, PACKAGE_VERSION, protocol);
695 	set_string(confs[OPT_CLIENTCONFDIR], CLIENTCONFDIR);
696 	build_file(CLIENTCONFDIR "/cli2", "restore_client=" TESTCLIENT);
697 	setup_send_features_proto_begin(asfd, confs, cconfs,
698 		protocol, &r, &w, PACKAGE_VERSION, /*srestore*/1);
699 
700 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "srestore ok");
701 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "overwrite = 1");
702 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "strip = 0");
703 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "regex_case_insensitive = 0");
704 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "srestore end");
705 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "srestore end ok");
706 
707 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "orig_client=cli2");
708 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "orig_client ok");
709 
710 	// Should get the same as before, with orig_client added.
711 	// That is, it should not read from cli2's restore file.
712 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "srestore ok");
713 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "overwrite = 1");
714 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "strip = 0");
715 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "regex_case_insensitive = 0");
716 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "orig_client = cli2");
717 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "srestore end");
718 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "srestore end ok");
719 
720 	setup_send_features_proto_end(asfd, &r, &w);
721 }
722 
checks_orig_client_srestore(struct conf ** confs,struct conf ** cconfs,const char * incexc,int srestore)723 static void checks_orig_client_srestore(struct conf **confs,
724 	struct conf **cconfs, const char *incexc, int srestore)
725 {
726 	struct stat statp;
727 	fail_unless(srestore==1);
728 	// Should not have deleted either restore file.
729 	fail_unless(!lstat(SRESTORE_FILE, &statp));
730 	fail_unless(!lstat(SRESTORE_FILE_CLI2, &statp));
731 }
732 
START_TEST(test_server_extra_comms)733 START_TEST(test_server_extra_comms)
734 {
735 	run_test(0, setup_no_version, NULL);
736 	run_test(0, setup_old_version, NULL);
737 
738 	run_test(-1, setup_unexpected_first_string, NULL);
739 	run_test(-1, setup_1_3_0_write_problem, NULL);
740 	run_test(-1, setup_feature_write_problem, NULL);
741 
742 	run_test(0, setup_send_features_proto_auto,
743 		checks_proto_auto_no_features_from_client);
744 	run_test(0, setup_send_features_proto1,
745 		checks_proto1_no_features_from_client);
746 	run_test(0, setup_send_features_proto2,
747 		checks_proto2_no_features_from_client);
748 	run_test(0, setup_send_features_proto_auto_1,
749 		checks_proto_auto_1);
750 	run_test(0, setup_send_features_proto_auto_2,
751 		checks_proto_auto_2);
752 
753 	run_test(0, setup_send_features_proto_auto_old_client,
754 		checks_proto_auto_no_features_from_client_old_client);
755 	run_test(0, setup_send_features_proto1_old_client,
756 		checks_proto1_no_features_from_client_old_client);
757 	run_test(-1, setup_send_features_proto2_old_client,
758 		NULL);
759 	run_test(0, setup_send_features_proto_auto_1_old_client,
760 		checks_proto_auto_1);
761 	run_test(-1, setup_send_features_proto_auto_2_old_client,
762 		NULL);
763 
764 	run_test(-1, setup_send_features_proto_auto_auto,
765 		NULL);
766 	run_test(-1, setup_send_features_proto_1_auto,
767 		NULL);
768 	run_test(-1, setup_send_features_proto_2_auto,
769 		NULL);
770 	run_test(-1, setup_send_features_proto_1_2,
771 		NULL);
772 	run_test(-1, setup_send_features_proto_2_1,
773 		NULL);
774 
775 	run_test(0, setup_send_features_proto_1_1,
776 		NULL);
777 	run_test(0, setup_send_features_proto_2_2,
778 		NULL);
779 
780 	run_test(-1, setup_unexpected_cmd_feature,
781 		NULL);
782 
783 	run_test(0, setup_autoupgrade_no_os,
784 		NULL);
785 	run_test(0, setup_autoupgrade,
786 		NULL);
787 
788 #ifdef HAVE_BLAKE2
789 	run_test(0, setup_rshash_blake2, checks_rshash_blake2);
790 #else
791 	run_test(-1, setup_rshash_blake2, checks_rshash_blake2);
792 #endif
793 	run_test(0, setup_counters_ok, checks_counters_ok);
794 	run_test(0, setup_msg, checks_msg);
795 	run_test(0, setup_uname, checks_uname);
796 	run_test(0, setup_uname_is_windows, checks_uname_is_windows);
797 	run_test(-1, setup_unexpected_feature, NULL);
798 	run_test(0, setup_srestore_not_ok, checks_srestore_not_ok);
799 
800 	run_test(0, setup_srestore_ok, checks_srestore_ok);
801 	run_test(-1, setup_srestore_ok_error, NULL);
802 	run_test(0, setup_sincexc_ok, NULL);
803 	run_test(0, setup_incexc, checks_incexc);
804 	run_test(-1, setup_orig_client_not_existing, NULL);
805 	run_test(0, setup_orig_client, checks_orig_client);
806 	run_test(0, setup_orig_client_srestore, checks_orig_client_srestore);
807 }
808 END_TEST
809 
suite_server_extra_comms(void)810 Suite *suite_server_extra_comms(void)
811 {
812 	Suite *s;
813 	TCase *tc_core;
814 
815 	s=suite_create("server_extra_comms");
816 
817 	tc_core=tcase_create("Core");
818 	tcase_set_timeout(tc_core, 60);
819 
820 	tcase_add_test(tc_core, test_server_extra_comms);
821 
822 	suite_add_tcase(s, tc_core);
823 
824 	return s;
825 }
826