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