2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
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.
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
34 * Think of ndma_dispatch_request() as a parser (like yacc(1) input).
35 * This parses (audits) the sequence of requests. If the requests
36 * conform to the "grammar", semantic actions are taken.
38 * This is, admittedly, a huge source file. The idea
39 * is to have all audits and associated errors here. This
40 * makes review, study, comparing to the specification, and
41 * discussion easier because we don't get balled up in
42 * the implementation of semantics. Further, with the hope
43 * of wide-scale deployment, revisions of this source file
44 * can readily be integrated into derivative works without
45 * disturbing other portions.
49 #include "ndmagents.h"
52 extern struct ndm_dispatch_version_table ndma_dispatch_version_table[];
54 static int connect_open_common (struct ndm_session *sess,
55 struct ndmp_xa_buf *xa,
56 struct ndmconn *ref_conn,
57 int protocol_version);
62 ndma_dispatch_request (struct ndm_session *sess,
63 struct ndmp_xa_buf *arg_xa, struct ndmconn *ref_conn)
65 struct ndm_dispatch_request_table *drt;
66 struct ndmp_xa_buf * xa = arg_xa;
67 struct ndmp_xa_buf xl_xa;
68 struct reqrep_xlate * rrxl = 0;
69 unsigned protocol_version = ref_conn->protocol_version;
70 unsigned msg = xa->request.header.message;
73 NDMOS_MACRO_ZEROFILL (&xa->reply);
75 xa->reply.protocol_version = xa->request.protocol_version;
76 xa->reply.flags |= NDMNMB_FLAG_NO_FREE;
78 xa->reply.header.sequence = 0; /* filled-in by xmit logic */
79 xa->reply.header.time_stamp = 0; /* filled-in by xmit logic */
80 xa->reply.header.message_type = NDMP0_MESSAGE_REPLY;
81 xa->reply.header.message = xa->request.header.message;
82 xa->reply.header.reply_sequence = xa->request.header.sequence;
83 xa->reply.header.error = NDMP0_NO_ERR;
86 ndmnmb_set_reply_error_raw (&xa->reply, NDMP0_NO_ERR);
88 switch ((int)msg & 0xFFFFFF00) {
89 case 0x0500: /* notify */
90 case 0x0600: /* log */
91 case 0x0700: /* file history */
92 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
97 if (xa->request.protocol_version != protocol_version) {
98 xa->reply.header.error = NDMP0_UNDEFINED_ERR;
103 * If the session is not open and the message
104 * is anything other than CONNECT_OPEN, the client
105 * has implicitly agreed to the protocol_version
106 * offered by NOTIFY_CONNECTED (ref ndmconn_accept()).
107 * Effectively perform CONNECT_OPEN for that
110 if (!sess->conn_open && msg != NDMP0_CONNECT_OPEN) {
111 connect_open_common (sess, xa, ref_conn,
112 ref_conn->protocol_version);
116 * Give the OS/implementation specific module a chance
117 * to intercept the request. Some requests are only implemented
118 * by the module. Some requests are reimplemented by the module
119 * when the standard implementation is inadequate to the app.
121 rc = ndmos_dispatch_request (sess, xa, ref_conn);
123 return rc; /* request intercepted */
127 * See if there is a standard, protocol_version specific
128 * dispatch function for the request.
130 drt = ndma_drt_lookup (ndma_dispatch_version_table,
131 protocol_version, msg);
138 * Find the protocol_version specific translation
139 * functions for this request/reply. The request
140 * is translated from its native version, NDMPvX,
141 * into NDMPv9. The NDMPv9 form is dispatched.
142 * The resulting reply is translated back to
146 rrxl = reqrep_xlate_lookup_version (reqrep_xlate_version_table,
149 /* find the protocol_version translation table */
152 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
156 /* find the interface's translation table entry */
157 rrxl = ndmp_reqrep_by_vx (rrxl, msg);
160 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
164 /* find the NDMPv9 dispatch table entry */
165 drt = ndma_drt_lookup (ndma_dispatch_version_table, NDMP9VER,
170 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
176 * Permission checks, always.
180 && !(drt->flags & NDM_DRT_FLAG_OK_NOT_CONNECTED)) {
181 xa->reply.header.error = NDMP0_PERMISSION_ERR;
185 if (!sess->conn_authorized
186 && !(drt->flags & NDM_DRT_FLAG_OK_NOT_AUTHORIZED)) {
187 xa->reply.header.error = NDMP0_NOT_AUTHORIZED_ERR;
192 * If there is a translation afoot, translate the request now.
196 NDMOS_MACRO_ZEROFILL (&xl_xa);
199 xa->request.header = arg_xa->request.header;
200 xa->request.header.message = rrxl->v9_message;
201 xa->request.protocol_version = NDMP9VER;
203 xa->reply.header = arg_xa->reply.header;
204 xa->reply.flags = arg_xa->reply.flags;
205 xa->reply.protocol_version = NDMP9VER;
207 rc = (*rrxl->request_xto9)(
208 (void*)&arg_xa->request.body,
209 (void*)&xa->request.body);
212 /* unrecoverable translation error */
214 xa->reply.header.error = NDMP0_UNDEFINED_ERR;
217 /* NB: rc>0 means that there were tolerated xlate errors */
219 /* allow reply to be freed */
220 xa->reply.flags &= ~NDMNMB_FLAG_NO_FREE;
223 rc = (*drt->dispatch_request)(sess, xa, ref_conn);
225 /* free up any memory allocated as part of the xto9 request */
227 (*rrxl->free_request_xto9)((void*)&xa->request.body);
230 /* unrecoverable dispatch error */
232 ndmnmb_free (&xa->reply); /* clean up partials */
235 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
240 rc = (*rrxl->reply_9tox)(
241 (void*)&xa->reply.body,
242 (void*)&arg_xa->reply.body);
244 /* free up any memory allocated as part of the 9tox reply */
246 (*rrxl->free_reply_9tox)((void*)&arg_xa->reply.body);
248 ndmnmb_free (&xa->reply); /* clean up */
253 /* unrecoverable translation error */
254 xa->reply.header.error = NDMP0_UNDEFINED_ERR;
257 /* NB: rc>0 means that there were tolerated xlate errors */
263 ndma_dispatch_raise_error (struct ndm_session *sess,
264 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
265 ndmp9_error error, char *errstr)
267 int protocol_version = ref_conn->protocol_version;
268 ndmp0_message msg = xa->request.header.message;
271 ndmalogf (sess, 0, 2, "op=%s err=%s why=%s",
272 ndmp_message_to_str (protocol_version, msg),
273 ndmp9_error_to_str (error),
277 ndmnmb_set_reply_error (&xa->reply, error);
286 * Access paths to ndma_dispatch_request()
287 ****************************************************************
290 /* incomming requests on a ndmconn connection */
292 ndma_dispatch_conn (struct ndm_session *sess, struct ndmconn *conn)
294 struct ndmp_xa_buf xa;
297 NDMOS_MACRO_ZEROFILL (&xa);
299 rc = ndmconn_recv_nmb (conn, &xa.request);
301 ndmnmb_free (&xa.request);
305 ndma_dispatch_request (sess, &xa, conn);
306 ndmnmb_free (&xa.request);
308 if (! (xa.reply.flags & NDMNMB_FLAG_NO_SEND)) {
309 rc = ndmconn_send_nmb (conn, &xa.reply);
313 ndmnmb_free (&xa.reply);
319 ndma_dispatch_ctrl_unexpected (struct ndmconn *conn, struct ndmp_msg_buf *nmb)
321 int protocol_version = conn->protocol_version;
322 struct ndm_session * sess = conn->context;
323 struct ndmp_xa_buf xa;
325 if (nmb->header.message_type != NDMP0_MESSAGE_REQUEST) {
326 ndmalogf (sess, conn->chan.name, 1,
327 "Unexpected message -- probably reply "
328 "w/ wrong reply_sequence");
330 /* causes crash, needs investigation */
331 ndmnmb_snoop (&sess->param.log, "WTF", 5,
332 nmb, conn->chan.name);
338 NDMOS_MACRO_ZEROFILL (&xa);
341 ndmalogf (sess, conn->chan.name, 4, "Async request %s",
342 ndmp_message_to_str (protocol_version,
343 xa.request.header.message));
345 ndma_dispatch_request (sess, &xa, conn);
347 if (! (xa.reply.flags & NDMNMB_FLAG_NO_SEND)) {
348 ndmconn_send_nmb (conn, &xa.reply);
351 ndmnmb_free (&xa.reply);
357 ndma_call_no_tattle (struct ndmconn *conn, struct ndmp_xa_buf *arg_xa)
359 struct ndmp_xa_buf * xa = arg_xa;
360 struct ndmp_xa_buf xl_xa;
361 struct reqrep_xlate * rrxl = 0;
362 unsigned protocol_version = conn->protocol_version;
363 unsigned msg = xa->request.header.message;
366 if (xa->request.protocol_version == NDMP9VER) {
369 * Find the protocol_version specific translation
370 * functions for this request/reply. The request
371 * is translated to its native version, NDMPvX,
372 * from NDMPv9. The NDMPvX form is transmitted.
373 * The resulting reply is translated back to NDMPv9.
374 * NDMPvX is determined by the connection.
377 rrxl = reqrep_xlate_lookup_version (reqrep_xlate_version_table,
380 /* find the protocol_version translation table */
383 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
384 rc = NDMCONN_CALL_STATUS_HDR_ERROR;
385 conn->last_header_error = xa->reply.header.error;
389 /* find the interface's translation table entry */
390 rrxl = ndmp_reqrep_by_v9 (rrxl, msg);
393 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
394 rc = NDMCONN_CALL_STATUS_HDR_ERROR;
395 conn->last_header_error = xa->reply.header.error;
399 NDMOS_MACRO_ZEROFILL (&xl_xa);
402 xa->request.header = arg_xa->request.header;
403 xa->request.header.message = rrxl->vx_message;
404 xa->request.protocol_version = protocol_version;
406 rc = (*rrxl->request_9tox)(
407 (void*)&arg_xa->request.body,
408 (void*)&xa->request.body);
411 /* unrecoverable translation error */
412 ndmnmb_free (&xa->request); /* clean up partials */
414 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
415 rc = NDMCONN_CALL_STATUS_HDR_ERROR;
416 conn->last_header_error = xa->reply.header.error;
419 /* NB: rc>0 means that there were tolerated xlate errors */
422 if (conn->conn_type == NDMCONN_TYPE_RESIDENT) {
423 struct ndm_session *sess = conn->context;
425 conn->last_message = xa->request.header.message;
426 conn->last_call_status = NDMCONN_CALL_STATUS_BOTCH;
427 conn->last_header_error = -1; /* invalid */
428 conn->last_reply_error = -1; /* invalid */
430 xa->request.header.sequence = conn->next_sequence++;
432 ndmconn_snoop_nmb (conn, &xa->request, "Send");
434 rc = ndma_dispatch_request (sess, xa, conn);
436 xa->reply.header.sequence = conn->next_sequence++;
438 if (! (xa->reply.flags & NDMNMB_FLAG_NO_SEND))
439 ndmconn_snoop_nmb (conn, &xa->reply, "Recv");
442 } else if (xa->reply.header.error != NDMP0_NO_ERR) {
443 rc = NDMCONN_CALL_STATUS_HDR_ERROR;
444 conn->last_header_error = xa->reply.header.error;
446 conn->last_header_error = NDMP9_NO_ERR;
447 conn->last_reply_error =
448 ndmnmb_get_reply_error (&xa->reply);
450 if (conn->last_reply_error == NDMP9_NO_ERR) {
451 rc = NDMCONN_CALL_STATUS_OK;
453 rc = NDMCONN_CALL_STATUS_REPLY_ERROR;
457 rc = ndmconn_call (conn, xa);
459 if ((conn->time_limit > 0) &&
460 (conn->received_time > conn->sent_time)) {
463 delta = conn->received_time - conn->sent_time;
464 if (delta > conn->time_limit)
465 rc = NDMCONN_CALL_STATUS_REPLY_LATE;
474 xrc = (*rrxl->reply_xto9)(
475 (void*)&xa->reply.body,
476 (void*)&arg_xa->reply.body);
478 ndmnmb_free (&xa->request); /* clean up */
479 ndmnmb_free (&xa->reply); /* clean up */
481 arg_xa->reply.header = xa->reply.header;
482 arg_xa->reply.flags = xa->reply.flags;
483 arg_xa->reply.protocol_version = NDMP9VER;
488 /* unrecoverable translation error */
489 xa->reply.header.error = NDMP0_UNDEFINED_ERR;
490 rc = NDMCONN_CALL_STATUS_HDR_ERROR;
491 conn->last_header_error = xa->reply.header.error;
494 /* NB: rc>0 means that there were tolerated xlate errors */
501 ndma_call (struct ndmconn *conn, struct ndmp_xa_buf *xa)
505 rc = ndma_call_no_tattle (conn, xa);
508 ndma_tattle (conn, xa, rc);
514 ndma_send_to_control (struct ndm_session *sess, struct ndmp_xa_buf *xa,
515 struct ndmconn *from_conn)
517 struct ndmconn * conn = sess->plumb.control;
520 if (conn->conn_type == NDMCONN_TYPE_RESIDENT && from_conn) {
522 * Control and sending agent are
523 * resident. Substitute the sending
524 * agents "connection" so that logs
525 * look right and right protocol_version
531 rc = ndma_call_no_tattle (conn, xa);
534 ndma_tattle (conn, xa, rc);
540 ndma_tattle (struct ndmconn *conn, struct ndmp_xa_buf *xa, int rc)
542 struct ndm_session *sess = conn->context;
543 int protocol_version = conn->protocol_version;
544 unsigned msg = xa->request.header.message;
545 char * tag = conn->chan.name;
546 char * msgname = ndmp_message_to_str (protocol_version, msg);
551 ndmalogf (sess, tag, 2, " ?OK %s", msgname);
554 case 1: /* no error in header, error in reply */
555 err = ndmnmb_get_reply_error_raw (&xa->reply);
556 ndmalogf (sess, tag, 2, " ERR %s %s",
558 ndmp_error_to_str (protocol_version, err));
561 case 2: /* no error in header or in reply, response late */
562 ndmalogf (sess, tag, 2, " REPLY LATE %s, took %d seconds",
564 (conn->received_time - conn->sent_time));
567 case -2: /* error in header, no reply body */
568 err = xa->reply.header.error;
569 ndmalogf (sess, tag, 2, " ERR-AGENT %s %s",
571 ndmp_error_to_str (protocol_version, err));
575 ndmalogf (sess, tag, 2, " ERR-CONN %s %s",
577 ndmconn_get_err_msg (conn));
588 * NDMPx_CONNECT Interfaces
589 ****************************************************************
596 * NDMP[0234]_CONNECT_OPEN
599 ndmp_sxa_connect_open (struct ndm_session *sess,
600 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
602 NDMS_WITH(ndmp0_connect_open)
603 if (sess->conn_open) {
604 if (request->protocol_version != ref_conn->protocol_version) {
605 NDMADR_RAISE_ILLEGAL_ARGS("too late to change version");
608 switch (request->protocol_version) {
609 #ifndef NDMOS_OPTION_NO_NDMP2
611 #endif /* !NDMOS_OPTION_NO_NDMP2 */
612 #ifndef NDMOS_OPTION_NO_NDMP3
614 #endif /* !NDMOS_OPTION_NO_NDMP3 */
615 #ifndef NDMOS_OPTION_NO_NDMP4
617 #endif /* !NDMOS_OPTION_NO_NDMP4 */
618 connect_open_common (sess, xa, ref_conn,
619 request->protocol_version);
623 NDMADR_RAISE_ILLEGAL_ARGS("unsupport protocol version");
633 connect_open_common (struct ndm_session *sess,
634 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
635 int protocol_version)
637 #ifndef NDMOS_OPTION_NO_DATA_AGENT
638 sess->data_acb.protocol_version = protocol_version;
639 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
640 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
641 sess->tape_acb.protocol_version = protocol_version;
642 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
643 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
644 sess->robot_acb.protocol_version = protocol_version;
645 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
647 ref_conn->protocol_version = protocol_version;
657 * NDMP[234]_CONNECT_CLIENT_AUTH
660 ndmp_sxa_connect_client_auth (struct ndm_session *sess,
661 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
663 ndmp9_auth_type auth_type;
667 NDMS_WITH(ndmp9_connect_client_auth)
669 auth_type = request->auth_data.auth_type;
672 NDMADR_RAISE_ILLEGAL_ARGS ("auth_type");
674 case NDMP9_AUTH_TEXT:
678 p = &request->auth_data.ndmp9_auth_data_u.auth_text;
680 proof = p->auth_password;
681 if (!ndmos_ok_name_password (sess, name, proof)) {
682 NDMADR_RAISE(NDMP9_NOT_AUTHORIZED_ERR,
692 p = &request->auth_data.ndmp9_auth_data_u.auth_md5;
694 proof = p->auth_digest;
696 if (!sess->md5_challenge_valid) {
697 NDMADR_RAISE(NDMP9_NOT_AUTHORIZED_ERR,
701 if (!ndmos_ok_name_md5_digest (sess, name, proof)) {
702 NDMADR_RAISE(NDMP9_NOT_AUTHORIZED_ERR,
708 sess->conn_authorized = 1;
718 * NDMP[023]_CONNECT_CLOSE
721 ndmp_sxa_connect_close (struct ndm_session *sess,
722 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
724 xa->reply.flags |= NDMNMB_FLAG_NO_SEND; /* ??? */
726 /* TODO: shutdown everything */
727 sess->connect_status = 0;
728 ndmchan_set_eof (&ref_conn->chan);
737 * NDMP[23]_CONNECT_SERVER_AUTH
740 ndmp_sxa_connect_server_auth (struct ndm_session *sess,
741 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
743 return NDMADR_UNIMPLEMENTED_MESSAGE;
750 * NDMPx_CONFIG Interfaces
751 ****************************************************************
758 * NDMP[234]_CONFIG_GET_HOST_INFO
759 * NDMP[34]_CONFIG_GET_SERVER_INFO
760 * NDMP2_CONFIG_GET_MOVER_TYPE
761 * NDMP[34]_CONFIG_GET_CONNECTION_TYPE
762 * NDMP[34]_CONFIG_GET_BUTYPE_INFO
763 * NDMP[34]_CONFIG_GET_FS_INFO
764 * NDMP[34]_CONFIG_GET_TAPE_INFO
765 * NDMP[34]_CONFIG_GET_SCSI_INFO
768 ndmp_sxa_config_get_info (struct ndm_session *sess,
769 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
771 NDMS_WITH_VOID_REQUEST(ndmp9_config_get_info)
772 ndmos_sync_config_info (sess);
774 if (sess->config_info.conntypes == 0) {
775 /* OS left it for us to do */
776 #ifndef NDMOS_OPTION_NO_DATA_AGENT
777 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
778 sess->config_info.conntypes |= NDMP9_CONFIG_CONNTYPE_LOCAL;
779 sess->config_info.conntypes |= NDMP9_CONFIG_CONNTYPE_TCP;
780 #else /* !NDMOS_OPTION_NO_TAPE_AGENT */
781 sess->config_info.conntypes |= NDMP9_CONFIG_CONNTYPE_TCP;
782 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
783 #else /* !NDMOS_OPTION_NO_DATA_AGENT */
784 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
785 sess->config_info.conntypes |= NDMP9_CONFIG_CONNTYPE_TCP;
786 #else /* !NDMOS_OPTION_NO_TAPE_AGENT */
787 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
788 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
791 if (sess->config_info.authtypes == 0) {
792 /* OS left it for us to do */
793 sess->config_info.authtypes |= NDMP9_CONFIG_AUTHTYPE_TEXT;
794 sess->config_info.authtypes |= NDMP9_CONFIG_AUTHTYPE_MD5;
797 reply->config_info = sess->config_info;
806 #ifndef NDMOS_OPTION_NO_NDMP2
808 * NDMP2_CONFIG_GET_BUTYPE_ATTR
811 ndmp2_sxa_config_get_butype_attr (struct ndm_session *sess,
812 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
814 ndmp9_config_info * ci = &sess->config_info;
815 ndmp9_butype_info * bu = 0;
818 assert (xa->request.protocol_version == NDMP2VER);
820 NDMS_WITH(ndmp2_config_get_butype_attr)
821 ndmos_sync_config_info (sess);
823 for (i = 0; i < ci->butype_info.butype_info_len; i++) {
824 bu = &ci->butype_info.butype_info_val[i];
826 if (strcmp (request->name, bu->butype_name) == 0) {
831 if (i >= ci->butype_info.butype_info_len) {
832 NDMADR_RAISE_ILLEGAL_ARGS("butype");
835 reply->attrs = bu->v2attr.value;
840 #endif /* !NDMOS_OPTION_NO_NDMP2 */
846 * NDMP[234]_CONFIG_GET_AUTH_ATTR
848 * Credits to Rajiv of NetApp for helping with MD5 stuff.
851 ndmp_sxa_config_get_auth_attr (struct ndm_session *sess,
852 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
854 NDMS_WITH(ndmp9_config_get_auth_attr)
855 switch (request->auth_type) {
857 NDMADR_RAISE_ILLEGAL_ARGS ("auth_type");
859 case NDMP9_AUTH_NONE:
862 case NDMP9_AUTH_TEXT:
866 ndmos_get_md5_challenge (sess);
867 NDMOS_API_BCOPY (sess->md5_challenge,
868 reply->server_attr.ndmp9_auth_attr_u.challenge, 64);
871 reply->server_attr.auth_type = request->auth_type;
880 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT /* Surrounds SCSI intfs */
882 * NDMPx_SCSI Interfaces
883 ****************************************************************
885 * If these are implemented, they should already have been
886 * intercepted by ndmos_dispatch_request(). There is absolutely
887 * no way to implement this generically, nor is there merit to
890 * Still, just in case, they are implemented here.
893 static ndmp9_error scsi_open_ok (struct ndm_session *sess);
894 static ndmp9_error scsi_op_ok (struct ndm_session *sess);
900 * NDMP[234]_SCSI_OPEN
903 ndmp_sxa_scsi_open (struct ndm_session *sess,
904 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
908 NDMS_WITH(ndmp9_scsi_open)
909 error = scsi_open_ok (sess);
910 if (error != NDMP9_NO_ERR) {
911 NDMADR_RAISE(error, "!scsi_open_ok");
914 error = ndmos_scsi_open (sess, request->device);
915 if (error != NDMP9_NO_ERR) {
916 NDMADR_RAISE(error, "scsi_open");
927 * NDMP[234]_SCSI_CLOSE
930 ndmp_sxa_scsi_close (struct ndm_session *sess,
931 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
935 NDMS_WITH_VOID_REQUEST(ndmp9_scsi_close)
936 error = scsi_op_ok (sess);
937 if (error != NDMP9_NO_ERR) {
938 NDMADR_RAISE(error, "!scsi_op_ok");
941 error = ndmos_scsi_close (sess);
942 if (error != NDMP9_NO_ERR) {
943 NDMADR_RAISE(error, "scsi_close");
954 * NDMP[234]_SCSI_GET_STATE
957 ndmp_sxa_scsi_get_state (struct ndm_session *sess,
958 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
960 struct ndm_robot_agent *ra = &sess->robot_acb;
962 NDMS_WITH_VOID_REQUEST(ndmp9_scsi_get_state)
963 ndmos_scsi_sync_state (sess);
965 *reply = ra->scsi_state;
975 * NDMP[23]_SCSI_SET_TARGET
978 ndmp_sxa_scsi_set_target (struct ndm_session *sess,
979 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
983 NDMS_WITH(ndmp9_scsi_set_target)
984 error = scsi_op_ok (sess);
985 if (error != NDMP9_NO_ERR) {
986 NDMADR_RAISE(error, "!scsi_op_ok");
989 error = ndmos_scsi_set_target (sess);
990 if (error != NDMP9_NO_ERR) {
991 NDMADR_RAISE(error, "scsi_set_target");
1002 * NDMP[234]_SCSI_RESET_DEVICE
1005 ndmp_sxa_scsi_reset_device (struct ndm_session *sess,
1006 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1010 NDMS_WITH_VOID_REQUEST(ndmp9_scsi_reset_device)
1011 error = scsi_op_ok (sess);
1012 if (error != NDMP9_NO_ERR) {
1013 NDMADR_RAISE(error, "!scsi_op_ok");
1016 error = ndmos_scsi_reset_device (sess);
1017 if (error != NDMP9_NO_ERR) {
1018 NDMADR_RAISE(error, "scsi_reset_device");
1029 * NDMP[23]_SCSI_RESET_BUS
1032 ndmp_sxa_scsi_reset_bus (struct ndm_session *sess,
1033 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1037 NDMS_WITH_VOID_REQUEST(ndmp9_scsi_reset_bus)
1038 error = scsi_op_ok (sess);
1039 if (error != NDMP9_NO_ERR) {
1040 NDMADR_RAISE(error, "!scsi_op_ok");
1043 error = ndmos_scsi_reset_bus (sess);
1044 if (error != NDMP9_NO_ERR) {
1045 NDMADR_RAISE(error, "scsi_reset_bus");
1056 * NDMP[234]_SCSI_EXECUTE_CDB
1059 ndmp_sxa_scsi_execute_cdb (struct ndm_session *sess,
1060 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1064 NDMS_WITH(ndmp9_scsi_execute_cdb)
1065 error = scsi_op_ok (sess);
1066 if (error != NDMP9_NO_ERR) {
1067 NDMADR_RAISE(error, "!scsi_op_ok");
1070 error = ndmos_scsi_execute_cdb (sess, request, reply);
1071 if (error != NDMP9_NO_ERR) {
1072 NDMADR_RAISE(error, "scsi_execute_cdb");
1083 * NDMPx_SCSI helper routines
1087 scsi_open_ok (struct ndm_session *sess)
1089 struct ndm_robot_agent * ra = &sess->robot_acb;
1091 ndmos_scsi_sync_state(sess);
1092 if (ra->scsi_state.error != NDMP9_DEV_NOT_OPEN_ERR)
1093 return NDMP9_DEVICE_OPENED_ERR;
1095 #ifndef NDMOS_OPTION_ALLOW_SCSI_AND_TAPE_BOTH_OPEN
1096 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
1097 ndmos_tape_sync_state(sess);
1098 if (sess->tape_acb.tape_state.error != NDMP9_DEV_NOT_OPEN_ERR)
1099 return NDMP9_DEVICE_OPENED_ERR;
1100 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
1101 #endif /* NDMOS_OPTION_ALLOW_SCSI_AND_TAPE_BOTH_OPEN */
1103 return NDMP9_NO_ERR;
1107 scsi_op_ok (struct ndm_session *sess)
1109 struct ndm_robot_agent * ra = &sess->robot_acb;
1111 ndmos_scsi_sync_state(sess);
1112 if (ra->scsi_state.error != NDMP9_NO_ERR)
1113 return NDMP9_DEV_NOT_OPEN_ERR;
1115 return NDMP9_NO_ERR;
1117 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */ /* Surrounds SCSI intfs */
1122 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds TAPE intfs */
1124 * NDMPx_TAPE Interfaces
1125 ****************************************************************
1127 static ndmp9_error tape_open_ok (struct ndm_session *sess,
1129 static ndmp9_error tape_op_ok (struct ndm_session *sess,
1136 * NDMP[234]_TAPE_OPEN
1139 ndmp_sxa_tape_open (struct ndm_session *sess,
1140 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1145 NDMS_WITH(ndmp9_tape_open)
1146 switch (request->mode) {
1148 NDMADR_RAISE_ILLEGAL_ARGS("tape_mode");
1150 case NDMP9_TAPE_READ_MODE:
1154 case NDMP9_TAPE_RDWR_MODE:
1155 case NDMP9_TAPE_RAW_MODE:
1160 error = tape_open_ok (sess, will_write);
1161 if (error != NDMP9_NO_ERR) {
1162 NDMADR_RAISE(error, "!tape_open_ok");
1165 error = ndmos_tape_open (sess, request->device, will_write);
1166 if (error != NDMP9_NO_ERR) {
1167 NDMADR_RAISE(error, "tape_open");
1178 * NDMP[234]_TAPE_CLOSE
1181 ndmp_sxa_tape_close (struct ndm_session *sess,
1182 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1186 NDMS_WITH_VOID_REQUEST(ndmp9_tape_close)
1187 error = tape_op_ok (sess, 0);
1188 if (error != NDMP9_NO_ERR) {
1189 NDMADR_RAISE(error, "!tape_op_ok");
1192 error = ndmos_tape_close (sess);
1193 if (error != NDMP9_NO_ERR) {
1194 NDMADR_RAISE(error, "tape_close");
1205 * NDMP[234]_TAPE_GET_STATE
1208 ndmp_sxa_tape_get_state (struct ndm_session *sess,
1209 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1211 struct ndm_tape_agent * ta = &sess->tape_acb;
1213 NDMS_WITH_VOID_REQUEST(ndmp9_tape_get_state)
1215 ndmos_tape_sync_state(sess);
1217 *reply = ta->tape_state;
1227 * NDMP[234]_TAPE_MTIO
1230 ndmp_sxa_tape_mtio (struct ndm_session *sess,
1231 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1234 ndmp9_tape_mtio_op tape_op;
1236 unsigned long resid = 0;
1238 NDMS_WITH(ndmp9_tape_mtio)
1240 switch (request->tape_op) {
1242 NDMADR_RAISE_ILLEGAL_ARGS("tape_op");
1244 case NDMP2_MTIO_EOF:
1246 tape_op = NDMP9_MTIO_EOF;
1249 case NDMP9_MTIO_FSF:
1250 case NDMP9_MTIO_BSF:
1251 case NDMP9_MTIO_FSR:
1252 case NDMP9_MTIO_BSR:
1253 case NDMP9_MTIO_REW:
1254 case NDMP9_MTIO_OFF:
1255 tape_op = request->tape_op;
1259 error = tape_op_ok (sess, will_write);
1260 if (error != NDMP9_NO_ERR) {
1261 NDMADR_RAISE(error, "!tape_op_ok");
1264 error = ndmos_tape_mtio (sess, tape_op, request->count, &resid);
1266 reply->error = error;
1267 reply->resid_count = resid;
1277 * NDMP[234]_TAPE_WRITE
1280 ndmp_sxa_tape_write (struct ndm_session *sess,
1281 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1284 unsigned long done_count = 0;
1286 NDMS_WITH(ndmp9_tape_write)
1287 if (request->data_out.data_out_len == 0) {
1289 * NDMPv4 clarification -- a tape read or write with
1290 * a count==0 is a no-op. This is undoubtedly influenced
1291 * by the SCSI Sequential Access specification which
1292 * says much the same thing.
1294 * NDMPv[23] MAY return NDMP_NO_ERR or
1295 * NDMP_ILLEGAL_ARGS_ERR.
1297 reply->error = NDMP9_NO_ERR;
1303 if (!NDMOS_MACRO_OK_TAPE_REC_LEN(request->data_out.data_out_len)) {
1304 NDMADR_RAISE_ILLEGAL_ARGS("!ok_tape_rec_len");
1307 error = tape_op_ok (sess, 1);
1308 if (error != NDMP9_NO_ERR) {
1309 NDMADR_RAISE(error, "!tape_op_ok");
1312 error = ndmos_tape_write (sess, request->data_out.data_out_val,
1313 request->data_out.data_out_len,
1315 reply->error = error;
1316 reply->count = done_count;
1326 * NDMP[234]_TAPE_READ
1329 ndmp_sxa_tape_read (struct ndm_session *sess,
1330 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1332 struct ndm_tape_agent * ta = &sess->tape_acb;
1334 unsigned long done_count = 0;
1336 NDMS_WITH(ndmp9_tape_read)
1337 if (request->count == 0) {
1339 * NDMPv4 clarification -- a tape read or write with
1340 * a count==0 is a no-op. This is undoubtedly influenced
1341 * by the SCSI Sequential Access specification which
1342 * says much the same thing.
1344 * NDMPv[23] MAY return NDMP_NO_ERR or
1345 * NDMP_ILLEGAL_ARGS_ERR.
1347 reply->error = NDMP9_NO_ERR;
1348 reply->data_in.data_in_val = ta->tape_buffer;
1349 reply->data_in.data_in_len = 0;
1354 if (!NDMOS_MACRO_OK_TAPE_REC_LEN(request->count)) {
1355 NDMADR_RAISE_ILLEGAL_ARGS("!ok_tape_rec_len");
1358 error = tape_op_ok (sess, 0);
1359 if (error != NDMP9_NO_ERR) {
1360 NDMADR_RAISE(error, "!tape_op_ok");
1363 error = ndmos_tape_read (sess, ta->tape_buffer,
1366 reply->error = error;
1367 reply->data_in.data_in_val = ta->tape_buffer;
1368 reply->data_in.data_in_len = done_count;
1378 * NDMP[234]_TAPE_EXECUTE_CDB
1380 * If this is implemented, it should already have been
1381 * intercepted by ndmos_dispatch_request().
1382 * There is absolutely no way to implement this generically,
1383 * nor is there merit to a generic "layer".
1384 * Still, just in case, it is implemented here.
1387 ndmp_sxa_tape_execute_cdb (struct ndm_session *sess,
1388 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1390 NDMS_WITH(ndmp9_tape_execute_cdb)
1391 return NDMADR_UNIMPLEMENTED_MESSAGE;
1399 * NDMPx_TAPE helper routines
1403 tape_open_ok (struct ndm_session *sess, int will_write)
1405 struct ndm_tape_agent * ta = &sess->tape_acb;
1407 ndmos_tape_sync_state(sess);
1408 if (ta->tape_state.state != NDMP9_TAPE_STATE_IDLE)
1409 return NDMP9_DEVICE_OPENED_ERR;
1411 #ifndef NDMOS_OPTION_ALLOW_SCSI_AND_TAPE_BOTH_OPEN
1412 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
1413 ndmos_scsi_sync_state(sess);
1414 if (sess->robot_acb.scsi_state.error != NDMP9_DEV_NOT_OPEN_ERR)
1415 return NDMP9_DEVICE_OPENED_ERR;
1416 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
1417 #endif /* NDMOS_OPTION_ALLOW_SCSI_AND_TAPE_BOTH_OPEN */
1419 return NDMP9_NO_ERR;
1423 * Tape operation is only OK if it is open and the MOVER
1424 * hasn't got a hold of it. We can't allow tape operations
1425 * to interfere with the MOVER.
1429 tape_op_ok (struct ndm_session *sess, int will_write)
1431 struct ndm_tape_agent * ta = &sess->tape_acb;
1433 ndmos_tape_sync_state(sess);
1434 switch (ta->tape_state.state) {
1435 case NDMP9_TAPE_STATE_IDLE:
1436 return NDMP9_DEV_NOT_OPEN_ERR;
1438 case NDMP9_TAPE_STATE_OPEN:
1439 if (will_write && !NDMTA_TAPE_IS_WRITABLE(ta))
1440 return NDMP9_PERMISSION_ERR;
1443 case NDMP9_TAPE_STATE_MOVER:
1444 return NDMP9_ILLEGAL_STATE_ERR;
1447 return NDMP9_NO_ERR;
1449 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds TAPE intfs */
1454 #ifndef NDMOS_OPTION_NO_DATA_AGENT /* Surrounds DATA intfs */
1456 * NDMPx_DATA Interfaces
1457 ****************************************************************
1460 static int data_ok_bu_type (struct ndm_session *sess,
1461 struct ndmp_xa_buf *xa,
1462 struct ndmconn *ref_conn,
1465 static int data_can_connect_and_start (struct ndm_session *sess,
1466 struct ndmp_xa_buf *xa,
1467 struct ndmconn *ref_conn,
1468 ndmp9_addr *data_addr,
1469 ndmp9_mover_mode mover_mode);
1471 static int data_can_connect (struct ndm_session *sess,
1472 struct ndmp_xa_buf *xa,
1473 struct ndmconn *ref_conn,
1474 ndmp9_addr *data_addr);
1476 static int data_can_start (struct ndm_session *sess,
1477 struct ndmp_xa_buf *xa,
1478 struct ndmconn *ref_conn,
1479 ndmp9_mover_mode mover_mode);
1481 static int data_connect (struct ndm_session *sess,
1482 struct ndmp_xa_buf *xa,
1483 struct ndmconn *ref_conn,
1484 ndmp9_addr *data_addr);
1486 static ndmp9_error data_copy_environment (struct ndm_session *sess,
1487 ndmp9_pval *env, unsigned n_env);
1489 static ndmp9_error data_copy_nlist (struct ndm_session *sess,
1490 ndmp9_name *nlist, unsigned n_nlist);
1497 * NDMP[234]_DATA_GET_STATE
1500 ndmp_sxa_data_get_state (struct ndm_session *sess,
1501 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1503 struct ndm_data_agent * da = &sess->data_acb;
1505 NDMS_WITH_VOID_REQUEST(ndmp9_data_get_state)
1506 *reply = da->data_state;
1516 * NDMP[234]_DATA_START_BACKUP
1519 ndmp_sxa_data_start_backup (struct ndm_session *sess,
1520 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1525 NDMS_WITH(ndmp9_data_start_backup)
1526 rc = data_ok_bu_type (sess, xa, ref_conn, request->bu_type);
1531 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1532 rc = data_can_connect_and_start (sess, xa, ref_conn,
1533 &request->addr, NDMP9_MOVER_MODE_READ);
1535 rc = data_can_start (sess, xa, ref_conn,
1536 NDMP9_MOVER_MODE_READ);
1539 return rc; /* already tattled */
1542 strcpy (sess->data_acb.bu_type, request->bu_type);
1544 error = data_copy_environment (sess,
1545 request->env.env_val, request->env.env_len);
1546 if (error != NDMP9_NO_ERR) {
1548 NDMADR_RAISE(error, "copy-env");
1551 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1552 rc = data_connect (sess, xa, ref_conn, &request->addr);
1555 return rc; /* already tattled */
1559 error = ndmda_data_start_backup (sess);
1560 if (error != NDMP9_NO_ERR) {
1561 /* TODO: undo everything */
1563 NDMADR_RAISE(error, "start_backup");
1574 * NDMP[234]_DATA_START_RECOVER
1577 ndmp_sxa_data_start_recover (struct ndm_session *sess,
1578 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1583 NDMS_WITH(ndmp9_data_start_recover)
1584 rc = data_ok_bu_type (sess, xa, ref_conn, request->bu_type);
1589 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1590 rc = data_can_connect_and_start (sess, xa, ref_conn,
1591 &request->addr, NDMP9_MOVER_MODE_WRITE);
1593 rc = data_can_start (sess, xa, ref_conn,
1594 NDMP9_MOVER_MODE_WRITE);
1597 return rc; /* already tattled */
1600 strcpy (sess->data_acb.bu_type, request->bu_type);
1602 error = data_copy_environment (sess,
1603 request->env.env_val, request->env.env_len);
1604 if (error != NDMP9_NO_ERR) {
1606 NDMADR_RAISE(error, "copy-env");
1609 error = data_copy_nlist (sess,
1610 request->nlist.nlist_val, request->nlist.nlist_len);
1612 if (error != NDMP9_NO_ERR) {
1614 NDMADR_RAISE(error, "copy-nlist");
1617 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1618 rc = data_connect (sess, xa, ref_conn, &request->addr);
1621 return rc; /* already tattled */
1625 error = ndmda_data_start_recover (sess);
1626 if (error != NDMP9_NO_ERR) {
1627 /* TODO: undo everything */
1629 NDMADR_RAISE(error, "start_recover");
1640 * NDMP[234]_DATA_ABORT
1643 ndmp_sxa_data_abort (struct ndm_session *sess,
1644 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1646 struct ndm_data_agent * da = &sess->data_acb;
1648 NDMS_WITH_VOID_REQUEST(ndmp9_data_abort)
1649 if (da->data_state.state != NDMP9_DATA_STATE_ACTIVE)
1650 NDMADR_RAISE_ILLEGAL_STATE("data_state !ACTIVE");
1652 ndmda_data_abort (sess);
1662 * NDMP[234]_DATA_GET_ENV
1665 ndmp_sxa_data_get_env (struct ndm_session *sess,
1666 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1668 struct ndm_data_agent * da = &sess->data_acb;
1670 NDMS_WITH_VOID_REQUEST(ndmp9_data_get_env)
1671 if (da->data_state.state == NDMP9_DATA_STATE_IDLE) {
1672 NDMADR_RAISE_ILLEGAL_STATE("data_state IDLE");
1674 if (da->data_state.operation != NDMP9_DATA_OP_BACKUP) {
1675 NDMADR_RAISE_ILLEGAL_STATE("data_op !BACKUP");
1678 ndmda_sync_environment (sess);
1680 ndmalogf (sess, ref_conn->chan.name, 6, "n_env=%d", da->env_tab.n_env);
1682 reply->env.env_len = da->env_tab.n_env;
1683 reply->env.env_val = da->env_tab.env;
1686 xa->reply.flags &= ~NDMNMB_FLAG_NO_FREE; /* free env after xmit */
1697 * NDMP[234]_DATA_STOP
1700 ndmp_sxa_data_stop (struct ndm_session *sess,
1701 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1703 struct ndm_data_agent * da = &sess->data_acb;
1705 NDMS_WITH_VOID_REQUEST(ndmp2_data_stop)
1706 if (da->data_state.state != NDMP9_DATA_STATE_HALTED) {
1707 NDMADR_RAISE_ILLEGAL_STATE("data_state !HALTED");
1710 ndmda_data_stop (sess);
1720 * NDMP[234]_DATA_START_RECOVER_FILEHIST
1721 * This is a Traakan extension to NDMPv2 and NDMPv3
1722 * Adopted for NDMPv4
1725 ndmp_sxa_data_start_recover_filehist (struct ndm_session *sess,
1726 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1731 NDMS_WITH(ndmp9_data_start_recover)
1732 rc = data_ok_bu_type (sess, xa, ref_conn, request->bu_type);
1737 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1738 rc = data_can_connect_and_start (sess, xa, ref_conn,
1739 &request->addr, NDMP9_MOVER_MODE_WRITE);
1741 rc = data_can_start (sess, xa, ref_conn,
1742 NDMP9_MOVER_MODE_WRITE);
1745 return rc; /* already tattled */
1748 strcpy (sess->data_acb.bu_type, request->bu_type);
1750 error = data_copy_environment (sess,
1751 request->env.env_val, request->env.env_len);
1752 if (error != NDMP9_NO_ERR) {
1754 NDMADR_RAISE(error, "copy-env");
1757 error = data_copy_nlist (sess,
1758 request->nlist.nlist_val, request->nlist.nlist_len);
1760 if (error != NDMP9_NO_ERR) {
1762 NDMADR_RAISE(error, "copy-nlist");
1765 if (request->addr.addr_type != NDMP9_ADDR_AS_CONNECTED) {
1766 rc = data_connect (sess, xa, ref_conn, &request->addr);
1769 return rc; /* already tattled */
1773 error = ndmda_data_start_recover_fh (sess);
1774 if (error != NDMP9_NO_ERR) {
1775 /* TODO: undo everything */
1777 NDMADR_RAISE(error, "start_recover_filehist");
1785 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 /* Surrounds NDMPv[34] DATA intfs */
1787 * NDMP[34]_DATA_CONNECT
1790 ndmp_sxa_data_connect (struct ndm_session *sess,
1791 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1794 NDMS_WITH(ndmp9_data_connect)
1795 return data_connect (sess, xa, ref_conn, &request->addr);
1803 static int data_listen_common34 (struct ndm_session *sess,
1804 struct ndmp_xa_buf *xa,
1805 struct ndmconn *ref_conn,
1806 ndmp9_addr_type addr_type);
1809 * NDMP[34]_DATA_LISTEN
1812 ndmadr_data_listen (struct ndm_session *sess,
1813 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
1815 struct ndm_data_agent * da = &sess->data_acb;
1818 switch (xa->request.protocol_version) {
1819 default: return NDMADR_UNIMPLEMENTED_VERSION; /* should never happen */
1821 #ifndef NDMOS_OPTION_NO_NDMP2
1823 /* not part of NDMPv2 */
1824 return NDMADR_UNSPECIFIED_MESSAGE;
1825 #endif /* !NDMOS_OPTION_NO_NDMP2 */
1827 #ifndef NDMOS_OPTION_NO_NDMP3
1829 NDMS_WITH(ndmp3_data_listen)
1830 ndmp9_addr_type addr_type;
1832 /* Check args, map along the way */
1833 switch (request->addr_type) {
1834 default: addr_type = -1; break;
1835 case NDMP3_ADDR_LOCAL: addr_type = NDMP9_ADDR_LOCAL; break;
1836 case NDMP3_ADDR_TCP: addr_type = NDMP9_ADDR_TCP; break;
1839 rc = data_listen_common34 (sess, xa, ref_conn, addr_type);
1841 return rc; /* something went wrong */
1843 ndmp_9to3_addr (&da->data_state.data_connection_addr,
1844 &reply->data_connection_addr);
1845 /* reply->error already set to NDMPx_NO_ERROR */
1848 #endif /* !NDMOS_OPTION_NO_NDMP3 */
1850 #ifndef NDMOS_OPTION_NO_NDMP4
1852 NDMS_WITH(ndmp4_data_listen)
1853 ndmp9_addr_type addr_type;
1855 /* Check args, map along the way */
1856 switch (request->addr_type) {
1857 default: addr_type = -1; break;
1858 case NDMP4_ADDR_LOCAL: addr_type = NDMP9_ADDR_LOCAL; break;
1859 case NDMP4_ADDR_TCP: addr_type = NDMP9_ADDR_TCP; break;
1862 rc = data_listen_common34 (sess, xa, ref_conn, addr_type);
1864 return rc; /* something went wrong */
1866 ndmp_9to4_addr (&da->data_state.data_connection_addr,
1867 &reply->data_connection_addr);
1868 /* reply->error already set to NDMPx_NO_ERROR */
1871 #endif /* !NDMOS_OPTION_NO_NDMP4 */
1876 /* this same intf is expected in v4, so _common() now */
1878 data_listen_common34 (struct ndm_session *sess,
1879 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
1880 ndmp9_addr_type addr_type)
1882 struct ndm_data_agent * da = &sess->data_acb;
1883 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
1884 struct ndm_tape_agent * ta = &sess->tape_acb;
1885 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
1891 switch (addr_type) {
1892 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_addr_type");
1893 case NDMP9_ADDR_LOCAL:
1894 #ifdef NDMOS_OPTION_NO_TAPE_AGENT
1895 NDMADR_RAISE_ILLEGAL_ARGS("data LOCAL w/o local TAPE agent");
1896 #endif /* NDMOS_OPTION_NO_TAPE_AGENT */
1899 case NDMP9_ADDR_TCP:
1903 /* Check states -- this should cover everything */
1904 if (da->data_state.state != NDMP9_DATA_STATE_IDLE)
1905 NDMADR_RAISE_ILLEGAL_STATE("data_state !IDLE");
1906 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
1907 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE)
1908 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
1909 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
1912 * Check image stream state -- should already be reflected
1913 * in the mover and data states. This extra check gives
1914 * us an extra measure of robustness and sanity
1915 * check on the implementation.
1917 error = ndmis_audit_data_listen (sess, addr_type, reason);
1918 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
1920 error = ndmis_data_listen (sess, addr_type,
1921 &da->data_state.data_connection_addr,
1923 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
1925 error = ndmda_data_listen(sess);
1926 if (error != NDMP9_NO_ERR) {
1927 /* TODO: belay ndmis_data_listen() */
1928 NDMADR_RAISE(error, "!data_listen");
1935 #endif /* !NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 Surrounds NDMPv[34] DATA intfs */
1941 * NDMPx_DATA helper routines
1946 data_ok_bu_type (struct ndm_session *sess,
1947 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
1950 ndmp9_config_info * ci = &sess->config_info;
1951 ndmp9_butype_info * bu;
1954 ndmos_sync_config_info (sess);
1956 for (i = 0; i < ci->butype_info.butype_info_len; i++) {
1957 bu = &ci->butype_info.butype_info_val[i];
1959 if (strcmp (bu_type, bu->butype_name) == 0) {
1964 NDMADR_RAISE_ILLEGAL_ARGS ("bu_type");
1969 * Data can only start if the mover is ready.
1970 * Just mode and state checks.
1974 data_can_connect_and_start (struct ndm_session *sess,
1975 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
1976 ndmp9_addr *data_addr,
1977 ndmp9_mover_mode mover_mode)
1982 switch (mover_mode) {
1983 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_mode");
1984 case NDMP9_MOVER_MODE_READ: /* aka BACKUP */
1985 case NDMP9_MOVER_MODE_WRITE: /* aka RECOVER */
1989 rc = data_can_connect (sess, xa, ref_conn, data_addr);
1992 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
1993 if (data_addr->addr_type == NDMP9_ADDR_LOCAL) {
1994 struct ndm_tape_agent * ta = &sess->tape_acb;
1995 ndmp9_mover_get_state_reply * ms = &ta->mover_state;
1997 if (ms->mode != mover_mode)
1998 NDMADR_RAISE_ILLEGAL_STATE("mover_mode mismatch");
2000 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
2006 data_can_connect (struct ndm_session *sess,
2007 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
2008 ndmp9_addr *data_addr)
2010 struct ndm_data_agent * da = &sess->data_acb;
2011 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
2012 struct ndm_tape_agent * ta = &sess->tape_acb;
2013 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
2018 switch (data_addr->addr_type) {
2019 default: NDMADR_RAISE_ILLEGAL_ARGS("addr_type");
2020 case NDMP9_ADDR_LOCAL:
2021 #ifdef NDMOS_OPTION_NO_TAPE_AGENT
2022 NDMADR_RAISE_ILLEGAL_ARGS("mover LOCAL w/o local DATA agent");
2023 #endif /* NDMOS_OPTION_NO_TAPE_AGENT */
2026 case NDMP9_ADDR_TCP:
2030 /* Check states -- this should cover everything */
2031 if (da->data_state.state != NDMP9_DATA_STATE_IDLE)
2032 NDMADR_RAISE_ILLEGAL_STATE("data_state !IDLE");
2034 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
2035 if (data_addr->addr_type == NDMP9_ADDR_LOCAL) {
2036 ndmp9_mover_get_state_reply *ms = &ta->mover_state;
2038 if (ms->state != NDMP9_MOVER_STATE_LISTEN)
2039 NDMADR_RAISE_ILLEGAL_STATE("mover_state !LISTEN");
2041 if (ms->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL)
2042 NDMADR_RAISE_ILLEGAL_STATE("mover_addr !LOCAL");
2045 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE)
2046 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2048 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
2051 * Check image stream state -- should already be reflected
2052 * in the mover and data states. This extra check gives
2053 * us an extra measure of robustness and sanity
2054 * check on the implementation.
2056 error = ndmis_audit_data_connect (sess, data_addr->addr_type, reason);
2057 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2063 data_can_start (struct ndm_session *sess,
2064 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
2065 ndmp9_mover_mode mover_mode)
2067 struct ndm_data_agent * da = &sess->data_acb;
2068 ndmp9_data_get_state_reply *ds = &da->data_state;
2069 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
2070 struct ndm_tape_agent * ta = &sess->tape_acb;
2071 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
2074 switch (mover_mode) {
2075 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_mode");
2076 case NDMP9_MOVER_MODE_READ: /* aka BACKUP */
2077 case NDMP9_MOVER_MODE_WRITE: /* aka RECOVER */
2081 /* Check states -- this should cover everything */
2082 if (da->data_state.state != NDMP9_DATA_STATE_CONNECTED)
2083 NDMADR_RAISE_ILLEGAL_STATE("data_state !CONNECTED");
2085 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
2086 if (ds->data_connection_addr.addr_type == NDMP9_ADDR_LOCAL) {
2087 ndmp9_mover_get_state_reply *ms = &ta->mover_state;
2089 if (ms->state != NDMP9_MOVER_STATE_ACTIVE)
2090 NDMADR_RAISE_ILLEGAL_STATE("mover_state !ACTIVE");
2092 if (ms->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL)
2093 NDMADR_RAISE_ILLEGAL_STATE("mover_addr !LOCAL");
2095 if (ms->mode != mover_mode)
2096 NDMADR_RAISE_ILLEGAL_STATE("mover_mode mismatch");
2098 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE)
2099 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2101 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
2107 * For NDMPv2, called from ndmadr_data_start_{backup,recover,recover_filhist}()
2108 * For NDMPv[34], called from ndmp_sxa_data_connect()
2111 data_connect (struct ndm_session *sess,
2112 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
2113 ndmp9_addr *data_addr)
2115 struct ndm_data_agent * da = &sess->data_acb;
2120 rc = data_can_connect (sess, xa, ref_conn, data_addr);
2125 * Audits done, connect already
2127 error = ndmis_data_connect (sess, data_addr, reason);
2128 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2130 da->data_state.data_connection_addr = *data_addr;
2131 /* alt: da->....data_connection_addr = sess->...peer_addr */
2133 error = ndmda_data_connect (sess);
2134 if (error != NDMP9_NO_ERR) {
2135 /* TODO: belay ndmis_data_connect() */
2136 NDMADR_RAISE(error, "!data_connect");
2139 da->data_state.data_connection_addr = *data_addr;
2145 data_copy_environment (struct ndm_session *sess,
2146 ndmp9_pval *env, unsigned n_env)
2150 if (n_env > NDM_MAX_ENV)
2151 return NDMP9_ILLEGAL_ARGS_ERR;
2153 rc = ndmda_copy_environment (sess, env, n_env);
2155 return NDMP9_NO_MEM_ERR;
2157 return NDMP9_NO_ERR;
2161 data_copy_nlist (struct ndm_session *sess,
2162 ndmp9_name *nlist, unsigned n_nlist)
2166 if (n_nlist >= NDM_MAX_NLIST)
2167 return NDMP9_ILLEGAL_ARGS_ERR;
2169 rc = ndmda_copy_nlist (sess, nlist, n_nlist);
2171 return NDMP9_NO_MEM_ERR;
2173 return NDMP9_NO_ERR;
2177 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */ /* Surrounds DATA intfs */
2182 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds MOVER intfs */
2184 * NDMPx_MOVER Interfaces
2185 ****************************************************************
2188 static ndmp9_error mover_can_proceed (struct ndm_session *sess,
2198 * NDMP[234]_MOVER_GET_STATE
2201 ndmp_sxa_mover_get_state (struct ndm_session *sess,
2202 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2204 struct ndm_tape_agent * ta = &sess->tape_acb;
2206 NDMS_WITH_VOID_REQUEST(ndmp9_mover_get_state)
2207 ndmta_mover_sync_state(sess);
2208 *reply = ta->mover_state;
2217 * NDMP[234]_MOVER_LISTEN
2220 ndmp_sxa_mover_listen (struct ndm_session *sess,
2221 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2223 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2224 struct ndm_data_agent * da = &sess->data_acb;
2225 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2226 struct ndm_tape_agent * ta = &sess->tape_acb;
2231 NDMS_WITH(ndmp9_mover_listen)
2232 ndmalogf (sess, 0, 6, "mover_listen_common() addr_type=%s mode=%s",
2233 ndmp9_addr_type_to_str (request->addr_type),
2234 ndmp9_mover_mode_to_str (request->mode));
2237 switch (request->mode) {
2239 NDMADR_RAISE_ILLEGAL_ARGS("mover_mode");
2241 case NDMP9_MOVER_MODE_READ:
2245 case NDMP9_MOVER_MODE_WRITE:
2250 switch (request->addr_type) {
2252 NDMADR_RAISE_ILLEGAL_ARGS("mover_addr_type");
2254 case NDMP9_ADDR_LOCAL:
2255 #ifdef NDMOS_OPTION_NO_DATA_AGENT
2256 NDMADR_RAISE_ILLEGAL_ARGS("mover LOCAL w/o local DATA agent");
2257 #endif /* NDMOS_OPTION_NO_DATA_AGENT */
2260 case NDMP9_ADDR_TCP:
2264 /* Check states -- this should cover everything */
2265 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE) {
2266 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2268 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2269 if (da->data_state.state != NDMP9_DATA_STATE_IDLE) {
2270 NDMADR_RAISE_ILLEGAL_STATE("data_state !IDLE");
2272 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2274 /* Check that the tape is ready to go */
2275 error = mover_can_proceed (sess, will_write);
2276 if (error != NDMP9_NO_ERR) {
2277 NDMADR_RAISE(error, "!mover_can_proceed");
2281 * Check image stream state -- should already be reflected
2282 * in the mover and data states. This extra check gives
2283 * us an extra measure of robustness and sanity
2284 * check on the implementation.
2286 error = ndmis_audit_tape_listen (sess, request->addr_type, reason);
2287 if (error != NDMP9_NO_ERR) {
2288 NDMADR_RAISE(error, reason);
2291 error = ndmis_tape_listen (sess, request->addr_type,
2292 &ta->mover_state.data_connection_addr,
2294 if (error != NDMP9_NO_ERR) {
2295 NDMADR_RAISE(error, reason);
2298 error = ndmta_mover_listen(sess, request->mode);
2299 if (error != NDMP9_NO_ERR) {
2300 /* TODO: belay ndmis_tape_listen() */
2301 NDMADR_RAISE(error, "!mover_listen");
2304 reply->data_connection_addr = ta->mover_state.data_connection_addr;
2314 * NDMP[234]_MOVER_CONTINUE
2317 ndmp_sxa_mover_continue (struct ndm_session *sess,
2318 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2320 struct ndm_tape_agent * ta = &sess->tape_acb;
2324 NDMS_WITH_VOID_REQUEST(ndmp9_mover_continue)
2325 if (ta->mover_state.state != NDMP9_MOVER_STATE_PAUSED) {
2326 NDMADR_RAISE_ILLEGAL_STATE("mover_state !PAUSED");
2329 will_write = ta->mover_state.mode == NDMP9_MOVER_MODE_READ;
2331 error = mover_can_proceed (sess, will_write);
2332 if (error != NDMP9_NO_ERR) {
2333 NDMADR_RAISE(error, "!mover_can_proceed");
2336 ndmta_mover_continue (sess);
2346 * NDMP[234]_MOVER_ABORT
2349 ndmp_sxa_mover_abort (struct ndm_session *sess,
2350 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2352 struct ndm_tape_agent * ta = &sess->tape_acb;
2354 NDMS_WITH_VOID_REQUEST(ndmp9_mover_abort)
2355 if (ta->mover_state.state != NDMP9_MOVER_STATE_LISTEN
2356 && ta->mover_state.state != NDMP9_MOVER_STATE_ACTIVE
2357 && ta->mover_state.state != NDMP9_MOVER_STATE_PAUSED) {
2358 NDMADR_RAISE_ILLEGAL_STATE("mover_state");
2361 ndmta_mover_abort (sess);
2371 * NDMP[234]_MOVER_STOP
2374 ndmp_sxa_mover_stop (struct ndm_session *sess,
2375 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2377 struct ndm_tape_agent * ta = &sess->tape_acb;
2379 NDMS_WITH_VOID_REQUEST(ndmp9_mover_stop)
2380 if (ta->mover_state.state != NDMP9_MOVER_STATE_HALTED) {
2381 NDMADR_RAISE_ILLEGAL_STATE("mover_state !HALTED");
2384 ndmta_mover_stop (sess);
2394 * NDMP[234]_MOVER_SET_WINDOW
2397 ndmp_sxa_mover_set_window (struct ndm_session *sess,
2398 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2400 struct ndm_tape_agent * ta = &sess->tape_acb;
2401 struct ndmp9_mover_get_state_reply *ms = &ta->mover_state;
2402 unsigned long long max_len;
2403 unsigned long long end_win;
2405 NDMS_WITH(ndmp9_mover_set_window)
2406 ndmta_mover_sync_state (sess);
2408 if (ref_conn->protocol_version < NDMP4VER) {
2410 * NDMP[23] require the Mover be in LISTEN state.
2411 * Unclear sequence for MOVER_CONNECT.
2413 if (ms->state != NDMP9_MOVER_STATE_LISTEN
2414 && ms->state != NDMP9_MOVER_STATE_PAUSED) {
2415 NDMADR_RAISE_ILLEGAL_STATE("mover_state !LISTEN/PAUSED");
2419 * NDMP4 require the Mover be in IDLE state.
2420 * This always preceeds both MOVER_LISTEN or
2423 if (ms->state != NDMP9_MOVER_STATE_IDLE
2424 && ms->state != NDMP9_MOVER_STATE_PAUSED) {
2425 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE/PAUSED");
2429 if (request->offset % ms->record_size != 0) {
2430 NDMADR_RAISE_ILLEGAL_ARGS("off !record_size");
2433 /* TODO: NDMPv4 subtle semantic changes here */
2435 /* If a maximum length window is required following a mover transition
2436 * to the PAUSED state, a window length of all ones (binary) minus the
2437 * current window offset MUST be specified." (NDMPv4 RFC, Section
2438 * 3.6.2.2) -- we allow length = NDMP_LENGTH_INFINITY too */
2440 if (request->length != NDMP_LENGTH_INFINITY
2441 && request->length + request->offset != NDMP_LENGTH_INFINITY) {
2442 if (request->length % ms->record_size != 0) {
2443 NDMADR_RAISE_ILLEGAL_ARGS("len !record_size");
2446 /* Too pedantic. Sometimes needed (like for testing) */
2447 if (request->length == 0) {
2448 NDMADR_RAISE_ILLEGAL_ARGS("length 0");
2452 max_len = NDMP_LENGTH_INFINITY - request->offset;
2453 max_len -= max_len % ms->record_size;
2454 if (request->length > max_len) { /* learn math fella */
2455 NDMADR_RAISE_ILLEGAL_ARGS("length too long");
2457 end_win = request->offset + request->length;
2459 end_win = NDMP_LENGTH_INFINITY;
2461 ms->window_offset = request->offset;
2462 /* record_num should probably be one less than this value, but the spec
2463 * says to divide, so we divide */
2464 ms->record_num = request->offset / ms->record_size;
2465 ms->window_length = request->length;
2466 ta->mover_window_end = end_win;
2467 ta->mover_window_first_blockno = ta->tape_state.blockno.value;
2477 * NDMP[234]_MOVER_READ
2480 ndmp_sxa_mover_read (struct ndm_session *sess,
2481 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2483 struct ndm_tape_agent * ta = &sess->tape_acb;
2484 struct ndmp9_mover_get_state_reply *ms = &ta->mover_state;
2486 NDMS_WITH(ndmp9_mover_read)
2487 ndmta_mover_sync_state (sess);
2489 if (ms->state != NDMP9_MOVER_STATE_ACTIVE) {
2490 NDMADR_RAISE_ILLEGAL_STATE("mover_state !ACTIVE");
2493 if (ms->bytes_left_to_read > 0) {
2494 NDMADR_RAISE_ILLEGAL_STATE("byte_left_to_read");
2497 if (ms->data_connection_addr.addr_type != NDMP9_ADDR_TCP) {
2498 NDMADR_RAISE_ILLEGAL_STATE("mover_addr !TCP");
2501 if (ms->mode != NDMP9_MOVER_MODE_WRITE) {
2502 NDMADR_RAISE_ILLEGAL_STATE("mover_mode !WRITE");
2505 ndmta_mover_read (sess, request->offset, request->length);
2515 * NDMP[234]_MOVER_CLOSE
2518 ndmp_sxa_mover_close (struct ndm_session *sess,
2519 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2521 struct ndm_tape_agent * ta = &sess->tape_acb;
2523 NDMS_WITH_VOID_REQUEST(ndmp9_mover_close) {
2524 if (ta->mover_state.state == NDMP9_MOVER_STATE_IDLE)
2525 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2528 ndmta_mover_close (sess);
2538 * NDMP[234]_MOVER_SET_RECORD_SIZE
2541 ndmp_sxa_mover_set_record_size (struct ndm_session *sess,
2542 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2544 struct ndm_tape_agent * ta = &sess->tape_acb;
2545 struct ndmp9_mover_get_state_reply *ms = &ta->mover_state;
2547 NDMS_WITH(ndmp9_mover_set_record_size)
2548 ndmta_mover_sync_state (sess);
2550 if (ms->state != NDMP9_MOVER_STATE_IDLE
2551 && ms->state != NDMP9_MOVER_STATE_PAUSED)
2552 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE/PAUSED");
2554 if (!NDMOS_MACRO_OK_TAPE_REC_LEN(request->record_size))
2555 NDMADR_RAISE_ILLEGAL_ARGS("!ok_tape_rec_len");
2557 ta->mover_state.record_size = request->record_size;
2568 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 /* Surrounds NDMPv[34] MOVER intfs */
2570 static int mover_connect_common34 (struct ndm_session *sess,
2571 struct ndmp_xa_buf *xa,
2572 struct ndmconn *ref_conn,
2574 ndmp9_mover_mode mover_mode);
2577 * NDMP[34]_MOVER_CONNECT
2580 ndmadr_mover_connect (struct ndm_session *sess,
2581 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2583 switch (xa->request.protocol_version) {
2584 default: return NDMADR_UNIMPLEMENTED_VERSION; /* should never happen */
2586 #ifndef NDMOS_OPTION_NO_NDMP2
2588 /* not part of NDMPv2 */
2589 return NDMADR_UNSPECIFIED_MESSAGE;
2590 #endif /* !NDMOS_OPTION_NO_NDMP2 */
2592 #ifndef NDMOS_OPTION_NO_NDMP3
2594 NDMS_WITH(ndmp3_mover_connect)
2595 ndmp9_mover_mode mover_mode;
2596 ndmp9_addr data_addr;
2598 switch (request->mode) {
2599 default: mover_mode = -1; break;
2600 case NDMP3_MOVER_MODE_READ: mover_mode = NDMP9_MOVER_MODE_READ; break;
2601 case NDMP3_MOVER_MODE_WRITE:mover_mode = NDMP9_MOVER_MODE_WRITE;break;
2604 ndmp_3to9_addr (&request->addr, &data_addr);
2606 return mover_connect_common34 (sess, xa, ref_conn,
2607 &data_addr, mover_mode);
2610 #endif /* !NDMOS_OPTION_NO_NDMP3 */
2615 /* this same intf is expected in v4, so _common() now */
2617 mover_connect_common34 (struct ndm_session *sess,
2618 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
2619 ndmp9_addr *data_addr, ndmp9_mover_mode mover_mode)
2621 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2622 struct ndm_data_agent * da = &sess->data_acb;
2623 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2624 struct ndm_tape_agent * ta = &sess->tape_acb;
2630 switch (mover_mode) {
2631 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_mode");
2632 case NDMP9_MOVER_MODE_READ:
2636 case NDMP9_MOVER_MODE_WRITE:
2641 switch (data_addr->addr_type) {
2642 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_addr_type");
2643 case NDMP9_ADDR_LOCAL:
2644 #ifdef NDMOS_OPTION_NO_DATA_AGENT
2645 NDMADR_RAISE_ILLEGAL_ARGS("mover LOCAL w/o local DATA agent");
2646 #endif /* NDMOS_OPTION_NO_DATA_AGENT */
2649 case NDMP9_ADDR_TCP:
2653 /* Check states -- this should cover everything */
2654 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE)
2655 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2656 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2657 if (data_addr->addr_type == NDMP9_ADDR_LOCAL) {
2658 ndmp9_data_get_state_reply *ds = &da->data_state;
2660 if (ds->state != NDMP9_DATA_STATE_LISTEN)
2661 NDMADR_RAISE_ILLEGAL_STATE("data_state !LISTEN");
2663 if (ds->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL)
2664 NDMADR_RAISE_ILLEGAL_STATE("data_addr !LOCAL");
2666 if (da->data_state.state != NDMP9_DATA_STATE_IDLE)
2667 NDMADR_RAISE_ILLEGAL_STATE("data_state !IDLE");
2669 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2671 /* Check that the tape is ready to go */
2672 error = mover_can_proceed (sess, will_write);
2673 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, "!mover_can_proceed");
2676 * Check image stream state -- should already be reflected
2677 * in the mover and data states. This extra check gives
2678 * us an extra measure of robustness and sanity
2679 * check on the implementation.
2681 error = ndmis_audit_tape_connect (sess, data_addr->addr_type, reason);
2682 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2684 error = ndmis_tape_connect (sess, data_addr, reason);
2685 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2687 ta->mover_state.data_connection_addr = *data_addr;
2688 /* alt: ta->....data_connection_addr = sess->...peer_addr */
2690 error = ndmta_mover_connect (sess, mover_mode);
2691 if (error != NDMP9_NO_ERR) {
2692 /* TODO: belay ndmis_tape_connect() */
2693 NDMADR_RAISE(error, "!mover_connect");
2698 #endif /* !NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 Surrounds NDMPv[34] MOVER intfs */
2705 * NDMPx_MOVER helper routines
2709 * MOVER can only proceed from IDLE->LISTEN or PAUSED->ACTIVE
2710 * if the tape drive is ready.
2714 mover_can_proceed (struct ndm_session *sess, int will_write)
2716 struct ndm_tape_agent * ta = &sess->tape_acb;
2718 ndmos_tape_sync_state(sess);
2719 if (ta->tape_state.state != NDMP9_TAPE_STATE_OPEN)
2720 return NDMP9_DEV_NOT_OPEN_ERR;
2722 if (will_write && !NDMTA_TAPE_IS_WRITABLE(ta))
2723 return NDMP9_PERMISSION_ERR;
2725 return NDMP9_NO_ERR;
2728 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds MOVER intfs */
2733 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
2735 * NDMPx_NOTIFY Interfaces
2736 ****************************************************************
2743 * NDMP[234]_NOTIFY_DATA_HALTED
2746 ndmp_sxa_notify_data_halted (struct ndm_session *sess,
2747 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2749 struct ndm_control_agent *ca = &sess->control_acb;
2751 NDMS_WITH_NO_REPLY(ndmp9_notify_data_halted)
2752 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2754 ca->pending_notify_data_halted++;
2764 * NDMP[234]_NOTIFY_CONNECTED
2767 ndmp_sxa_notify_connected (struct ndm_session *sess,
2768 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2770 NDMS_WITH_NO_REPLY(ndmp2_notify_connected)
2771 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2781 * NDMP[234]_NOTIFY_MOVER_HALTED
2784 ndmp_sxa_notify_mover_halted (struct ndm_session *sess,
2785 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2787 struct ndm_control_agent * ca = &sess->control_acb;
2789 NDMS_WITH_NO_REPLY(ndmp2_notify_mover_halted)
2790 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2792 ca->pending_notify_mover_halted++;
2802 * NDMP[234]_NOTIFY_MOVER_PAUSED
2805 ndmp_sxa_notify_mover_paused (struct ndm_session *sess,
2806 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2808 struct ndm_control_agent * ca = &sess->control_acb;
2810 NDMS_WITH_NO_REPLY(ndmp9_notify_mover_paused)
2811 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2813 ca->pending_notify_mover_paused++;
2814 ca->last_notify_mover_paused.reason = request->reason;
2815 ca->last_notify_mover_paused.seek_position = request->seek_position;
2825 * NDMP[234]_NOTIFY_DATA_READ
2828 ndmp_sxa_notify_data_read (struct ndm_session *sess,
2829 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2831 struct ndm_control_agent * ca = &sess->control_acb;
2833 NDMS_WITH_NO_REPLY(ndmp9_notify_data_read)
2834 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2836 ca->pending_notify_data_read++;
2837 ca->last_notify_data_read.offset = request->offset;
2838 ca->last_notify_data_read.length = request->length;
2843 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
2848 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds LOG intfs */
2850 * NDMPx_LOG Interfaces
2851 ****************************************************************
2857 * NDMP[234]_LOG_FILE
2860 ndmp_sxa_log_file (struct ndm_session *sess,
2861 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2863 struct ndm_control_agent *ca = &sess->control_acb;
2868 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2870 NDMS_WITH_NO_REPLY(ndmp9_log_file)
2871 switch (request->recovery_status) {
2872 case NDMP9_RECOVERY_SUCCESSFUL:
2877 case NDMP9_RECOVERY_FAILED_PERMISSION:
2878 tag = "Bad Permission";
2881 case NDMP9_RECOVERY_FAILED_NOT_FOUND:
2885 case NDMP9_RECOVERY_FAILED_NO_DIRECTORY:
2886 tag = "No directory";
2889 case NDMP9_RECOVERY_FAILED_OUT_OF_MEMORY:
2893 case NDMP9_RECOVERY_FAILED_IO_ERROR:
2897 case NDMP9_RECOVERY_FAILED_UNDEFINED_ERROR:
2898 tag = "General error";
2906 /* count the notification and whether it is good news or not */
2907 ca->recover_log_file_count++;
2909 ca->recover_log_file_ok++;
2911 ca->recover_log_file_error++;
2914 sprintf (prefix, "%cLF", ref_conn->chan.name[1]);
2916 ndmalogf (sess, prefix, lev, "%s: %s", tag, request->name);
2925 #ifndef NDMOS_OPTION_NO_NDMP2
2930 ndmp2_sxa_log_log (struct ndm_session *sess,
2931 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2937 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2939 NDMS_WITH_NO_REPLY(ndmp2_log_log)
2943 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
2945 ndmalogf (sess, prefix, lev, "LOG_LOG: '%s'", request->entry);
2955 ndmp2_sxa_log_debug (struct ndm_session *sess,
2956 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2962 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2964 NDMS_WITH_NO_REPLY(ndmp2_log_debug)
2968 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
2970 ndmalogf (sess, prefix, lev, "LOG_DEBUG: '%s'", request->message);
2976 #endif /* !NDMOS_OPTION_NO_NDMP2 */
2982 * NDMP[34]_LOG_MESSAGE
2985 ndmp_sxa_log_message (struct ndm_session *sess,
2986 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2992 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2994 NDMS_WITH_NO_REPLY(ndmp9_log_message)
2995 switch (request->log_type) {
2996 case NDMP9_LOG_NORMAL:
3001 case NDMP9_LOG_DEBUG:
3006 case NDMP9_LOG_ERROR:
3011 case NDMP9_LOG_WARNING:
3022 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
3024 ndmalogf (sess, prefix, lev, "LOG_MESSAGE: '%s'", request->entry);
3030 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds LOG intfs */
3035 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds FH intfs */
3037 * NDMPx_FH Interfaces
3038 ****************************************************************
3045 * NDMP2_FH_ADD_UNIX_PATH
3046 * NDMP[34]_FH_ADD_FILE
3049 ndmp_sxa_fh_add_file (struct ndm_session *sess,
3050 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3052 struct ndm_control_agent *ca = &sess->control_acb;
3053 struct ndmlog * ixlog = &ca->job.index_log;
3054 int tagc = ref_conn->chan.name[1];
3058 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3060 NDMS_WITH_NO_REPLY(ndmp9_fh_add_file)
3061 for (i = 0; i < request->files.files_len; i++) {
3062 file = &request->files.files_val[i];
3064 ndmfhdb_add_file (ixlog, tagc,
3065 file->unix_path, &file->fstat);
3076 * NDMP2_FH_ADD_UNIX_DIR
3077 * NDMP[34]_FH_ADD_DIR
3080 ndmp_sxa_fh_add_dir (struct ndm_session *sess,
3081 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3083 struct ndm_control_agent *ca = &sess->control_acb;
3084 struct ndmlog * ixlog = &ca->job.index_log;
3085 int tagc = ref_conn->chan.name[1];
3090 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3092 NDMS_WITH_NO_REPLY(ndmp9_fh_add_dir)
3093 for (i = 0; i < request->dirs.dirs_len; i++) {
3094 dir = &request->dirs.dirs_val[i];
3096 raw_name = dir->unix_name;
3098 switch (ca->job.n_dir_entry) {
3100 if (strcmp (raw_name, ".") == 0) {
3102 ndmfhdb_add_dirnode_root (ixlog,
3104 ca->job.root_node = dir->node;
3107 ndmalogf (sess, 0, 0,
3108 "WARNING: First add_dir "
3109 "entry is non-conforming");
3114 if (strcmp (raw_name, "..") == 0
3115 && dir->parent == dir->node
3116 && dir->node == ca->job.root_node) {
3120 /* NetApp is non-conforming */
3121 /* ndmalogf (sess, 0, 0,
3122 "WARNING: Second add_dir "
3123 "entry is non-conforming"); */
3131 ndmfhdb_add_dir (ixlog, tagc,
3132 dir->unix_name, dir->parent, dir->node);
3134 ca->job.n_dir_entry++;
3145 * NDMP2_FH_ADD_UNIX_NODE
3146 * NDMP[34]_FH_ADD_NODE
3149 ndmp_sxa_fh_add_node (struct ndm_session *sess,
3150 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3152 struct ndm_control_agent *ca = &sess->control_acb;
3153 struct ndmlog * ixlog = &ca->job.index_log;
3154 int tagc = ref_conn->chan.name[1];
3158 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3160 NDMS_WITH_NO_REPLY(ndmp9_fh_add_node)
3161 for (i = 0; i < request->nodes.nodes_len; i++) {
3162 node = &request->nodes.nodes_val[i];
3164 ndmfhdb_add_node (ixlog, tagc,
3165 node->fstat.node.value, &node->fstat);
3171 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds FH intfs */
3176 * Common helper interfaces
3177 ****************************************************************
3178 * These do complicated state checks which are called from
3179 * several of the interfaces above.
3190 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
3192 * Shortcut for DATA->MOVER READ requests when NDMP9_ADDR_LOCAL
3193 * (local MOVER). This is implemented here because of the
3194 * state (sanity) checks. This should track the
3195 * NDMP9_MOVER_READ stanza in ndma_dispatch_request().
3199 ndmta_local_mover_read (struct ndm_session *sess,
3200 unsigned long long offset, unsigned long long length)
3202 struct ndm_tape_agent * ta = &sess->tape_acb;
3203 struct ndmp9_mover_get_state_reply *ms = &ta->mover_state;
3206 if (ms->state != NDMP9_MOVER_STATE_ACTIVE
3207 && ms->state != NDMP9_MOVER_STATE_LISTEN) {
3208 errstr = "mover_state !ACTIVE";
3211 if (ms->bytes_left_to_read > 0) {
3212 errstr = "byte_left_to_read";
3215 if (ms->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL) {
3216 errstr = "mover_addr !LOCAL";
3219 if (ms->mode != NDMP9_MOVER_MODE_WRITE) {
3220 errstr = "mover_mode !WRITE";
3224 ms->seek_position = offset;
3225 ms->bytes_left_to_read = length;
3226 ta->mover_want_pos = offset;
3232 ndmalogf (sess, 0, 2, "local_read error why=%s", errstr);
3237 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
3246 * Dispatch Version Table and Dispatch Request Tables (DVT/DRT)
3247 ****************************************************************
3250 struct ndm_dispatch_request_table *
3251 ndma_drt_lookup (struct ndm_dispatch_version_table *dvt,
3252 unsigned protocol_version, unsigned message)
3254 struct ndm_dispatch_request_table * drt;
3256 for (; dvt->protocol_version >= 0; dvt++) {
3257 if (dvt->protocol_version == (int)protocol_version)
3261 if (dvt->protocol_version < 0)
3264 for (drt = dvt->dispatch_request_table; drt->message; drt++) {
3265 if (drt->message == message)
3272 struct ndm_dispatch_request_table ndma_dispatch_request_table_v0[] = {
3273 { NDMP0_CONNECT_OPEN,
3274 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3275 ndmp_sxa_connect_open,
3277 { NDMP0_CONNECT_CLOSE,
3278 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3279 ndmp_sxa_connect_close,
3281 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
3282 { NDMP0_NOTIFY_CONNECTED,
3284 ndmp_sxa_notify_connected,
3286 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
3292 #ifndef NDMOS_OPTION_NO_NDMP2
3293 struct ndm_dispatch_request_table ndma_dispatch_request_table_v2[] = {
3294 { NDMP2_CONFIG_GET_BUTYPE_ATTR,
3295 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3296 ndmp2_sxa_config_get_butype_attr
3298 { NDMP2_LOG_LOG, 0, ndmp2_sxa_log_log },
3299 { NDMP2_LOG_DEBUG, 0, ndmp2_sxa_log_debug },
3302 #endif /* !NDMOS_OPTION_NO_NDMP2 */
3304 #ifndef NDMOS_OPTION_NO_NDMP3
3305 struct ndm_dispatch_request_table ndma_dispatch_request_table_v3[] = {
3308 #endif /* !NDMOS_OPTION_NO_NDMP3 */
3310 #ifndef NDMOS_OPTION_NO_NDMP4
3311 struct ndm_dispatch_request_table ndma_dispatch_request_table_v4[] = {
3314 #endif /* !NDMOS_OPTION_NO_NDMP4 */
3317 struct ndm_dispatch_request_table ndma_dispatch_request_table_v9[] = {
3318 { NDMP9_CONNECT_OPEN,
3319 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3320 ndmp_sxa_connect_open
3322 { NDMP9_CONNECT_CLIENT_AUTH,
3323 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3324 ndmp_sxa_connect_client_auth
3326 { NDMP9_CONNECT_CLOSE,
3327 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3328 ndmp_sxa_connect_close
3330 { NDMP9_CONNECT_SERVER_AUTH,
3331 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3332 ndmp_sxa_connect_server_auth
3334 { NDMP9_CONFIG_GET_HOST_INFO,
3335 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3336 ndmp_sxa_config_get_info
3338 { NDMP9_CONFIG_GET_CONNECTION_TYPE,
3339 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3340 ndmp_sxa_config_get_info
3342 { NDMP9_CONFIG_GET_AUTH_ATTR,
3343 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3344 ndmp_sxa_config_get_auth_attr
3346 { NDMP9_CONFIG_GET_BUTYPE_INFO,
3347 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3348 ndmp_sxa_config_get_info
3350 { NDMP9_CONFIG_GET_FS_INFO,
3351 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3352 ndmp_sxa_config_get_info
3354 { NDMP9_CONFIG_GET_TAPE_INFO,
3355 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3356 ndmp_sxa_config_get_info
3358 { NDMP9_CONFIG_GET_SCSI_INFO,
3359 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3360 ndmp_sxa_config_get_info
3362 { NDMP9_CONFIG_GET_SERVER_INFO,
3363 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3364 ndmp_sxa_config_get_info
3366 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT /* Surrounds SCSI intfs */
3367 { NDMP9_SCSI_OPEN, 0, ndmp_sxa_scsi_open },
3368 { NDMP9_SCSI_CLOSE, 0, ndmp_sxa_scsi_close },
3369 { NDMP9_SCSI_GET_STATE, 0, ndmp_sxa_scsi_get_state },
3370 { NDMP9_SCSI_SET_TARGET, 0, ndmp_sxa_scsi_set_target },
3371 { NDMP9_SCSI_RESET_DEVICE, 0, ndmp_sxa_scsi_reset_device },
3372 { NDMP9_SCSI_RESET_BUS, 0, ndmp_sxa_scsi_reset_bus },
3373 { NDMP9_SCSI_EXECUTE_CDB, 0, ndmp_sxa_scsi_execute_cdb },
3374 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */ /* Surrounds SCSI intfs */
3375 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds TAPE intfs */
3376 { NDMP9_TAPE_OPEN, 0, ndmp_sxa_tape_open },
3377 { NDMP9_TAPE_CLOSE, 0, ndmp_sxa_tape_close },
3378 { NDMP9_TAPE_GET_STATE, 0, ndmp_sxa_tape_get_state },
3379 { NDMP9_TAPE_MTIO, 0, ndmp_sxa_tape_mtio },
3380 { NDMP9_TAPE_WRITE, 0, ndmp_sxa_tape_write },
3381 { NDMP9_TAPE_READ, 0, ndmp_sxa_tape_read },
3382 { NDMP9_TAPE_EXECUTE_CDB, 0, ndmp_sxa_tape_execute_cdb },
3383 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds TAPE intfs */
3384 #ifndef NDMOS_OPTION_NO_DATA_AGENT /* Surrounds DATA intfs */
3385 { NDMP9_DATA_GET_STATE, 0, ndmp_sxa_data_get_state },
3386 { NDMP9_DATA_START_BACKUP, 0, ndmp_sxa_data_start_backup },
3387 { NDMP9_DATA_START_RECOVER, 0, ndmp_sxa_data_start_recover },
3388 { NDMP9_DATA_ABORT, 0, ndmp_sxa_data_abort },
3389 { NDMP9_DATA_GET_ENV, 0, ndmp_sxa_data_get_env },
3390 { NDMP9_DATA_STOP, 0, ndmp_sxa_data_stop },
3391 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 /* Surrounds NDMPv[34] DATA intfs */
3393 { NDMP9_DATA_LISTEN, 0, ndmp_sxa_data_listen },
3395 { NDMP9_DATA_CONNECT, 0, ndmp_sxa_data_connect },
3396 #endif /* NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 Surrounds NDMPv[34] DATA intfs */
3397 { NDMP9_DATA_START_RECOVER_FILEHIST, 0,
3398 ndmp_sxa_data_start_recover_filehist },
3399 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */ /* Surrounds DATA intfs */
3400 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
3401 { NDMP9_NOTIFY_DATA_HALTED, 0, ndmp_sxa_notify_data_halted },
3402 { NDMP9_NOTIFY_CONNECTED, 0, ndmp_sxa_notify_connected },
3403 { NDMP9_NOTIFY_MOVER_HALTED, 0, ndmp_sxa_notify_mover_halted },
3404 { NDMP9_NOTIFY_MOVER_PAUSED, 0, ndmp_sxa_notify_mover_paused },
3405 { NDMP9_NOTIFY_DATA_READ, 0, ndmp_sxa_notify_data_read },
3406 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
3407 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds LOG intfs */
3408 { NDMP9_LOG_FILE, 0, ndmp_sxa_log_file },
3409 { NDMP9_LOG_MESSAGE, 0, ndmp_sxa_log_message },
3410 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds LOG intfs */
3411 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds FH intfs */
3412 { NDMP9_FH_ADD_FILE, 0, ndmp_sxa_fh_add_file },
3413 { NDMP9_FH_ADD_DIR, 0, ndmp_sxa_fh_add_dir },
3414 { NDMP9_FH_ADD_NODE, 0, ndmp_sxa_fh_add_node },
3415 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds FH intfs */
3416 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds MOVER intfs */
3417 { NDMP9_MOVER_GET_STATE, 0, ndmp_sxa_mover_get_state },
3418 { NDMP9_MOVER_LISTEN, 0, ndmp_sxa_mover_listen },
3419 { NDMP9_MOVER_CONTINUE, 0, ndmp_sxa_mover_continue },
3420 { NDMP9_MOVER_ABORT, 0, ndmp_sxa_mover_abort },
3421 { NDMP9_MOVER_STOP, 0, ndmp_sxa_mover_stop },
3422 { NDMP9_MOVER_SET_WINDOW, 0, ndmp_sxa_mover_set_window },
3423 { NDMP9_MOVER_READ, 0, ndmp_sxa_mover_read },
3424 { NDMP9_MOVER_CLOSE, 0, ndmp_sxa_mover_close },
3425 { NDMP9_MOVER_SET_RECORD_SIZE, 0, ndmp_sxa_mover_set_record_size },
3427 { NDMP9_MOVER_CONNECT, 0, ndmp_sxa_mover_connect },
3429 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds MOVER intfs */
3434 struct ndm_dispatch_version_table ndma_dispatch_version_table[] = {
3435 { 0, ndma_dispatch_request_table_v0 },
3436 #ifndef NDMOS_OPTION_NO_NDMP2
3437 { NDMP2VER, ndma_dispatch_request_table_v2 },
3438 #endif /* !NDMOS_OPTION_NO_NDMP2 */
3439 #ifndef NDMOS_OPTION_NO_NDMP3
3440 { NDMP3VER, ndma_dispatch_request_table_v3 },
3441 #endif /* !NDMOS_OPTION_NO_NDMP3 */
3442 #ifndef NDMOS_OPTION_NO_NDMP4
3443 { NDMP4VER, ndma_dispatch_request_table_v4 },
3444 #endif /* !NDMOS_OPTION_NO_NDMP4 */
3445 { NDMP9VER, ndma_dispatch_request_table_v9 },