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 NDMP9_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(ndmp9_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;
2565 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 /* Surrounds NDMPv[34] MOVER intfs */
2567 static int mover_connect_common34 (struct ndm_session *sess,
2568 struct ndmp_xa_buf *xa,
2569 struct ndmconn *ref_conn,
2571 ndmp9_mover_mode mover_mode);
2574 * NDMP[34]_MOVER_CONNECT
2577 ndmp_sxa_mover_connect (struct ndm_session *sess,
2578 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2580 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2581 struct ndm_data_agent * da = &sess->data_acb;
2582 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2583 struct ndm_tape_agent * ta = &sess->tape_acb;
2588 NDMS_WITH(ndmp9_mover_connect)
2591 switch (request->mode) {
2592 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_mode");
2593 case NDMP9_MOVER_MODE_READ:
2597 case NDMP9_MOVER_MODE_WRITE:
2602 switch (request->addr.addr_type) {
2603 default: NDMADR_RAISE_ILLEGAL_ARGS("mover_addr_type");
2604 case NDMP9_ADDR_LOCAL:
2605 #ifdef NDMOS_OPTION_NO_DATA_AGENT
2606 NDMADR_RAISE_ILLEGAL_ARGS("mover LOCAL w/o local DATA agent");
2607 #endif /* NDMOS_OPTION_NO_DATA_AGENT */
2610 case NDMP9_ADDR_TCP:
2614 /* Check states -- this should cover everything */
2615 if (ta->mover_state.state != NDMP9_MOVER_STATE_IDLE)
2616 NDMADR_RAISE_ILLEGAL_STATE("mover_state !IDLE");
2617 #ifndef NDMOS_OPTION_NO_DATA_AGENT
2618 if (request->addr.addr_type == NDMP9_ADDR_LOCAL) {
2619 ndmp9_data_get_state_reply *ds = &da->data_state;
2621 if (ds->state != NDMP9_DATA_STATE_LISTEN)
2622 NDMADR_RAISE_ILLEGAL_STATE("data_state !LISTEN");
2624 if (ds->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL)
2625 NDMADR_RAISE_ILLEGAL_STATE("data_addr !LOCAL");
2627 if (da->data_state.state != NDMP9_DATA_STATE_IDLE)
2628 NDMADR_RAISE_ILLEGAL_STATE("data_state !IDLE");
2630 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
2632 /* Check that the tape is ready to go */
2633 error = mover_can_proceed (sess, will_write);
2634 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, "!mover_can_proceed");
2637 * Check image stream state -- should already be reflected
2638 * in the mover and data states. This extra check gives
2639 * us an extra measure of robustness and sanity
2640 * check on the implementation.
2642 error = ndmis_audit_tape_connect (sess, request->addr.addr_type, reason);
2643 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2645 error = ndmis_tape_connect (sess, &request->addr, reason);
2646 if (error != NDMP9_NO_ERR) NDMADR_RAISE(error, reason);
2648 ta->mover_state.data_connection_addr = request->addr;
2649 /* alt: ta->....data_connection_addr = sess->...peer_addr */
2651 error = ndmta_mover_connect (sess, request->mode);
2652 if (error != NDMP9_NO_ERR) {
2653 /* TODO: belay ndmis_tape_connect() */
2654 NDMADR_RAISE(error, "!mover_connect");
2660 #endif /* !NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 Surrounds NDMPv[34] MOVER intfs */
2665 * NDMPx_MOVER helper routines
2669 * MOVER can only proceed from IDLE->LISTEN or PAUSED->ACTIVE
2670 * if the tape drive is ready.
2674 mover_can_proceed (struct ndm_session *sess, int will_write)
2676 struct ndm_tape_agent * ta = &sess->tape_acb;
2678 ndmos_tape_sync_state(sess);
2679 if (ta->tape_state.state != NDMP9_TAPE_STATE_OPEN)
2680 return NDMP9_DEV_NOT_OPEN_ERR;
2682 if (will_write && !NDMTA_TAPE_IS_WRITABLE(ta))
2683 return NDMP9_PERMISSION_ERR;
2685 return NDMP9_NO_ERR;
2688 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds MOVER intfs */
2693 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
2695 * NDMPx_NOTIFY Interfaces
2696 ****************************************************************
2703 * NDMP[234]_NOTIFY_DATA_HALTED
2706 ndmp_sxa_notify_data_halted (struct ndm_session *sess,
2707 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2709 struct ndm_control_agent *ca = &sess->control_acb;
2711 NDMS_WITH_NO_REPLY(ndmp9_notify_data_halted)
2712 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2714 ca->pending_notify_data_halted++;
2724 * NDMP[234]_NOTIFY_CONNECTED
2727 ndmp_sxa_notify_connected (struct ndm_session *sess,
2728 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2730 NDMS_WITH_NO_REPLY(ndmp9_notify_connected)
2731 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2741 * NDMP[234]_NOTIFY_MOVER_HALTED
2744 ndmp_sxa_notify_mover_halted (struct ndm_session *sess,
2745 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2747 struct ndm_control_agent * ca = &sess->control_acb;
2749 NDMS_WITH_NO_REPLY(ndmp9_notify_mover_halted)
2750 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2752 ca->pending_notify_mover_halted++;
2762 * NDMP[234]_NOTIFY_MOVER_PAUSED
2765 ndmp_sxa_notify_mover_paused (struct ndm_session *sess,
2766 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2768 struct ndm_control_agent * ca = &sess->control_acb;
2770 NDMS_WITH_NO_REPLY(ndmp9_notify_mover_paused)
2771 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2773 ca->pending_notify_mover_paused++;
2774 ca->last_notify_mover_paused.reason = request->reason;
2775 ca->last_notify_mover_paused.seek_position = request->seek_position;
2785 * NDMP[234]_NOTIFY_DATA_READ
2788 ndmp_sxa_notify_data_read (struct ndm_session *sess,
2789 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2791 struct ndm_control_agent * ca = &sess->control_acb;
2793 NDMS_WITH_NO_REPLY(ndmp9_notify_data_read)
2794 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2796 ca->pending_notify_data_read++;
2797 ca->last_notify_data_read.offset = request->offset;
2798 ca->last_notify_data_read.length = request->length;
2803 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
2808 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds LOG intfs */
2810 * NDMPx_LOG Interfaces
2811 ****************************************************************
2817 * NDMP[234]_LOG_FILE
2820 ndmp_sxa_log_file (struct ndm_session *sess,
2821 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2823 struct ndm_control_agent *ca = &sess->control_acb;
2828 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2830 NDMS_WITH_NO_REPLY(ndmp9_log_file)
2831 switch (request->recovery_status) {
2832 case NDMP9_RECOVERY_SUCCESSFUL:
2837 case NDMP9_RECOVERY_FAILED_PERMISSION:
2838 tag = "Bad Permission";
2841 case NDMP9_RECOVERY_FAILED_NOT_FOUND:
2845 case NDMP9_RECOVERY_FAILED_NO_DIRECTORY:
2846 tag = "No directory";
2849 case NDMP9_RECOVERY_FAILED_OUT_OF_MEMORY:
2853 case NDMP9_RECOVERY_FAILED_IO_ERROR:
2857 case NDMP9_RECOVERY_FAILED_UNDEFINED_ERROR:
2858 tag = "General error";
2866 /* count the notification and whether it is good news or not */
2867 ca->recover_log_file_count++;
2869 ca->recover_log_file_ok++;
2871 ca->recover_log_file_error++;
2874 sprintf (prefix, "%cLF", ref_conn->chan.name[1]);
2876 ndmalogf (sess, prefix, lev, "%s: %s", tag, request->name);
2885 #ifndef NDMOS_OPTION_NO_NDMP2
2890 ndmp2_sxa_log_log (struct ndm_session *sess,
2891 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2897 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2899 NDMS_WITH_NO_REPLY(ndmp2_log_log)
2903 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
2905 ndmalogf (sess, prefix, lev, "LOG_LOG: '%s'", request->entry);
2915 ndmp2_sxa_log_debug (struct ndm_session *sess,
2916 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2922 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2924 NDMS_WITH_NO_REPLY(ndmp2_log_debug)
2928 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
2930 ndmalogf (sess, prefix, lev, "LOG_DEBUG: '%s'", request->message);
2936 #endif /* !NDMOS_OPTION_NO_NDMP2 */
2942 * NDMP[34]_LOG_MESSAGE
2945 ndmp_sxa_log_message (struct ndm_session *sess,
2946 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
2952 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
2954 NDMS_WITH_NO_REPLY(ndmp9_log_message)
2955 switch (request->log_type) {
2956 case NDMP9_LOG_NORMAL:
2961 case NDMP9_LOG_DEBUG:
2966 case NDMP9_LOG_ERROR:
2971 case NDMP9_LOG_WARNING:
2982 sprintf (prefix, "%cLM%s", ref_conn->chan.name[1], tag);
2984 ndmalogf (sess, prefix, lev, "LOG_MESSAGE: '%s'", request->entry);
2990 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds LOG intfs */
2995 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds FH intfs */
2997 * NDMPx_FH Interfaces
2998 ****************************************************************
3005 * NDMP2_FH_ADD_UNIX_PATH
3006 * NDMP[34]_FH_ADD_FILE
3009 ndmp_sxa_fh_add_file (struct ndm_session *sess,
3010 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3012 struct ndm_control_agent *ca = &sess->control_acb;
3013 struct ndmlog * ixlog = &ca->job.index_log;
3014 int tagc = ref_conn->chan.name[1];
3018 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3020 NDMS_WITH_NO_REPLY(ndmp9_fh_add_file)
3021 for (i = 0; i < request->files.files_len; i++) {
3022 file = &request->files.files_val[i];
3024 ndmfhdb_add_file (ixlog, tagc,
3025 file->unix_path, &file->fstat);
3036 * NDMP2_FH_ADD_UNIX_DIR
3037 * NDMP[34]_FH_ADD_DIR
3040 ndmp_sxa_fh_add_dir (struct ndm_session *sess,
3041 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3043 struct ndm_control_agent *ca = &sess->control_acb;
3044 struct ndmlog * ixlog = &ca->job.index_log;
3045 int tagc = ref_conn->chan.name[1];
3050 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3052 NDMS_WITH_NO_REPLY(ndmp9_fh_add_dir)
3053 for (i = 0; i < request->dirs.dirs_len; i++) {
3054 dir = &request->dirs.dirs_val[i];
3056 raw_name = dir->unix_name;
3058 switch (ca->job.n_dir_entry) {
3060 if (strcmp (raw_name, ".") == 0) {
3062 ndmfhdb_add_dirnode_root (ixlog,
3064 ca->job.root_node = dir->node;
3067 ndmalogf (sess, 0, 0,
3068 "WARNING: First add_dir "
3069 "entry is non-conforming");
3074 if (strcmp (raw_name, "..") == 0
3075 && dir->parent == dir->node
3076 && dir->node == ca->job.root_node) {
3080 /* NetApp is non-conforming */
3081 /* ndmalogf (sess, 0, 0,
3082 "WARNING: Second add_dir "
3083 "entry is non-conforming"); */
3091 ndmfhdb_add_dir (ixlog, tagc,
3092 dir->unix_name, dir->parent, dir->node);
3094 ca->job.n_dir_entry++;
3105 * NDMP2_FH_ADD_UNIX_NODE
3106 * NDMP[34]_FH_ADD_NODE
3109 ndmp_sxa_fh_add_node (struct ndm_session *sess,
3110 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
3112 struct ndm_control_agent *ca = &sess->control_acb;
3113 struct ndmlog * ixlog = &ca->job.index_log;
3114 int tagc = ref_conn->chan.name[1];
3118 xa->reply.flags |= NDMNMB_FLAG_NO_SEND;
3120 NDMS_WITH_NO_REPLY(ndmp9_fh_add_node)
3121 for (i = 0; i < request->nodes.nodes_len; i++) {
3122 node = &request->nodes.nodes_val[i];
3124 ndmfhdb_add_node (ixlog, tagc,
3125 node->fstat.node.value, &node->fstat);
3131 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds FH intfs */
3136 * Common helper interfaces
3137 ****************************************************************
3138 * These do complicated state checks which are called from
3139 * several of the interfaces above.
3150 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
3152 * Shortcut for DATA->MOVER READ requests when NDMP9_ADDR_LOCAL
3153 * (local MOVER). This is implemented here because of the
3154 * state (sanity) checks. This should track the
3155 * NDMP9_MOVER_READ stanza in ndma_dispatch_request().
3159 ndmta_local_mover_read (struct ndm_session *sess,
3160 unsigned long long offset, unsigned long long length)
3162 struct ndm_tape_agent * ta = &sess->tape_acb;
3163 struct ndmp9_mover_get_state_reply *ms = &ta->mover_state;
3166 if (ms->state != NDMP9_MOVER_STATE_ACTIVE
3167 && ms->state != NDMP9_MOVER_STATE_LISTEN) {
3168 errstr = "mover_state !ACTIVE";
3171 if (ms->bytes_left_to_read > 0) {
3172 errstr = "byte_left_to_read";
3175 if (ms->data_connection_addr.addr_type != NDMP9_ADDR_LOCAL) {
3176 errstr = "mover_addr !LOCAL";
3179 if (ms->mode != NDMP9_MOVER_MODE_WRITE) {
3180 errstr = "mover_mode !WRITE";
3184 ms->seek_position = offset;
3185 ms->bytes_left_to_read = length;
3186 ta->mover_want_pos = offset;
3192 ndmalogf (sess, 0, 2, "local_read error why=%s", errstr);
3197 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
3206 * Dispatch Version Table and Dispatch Request Tables (DVT/DRT)
3207 ****************************************************************
3210 struct ndm_dispatch_request_table *
3211 ndma_drt_lookup (struct ndm_dispatch_version_table *dvt,
3212 unsigned protocol_version, unsigned message)
3214 struct ndm_dispatch_request_table * drt;
3216 for (; dvt->protocol_version >= 0; dvt++) {
3217 if (dvt->protocol_version == (int)protocol_version)
3221 if (dvt->protocol_version < 0)
3224 for (drt = dvt->dispatch_request_table; drt->message; drt++) {
3225 if (drt->message == message)
3232 struct ndm_dispatch_request_table ndma_dispatch_request_table_v0[] = {
3233 { NDMP0_CONNECT_OPEN,
3234 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3235 ndmp_sxa_connect_open,
3237 { NDMP0_CONNECT_CLOSE,
3238 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3239 ndmp_sxa_connect_close,
3241 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
3242 { NDMP0_NOTIFY_CONNECTED,
3244 ndmp_sxa_notify_connected,
3246 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
3252 #ifndef NDMOS_OPTION_NO_NDMP2
3253 struct ndm_dispatch_request_table ndma_dispatch_request_table_v2[] = {
3254 { NDMP2_CONFIG_GET_BUTYPE_ATTR,
3255 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3256 ndmp2_sxa_config_get_butype_attr
3258 { NDMP2_LOG_LOG, 0, ndmp2_sxa_log_log },
3259 { NDMP2_LOG_DEBUG, 0, ndmp2_sxa_log_debug },
3262 #endif /* !NDMOS_OPTION_NO_NDMP2 */
3264 #ifndef NDMOS_OPTION_NO_NDMP3
3265 struct ndm_dispatch_request_table ndma_dispatch_request_table_v3[] = {
3268 #endif /* !NDMOS_OPTION_NO_NDMP3 */
3270 #ifndef NDMOS_OPTION_NO_NDMP4
3271 struct ndm_dispatch_request_table ndma_dispatch_request_table_v4[] = {
3274 #endif /* !NDMOS_OPTION_NO_NDMP4 */
3277 struct ndm_dispatch_request_table ndma_dispatch_request_table_v9[] = {
3278 { NDMP9_CONNECT_OPEN,
3279 NDM_DRT_FLAG_OK_NOT_CONNECTED+NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3280 ndmp_sxa_connect_open
3282 { NDMP9_CONNECT_CLIENT_AUTH,
3283 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3284 ndmp_sxa_connect_client_auth
3286 { NDMP9_CONNECT_CLOSE,
3287 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3288 ndmp_sxa_connect_close
3290 { NDMP9_CONNECT_SERVER_AUTH,
3291 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3292 ndmp_sxa_connect_server_auth
3294 { NDMP9_CONFIG_GET_HOST_INFO,
3295 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3296 ndmp_sxa_config_get_info
3298 { NDMP9_CONFIG_GET_CONNECTION_TYPE,
3299 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3300 ndmp_sxa_config_get_info
3302 { NDMP9_CONFIG_GET_AUTH_ATTR,
3303 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3304 ndmp_sxa_config_get_auth_attr
3306 { NDMP9_CONFIG_GET_BUTYPE_INFO,
3307 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3308 ndmp_sxa_config_get_info
3310 { NDMP9_CONFIG_GET_FS_INFO,
3311 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3312 ndmp_sxa_config_get_info
3314 { NDMP9_CONFIG_GET_TAPE_INFO,
3315 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3316 ndmp_sxa_config_get_info
3318 { NDMP9_CONFIG_GET_SCSI_INFO,
3319 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3320 ndmp_sxa_config_get_info
3322 { NDMP9_CONFIG_GET_SERVER_INFO,
3323 NDM_DRT_FLAG_OK_NOT_AUTHORIZED,
3324 ndmp_sxa_config_get_info
3326 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT /* Surrounds SCSI intfs */
3327 { NDMP9_SCSI_OPEN, 0, ndmp_sxa_scsi_open },
3328 { NDMP9_SCSI_CLOSE, 0, ndmp_sxa_scsi_close },
3329 { NDMP9_SCSI_GET_STATE, 0, ndmp_sxa_scsi_get_state },
3330 { NDMP9_SCSI_SET_TARGET, 0, ndmp_sxa_scsi_set_target },
3331 { NDMP9_SCSI_RESET_DEVICE, 0, ndmp_sxa_scsi_reset_device },
3332 { NDMP9_SCSI_RESET_BUS, 0, ndmp_sxa_scsi_reset_bus },
3333 { NDMP9_SCSI_EXECUTE_CDB, 0, ndmp_sxa_scsi_execute_cdb },
3334 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */ /* Surrounds SCSI intfs */
3335 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds TAPE intfs */
3336 { NDMP9_TAPE_OPEN, 0, ndmp_sxa_tape_open },
3337 { NDMP9_TAPE_CLOSE, 0, ndmp_sxa_tape_close },
3338 { NDMP9_TAPE_GET_STATE, 0, ndmp_sxa_tape_get_state },
3339 { NDMP9_TAPE_MTIO, 0, ndmp_sxa_tape_mtio },
3340 { NDMP9_TAPE_WRITE, 0, ndmp_sxa_tape_write },
3341 { NDMP9_TAPE_READ, 0, ndmp_sxa_tape_read },
3342 { NDMP9_TAPE_EXECUTE_CDB, 0, ndmp_sxa_tape_execute_cdb },
3343 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds TAPE intfs */
3344 #ifndef NDMOS_OPTION_NO_DATA_AGENT /* Surrounds DATA intfs */
3345 { NDMP9_DATA_GET_STATE, 0, ndmp_sxa_data_get_state },
3346 { NDMP9_DATA_START_BACKUP, 0, ndmp_sxa_data_start_backup },
3347 { NDMP9_DATA_START_RECOVER, 0, ndmp_sxa_data_start_recover },
3348 { NDMP9_DATA_ABORT, 0, ndmp_sxa_data_abort },
3349 { NDMP9_DATA_GET_ENV, 0, ndmp_sxa_data_get_env },
3350 { NDMP9_DATA_STOP, 0, ndmp_sxa_data_stop },
3351 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 /* Surrounds NDMPv[34] DATA intfs */
3353 { NDMP9_DATA_LISTEN, 0, ndmp_sxa_data_listen },
3355 { NDMP9_DATA_CONNECT, 0, ndmp_sxa_data_connect },
3356 #endif /* NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 Surrounds NDMPv[34] DATA intfs */
3357 { NDMP9_DATA_START_RECOVER_FILEHIST, 0,
3358 ndmp_sxa_data_start_recover_filehist },
3359 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */ /* Surrounds DATA intfs */
3360 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds NOTIFY intfs */
3361 { NDMP9_NOTIFY_DATA_HALTED, 0, ndmp_sxa_notify_data_halted },
3362 { NDMP9_NOTIFY_CONNECTED, 0, ndmp_sxa_notify_connected },
3363 { NDMP9_NOTIFY_MOVER_HALTED, 0, ndmp_sxa_notify_mover_halted },
3364 { NDMP9_NOTIFY_MOVER_PAUSED, 0, ndmp_sxa_notify_mover_paused },
3365 { NDMP9_NOTIFY_DATA_READ, 0, ndmp_sxa_notify_data_read },
3366 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds NOTIFY intfs */
3367 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds LOG intfs */
3368 { NDMP9_LOG_FILE, 0, ndmp_sxa_log_file },
3369 { NDMP9_LOG_MESSAGE, 0, ndmp_sxa_log_message },
3370 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds LOG intfs */
3371 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT /* Surrounds FH intfs */
3372 { NDMP9_FH_ADD_FILE, 0, ndmp_sxa_fh_add_file },
3373 { NDMP9_FH_ADD_DIR, 0, ndmp_sxa_fh_add_dir },
3374 { NDMP9_FH_ADD_NODE, 0, ndmp_sxa_fh_add_node },
3375 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */ /* Surrounds FH intfs */
3376 #ifndef NDMOS_OPTION_NO_TAPE_AGENT /* Surrounds MOVER intfs */
3377 { NDMP9_MOVER_GET_STATE, 0, ndmp_sxa_mover_get_state },
3378 { NDMP9_MOVER_LISTEN, 0, ndmp_sxa_mover_listen },
3379 { NDMP9_MOVER_CONTINUE, 0, ndmp_sxa_mover_continue },
3380 { NDMP9_MOVER_ABORT, 0, ndmp_sxa_mover_abort },
3381 { NDMP9_MOVER_STOP, 0, ndmp_sxa_mover_stop },
3382 { NDMP9_MOVER_SET_WINDOW, 0, ndmp_sxa_mover_set_window },
3383 { NDMP9_MOVER_READ, 0, ndmp_sxa_mover_read },
3384 { NDMP9_MOVER_CLOSE, 0, ndmp_sxa_mover_close },
3385 { NDMP9_MOVER_SET_RECORD_SIZE, 0, ndmp_sxa_mover_set_record_size },
3386 { NDMP9_MOVER_CONNECT, 0, ndmp_sxa_mover_connect },
3387 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ /* Surrounds MOVER intfs */
3392 struct ndm_dispatch_version_table ndma_dispatch_version_table[] = {
3393 { 0, ndma_dispatch_request_table_v0 },
3394 #ifndef NDMOS_OPTION_NO_NDMP2
3395 { NDMP2VER, ndma_dispatch_request_table_v2 },
3396 #endif /* !NDMOS_OPTION_NO_NDMP2 */
3397 #ifndef NDMOS_OPTION_NO_NDMP3
3398 { NDMP3VER, ndma_dispatch_request_table_v3 },
3399 #endif /* !NDMOS_OPTION_NO_NDMP3 */
3400 #ifndef NDMOS_OPTION_NO_NDMP4
3401 { NDMP4VER, ndma_dispatch_request_table_v4 },
3402 #endif /* !NDMOS_OPTION_NO_NDMP4 */
3403 { NDMP9VER, ndma_dispatch_request_table_v9 },