Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndma_ctrl_calls.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
38 #include "ndmagents.h"
39
40 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
41
42
43 /*
44  * DATA Agent calls
45  ****************************************************************
46  */
47
48 int
49 ndmca_data_get_state (struct ndm_session *sess)
50 {
51         struct ndmconn *        conn = sess->plumb.data;
52         struct ndm_control_agent *ca = &sess->control_acb;
53         struct ndmp9_data_get_state_reply *state = &ca->data_state;
54         int                     rc;
55
56         NDMC_WITH_VOID_REQUEST(ndmp9_data_get_state, NDMP9VER)
57                 rc = NDMC_CALL(conn);
58                 if (rc) {
59                         NDMOS_MACRO_ZEROFILL (state);
60                         ca->data_state.state = -1;
61                 } else {
62                         *state = *reply;
63                 }
64         NDMC_ENDWITH
65
66         return rc;
67 }
68
69 int
70 ndmca_data_listen (struct ndm_session *sess)
71 {
72         struct ndmconn *        conn = sess->plumb.data;
73         struct ndm_control_agent *ca = &sess->control_acb;
74         int                     rc;
75
76         NDMC_WITH(ndmp9_data_listen, NDMP9VER)
77                 if (sess->plumb.tape == sess->plumb.data) {
78                         request->addr_type = NDMP9_ADDR_LOCAL;
79                 } else {
80                         request->addr_type = NDMP9_ADDR_TCP;
81                 }
82                 rc = NDMC_CALL(conn);
83                 if (rc) return rc;
84
85                 if (request->addr_type
86                  != reply->data_connection_addr.addr_type) {
87                         ndmalogf (sess, 0, 0,
88                                 "DATA_LISTEN addr_type mismatch");
89                         return -1;
90                 }
91
92                 ca->data_addr = reply->data_connection_addr;
93         NDMC_ENDWITH
94
95         return 0;
96 }
97
98 int
99 ndmca_data_connect (struct ndm_session *sess)
100 {
101         struct ndmconn *        conn = sess->plumb.data;
102         struct ndm_control_agent *ca = &sess->control_acb;
103         int                     rc;
104         ndmp9_addr              addr;
105
106         if (ca->job.tape_tcp) {
107                 char *host;
108                 char *port;
109                 struct sockaddr_in sin;
110
111                 host = ca->job.tape_tcp;
112                 port = strchr(ca->job.tape_tcp, ':');
113                 *port++ = '\0';
114                 rc = ndmhost_lookup(host, &sin);
115                 addr.addr_type = NDMP9_ADDR_TCP;
116                 addr.ndmp9_addr_u.tcp_addr.ip_addr = ntohl(sin.sin_addr.s_addr);
117                 addr.ndmp9_addr_u.tcp_addr.port = atoi(port);
118         } else {
119                 addr = ca->mover_addr;
120         }
121
122         NDMC_WITH(ndmp9_data_connect, NDMP9VER)
123                 request->addr = addr;
124                 rc = NDMC_CALL(conn);
125         NDMC_ENDWITH
126
127         return rc;
128 }
129
130 int
131 ndmca_data_start_backup (struct ndm_session *sess)
132 {
133         struct ndmconn *        conn = sess->plumb.data;
134         struct ndm_control_agent *ca = &sess->control_acb;
135         unsigned                n_env = ca->job.env_tab.n_env;
136         ndmp9_pval *            env = ca->job.env_tab.env;
137         ndmp9_addr              addr;
138         int                     rc;
139
140         if (conn->protocol_version > 2) {
141             if (ca->swap_connect) {
142                 if ( (rc = ndmca_mover_connect (sess)) != 0) {
143                         return rc;
144                 }
145             } else {
146                 if ( (rc = ndmca_data_connect (sess)) != 0) {
147                         return rc;
148                 }
149             }
150             addr.addr_type = NDMP9_ADDR_AS_CONNECTED;
151         } else {
152                 addr = ca->mover_addr;
153         }
154
155         NDMC_WITH(ndmp9_data_start_backup, NDMP9VER)
156                 request->addr = addr;
157                 request->bu_type = ca->job.bu_type;
158                 request->env.env_len = n_env;
159                 request->env.env_val = env;
160
161                 rc = NDMC_CALL(conn);
162         NDMC_ENDWITH
163
164         return rc;
165 }
166
167 int
168 ndmca_data_start_recover (struct ndm_session *sess)
169 {
170         struct ndmconn *        conn = sess->plumb.data;
171         struct ndm_control_agent *ca = &sess->control_acb;
172         unsigned                n_env = ca->job.env_tab.n_env;
173         ndmp9_pval *            env = ca->job.env_tab.env;
174         unsigned                n_nlist = ca->job.nlist_tab.n_nlist;
175         ndmp9_name *            nlist = ca->job.nlist_tab.nlist;
176         ndmp9_addr              addr;
177         int                     rc;
178
179         if (conn->protocol_version > 2) {
180             if (ca->swap_connect) {
181                 if ( (rc = ndmca_mover_connect (sess)) != 0) {
182                         return rc;
183                 }
184             } else {
185                 if ( (rc = ndmca_data_connect (sess)) != 0) {
186                         return rc;
187                 }
188             }
189             addr.addr_type = NDMP9_ADDR_AS_CONNECTED;
190         } else {
191                 addr = ca->mover_addr;
192         }
193
194         NDMC_WITH(ndmp9_data_start_recover, NDMP9VER)
195                 request->addr = addr;
196                 request->bu_type = ca->job.bu_type;
197                 request->env.env_len = n_env;
198                 request->env.env_val = env;
199                 request->nlist.nlist_len = n_nlist;
200                 request->nlist.nlist_val = nlist;
201
202                 rc = NDMC_CALL(conn);
203         NDMC_ENDWITH
204
205         return rc;
206 }
207
208 int
209 ndmca_data_start_recover_filehist (struct ndm_session *sess)
210 {
211         struct ndmconn *        conn = sess->plumb.data;
212         struct ndm_control_agent *ca = &sess->control_acb;
213         unsigned                n_env = ca->job.env_tab.n_env;
214         ndmp9_pval *            env = ca->job.env_tab.env;
215         unsigned                n_nlist = ca->job.nlist_tab.n_nlist;
216         ndmp9_name *            nlist = ca->job.nlist_tab.nlist;
217         ndmp9_addr              addr;
218         int                     rc;
219
220         if (conn->protocol_version > 2) {
221             if (ca->swap_connect) {
222                 if ( (rc = ndmca_mover_connect (sess)) != 0) {
223                         return rc;
224                 }
225             } else {
226                 if ( (rc = ndmca_data_connect (sess)) != 0) {
227                         return rc;
228                 }
229             }
230                 addr.addr_type = NDMP9_ADDR_AS_CONNECTED;
231         } else {
232                 addr = ca->mover_addr;
233         }
234
235         NDMC_WITH(ndmp9_data_start_recover_filehist, NDMP9VER)
236                 request->addr = addr;
237                 request->bu_type = ca->job.bu_type;
238                 request->env.env_len = n_env;
239                 request->env.env_val = env;
240                 request->nlist.nlist_len = n_nlist;
241                 request->nlist.nlist_val = nlist;
242
243                 rc = NDMC_CALL(conn);
244         NDMC_ENDWITH
245
246         return rc;
247 }
248
249 int
250 ndmca_data_abort (struct ndm_session *sess)
251 {
252         struct ndmconn *        conn = sess->plumb.data;
253         int                     rc;
254
255         NDMC_WITH_VOID_REQUEST(ndmp9_data_abort, NDMP9VER)
256                 rc = NDMC_CALL(conn);
257         NDMC_ENDWITH
258
259         return rc;
260 }
261
262 int
263 ndmca_data_get_env (struct ndm_session *sess)
264 {
265         struct ndmconn *        conn = sess->plumb.data;
266         struct ndm_control_agent *ca = &sess->control_acb;
267         int                     rc;
268         unsigned int            i;
269         ndmp9_pval *            d_pv;
270         ndmp9_pval *            s_pv;
271
272         NDMC_WITH_VOID_REQUEST(ndmp9_data_get_env, NDMP9VER)
273                 rc = NDMC_CALL(conn);
274                 if (rc) return rc;
275
276                 for (i = 0; i < reply->env.env_len; i++) {
277                         s_pv = &reply->env.env_val[i];
278                         d_pv = &ca->job.result_env_tab.env[i];
279                         d_pv->name  = NDMOS_API_STRDUP (s_pv->name);
280                         d_pv->value = NDMOS_API_STRDUP (s_pv->value);
281                 }
282                 ca->job.result_env_tab.n_env = i;
283
284                 NDMC_FREE_REPLY();
285         NDMC_ENDWITH
286
287         return rc;
288 }
289
290 int
291 ndmca_data_stop (struct ndm_session *sess)
292 {
293         struct ndmconn *        conn = sess->plumb.data;
294         int                     rc;
295
296         NDMC_WITH_VOID_REQUEST(ndmp9_data_stop, NDMP9VER)
297                 rc = NDMC_CALL(conn);
298         NDMC_ENDWITH
299
300         return rc;
301 }
302
303
304
305
306
307 /*
308  * TAPE Agent calls -- TAPE
309  ****************************************************************
310  */
311
312 int
313 ndmca_tape_open (struct ndm_session *sess)
314 {
315         struct ndmconn *        conn = sess->plumb.tape;
316         struct ndm_control_agent *ca = &sess->control_acb;
317         int                     rc;
318
319         NDMC_WITH (ndmp9_tape_open, NDMP9VER)
320                 request->device = ca->job.tape_device;
321                 request->mode = ca->tape_mode;
322                 rc = NDMC_CALL(conn);
323                 ca->tape_state.error = reply->error;
324         NDMC_ENDWITH
325
326         return rc;
327 }
328
329 int
330 ndmca_tape_close (struct ndm_session *sess)
331 {
332         struct ndmconn *        conn = sess->plumb.tape;
333         int                     rc;
334
335         NDMC_WITH_VOID_REQUEST(ndmp9_tape_close, NDMP9VER)
336                 rc = NDMC_CALL(conn);
337         NDMC_ENDWITH
338
339         return rc;
340 }
341
342 int
343 ndmca_tape_get_state (struct ndm_session *sess)
344 {
345         struct ndmconn *        conn = sess->plumb.tape;
346         struct ndm_control_agent *ca = &sess->control_acb;
347         struct ndmp9_tape_get_state_reply *state = &ca->tape_state;
348         int                     rc;
349
350         NDMC_WITH_VOID_REQUEST(ndmp9_tape_get_state, NDMP9VER)
351                 rc = NDMC_CALL(conn);
352                 if (rc) {
353                         NDMOS_MACRO_ZEROFILL (state);
354                         /* tape_state.state = -1; */
355                         state->error = reply->error;
356                 } else {
357                         *state = *reply;
358                 }
359         NDMC_ENDWITH
360
361         return rc;
362 }
363
364 int
365 ndmca_tape_get_state_no_tattle (struct ndm_session *sess)
366 {
367         struct ndmconn *        conn = sess->plumb.tape;
368         struct ndm_control_agent *ca = &sess->control_acb;
369         struct ndmp9_tape_get_state_reply *state = &ca->tape_state;
370         int                     rc;
371
372         NDMC_WITH_VOID_REQUEST(ndmp9_tape_get_state, NDMP9VER)
373                 rc = ndma_call_no_tattle (conn, xa);
374                 if (rc) {
375                         NDMOS_MACRO_ZEROFILL (state);
376                         /* tape_state.state = -1; */
377                 } else {
378                         *state = *reply;
379                 }
380                 if (rc < 0
381                  ||  (reply->error != NDMP9_DEV_NOT_OPEN_ERR
382                    && reply->error != NDMP9_NO_ERR))
383                         ndma_tattle (sess->plumb.tape, xa, rc);
384         NDMC_ENDWITH
385
386         return rc;
387 }
388
389 int
390 ndmca_tape_mtio (struct ndm_session *sess,
391   ndmp9_tape_mtio_op op, u_long count, u_long *resid)
392 {
393         struct ndmconn *        conn = sess->plumb.tape;
394         int                     rc;
395
396         NDMC_WITH(ndmp9_tape_mtio, NDMP9VER)
397                 request->tape_op = op;
398                 request->count = count;
399
400                 rc = NDMC_CALL(conn);
401                 if (!rc) {
402                         if (resid) {
403                                 *resid = reply->resid_count;
404                         } else if (reply->resid_count != 0) {
405                                 return -1;
406                         }
407                 }
408         NDMC_ENDWITH
409
410         return rc;
411 }
412
413 int
414 ndmca_tape_write (struct ndm_session *sess, char *buf, unsigned count)
415 {
416         struct ndmconn *        conn = sess->plumb.tape;
417         int                     rc;
418
419         NDMC_WITH(ndmp9_tape_write, NDMP9VER)
420                 request->data_out.data_out_len = count;
421                 request->data_out.data_out_val = buf;
422                 rc = NDMC_CALL(conn);
423                 if (rc == 0) {
424                         if (reply->count != count)
425                                 rc = -1;
426                 }
427         NDMC_ENDWITH
428
429         return rc;
430 }
431
432 int
433 ndmca_tape_read (struct ndm_session *sess, char *buf, unsigned count)
434 {
435         struct ndmconn *        conn = sess->plumb.tape;
436         int                     rc;
437
438         NDMC_WITH(ndmp9_tape_read, NDMP9VER)
439                 request->count = count;
440                 rc = NDMC_CALL(conn);
441                 if (rc == 0) {
442                         if (reply->data_in.data_in_len == count) {
443                                 bcopy (reply->data_in.data_in_val,
444                                                         buf, count);
445                         } else {
446                                 rc = -1;
447                         }
448                 }
449                 NDMC_FREE_REPLY();
450         NDMC_ENDWITH
451
452         return rc;
453 }
454
455
456 int
457 ndmca_tape_read_partial (struct ndm_session *sess, char *buf, unsigned count, int *read_count)
458 {
459         struct ndmconn *        conn = sess->plumb.tape;
460         int                     rc;
461
462         NDMC_WITH(ndmp9_tape_read, NDMP9VER)
463                 request->count = count;
464                 rc = NDMC_CALL(conn);
465                 if (rc == 0) {
466                         *read_count = reply->data_in.data_in_len;
467                         bcopy (reply->data_in.data_in_val, buf, *read_count);
468                 } else {
469                         rc = reply->error;
470                 }
471                 NDMC_FREE_REPLY();
472         NDMC_ENDWITH
473
474         return rc;
475 }
476
477
478 /*
479  * TAPE Agent calls -- MOVER
480  ****************************************************************
481  */
482
483 int
484 ndmca_mover_get_state (struct ndm_session *sess)
485 {
486         struct ndmconn *        conn = sess->plumb.tape;
487         struct ndm_control_agent *ca = &sess->control_acb;
488         struct ndmp9_mover_get_state_reply *state = &ca->mover_state;
489         int                     rc;
490
491         NDMC_WITH_VOID_REQUEST(ndmp9_mover_get_state, NDMP9VER)
492                 rc = NDMC_CALL(conn);
493                 if (rc) {
494                         NDMOS_MACRO_ZEROFILL (state);
495                         ca->mover_state.state = -1;
496                 } else {
497                         *state = *reply;
498                 }
499         NDMC_ENDWITH
500
501         return rc;
502 }
503
504 int
505 ndmca_mover_listen (struct ndm_session *sess)
506 {
507         struct ndmconn *        conn = sess->plumb.tape;
508         struct ndm_control_agent *ca = &sess->control_acb;
509         int                     rc;
510
511         NDMC_WITH(ndmp9_mover_listen, NDMP9VER)
512                 request->mode = ca->mover_mode;
513
514                 if (sess->plumb.tape == sess->plumb.data) {
515                         request->addr_type = NDMP9_ADDR_LOCAL;
516                 } else {
517                         request->addr_type = NDMP9_ADDR_TCP;
518                 }
519                 rc = NDMC_CALL(conn);
520                 if (rc) return rc;
521
522                 if (request->addr_type
523                  != reply->data_connection_addr.addr_type) {
524                         ndmalogf (sess, 0, 0,
525                                 "MOVER_LISTEN addr_type mismatch");
526                         return -1;
527                 }
528
529                 ca->mover_addr = reply->data_connection_addr;
530         NDMC_ENDWITH
531
532         return 0;
533 }
534
535 int
536 ndmca_mover_connect (struct ndm_session *sess)
537 {
538         struct ndmconn *        conn = sess->plumb.tape;
539         struct ndm_control_agent *ca = &sess->control_acb;
540         int                     rc;
541
542         NDMC_WITH(ndmp9_mover_connect, NDMP9VER)
543                 request->mode = ca->mover_mode;
544                 request->addr = ca->data_addr;
545                 rc = NDMC_CALL(conn);
546         NDMC_ENDWITH
547
548         return rc;
549 }
550
551 int
552 ndmca_mover_continue (struct ndm_session *sess)
553 {
554         struct ndmconn *        conn = sess->plumb.tape;
555         int                     rc;
556
557         NDMC_WITH_VOID_REQUEST(ndmp9_mover_continue, NDMP9VER)
558                 rc = NDMC_CALL(conn);
559         NDMC_ENDWITH
560
561         return rc;
562 }
563
564 int
565 ndmca_mover_abort (struct ndm_session *sess)
566 {
567         struct ndmconn *        conn = sess->plumb.tape;
568         int                     rc;
569
570         NDMC_WITH_VOID_REQUEST(ndmp9_mover_abort, NDMP9VER)
571                 rc = NDMC_CALL(conn);
572         NDMC_ENDWITH
573
574         return rc;
575 }
576
577 int
578 ndmca_mover_stop (struct ndm_session *sess)
579 {
580         struct ndmconn *        conn = sess->plumb.tape;
581         int                     rc;
582
583         NDMC_WITH_VOID_REQUEST(ndmp9_mover_stop, NDMP9VER)
584                 rc = NDMC_CALL(conn);
585         NDMC_ENDWITH
586
587         return rc;
588 }
589
590 int
591 ndmca_mover_set_window (struct ndm_session *sess,
592   unsigned long long offset, unsigned long long length)
593 {
594         struct ndmconn *        conn = sess->plumb.tape;
595         int                     rc;
596
597         NDMC_WITH(ndmp9_mover_set_window, NDMP9VER)
598                 request->offset = offset;
599                 request->length = length;
600                 rc = NDMC_CALL(conn);
601         NDMC_ENDWITH
602
603         return rc;
604 }
605
606 int
607 ndmca_mover_read (struct ndm_session *sess,
608   unsigned long long offset, unsigned long long length)
609 {
610         struct ndmconn *        conn = sess->plumb.tape;
611         int                     rc;
612
613         NDMC_WITH(ndmp9_mover_read, NDMP9VER)
614                 request->offset = offset;
615                 request->length = length;
616                 rc = NDMC_CALL(conn);
617         NDMC_ENDWITH
618
619         return rc;
620 }
621
622 int
623 ndmca_mover_close (struct ndm_session *sess)
624 {
625         struct ndmconn *        conn = sess->plumb.tape;
626         int                     rc;
627
628         NDMC_WITH_VOID_REQUEST(ndmp9_mover_close, NDMP9VER)
629                 rc = NDMC_CALL(conn);
630         NDMC_ENDWITH
631
632         return rc;
633 }
634
635 int
636 ndmca_mover_set_record_size (struct ndm_session *sess)
637 {
638         struct ndmconn *        conn = sess->plumb.tape;
639         struct ndm_control_agent *ca = &sess->control_acb;
640         int                     rc;
641
642         NDMC_WITH(ndmp9_mover_set_record_size, NDMP9VER)
643                 request->record_size = ca->job.record_size;
644                 rc = NDMC_CALL(conn);
645         NDMC_ENDWITH
646
647         return rc;
648 }
649 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */