Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_ctst_data.c
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 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
66
67
68 extern int      ndmca_td_wrapper (struct ndm_session *sess,
69                                 int (*func)(struct ndm_session *sess));
70
71
72 extern int      ndmca_op_test_data (struct ndm_session *sess);
73 extern int      ndmca_td_idle (struct ndm_session *sess);
74
75 extern int      ndmca_td_listen (struct ndm_session *sess);
76 extern int      ndmca_td_listen_subr (struct ndm_session *sess,
77                                       ndmp9_error expect_err,
78                                       ndmp9_addr_type addr_type);
79 extern int      ndmca_test_check_data_state  (struct ndm_session *sess,
80                         ndmp9_data_state expected, int reason);
81 extern int      ndmca_test_data_get_state (struct ndm_session *sess,
82                         ndmp9_error expect_err);
83 extern int      ndmca_test_data_abort (struct ndm_session *sess,
84                         ndmp9_error expect_err);
85 extern int      ndmca_test_data_stop (struct ndm_session *sess,
86                         ndmp9_error expect_err);
87
88
89
90 int
91 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,
96                                                 struct ndmp_xa_buf *xa);
97         int                     rc;
98
99         rc = ndmca_connect_data_agent(sess);
100         if (rc) {
101                 ndmconn_destruct (sess->plumb.data);
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
135 int
136 ndmca_td_wrapper (struct ndm_session *sess,
137   int (*func)(struct ndm_session *sess))
138 {
139         int             rc;
140
141         rc = (*func)(sess);
142
143         if (rc != 0) {
144                 ndmalogf (sess, "Test", 1, "Failure");
145         }
146
147         ndmca_test_done_phase (sess);
148
149         /* clean up mess */
150         ndmca_test_log_note (sess, 2, "Cleaning up...");
151
152         rc = 0;
153
154         return rc;
155 }
156
157 int
158 ndmca_td_idle (struct ndm_session *sess)
159 {
160         int             rc;
161
162         ndmca_test_phase (sess, "D-IDLE", "Data IDLE State Series");
163
164         rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
165         if (rc) return rc;
166
167         rc = ndmca_test_data_abort (sess, NDMP9_ILLEGAL_STATE_ERR);
168         if (rc) return rc;
169
170         rc = ndmca_test_data_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
171         if (rc) return rc;
172
173         return 0;       /* pass */
174 }
175
176
177
178 #define NDMTEST_CALL(CONN) ndmca_test_call(CONN, xa, expect_err);
179
180
181
182 int
183 ndmca_test_data_listen (struct ndm_session *sess, ndmp9_error expect_err,
184                         ndmp9_addr_type addr_type)
185 {
186         struct ndmconn *        conn = sess->plumb.data;
187         struct ndm_control_agent *ca = &sess->control_acb;
188         int                     rc;
189
190         /* close previous test if there is one */
191         ndmca_test_close (sess);
192
193         switch (conn->protocol_version) {
194         default:        return -1234;
195
196 #ifndef NDMOS_OPTION_NO_NDMP3
197         case NDMP3VER:
198             NDMC_WITH(ndmp3_data_listen, NDMP3VER)
199                 request->addr_type = addr_type;
200
201                 rc = NDMTEST_CALL(conn);
202                 if (rc) return rc;
203
204                 if (expect_err == NDMP9_NO_ERR
205                  && request->addr_type
206                     != reply->data_connection_addr.addr_type) {
207                         /* TODO: use proper test format */
208                         ndmalogf (sess, "Test", 1,
209                                 "DATA_LISTEN addr_type mismatch");
210                         return -1;
211                 }
212                 ndmp_3to9_addr (&reply->data_connection_addr, &ca->data_addr);
213             NDMC_ENDWITH
214             break;
215 #endif /* !NDMOS_OPTION_NO_NDMP3 */
216 #ifndef NDMOS_OPTION_NO_NDMP4
217         case NDMP4VER:
218             NDMC_WITH(ndmp4_data_listen, NDMP4VER)
219                 request->addr_type = addr_type;
220
221                 rc = NDMTEST_CALL(conn);
222                 if (rc) return rc;
223
224                 if (expect_err == NDMP9_NO_ERR
225                  && request->addr_type
226                     != reply->connect_addr.addr_type) {
227                         /* TODO: use proper test format */
228                         ndmalogf (sess, "Test", 1,
229                                 "DATA_LISTEN addr_type mismatch");
230                         return -1;
231                 }
232                 ndmp_4to9_addr (&reply->connect_addr, &ca->data_addr);
233             NDMC_ENDWITH
234             break;
235 #endif /* !NDMOS_OPTION_NO_NDMP4 */
236         }
237
238         return 0;
239 }
240
241
242 int
243 ndmca_td_listen (struct ndm_session *sess)
244 {
245         struct ndm_control_agent *ca = &sess->control_acb;
246         int             rc;
247
248         ndmca_test_phase (sess, "D-LISTEN", "Data LISTEN State Series");
249
250         rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
251         if (rc) return rc;
252
253         if (ca->has_tcp_addr) {
254             rc = ndmca_td_listen_subr (sess, NDMP9_NO_ERR, NDMP9_ADDR_TCP);
255             if (rc) return rc;
256         }
257
258         if (ca->has_local_addr) {
259             rc = ndmca_td_listen_subr (sess, NDMP9_NO_ERR, NDMP9_ADDR_LOCAL);
260             if (rc) return rc;
261         }
262
263         ndmca_test_done_phase (sess);
264
265         /*
266          * Bogus arguments
267          */
268         ndmca_test_phase (sess, "D-LISTEN/bogus-args",
269                                 "Data LISTEN State Series w/ bogus args");
270
271         rc = ndmca_test_data_listen (sess, NDMP9_ILLEGAL_ARGS_ERR,
272                                      123);
273         if (rc) return rc;
274
275         ndmca_test_done_phase (sess);
276
277
278         return 0;       /* pass */
279 }
280
281 int
282 ndmca_td_listen_subr (struct ndm_session *sess,
283                       ndmp9_error expect_err,
284                       ndmp9_addr_type addr_type)
285 {
286         int             rc;
287
288         rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
289         if (rc) return rc;
290
291         rc = ndmca_test_data_listen (sess, expect_err, addr_type);
292         if (rc) return rc;
293
294         if (expect_err != NDMP9_NO_ERR)
295                 return 0;               /* got expected error */
296
297         rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_LISTEN, 0);
298         if (rc) return rc;
299
300         rc = ndmca_test_data_listen (sess, NDMP9_ILLEGAL_STATE_ERR,
301                 addr_type);
302         if (rc) return rc;
303
304         rc = ndmca_test_data_stop (sess, NDMP9_ILLEGAL_STATE_ERR);
305         if (rc) return rc;
306
307         rc = ndmca_test_data_abort (sess, NDMP9_NO_ERR);
308         if (rc) return rc;
309
310         rc = ndmca_test_check_data_state  (sess,
311                 NDMP9_DATA_STATE_HALTED, NDMP9_DATA_HALT_ABORTED);
312         if (rc) return rc;
313
314         rc = ndmca_test_data_stop (sess, NDMP9_NO_ERR);
315         if (rc) return rc;
316
317         rc = ndmca_test_check_data_state  (sess, NDMP9_DATA_STATE_IDLE, 0);
318         if (rc) return rc;
319
320         return 0;
321 }
322
323 int
324 ndmca_test_check_data_state  (struct ndm_session *sess,
325   ndmp9_data_state expected, int reason)
326 {
327         struct ndm_control_agent *      ca = &sess->control_acb;
328         ndmp9_data_get_state_reply *    ds = &ca->data_state;
329         int                             rc;
330         char *                          what;
331         char                            errbuf[100];
332         char                            tmpbuf[256];
333
334         /* close previous test if there is one */
335         ndmca_test_close (sess);
336
337         /* open new test */
338         ndmca_test_open (sess,
339                          "data check",
340                          ndmp9_data_state_to_str (expected));
341
342         strcpy (errbuf, "???");
343
344         what = "get_state";
345         rc = ndmca_data_get_state (sess);
346         if (rc) goto fail;
347
348         what = "state self-consistent";
349         /* make sure the sensed state is self consistent */
350         switch (ds->state) {
351         case NDMP9_DATA_STATE_IDLE:
352         case NDMP9_DATA_STATE_ACTIVE:
353         case NDMP9_DATA_STATE_LISTEN:
354         case NDMP9_DATA_STATE_CONNECTED:
355                 if (ds->halt_reason != NDMP9_DATA_HALT_NA) {
356                         strcpy (errbuf, "reason != NA");
357                         goto fail;
358                 }
359                 break;
360
361         case NDMP9_DATA_STATE_HALTED:
362                 break;
363
364         default:
365                 strcpy (errbuf, "bogus state");
366                 goto fail;
367         }
368
369         what = "state";
370         if (ds->state != expected) {
371                 sprintf (errbuf, "expected %s got %s",
372                         ndmp9_data_state_to_str (expected),
373                         ndmp9_data_state_to_str (ds->state));
374                 goto fail;
375         }
376
377         what = "reason";
378         switch (ds->state) {
379         case NDMP9_DATA_STATE_HALTED:
380                 if (ds->halt_reason != (ndmp9_data_halt_reason)reason) {
381                         sprintf (errbuf, "expected %s got %s",
382                             ndmp9_data_halt_reason_to_str (reason),
383                             ndmp9_data_halt_reason_to_str (ds->halt_reason));
384                         goto fail;
385                 }
386                 break;
387
388         default:
389                 break;
390         }
391
392         /* test passed */
393         ndmca_test_close (sess);
394
395         return 0;
396
397   fail:
398         /* test failed */
399         sprintf(tmpbuf, "%s: %s", what, errbuf);
400         ndmca_test_fail(sess, tmpbuf);
401
402         ndmca_test_close (sess);
403
404         return -1;
405 }
406
407
408
409 int
410 ndmca_test_data_get_state (struct ndm_session *sess, ndmp9_error expect_err)
411 {
412         struct ndmconn *        conn = sess->plumb.data;
413         int                     rc;
414
415         /* close previous test if there is one */
416         ndmca_test_close (sess);
417
418         rc = ndmca_data_get_state (sess);
419
420         rc = ndmca_test_check_expect (conn, rc, expect_err);
421
422         return rc;
423 }
424
425 int
426 ndmca_test_data_abort (struct ndm_session *sess, ndmp9_error expect_err)
427 {
428         struct ndmconn *        conn = sess->plumb.data;
429         int                     rc;
430
431         /* close previous test if there is one */
432         ndmca_test_close (sess);
433
434         rc = ndmca_data_abort (sess);
435
436         rc = ndmca_test_check_expect (conn, rc, expect_err);
437
438         return rc;
439 }
440
441 int
442 ndmca_test_data_stop (struct ndm_session *sess, ndmp9_error expect_err)
443 {
444         struct ndmconn *        conn = sess->plumb.data;
445         int                     rc;
446
447         /* close previous test if there is one */
448         ndmca_test_close (sess);
449
450         rc = ndmca_data_stop (sess);
451
452         rc = ndmca_test_check_expect (conn, rc, expect_err);
453
454         return rc;
455 }
456
457
458
459
460
461
462 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */