1 /*
2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 /*
30 * Project: NDMJOB
31 * Ident: $Id: $
32 *
33 * Description:
34 *
35 ********************************************************************
36 *
37 * NDMP Elements of a test-data session
38 *
39 * +-----+ ###########
40 * | Job |----># CONTROL #
41 * +-----+ # Agent #
42 * # #
43 * ###########
44 * | #
45 * +----------------+ #
46 * | control connection # CONTROL
47 * V # impersonates
48 * ############ # TAPE side of
49 * # DATA # # image stream
50 * # Agent # #
51 * +-----+ # +------+ # image #
52 * |FILES|====|butype|===================#
53 * +-----+ # +------+ # stream
54 * ############
55 *
56 *
57 ********************************************************************
58 *
59 */
60
61
62 #include "ndmagents.h"
63
64
65 #if !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && \
66 !defined(NDMOS_OPTION_NO_TEST_AGENTS)
67
68
69 extern int ndmca_td_wrapper(struct ndm_session* sess,
70 int (*func)(struct ndm_session* sess));
71
72
73 extern int ndmca_op_test_data(struct ndm_session* sess);
74 extern int ndmca_td_idle(struct ndm_session* sess);
75
76 extern int ndmca_td_listen(struct ndm_session* sess);
77 extern int ndmca_td_listen_subr(struct ndm_session* sess,
78 ndmp9_error expect_err,
79 ndmp9_addr_type addr_type);
80 extern int ndmca_test_check_data_state(struct ndm_session* sess,
81 ndmp9_data_state expected,
82 int reason);
83 extern int ndmca_test_data_get_state(struct ndm_session* sess,
84 ndmp9_error expect_err);
85 extern int ndmca_test_data_abort(struct ndm_session* sess,
86 ndmp9_error expect_err);
87 extern int ndmca_test_data_stop(struct ndm_session* sess,
88 ndmp9_error expect_err);
89
90
ndmca_op_test_data(struct ndm_session * sess)91 int ndmca_op_test_data(struct ndm_session* sess)
92 {
93 struct ndm_control_agent* ca = sess->control_acb;
94 struct ndmconn* conn;
95 int (*save_call)(struct ndmconn * conn, struct ndmp_xa_buf * xa);
96 int rc;
97
98 rc = ndmca_connect_data_agent(sess);
99 if (rc) {
100 ndmconn_destruct(sess->plumb.data);
101 sess->plumb.data = NULL;
102 return rc;
103 }
104
105 conn = sess->plumb.data;
106 save_call = conn->call;
107 conn->call = ndma_call_no_tattle;
108
109 /* perform query to find out about TCP and LOCAL support */
110 rc = ndmca_test_query_conn_types(sess, conn);
111 if (rc) return rc;
112
113 rc = ndmca_td_wrapper(sess, ndmca_td_idle);
114 if (sess->plumb.data->protocol_version >= 3) {
115 // version 3 and later adds LISTEN
116 rc = ndmca_td_wrapper(sess, ndmca_td_listen);
117 }
118
119 ndmca_test_done_series(sess, "test-data");
120
121 ca = sess->control_acb;
122 if (ca->has_tcp_addr && ca->has_local_addr) {
123 ndmalogf(sess, "TEST", 0, "LOCAL and TCP addressing tested.");
124 } else if (ca->has_tcp_addr) {
125 ndmalogf(sess, "TEST", 0, "TCP addressing ONLY tested.");
126 } else if (ca->has_local_addr) {
127 ndmalogf(sess, "TEST", 0, "LOCAL addressing ONLY tested.");
128 } else {
129 ndmalogf(sess, "TEST", 0, "Neither TCP or LOCAL addressing tested.");
130 }
131
132 return 0;
133 }
134
ndmca_td_wrapper(struct ndm_session * sess,int (* func)(struct ndm_session * sess))135 int ndmca_td_wrapper(struct ndm_session* sess,
136 int (*func)(struct ndm_session* sess))
137 {
138 int rc;
139
140 rc = (*func)(sess);
141
142 if (rc != 0) { ndmalogf(sess, "Test", 1, "Failure"); }
143
144 ndmca_test_done_phase(sess);
145
146 /* clean up mess */
147 ndmca_test_log_note(sess, 2, "Cleaning up...");
148
149 rc = 0;
150
151 return rc;
152 }
153
ndmca_td_idle(struct ndm_session * sess)154 int ndmca_td_idle(struct ndm_session* sess)
155 {
156 int rc;
157
158 ndmca_test_phase(sess, "D-IDLE", "Data IDLE State Series");
159
160 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_IDLE, 0);
161 if (rc) return rc;
162
163 rc = ndmca_test_data_abort(sess, NDMP9_ILLEGAL_STATE_ERR);
164 if (rc) return rc;
165
166 rc = ndmca_test_data_stop(sess, NDMP9_ILLEGAL_STATE_ERR);
167 if (rc) return rc;
168
169 return 0; /* pass */
170 }
171
172
173 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
174
175
ndmca_test_data_listen(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_addr_type addr_type)176 int ndmca_test_data_listen(struct ndm_session* sess,
177 ndmp9_error expect_err,
178 ndmp9_addr_type addr_type)
179 {
180 struct ndmconn* conn = sess->plumb.data;
181 struct ndm_control_agent* ca = sess->control_acb;
182 int rc;
183
184 /* close previous test if there is one */
185 ndmca_test_close(sess);
186
187 switch (conn->protocol_version) {
188 default:
189 return -1234;
190
191 #ifndef NDMOS_OPTION_NO_NDMP3
192 case NDMP3VER:
193 NDMC_WITH(ndmp3_data_listen, NDMP3VER)
194 request->addr_type = addr_type;
195
196 rc = NDMTEST_CALL(conn);
197 if (rc) return rc;
198
199 if (expect_err == NDMP9_NO_ERR &&
200 request->addr_type != reply->data_connection_addr.addr_type) {
201 /* TODO: use proper test format */
202 ndmalogf(sess, "Test", 1, "DATA_LISTEN addr_type mismatch");
203 return -1;
204 }
205 ndmp_3to9_addr(&reply->data_connection_addr, &ca->data_addr);
206 NDMC_ENDWITH
207 break;
208 #endif /* !NDMOS_OPTION_NO_NDMP3 */
209 #ifndef NDMOS_OPTION_NO_NDMP4
210 case NDMP4VER:
211 NDMC_WITH(ndmp4_data_listen, NDMP4VER)
212 request->addr_type = addr_type;
213
214 rc = NDMTEST_CALL(conn);
215 if (rc) return rc;
216
217 if (expect_err == NDMP9_NO_ERR &&
218 request->addr_type != reply->connect_addr.addr_type) {
219 /* TODO: use proper test format */
220 ndmalogf(sess, "Test", 1, "DATA_LISTEN addr_type mismatch");
221 return -1;
222 }
223 ndmp_4to9_addr(&reply->connect_addr, &ca->data_addr);
224 NDMC_ENDWITH
225 break;
226 #endif /* !NDMOS_OPTION_NO_NDMP4 */
227 }
228
229 return 0;
230 }
231
232
ndmca_td_listen(struct ndm_session * sess)233 int ndmca_td_listen(struct ndm_session* sess)
234 {
235 struct ndm_control_agent* ca = sess->control_acb;
236 int rc;
237
238 ndmca_test_phase(sess, "D-LISTEN", "Data LISTEN State Series");
239
240 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_IDLE, 0);
241 if (rc) return rc;
242
243 if (ca->has_tcp_addr) {
244 rc = ndmca_td_listen_subr(sess, NDMP9_NO_ERR, NDMP9_ADDR_TCP);
245 if (rc) return rc;
246 }
247
248 if (ca->has_local_addr) {
249 rc = ndmca_td_listen_subr(sess, NDMP9_NO_ERR, NDMP9_ADDR_LOCAL);
250 if (rc) return rc;
251 }
252
253 ndmca_test_done_phase(sess);
254
255 /*
256 * Bogus arguments
257 */
258 ndmca_test_phase(sess, "D-LISTEN/bogus-args",
259 "Data LISTEN State Series w/ bogus args");
260
261 rc = ndmca_test_data_listen(sess, NDMP9_ILLEGAL_ARGS_ERR, 123);
262 if (rc) return rc;
263
264 ndmca_test_done_phase(sess);
265
266
267 return 0; /* pass */
268 }
269
ndmca_td_listen_subr(struct ndm_session * sess,ndmp9_error expect_err,ndmp9_addr_type addr_type)270 int ndmca_td_listen_subr(struct ndm_session* sess,
271 ndmp9_error expect_err,
272 ndmp9_addr_type addr_type)
273 {
274 int rc;
275
276 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_IDLE, 0);
277 if (rc) return rc;
278
279 rc = ndmca_test_data_listen(sess, expect_err, addr_type);
280 if (rc) return rc;
281
282 if (expect_err != NDMP9_NO_ERR) return 0; /* got expected error */
283
284 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_LISTEN, 0);
285 if (rc) return rc;
286
287 rc = ndmca_test_data_listen(sess, NDMP9_ILLEGAL_STATE_ERR, addr_type);
288 if (rc) return rc;
289
290 rc = ndmca_test_data_stop(sess, NDMP9_ILLEGAL_STATE_ERR);
291 if (rc) return rc;
292
293 rc = ndmca_test_data_abort(sess, NDMP9_NO_ERR);
294 if (rc) return rc;
295
296 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_HALTED,
297 NDMP9_DATA_HALT_ABORTED);
298 if (rc) return rc;
299
300 rc = ndmca_test_data_stop(sess, NDMP9_NO_ERR);
301 if (rc) return rc;
302
303 rc = ndmca_test_check_data_state(sess, NDMP9_DATA_STATE_IDLE, 0);
304 if (rc) return rc;
305
306 return 0;
307 }
308
ndmca_test_check_data_state(struct ndm_session * sess,ndmp9_data_state expected,int reason)309 int ndmca_test_check_data_state(struct ndm_session* sess,
310 ndmp9_data_state expected,
311 int reason)
312 {
313 struct ndm_control_agent* ca = sess->control_acb;
314 ndmp9_data_get_state_reply* ds = &ca->data_state;
315 int rc;
316 char* what;
317 char errbuf[100];
318 char tmpbuf[256];
319
320 /* close previous test if there is one */
321 ndmca_test_close(sess);
322
323 /* open new test */
324 ndmca_test_open(sess, "data check", ndmp9_data_state_to_str(expected));
325
326 strcpy(errbuf, "???");
327
328 what = "get_state";
329 rc = ndmca_data_get_state(sess);
330 if (rc) goto fail;
331
332 what = "state self-consistent";
333 /* make sure the sensed state is self consistent */
334 switch (ds->state) {
335 case NDMP9_DATA_STATE_IDLE:
336 case NDMP9_DATA_STATE_ACTIVE:
337 case NDMP9_DATA_STATE_LISTEN:
338 case NDMP9_DATA_STATE_CONNECTED:
339 if (ds->halt_reason != NDMP9_DATA_HALT_NA) {
340 strcpy(errbuf, "reason != NA");
341 goto fail;
342 }
343 break;
344
345 case NDMP9_DATA_STATE_HALTED:
346 break;
347
348 default:
349 strcpy(errbuf, "bogus state");
350 goto fail;
351 }
352
353 what = "state";
354 if (ds->state != expected) {
355 snprintf(errbuf, sizeof(errbuf), "expected %s got %s",
356 ndmp9_data_state_to_str(expected),
357 ndmp9_data_state_to_str(ds->state));
358 goto fail;
359 }
360
361 what = "reason";
362 switch (ds->state) {
363 case NDMP9_DATA_STATE_HALTED:
364 if (ds->halt_reason != (ndmp9_data_halt_reason)reason) {
365 snprintf(errbuf, sizeof(errbuf), "expected %s got %s",
366 ndmp9_data_halt_reason_to_str(reason),
367 ndmp9_data_halt_reason_to_str(ds->halt_reason));
368 goto fail;
369 }
370 break;
371
372 default:
373 break;
374 }
375
376 /* test passed */
377 ndmca_test_close(sess);
378
379 return 0;
380
381 fail:
382 /* test failed */
383 snprintf(tmpbuf, sizeof(tmpbuf), "%s: %s", what, errbuf);
384 ndmca_test_fail(sess, tmpbuf);
385
386 ndmca_test_close(sess);
387
388 return -1;
389 }
390
391
ndmca_test_data_get_state(struct ndm_session * sess,ndmp9_error expect_err)392 int ndmca_test_data_get_state(struct ndm_session* sess, ndmp9_error expect_err)
393 {
394 struct ndmconn* conn = sess->plumb.data;
395 int rc;
396
397 /* close previous test if there is one */
398 ndmca_test_close(sess);
399
400 rc = ndmca_data_get_state(sess);
401
402 rc = ndmca_test_check_expect(conn, rc, expect_err);
403
404 return rc;
405 }
406
ndmca_test_data_abort(struct ndm_session * sess,ndmp9_error expect_err)407 int ndmca_test_data_abort(struct ndm_session* sess, ndmp9_error expect_err)
408 {
409 struct ndmconn* conn = sess->plumb.data;
410 int rc;
411
412 /* close previous test if there is one */
413 ndmca_test_close(sess);
414
415 rc = ndmca_data_abort(sess);
416
417 rc = ndmca_test_check_expect(conn, rc, expect_err);
418
419 return rc;
420 }
421
ndmca_test_data_stop(struct ndm_session * sess,ndmp9_error expect_err)422 int ndmca_test_data_stop(struct ndm_session* sess, ndmp9_error expect_err)
423 {
424 struct ndmconn* conn = sess->plumb.data;
425 int rc;
426
427 /* close previous test if there is one */
428 ndmca_test_close(sess);
429
430 rc = ndmca_data_stop(sess);
431
432 rc = ndmca_test_check_expect(conn, rc, expect_err);
433
434 return rc;
435 }
436
437
438 #endif /* !defined(NDMOS_OPTION_NO_CONTROL_AGENT) && \
439 !defined(NDMOS_OPTION_NO_TEST_AGENTS) */
440