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