X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=ndmp-src%2Fndmos_common.c;fp=ndmp-src%2Fndmos_common.c;h=dfa652378061ca65fcd888b49bda7fe91f752c2c;hb=fd48f3e498442f0cbff5f3606c7c403d0566150e;hp=0000000000000000000000000000000000000000;hpb=96f35b20267e8b1a1c846d476f27fcd330e0b018;p=debian%2Famanda diff --git a/ndmp-src/ndmos_common.c b/ndmp-src/ndmos_common.c new file mode 100644 index 0000000..dfa6523 --- /dev/null +++ b/ndmp-src/ndmos_common.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 1998,2001 + * Traakan, Inc., Los Altos, CA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Project: NDMJOB + * Ident: $Id: $ + * + * Description: + * This contains code fragments common between the + * O/S (Operating System) portions of NDMJOBLIB. + * + * This file is #include'd by the O/S specific ndmos_*.c + * file, and fragments are selected by #ifdef's. + * + * There are four major portions: + * 1) Misc support routines: password check, local info, etc + * 2) Non-blocking I/O support routines + * 3) Tape interfacs ndmos_tape_xxx() + * 4) OS Specific NDMP request dispatcher which intercepts + * requests implemented here, such as SCSI operations + * and system configuration queries. + */ + + + + +/* + * CONFIG SUPPORT + **************************************************************** + */ + +#ifdef NDMOS_COMMON_SYNC_CONFIG_INFO +/* + * Get local info. Supports NDMPx_CONFIG_GET_HOST_INFO, + * NDMP3_CONFIG_GET_SERVER_INFO, and NDMPx_CONFIG_GET_SCSI_INFO. + */ +void +ndmos_sync_config_info (struct ndm_session *sess) +{ + static struct utsname unam; + static char osbuf[100]; + static char idbuf[30]; + static char revbuf[50]; + char obuf[5]; + + if (sess->config_info.hostname) { + /* already set */ + return; + } + + obuf[0] = (char)(NDMOS_ID >> 24); + obuf[1] = (char)(NDMOS_ID >> 16); + obuf[2] = (char)(NDMOS_ID >> 8); + obuf[3] = (char)(NDMOS_ID >> 0); + obuf[4] = 0; + + uname (&unam); + sprintf (idbuf, "%lu", gethostid()); + /* + * give CONTROL via NDMPv2 a chance to recognize this + * implementation (no ndmp2_config_get_server). + */ + sprintf (osbuf, "%s (running %s from %s)", + unam.sysname, + NDMOS_CONST_PRODUCT_NAME, + NDMOS_CONST_VENDOR_NAME); + + sess->config_info.hostname = unam.nodename; + sess->config_info.os_type = osbuf; + sess->config_info.os_vers = unam.release; + sess->config_info.hostid = idbuf; + + sess->config_info.vendor_name = NDMOS_CONST_VENDOR_NAME; + sess->config_info.product_name = NDMOS_CONST_PRODUCT_NAME; + + sprintf (revbuf, "%s LIB:%d.%d/%s OS:%s (%s)", + NDMOS_CONST_PRODUCT_REVISION, + NDMJOBLIB_VERSION, NDMJOBLIB_RELEASE, + NDMOS_CONST_NDMJOBLIB_REVISION, + NDMOS_CONST_NDMOS_REVISION, + obuf); + + sess->config_info.revision_number = revbuf; + + /* best effort; note that this loads scsi and tape config */ + ndmcfg_load (sess->param.config_file_name, &sess->config_info); +} +#endif /* NDMOS_COMMON_SYNC_CONFIG_INFO */ + + + + +/* + * AUTHENTICATION SUPPORT + **************************************************************** + */ + +#ifdef NDMOS_COMMON_OK_NAME_PASSWORD +/* + * Determine whether the clear-text account name and password + * are valid. Supports NDMPx_CONNECT_CLIENT_AUTH requests. + */ +int +ndmos_ok_name_password (struct ndm_session *sess, char *name, char *pass) +{ + if (strcmp (name, "ndmp") != 0) + return 0; + + if (strcmp (pass, "ndmp") != 0) + return 0; + + return 1; /* OK */ +} +#endif /* NDMOS_COMMON_OK_NAME_PASSWORD */ + + + + +#ifdef NDMOS_COMMON_MD5 +/* + * MD5 authentication support + * + * See ndml_md5.c + */ + +int +ndmos_get_md5_challenge (struct ndm_session *sess) +{ + ndmmd5_generate_challenge (sess->md5_challenge); + sess->md5_challenge_valid = 1; + return 0; +} + +int +ndmos_ok_name_md5_digest (struct ndm_session *sess, + char *name, char digest[16]) +{ + if (strcmp (name, "ndmp") != 0) + return 0; + + if (!ndmmd5_ok_digest (sess->md5_challenge, "ndmp", digest)) + return 0; + + return 1; /* OK */ +} +#endif /* NDMOS_COMMON_MD5 */ + + + +#ifdef NDMOS_COMMON_NONBLOCKING_IO_SUPPORT +/* + * NON-BLOCKING I/O SUPPORT + **************************************************************** + * As support non-blocking I/O for NDMCHAN, condition different + * types of file descriptors to not block. + */ + +void +ndmos_condition_listen_socket (struct ndm_session *sess, int sock) +{ + int flag; + + flag = 1; + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (void*)&flag, sizeof flag); +} + +void +ndmos_condition_control_socket (struct ndm_session *sess, int sock) +{ + /* nothing */ +} + +void +ndmos_condition_image_stream_socket (struct ndm_session *sess, int sock) +{ + fcntl (sock, F_SETFL, O_NONBLOCK); + signal (SIGPIPE, SIG_IGN); +} + +void +ndmos_condition_pipe_fd (struct ndm_session *sess, int fd) +{ + fcntl (fd, F_SETFL, O_NONBLOCK); + signal (SIGPIPE, SIG_IGN); +} +#endif /* NDMOS_COMMON_NONBLOCKING_IO_SUPPORT */ + + + + +#ifdef NDMOS_COMMON_TAPE_INTERFACE +#ifndef NDMOS_OPTION_NO_TAPE_AGENT +#ifndef NDMOS_OPTION_TAPE_SIMULATOR +/* + * TAPE INTERFACE + **************************************************************** + * These interface to the O/S specific tape drivers and subsystem. + * They must result in functionality equivalent to the reference + * tape simulator. The NDMP TAPE model is demanding, and it is + * often necessary to workaround the native device driver(s) + * to achieve NDMP TAPE model conformance. + * + * It's easy to test this ndmos_tape_xxx() implementation + * using the ndmjob(1) command in test-tape conformance mode. + * The tape simulator passes this test. To test this implementation, + * rebuild ndmjob, then use this command: + * + * ndmjob -o test-tape -T. -f /dev/whatever + * + * These ndmos_tape_xxx() interfaces must maintain the tape state + * (sess->tape_agent.tape_state). In particular, the position + * information (file_num and blockno) must be accurate at all + * times. A typical workaround is to maintain these here rather + * than relying on the native device drivers. Another workaround + * is to implement NDMP MTIO operations using repeated native MTIO + * operations with count=1, then interpret the results and errors + * to maintain accurate position and residual information. + * + * Workarounds in this implementation (please keep this updated): + * + */ + +int +ndmos_tape_initialize (struct ndm_session *sess) +{ + return -1; +} + +void +ndmos_tape_sync_state (struct ndm_session *sess) +{ + the_tape_state.error = NDMP9_DEV_NOT_OPEN_ERR; +} + +ndmp9_error +ndmos_tape_open (struct ndm_session *sess, char *name, int will_write) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_tape_close (struct ndm_session *sess) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_tape_write (struct ndm_session *sess, char *data, + unsigned long count, unsigned long * done_count) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_tape_read (struct ndm_session *sess, char *data, + unsigned long count, unsigned long * done_count) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_tape_mtio (struct ndm_session *sess, ndmp9_tape_mtio_op op, + unsigned long count, unsigned long * done_count) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_tape_execute_cdb (struct ndm_session *sess, + ndmp9_execute_cdb_request *request, + ndmp9_execute_cdb_reply *reply) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +#endif /* !NDMOS_OPTION_TAPE_SIMULATOR */ +#else /* !NDMOS_OPTION_NO_TAPE_AGENT */ +/* tape interfaces implemented in ndma_tape_simulator.c */ +#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */ +#endif /* NDMOS_COMMON_TAPE_INTERFACE */ + + +#ifdef NDMOS_COMMON_ROBOT_INTERFACE +#ifndef NDMOS_OPTION_NO_ROBOT_AGENT +#ifndef NDMOS_OPTION_ROBOT_SIMULATOR + +/* ndmos_robot_* functions here */ + +#endif /* !NDMOS_OPTION_ROBOT_SIMULATOR */ +#else /* !NDMOS_OPTION_NO_ROBOT_AGENT */ +/* robot interfaces implemented in ndma_robot_simulator.c */ +#endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */ +#endif /* NDMOS_COMMON_ROBOT_INTERFACE */ + + +#ifdef NDMOS_COMMON_SCSI_INTERFACE +#ifndef NDMOS_OPTION_NO_ROBOT_AGENT /* Surrounds all SCSI intfs */ +#ifndef NDMOS_OPTION_ROBOT_SIMULATOR +/* + * SCSI INTERFACE + **************************************************************** + */ + +int +ndmos_scsi_initialize (struct ndm_session *sess) +{ + return -1; +} + +void +ndmos_scsi_sync_state (struct ndm_session *sess) +{ + sess->robot_acb.scsi_state.error = NDMP9_DEV_NOT_OPEN_ERR; +} + +ndmp9_error +ndmos_scsi_open (struct ndm_session *sess, char *name) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_scsi_close (struct ndm_session *sess) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +/* deprecated */ +ndmp9_error +ndmos_scsi_set_target (struct ndm_session *sess) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + + +ndmp9_error +ndmos_scsi_reset_device (struct ndm_session *sess) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +/* deprecated */ +ndmp9_error +ndmos_scsi_reset_bus (struct ndm_session *sess) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +ndmp9_error +ndmos_scsi_execute_cdb (struct ndm_session *sess, + ndmp9_execute_cdb_request *request, + ndmp9_execute_cdb_reply *reply) +{ + return NDMP9_NOT_SUPPORTED_ERR; +} + +#endif /* NDMOS_OPTION_ROBOT_SIMULATOR */ +#endif /* NDMOS_OPTION_NO_ROBOT_AGENT Surrounds all SCSI intfs */ +#endif /* NDMOS_COMMON_SCSI_INTERFACE */ + + + + +#ifdef NDMOS_COMMON_DISPATCH_REQUEST +/* + * ndmos_dispatch_request() -- O/S Specific Agent Dispatch Request (ADR) + **************************************************************** + * Some NDMP requests can only be handled as O/S specific portions, + * and are implemented here. + * + * The more generic NDMP requests may be re-implemented here rather + * than modifying the main body of code. Extensions to the NDMP protocol + * may also be implemented here. Neither is ever a good idea beyond + * experimentation. The structures in ndmagents.h provide for O/S + * specific extensions. Such extensions are #define'd in the ndmos_xxx.h. + * + * The return value from ndmos_dispatch_request() tells the main + * dispatcher, ndma_dispatch_request(), whether or not the request + * was intercepted. ndmos_dispatch_request() is called after basic + * reply setup is done (message headers and buffers), but before + * the request is interpretted. + */ + +#ifndef I_HAVE_DISPATCH_REQUEST + +/* + * If we're not intercepting, keep it simple + */ +int +ndmos_dispatch_request (struct ndm_session *sess, + struct ndmp_xa_buf *xa, struct ndmconn *ref_conn) +{ + return -1; /* not intercepted */ +} + +#else /* !I_HAVE_DISPATCH_REQUEST */ + +/* + * The following fragment is here for reference. + * If the O/S module intercepts requests, copy + * all this into the module source file and + * #undef NDMOS_COMMON_DISPATCH_REQUEST. + */ + +extern struct ndm_dispatch_version_table ndmos_dispatch_version_table[]; + +int +ndmos_dispatch_request (struct ndm_session *sess, + struct ndmp_xa_buf *xa, struct ndmconn *ref_conn) +{ + struct ndm_dispatch_request_table *drt; + unsigned protocol_version = ref_conn->protocol_version; + unsigned msg = xa->request.header.message; + int rc; + + drt = ndma_drt_lookup (ndmos_dispatch_version_table, + protocol_version, msg); + + if (!drt) { + return -1; /* not intercepted */ + } + + /* + * Replicate the ndma_dispatch_request() permission checks + */ + if (!sess->conn_open + && !(drt->flags & NDM_DRT_FLAG_OK_NOT_CONNECTED)) { + xa->reply.header.error = NDMP0_PERMISSION_ERR; + return 0; + } + + if (!sess->conn_authorized + && !(drt->flags & NDM_DRT_FLAG_OK_NOT_AUTHORIZED)) { + xa->reply.header.error = NDMP9_NOT_AUTHORIZED_ERR; + return 0; + } + + rc = (*drt->dispatch_request)(sess, xa, ref_conn); + + if (rc < 0) { + xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR; + } + + return 0; +} + + + + +/* + * Dispatch Version Table and Dispatch Request Tables (DVT/DRT) + **************************************************************** + */ + +struct ndm_dispatch_request_table ndmos_dispatch_request_table_v0[] = { + {0} +}; + +#ifndef NDMOS_OPTION_NO_NDMP2 +struct ndm_dispatch_request_table ndmos_dispatch_request_table_v2[] = { + {0} +}; +#endif /* !NDMOS_OPTION_NO_NDMP2 */ + +#ifndef NDMOS_OPTION_NO_NDMP3 +struct ndm_dispatch_request_table ndmos_dispatch_request_table_v3[] = { + {0} +}; +#endif /* !NDMOS_OPTION_NO_NDMP3 */ + +#ifndef NDMOS_OPTION_NO_NDMP4 +struct ndm_dispatch_request_table ndmos_dispatch_request_table_v4[] = { + {0} +}; +#endif /* !NDMOS_OPTION_NO_NDMP4 */ + + +struct ndm_dispatch_version_table ndmos_dispatch_version_table[] = { + { 0, ndmos_dispatch_request_table_v0 }, +#ifndef NDMOS_OPTION_NO_NDMP2 + { NDMP2VER, ndmos_dispatch_request_table_v2 }, +#endif /* !NDMOS_OPTION_NO_NDMP2 */ +#ifndef NDMOS_OPTION_NO_NDMP3 + { NDMP3VER, ndmos_dispatch_request_table_v3 }, +#endif /* !NDMOS_OPTION_NO_NDMP2 */ +#ifndef NDMOS_OPTION_NO_NDMP4 + { NDMP4VER, ndmos_dispatch_request_table_v4 }, +#endif /* !NDMOS_OPTION_NO_NDMP4 */ + { -1 } +}; +#endif /* !I_HAVE_DISPATCH_REQUEST */ +#endif /* NDMOS_COMMON_DISPATCH_REQUEST */