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