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 *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
ndmca_data_start_backup(struct ndm_session * sess)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
ndmca_data_start_recover(struct ndm_session * sess)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
ndmca_data_start_recover_filehist(struct ndm_session * sess)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
ndmca_data_abort(struct ndm_session * sess)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
ndmca_data_get_env(struct ndm_session * sess)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
ndmca_data_stop(struct ndm_session * sess)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
ndmca_tape_open(struct ndm_session * sess)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
ndmca_tape_close(struct ndm_session * sess)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
ndmca_tape_get_state(struct ndm_session * sess)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
ndmca_tape_get_state_no_tattle(struct ndm_session * sess)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
ndmca_tape_mtio(struct ndm_session * sess,ndmp9_tape_mtio_op op,u_long count,u_long * resid)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
ndmca_tape_write(struct ndm_session * sess,char * buf,unsigned count)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
ndmca_tape_read(struct ndm_session * sess,char * buf,unsigned count)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
ndmca_tape_read_partial(struct ndm_session * sess,char * buf,unsigned count,int * read_count)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
ndmca_mover_get_state(struct ndm_session * sess)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
ndmca_mover_listen(struct ndm_session * sess)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
ndmca_mover_connect(struct ndm_session * sess)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
ndmca_mover_continue(struct ndm_session * sess)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
ndmca_mover_abort(struct ndm_session * sess)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
ndmca_mover_stop(struct ndm_session * sess)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
ndmca_mover_set_window(struct ndm_session * sess,unsigned long long offset,unsigned long long length)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
ndmca_mover_read(struct ndm_session * sess,unsigned long long offset,unsigned long long length)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
ndmca_mover_close(struct ndm_session * sess)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
ndmca_mover_set_record_size(struct ndm_session * sess)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 */
650