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